Project in progress
The Mill

The Mill

Commercial Automation for a lumber mill including relay controls and sensor networks to run daily operations.

  • 6,037 views
  • 5 comments
  • 9 respects

Components and supplies

Necessary tools and machines

09507 01
Soldering iron (generic)

About this project

So this project turned into something pretty crazy fairly quickly. There is a much larger back story, but for the sake of keeping this relatively short ill just tell you what happened when the sun finally came out for spring in the Mid Willamette Valley. Two of my brothers and I where college students in Oregon and naturally needed money for school.

We were on spring break complaining about our finals and decided we should do something for the break. My brothers said "Its a nice day, we should build a lumber mill". So the next day we began building a lumber mill on our family property. The machine we got our hands on was supposed to be complete and ready to run, all we had to do was move it.

Immateriality we began removing electrical and disassembling the equipment to move it. Once a majority of the equipment was move and installed on our property we finally opened the cabinet where the PLC automation controls where supposed to be. Once realizing there was nothing there we found ourselves in an interesting position. During lunch that day we talked about halting the project and doing something different or possibly figuring this out. Towards the end of lunch my brother asked me if i thought some Arduinos could take this whole project on, so after some thought i told him i would let him know. Later that night i had managed to accomplish enough with some minor tinkering abilities I had from a workshop class I took at my college to prove this was enough for proof of concept. The next day when we got together we decide that we were going to push forward with the mill using the Ardunios as our automation controllers.

Finger Jointer

This was an insanely large project that ended up turning into commercial business. Totaling  four control stations, a number of sensors and relay shield and many late nights of self teaching dc circuits and Arduino programming we were able make it work. Over the next year of debugging, new signal filters and additional experience things for the automation really smoothed out. The mill will be running on Arduinos for three years this summer of 2016. 

The world of makers and YouTube made this whole story possible, so i guess this is my way of giving back to the community. I will be posting all my code for the entire mill here. I have tried to comment as much as possible in my code, but i will do more as time goes one.

The "mill" is a vague term and you will notice there is slang that we use in the mill in my code. The mill is actually a 300 ft long high speed Western Pneumatic Finger-Jointer.  We make finger jointed studs for houses. This machine is really cool, different and very big.

Since I started this project it has opened so many doors for me. I have since taught Arduino workshops at physics conferences in San Diego and in my school. There is too much to write down but I am happy to share this with everyone! I learned a ton and want to share my knowledge.

Code

Left_Shield.inoArduino
Support code, used in the Serial monitor
void infoLeft () {
  while (true) {
    while (Serial.available() == 0);
    int command = Serial.read() - '0';

    switch (command) {

      case 1:
        turnOn(left[command]);
        Serial.print("Relay1 ON:  ");
        Serial.print(left[command]);
        Serial.print("  ");
        Serial.println(leftString[command]);
        break;

      case 2:
        turnOn(left[command]);
        Serial.print("Relay2 ON:  ");
        Serial.print(left[command]);
        Serial.print("  ");
        Serial.println(leftString[command]);
        break;

      case 3:
        turnOn(left[command]);
        Serial.print("Relay3 ON:  ");
        Serial.print(left[command]);
        Serial.print("  ");
        Serial.println(leftString[command]);
        break;

      case 4:
        turnOn(left[command]);
        Serial.print("Relay4 ON:  ");
        Serial.print(left[command]);
        Serial.print("  ");
        Serial.println(leftString[command]);
        break;

      case 5:
        turnOn(left[command]);
        Serial.print("Relay5 ON:  ");
        Serial.print(left[command]);
        Serial.print("  ");
        Serial.println(leftString[command]);
        break;

      case 6:
        turnOn(left[command]);
        Serial.print("Relay6 ON:  ");
        Serial.print(left[command]);
        Serial.print("  ");
        Serial.println(leftString[command]);
        break;

      case 7:
        turnOn(left[command]);
        Serial.print("Relay7 ON:  ");
        Serial.print(left[command]);
        Serial.print("  ");
        Serial.println(leftString[command]);
        break;

      case 8:
        turnOn(left[command]);
        Serial.print("Relay8 ON:  ");
        Serial.print(left[command]);
        Serial.print("  ");
        Serial.println(leftString[command]);
        break;

      case 0:
        Serial.println("Exiting Left Sheild...");
        break;

      default:
        shutdown();
        Serial.println("Shutdown");
        break;
    }
    if (command == 0) {
      break;
    }

  }
}
Middle_Shield.inoArduino
Support code for the Press, used in the Serial monitor
void infoMiddle () {
  while (true) {
    while (Serial.available() == 0);
    int command = Serial.read() - '0';

    switch (command) {

      case 1:
        turnOn(middle[command]);
        Serial.print("Relay1 ON:  ");
        Serial.print(middle[command]);
        Serial.print("  ");
        Serial.println(middleString[command]);
        break;

      case 2:
        turnOn(middle[command]);
        Serial.print("Relay2 ON:  ");
        Serial.print(middle[command]);
        Serial.print("  ");
        Serial.println(middleString[command]);
        break;

      case 3:
        turnOn(middle[command]);
        Serial.print("Relay3 ON:  ");
        Serial.print(middle[command]);
        Serial.print("  ");
        Serial.println(middleString[command]);
        break;

      case 4:
        turnOn(middle[command]);
        Serial.print("Relay4 ON:  ");
        Serial.print(middle[command]);
        Serial.print("  ");
        Serial.println(middleString[command]);
        break;

      case 5:
        turnOn(middle[command]);
        Serial.print("Relay5 ON:  ");
        Serial.print(middle[command]);
        Serial.print("  ");
        Serial.println(middleString[command]);
        break;

      case 6:
        turnOn(middle[command]);
        Serial.print("Relay6 ON:  ");
        Serial.print(middle[command]);
        Serial.print("  ");
        Serial.println(middleString[command]);
        break;

      case 7:
        turnOn(middle[command]);
        Serial.print("Relay7 ON:  ");
        Serial.print(middle[command]);
        Serial.print("  ");
        Serial.println(middleString[command]);
        break;

      case 8:
        turnOn(middle[command]);
        Serial.print("Relay8 ON:  ");
        Serial.print(middle[command]);
        Serial.print("  ");
        Serial.println(middleString[command]);
        break;

      case 0:
        Serial.println("Exiting Left Sheild...");
        break;

      default:
        shutdown();
        Serial.println("Shutdown");
        break;
    }
    if (command == 0) {
      break;
    }

  }
}
Right_Shield.inoArduino
Support code for the Press, used in the Serial monitor
void infoRight () {
  while (true) {
    while (Serial.available() == 0);
    int command = Serial.read() - '0';

    switch (command) {

      case 1:
        turnOn(right[command]);
        Serial.print("Relay1 ON:  ");
        Serial.print(right[command]);
        Serial.print("  ");
        Serial.println(rightString[command]);
        break;

      case 2:
        turnOn(right[command]);
        Serial.print("Relay2 ON:  ");
        Serial.print(right[command]);
        Serial.print("  ");
        Serial.println(rightString[command]);
        break;

      case 3:
        turnOn(right[command]);
        Serial.print("Relay3 ON:  ");
        Serial.print(right[command]);
        Serial.print("  ");
        Serial.println(rightString[command]);
        break;

      case 4:
        turnOn(right[command]);
        Serial.print("Relay4 ON:  ");
        Serial.print(right[command]);
        Serial.print("  ");
        Serial.println(rightString[command]);
        break;

      case 5:
        turnOn(right[command]);
        Serial.print("Relay5 ON:  ");
        Serial.print(right[command]);
        Serial.print("  ");
        Serial.println(rightString[command]);
        break;

      case 6:
        turnOn(right[command]);
        Serial.print("Relay6 ON:  ");
        Serial.print(right[command]);
        Serial.print("  ");
        Serial.println(rightString[command]);
        break;

      case 7:
        turnOn(right[command]);
        Serial.print("Relay7 ON:  ");
        Serial.print(right[command]);
        Serial.print("  ");
        Serial.println(rightString[command]);
        break;

      case 8:
        turnOn(right[command]);
        Serial.print("Relay8 ON:  ");
        Serial.print(right[command]);
        Serial.print("  ");
        Serial.println(rightString[command]);
        break;

      case 0:
        Serial.println("Exiting Left Sheild...");
        break;

      default:
        shutdown();
        Serial.println("Shutdown");
        break;
    }
    if (command == 0) {
      break;
    }

  }
}
Sensors.inoArduino
Support code for the Press, used in the Serial monitor
void sensorInfo() {
 
  while (state = true) {
    while (Serial.available() == 0);
    int selection = Serial.read() - '0';

    switch (selection) {

      case speedRollsSensor:
        while (state == true) {
          Serial.print(sensorsString[selection]);
          Serial.print(":  ");
          Serial.println(analogRead(sensors[selection]));
          choice = Serial.read() - '0';
          if (choice == 0) {
            state = false;
          }
        }
        break;

      case pushoutSensor:
        while (state == true) {
          Serial.print(sensorsString[selection]);
          Serial.print(":  ");
          Serial.println(analogRead(sensors[selection]));
          choice = Serial.read() - '0';
          if (choice == 0) {
            state = false;
          }
        }
        break;

      case endPressSensor:
        while (state == true) {
          Serial.print(sensorsString[selection]);
          Serial.print(":  ");
          Serial.println(analogRead(sensors[selection]));
          choice = Serial.read() - '0';
          if (choice == 0) {
            state = false;
          }
        }
        break;

      case fullStrokeSensor:
        while (state == true) {
          Serial.print(sensorsString[selection]);
          Serial.print(":  ");
          Serial.println(analogRead(sensors[selection]));
          choice = Serial.read() - '0';
          if (choice == 0) {
            state = false;
          }
        }
        break;

      case startUpSequenceButton:
        while (state == true) {
          Serial.print(sensorsString[selection]);
          Serial.print(":  ");
          Serial.println(analogRead(sensors[selection]));
          choice = Serial.read() - '0';
          if (choice == 0) {
            state = false;
          }
        }
        break;

      case A5:  // Open Pin
        while (state == true) {
          Serial.print(sensorsString[selection]);
          Serial.print(":  ");
          Serial.println(analogRead(sensors[selection]));
          choice = Serial.read() - '0';
          if (choice == 0) {
            state = false;
          }
        }
        break;

      case runButton:  // Open Pin
        while (state == true) {
          Serial.print(sensorsString[selection]);
          Serial.print(":  ");
          Serial.println(analogRead(sensors[selection]));
          choice = Serial.read() - '0';
          if (choice == 0) {
            state = false;
          }
        }
        break;

      case assemblySensor:  // Open Pin
        while (state == true) {
          Serial.print(sensorsString[selection]);
          Serial.print(":  ");
          Serial.println(analogRead(sensors[selection]));
          choice = Serial.read() - '0';
          if (choice == 0) {
            state = false;
          }
        }
        break;

      case A8:  // Open Pin
        while (state == true) {
          Serial.print(sensorsString[selection]);
          Serial.print(":  ");
          Serial.println(analogRead(sensors[selection]));
          choice = Serial.read() - '0';
          if (choice == 0) {
            state = false;
          }
        }
        break;

      case A9:  // Open Pin
        while (state == true) {
          Serial.print(sensorsString[selection]);
          Serial.print(":  ");
          Serial.println(analogRead(sensors[selection]));
          choice = Serial.read() - '0';
          if (choice == 0) {
            state = false;
          }
        }
        break;

      case flyingCutOffMoveSensor:  // Open Pin
        while (state == true) {
          Serial.print(sensorsString[selection]);
          Serial.print(":  ");
          Serial.println(analogRead(sensors[selection]));
          choice = Serial.read() - '0';
          if (choice == 0) {
            state = false;
          }
        }
        break;

      case maintenancePressed:  // Open Pin
        while (state == true) {
          Serial.print(sensorsString[selection]);
          Serial.print(":  ");
          Serial.println(analogRead(sensors[selection]));
          choice = Serial.read() - '0';
          if (choice == 0) {
            state = false;
          }
        }
        break;

      case drainSensor:  // Open Pin
        while (state == true) {
          Serial.print(sensorsString[selection]);
          Serial.print(":  ");
          Serial.println(analogRead(sensors[selection]));
          choice = Serial.read() - '0';
          if (choice == 0) {
            state = false;
          }
        }
        break;

      case A13:  // Open Pin
        while (state == true) {
          Serial.print(sensorsString[selection]);
          Serial.print(":  ");
          Serial.println(analogRead(sensors[selection]));
          choice = Serial.read() - '0';
          if (choice == 0) {
            state = false;
          }
        }
        break;

      case A14:  // Open Pin
        while (state == true) {
          Serial.print(sensorsString[selection]);
          Serial.print(":  ");
          Serial.println(analogRead(sensors[selection]));
          choice = Serial.read() - '0';
          if (choice == 0) {
            state = false;
          }
        }
        break;

      case A15:  // Open Pin
        while (state == true) {
          Serial.print(sensorsString[selection]);
          Serial.print(":  ");
          Serial.println(analogRead(sensors[selection]));
          choice = Serial.read() - '0';
          if (choice == 0) {
            state = false;
          }
        }
        break;

      default:
        return;
        break;

    }
  }
}
Stacker_Code.inoArduino
Code for the automatic stacker
/*  Written By: Amos Parmenter
                Jun 11, 2014 "Revised July 16, 2014"
                Parmenter INT.

  This is for the small green automatic stacker at the
  end of the finger jointer after the mulder. The purpouse
  is to stack one full layer of boards onto the outfeed
  chain deck in front of the machine. It runs in a cycle
  motion to acomplish this task and will use an array of
  sensor to determine postion of the forks the boards lay
  on to determine where and when the cylce is complete and
  ready to cycle again.
  
    *  Be sure to read the tab for the function calls.
  I keep all of the function off the main tab to
  make the code easier to read or find the values
  I am looking for. It helps the debuging process.

*/
#define ON LOW
#define OFF HIGH

//--- Sensors --------------------------
int button     = 0;  // The switch to start thde cycle
int allForward = 5;  // The sensor that says im forward
int unit       = 1;  // This sensor sees the unit
int allBack    = 3;  // The sensor that says im all the way back
int allUp      = 2;  // The sensor that says im all the way up
// I have three open filters on the shield for more sensors
//--------------------------------------
//--- Relays ---------------------------
int up      = 39;  // The relay going up
int down    = 41;  // The relay going down
int forward = 43;  // The relay going forward
int reverse = 45;  // The relay going reverse
int brake   = 47;  // The relay for the brake

// I have three relays left unused.
// int relay = 49;
// int relay = 51;
// int relay = 53;
//--------------------------------------

void setup() {
  Serial.begin(9600);

  pinMode(unit,       INPUT);
  pinMode(allForward, INPUT);
  pinMode(allBack,    INPUT);
  pinMode(button,     INPUT);
  pinMode(allUp,      INPUT);

  pinMode(forward, OUTPUT);       // This sets Relay 1 as an output
  digitalWrite(forward, OFF);     // Turns the relay off
  pinMode(reverse, OUTPUT);       // This sets Relay 2 as an output
  digitalWrite(reverse, OFF);     // Turns the relay off
  pinMode(up, OUTPUT);            // This sets Relay 3 as an output
  digitalWrite(up, OFF);          // Turns the relay off
  pinMode(down, OUTPUT);          // This sets Relay 4 as an output
  digitalWrite(down, OFF);        // Turns the relay off
  pinMode(brake, OUTPUT);         // This sets Relay 5 as an output
  digitalWrite(brake, OFF);       // Turns the relay off

}

void loop() {
  Serial.println(aRead(allForward));
  
  if (analogRead(button) >= 200 ) {
    turnOn(brake);      // Disengages the brake of on the F/R Motor
    while (isOn(brake)) {
      turnOn(brake);
      turnOn(forward);    // Sends the F/R motor FORWARD
      delay(1000);
      if (aRead(allForward) >= 200 ){
        delay(20);
        break;
      }
    }
  }

if (aRead(allForward) >= 200) {
  turnOff(forward);   // Turns the F/R motor OFF
  turnOn(down );   // This is the U/D Motor turning going DOWN
  delay(1000);
  turnOff(brake);   // Engages the brake of on the F/R Motor
}

if (aRead(unit) >= 200) {
  turnOn(brake);  // This Disengages the F/R brake
  while (isOn(brake)) {
    turnOn(brake);
    turnOn(reverse);  // This sends the F/R Motor REVERSE
    if (aRead(allBack) >= 150)
      break;
  }
}

if (aRead(allBack) >= 200 && aRead(allUp) <= 200 ) {
  turnOff(reverse);    // This turns the F/R Motor OFF
  delay(1250);
  turnOff(brake);    // Engages the F/R brake
  turnOff(down);
  turnOn(up );    // Sends the U/D Motor UP
}

if (aRead(allBack) >= 200 && aRead(allUp) >= 200) {
  shutDown();
}

//--- This is the end of the VOID LOOP -------------------------------
}
Stacker_functions.inoArduino
Support code for the stacker and function calls.
//--- Shut it Down ------------------------------------------
void shutDown(){
  turnOff(up);
  turnOff(down);
  turnOff(forward);
  turnOff(reverse);
  turnOff(brake);
  return;
}

//--- Turn the pin ON ----------------------------------------
void turnOn(int pinNumber){
  digitalWrite(pinNumber, ON);
}

//--- Turn the pin OFF ---------------------------------------
void turnOff(int pinNumber){
  digitalWrite(pinNumber, OFF);
}

//--- Return true if the pin is ON ---------------------------
boolean isOn(int pinNumber){
  return (digitalRead(pinNumber) == ON);
}

//--- Return true if the pin is OFF --------------------------
boolean isOff(int pinNumber){
  return (digitalRead(pinNumber) == OFF);
}
//--- Returns the analogRead for the pin ---------------------
int aRead(int pinNumber) {
  return analogRead(pinNumber);
}
FJ_Cutter_Heads_Start_UP.inoArduino
This is the main code that runs the start up sequence and automation for a single part of the machine. Since this is the main code, there are several other codes that run in tab to this code that I will also post
//--- Deffenitions -----------------------------------------------------------------------------------------------------------
#define ON LOW
#define OFF HIGH
#define delayTime 250

bool state = true;
int choice;
//-----------------------------------------------------------------------------------------------------------------------------
const int startUp = 0;       // This is the Cutter-Head E-Stop
const int motion  = 1;       // This is the Lug-Chain E-Stop

int sensor[] = {startUp, motion};
char* sensorString[] = {"startUp", "motion"};
//----------------------------------------------------------------------------------------------------------------------------

//--- This is for the relay shield on the LEFT
int cutterHeadA = 38;     // Cutter Head A
int cutterHeadB = 40;     // Cutter Head B
int trimSawA    = 42;     // Trimsaw A
int trimSawB    = 44;     // Trimsaw B
int scoringA    = 46;     // Scoring Saw A
int scoringB    = 48;     // Scoring Saw B
int crossOver   = 50;     // Cross Over belts
int lugChain    = 52;     // Lug Chain

int relays[] = {0, cutterHeadA, cutterHeadB, trimSawA, trimSawB, scoringA, scoringB, crossOver, lugChain};
char* relaysString[] = {"0", "cutterHeadA", "cutterHeadB", "trimSawA", "trimSawB",
                        "scoringA", "davidNorth", "crossOver", "lugChain"
                       };
//----------------------------------------------------------------------------------------------------------------------------
void setup() {

  Serial.begin(9600);
  //--------------------------------------------------------------------------------------------------------------------------
  for (int y = 0; y <= 1; y++) {
    Serial.print(sensorString[y]);
    Serial.print(": ");
    Serial.println(sensor[y]);
    pinMode(sensor[y], INPUT);
  }
  //--------------------------------------------------------------------------------------------------------------------------
  for (int x = 0; x <= 8; x++) {
    Serial.print(relaysString[x]);
    Serial.print(": ");
    Serial.println(relays[x]);
    pinMode(relays[x], OUTPUT);
    turnOff(relays[x]);
  }
  //----------------------------------------------------------------------------------------------------------------------------
}// This is the end of the Setup
//----------------------------------------------------------------------------------------------------------------------------


void loop() {

  Serial.println("making borads");
  while (Serial.available() < 0);
  int options = Serial.read() - '0';
  if (options == 1) {
    INFO();
  }

  //-----------------------------------
  //--- Start UP ----------------------
  if (systemCheck() == 0)
  {
    if (!eStopButtonPressed()) {
      spoolUp();
    }
  }
  if (eStopButtonPressed())
    shutdown();
  //----------------------------------

  //----------------------------------
  //--- Operation --------------------
  if (systemCheck() == 1)
  {
    if (!lugChainPressed())
    {
      turnOn(lugChain );
      turnOn(crossOver);
    }
    else
    {
      turnOff(lugChain );
      turnOff(crossOver);
      if (eStopButtonPressed())
        shutdown();
    }
  }

  //--------------------------------------------
}// This is the end of the loop!
//--------------------------------------------
Sart_UP_Sensors.inoArduino
For the Serial Monitor so that you can look at values while the machine is running. Creates a sort of menu.
void sensorInfo() {

  while (state = true) {
    while (Serial.available() == 0);
    int selection = Serial.read() - '0';

    switch (selection) {

      case startUp:
        while (state == true) {
          Serial.print(sensorString[selection]);
          Serial.print(":  ");
          Serial.println(analogRead(sensor[selection]));
          choice = Serial.read() - '0';
          if (choice == 0) {
            state = false;
          }
        }
        break;

      case motion:
        while (state == true) {
          Serial.print(sensorString[selection]);
          Serial.print(":  ");
          Serial.println(analogRead(sensor[selection]));
          choice = Serial.read() - '0';
          if (choice == 0) {
            state = false;
          }
        }
        break;

      default:
        return;
        break;

    }
  }
}
Start_UP_Controls.inoArduino
Functions that run in the main code.
bool eStopButtonPressed(){
  return (analogRead(startUp) <= 100);
}
bool lugChainPressed(){
  return (analogRead(motion) <= 100);
}
//--- Turn the pin ON ----------------------------------------
void turnOn(int pinNumber){
  digitalWrite(pinNumber, ON);
}
//------------------------------------------------------------
//--- Turn the pin OFF ---------------------------------------
void turnOff(int pinNumber){
  digitalWrite(pinNumber, OFF);
}
//------------------------------------------------------------
//--- Return true if the pin is ON ---------------------------
bool isOn(int pinNumber){
  return (digitalRead(pinNumber) == ON);
}
//------------------------------------------------------------
//--- Return true if the pin is OFF --------------------------
bool isOff(int pinNumber){
  return (digitalRead(pinNumber) == OFF);
}
//--------------------------------------------------------------------------------
// Give some time between actions to check if the e-stop button was pressed-------
void giveMeSomeTime(){
  for (int i = 0; i < 6; i++)
  {
    if (eStopButtonPressed())
      shutdown();
    delay (delayTime);
    if (eStopButtonPressed())
      shutdown();
  }
}

// Shutdown the process ------------------------------------------------------------
void shutdown(){
  for (int a = 0; a < 2; a++)
  {
    turnOff(cutterHeadA);
    turnOff(cutterHeadB);
    turnOff(trimSawA);
    turnOff(trimSawB);
    turnOff(scoringA);
    turnOff(scoringB);
    turnOff(lugChain);
    turnOff(crossOver);
  }
}
//-------------------------------------------------------------------------------------
bool systemCheck(){
  if (isOn(cutterHeadA) && isOn(cutterHeadB) && isOn(trimSawA) && isOn(trimSawB))
    return 1;
  if (isOff(cutterHeadA) && isOff(cutterHeadB) && isOff(trimSawA) && isOff(trimSawB))
    return 0;
}

void spoolUp(){
      turnOn(trimSawB);
      giveMeSomeTime();
      turnOn(trimSawA);
      giveMeSomeTime();
      turnOn(cutterHeadB);
      giveMeSomeTime();
      turnOn(cutterHeadA);
      giveMeSomeTime();
      if (eStopButtonPressed())
        shutdown();
}


void INFO() {
  Serial.println("Select what you want");
  Serial.println("1 = Relays, 2 = Sensors");

  while (Serial.available() == 0);
  int sheild = Serial.read() - '0';
  switch (sheild) {

    case 1:
      Serial.println("Relay Sheild");
      infoRelays();
      break;
    case 2:
      Serial.println("Sensor");
      sensorInfo();
      break;
  }

}
Start_UP_relayShield.inoArduino
For the Serial Monitor so that you can look at values while the machine is running. Creates a sort of menu.
I used 1-8 for the case number to associate with the relay shields.
void infoRelays () {
  while (true) {
    while (Serial.available() == 0);
    int command = Serial.read() - '0';

    switch (command) {

      case 1:
        turnOn(relays[command]);
        Serial.print("Relay1 ON:  ");
        Serial.print(relays[command]);
        Serial.print("  ");
        Serial.println(relaysString[command]);
        break;

      case 2:
        turnOn(relays[command]);
        Serial.print("Relay2 ON:  ");
        Serial.print(relays[command]);
        Serial.print("  ");
        Serial.println(relaysString[command]);
        break;

      case 3:
        turnOn(relays[command]);
        Serial.print("Relay3 ON:  ");
        Serial.print(relays[command]);
        Serial.print("  ");
        Serial.println(relaysString[command]);
        break;

      case 4:
        turnOn(relays[command]);
        Serial.print("Relay4 ON:  ");
        Serial.print(relays[command]);
        Serial.print("  ");
        Serial.println(relaysString[command]);
        break;

      case 5:
        turnOn(relays[command]);
        Serial.print("Relay5 ON:  ");
        Serial.print(relays[command]);
        Serial.print("  ");
        Serial.println(relaysString[command]);
        break;

      case 6:
        turnOn(relays[command]);
        Serial.print("Relay6 ON:  ");
        Serial.print(relays[command]);
        Serial.print("  ");
        Serial.println(relaysString[command]);
        break;

      case 7:
        turnOn(relays[command]);
        Serial.print("Relay7 ON:  ");
        Serial.print(relays[command]);
        Serial.print("  ");
        Serial.println(relaysString[command]);
        break;

      case 8:
        turnOn(relays[command]);
        Serial.print("Relay8 ON:  ");
        Serial.print(relays[command]);
        Serial.print("  ");
        Serial.println(relaysString[command]);
        break;

      case 0:
        Serial.println("Exiting Left Sheild...");
        break;

      default:
        shutdown();
        Serial.println("Shutdown");
        break;
    }
    if (command == 0) {
      break;
    }

  }
}
FJ_Grinder.inoArduino
Automation for grider
#define ON HIGH
#define OFF LOW
#define delayTime 200

boolean switching = true;
boolean state = true;

int choice;
int direction;

const int motionButton  = 0;       // This is the Lug-Chain E-Stop
const int frontSensor   = 1;
const int backSensor    = 2;

const int forward = 7;
const int reverse = 8;

int sensor[] = {motionButton, frontSensor, backSensor};
char* sensorString[] = {"motion", "front", "back"};

int relays[] = {0, 0, 0, 0, 0, 0, 0, forward, reverse};
char* relaysString[] = {"0", "0", "0", "0", "0", "0", "0", "forward", "reverse"};


void setup() {

  Serial.begin(9600);

  pinMode(motionButton, INPUT);
  pinMode(frontSensor,  INPUT);
  pinMode(backSensor ,  INPUT);

  pinMode(forward, OUTPUT);
  pinMode(reverse, OUTPUT);

}

void loop() {

  Serial.print("Grinding ");
  Serial.println(relaysString[direction]);
  while (Serial.available() < 0);
  int options = Serial.read() - '0';
  if (options == 1) {
    INFO();
  }

  if (direction = reverse) {
    if ( read(frontSensor) < 25) {
      switching = true;
      direction = forward;
    }
  }
  if (direction = forward) {
    if ( read(backSensor) < 25) {
      switching = true;
      direction = reverse;
    }
  }

  if (motionButtonPressed()) {
    switch (direction) {

      case forward:
        if (switching == true) {
          turnOff(reverse);
          giveMeSomeTime();
          turnOn(forward);
          switching = false;
        }
        break;

      case reverse:
        if (switching == true) {
          turnOff(forward);
          giveMeSomeTime();
          turnOn(reverse);
          switching = false;
        }
        break;
    }
  }
  else {
    shutdown();
  }
}
FJ_Grinder_Controls.inoArduino
Support Code for grinder
//--- Checks value of analoginput ---------------------------
int read(int pinNumber) {
  return analogRead(pinNumber);
}
//--- Checks the Motion Button -------------------------------
boolean motionButtonPressed()
{
  return (analogRead(motionButton) > 200);
}
//--- Turn the pin ON ----------------------------------------
void turnOn(int pinNumber) {
  digitalWrite(pinNumber, ON);
}
//------------------------------------------------------------
//--- Turn the pin OFF ---------------------------------------
void turnOff(int pinNumber) {
  digitalWrite(pinNumber, OFF);
}
//------------------------------------------------------------
//--- Return true if the pin is ON ---------------------------
bool isOn(int pinNumber) {
  return (digitalRead(pinNumber) == ON);
}
//------------------------------------------------------------
//--- Return true if the pin is OFF --------------------------
bool isOff(int pinNumber) {
  return (digitalRead(pinNumber) == OFF);
}
//----------------------------------------------------------------------------
// Give some time between actions to check if the e-stop button was pressed---
void giveMeSomeTime() {
  for (int i = 0; i < 1; i++)
  {
    delay (delayTime);
  }
}
// Shutdown the process ----------------------------------------------------
void shutdown() {
  for (int a = 0; a < 1; a++)
  {
    turnOff(reverse);
    turnOff(forward);
  }
}
void INFO() {

  Serial.println("Select what you want");
  Serial.println("1 = Relays, 2 = Sensors");

  while (Serial.available() == 0);
  int selection = Serial.read() - '0';
   switch (selection) {

    case 1:
      Serial.println("Relays");
      infoRelays();
      break;
    case 2:
      Serial.println("Sensors");
      sensorInfo();
      break;
  }
}

void sensorInfo() {

  while (state = true) {
    while (Serial.available() == 0);
    int selection = Serial.read() - '0';

    switch (selection) {
      case motionButton:
        while (state == true) {
          Serial.print(sensorString[selection]);
          Serial.print(":  ");
          Serial.println(analogRead(sensor[selection]));
          choice = Serial.read() - '0';
          if (choice == 0) {
            state = false;
          }
        }
        break;
      case frontSensor:
        while (state == true) {
          Serial.print(sensorString[selection]);
          Serial.print(":  ");
          Serial.println(analogRead(sensor[selection]));
          choice = Serial.read() - '0';
          if (choice == 0) {
            state = false;
          }
        }
        break;
      case backSensor:
        while (state == true) {
          Serial.print(sensorString[selection]);
          Serial.print(":  ");
          Serial.println(analogRead(sensor[selection]));
          choice = Serial.read() - '0';
          if (choice == 0) {
            state = false;
          }
        }
        break;
      default:
        return;
        break;
    }
  }
}

void infoRelays () {
  while (true) {
    while (Serial.available() == 0);
    int command = Serial.read() - '0';

    switch (command) {

      case forward:
        turnOn(relays[command]);
        Serial.print("Relay1 ON:  ");
        Serial.print(relays[command]);
        Serial.print("  ");
        Serial.println(relaysString[command]);
        break;

      case reverse:
        turnOn(relays[command]);
        Serial.print("Relay2 ON:  ");
        Serial.print(relays[command]);
        Serial.print("  ");
        Serial.println(relaysString[command]);
        break;

      case 0:
        Serial.println("Exiting Sheild...");
        break;

      default:
        shutdown();
        Serial.println("Shutdown");
        break;
    }
    if (command == 0) {
      break;
    }
  }
}
Press_Code_24VDC_wCommands.inoArduino
Main Press code. This runs the largest part of the machine that catches and cuts the boards, then compresses the boards together.
/*
Written by:      Amos Parmenter, Ricardo G, Brad Parmenter, Sam Parmenter.
Date Revised:    March 16, 2015

Purpose:  This code was intended to run the press section of the finger-jointer at Paremnter Intl.
          This code over sees the cycling of the press along with the e-stops and other functions
          pertaining to this section of the mill.
*/


//--- Deffenitions -----------------------------------------------------------------------------------------------------------
#define ON LOW
#define OFF HIGH
#define delayTime 250

bool state = true;

int choice;
int selection;
int x;

//-- Declare Buttons ---------------------------------------------------------------------------------------------------------
const int startUpSequenceButton = 4;			// Designates Upper Left E-Stop as start up sequence
const int runButton = 6;				          // Designates the Green E-Stop as Run for crowder rolls

//--- Declare Sensors --------------------------------------------------------------------------------------------------------
const int speedRollsSensor = 0;		      	// This is for the sensor on the speed up rolls at the begining of the press
const int pushoutSensor = 1;				      // This is for the sensor looking at the pushout
const int endPressSensor = 2;				      // This is for the sensor on at the end of the press
const int fullStrokeSensor = 3;		        // This is for the sensor on the flying cut off relase
const int assemblySensor = 7;				      // This is for the sensor in the assembly
const int flyingCutOffMoveSensor = 10;	  // This is for the sensor that sees the flying cut off move
const int drainSensor = 12;               // This is for the drain sensor in the press
const int maintenancePressed = 11;        // This is for the maintenance button that opens the press

int sensors[] = {
  speedRollsSensor, pushoutSensor, endPressSensor, fullStrokeSensor, startUpSequenceButton, 5,
  runButton, assemblySensor, 8, 9, flyingCutOffMoveSensor, maintenancePressed, drainSensor, 13, 14, 15
};
char* sensorsString[] = {
  "speedRollsSensor", "pushoutSensor", "endPressSensor", "fullStrokeSensor", "startUpSequenceButton", "5",
  "runButton", "assemblySensor", "8", "9", "flyingCutOffMoveSensor", "maintenancePressed", "drainSensor", "13", "14", "15"
};

//--- Relay Shield #1 on the left ---------------------------------------------------------------------------------------------
int pushoutRelay = 22;				            // press pushout in the press
int hydraulicCrowderRollsRelay = 24;	  	// hydraulic crowder rolls
int crowderRollsAirRelay = 26;			      // crowder rolls air
int flyingCutOffSawUpRelay = 28;		      // flying cutt off saw blade cuts the board
int flyingCutOffRetractRelay = 30;		    // flying cut off retract
int spikeHoldDownRelay = 32;		        	// spike hold down
int flyingCutOffSawGuardClampRelay = 34;	// flying cut off saw guard clamp
int pressTopHoldRelay = 36;			          // Press top hold

//--- Relay Shield #2 in the middle -------------------------------------------------------------------------------------------
int flyingCutOffSawMotorRelay = 38;		// The flying cut off saw motor
int PET3Relay = 40;			            	// PET #3
int PET4Relay = 42;				            // PET #4
int PET1Relay = 44;			            	// PET #1
int PET2Relay = 46;			             	// PET #2
int hydraulicTankRelay = 48;		    	// Hydraulic Tank
int bigSqueezeRelay = 50;		         	// the big squeeze  
int limitSwitchRelay = 52;			      // limit switch   

//--- Relay Shield #3 on the right ---------------------------------------------------------------------------------------------
int crowderRollsFreakDriveRelay = 43;		// the crowder rolls on the freak-drive
int airSolenoidCutterheadRelay = 45;		// the air selinod after Cuttterhead A
int clearingRollsRelay = 51;		      	// Clearing rolls
int assemblyChainRelay = 53;			      // Assembly chain

//--- Extra relays -------------------------------------------------------------------------------------------------------------
int relay21 = 39;
int relay22 = 41;
int relay25 = 47;
int relay26 = 49;


int left[] = {
  0, pushoutRelay, hydraulicCrowderRollsRelay, crowderRollsAirRelay, flyingCutOffSawUpRelay,
  flyingCutOffRetractRelay, spikeHoldDownRelay, flyingCutOffSawGuardClampRelay, pressTopHoldRelay
};
char* leftString[] = {
  "0", "pushoutRelay", "hydraulicCrowderRollsRelay", "crowderRollsAirRelay", "flyingCutOffSawUpRelay",
  "flyingCutOffRetractRelay", "spikeHoldDownRelay", "flyingCutOffSawGuardClampRelay", "pressTopHoldRelay"
};

int middle[] = {
  0, flyingCutOffSawMotorRelay, PET3Relay, PET4Relay, PET1Relay,
  PET2Relay, hydraulicTankRelay, bigSqueezeRelay, limitSwitchRelay
};
char* middleString[] = {
  "0", "flyingCutOffSawMotorRelay", "PET3Relay", "PET4Relay", "PET1Relay",
  "PET2Relay", "hydraulicTankRelay", "bigSqueezeRelay", "limitSwitchRelay"
};

int right[] = {
  0, crowderRollsFreakDriveRelay, airSolenoidCutterheadRelay, clearingRollsRelay, assemblyChainRelay,
  relay21, relay22, relay25, relay26
};
char* rightString[] = {
  "0", "crowderRollsFreakDriveRelay", "airSolenoidCutterheadRelay", "clearingRollsRelay", "assemblyChainRelay",
  "relay21", "relay22", "relay25", "relay26"
};



//------------------------------------------------------------------------------------------------------------------------------
//--- The Setup ----------------------------------------------------------------------------------------------------------------
void setup()
{
  Serial.begin(9600);       // Serial communication baud-rate

  // The Sensors
    for (int s = 0; s <= 15; s++) {
    pinMode(sensors[s], INPUT);
    Serial.print(sensorsString[s]);
    Serial.print(":  ");
    Serial.println(sensors[s]);
    if ( s == 15) {
      Serial.println("");
    }
  }
  
  //-------------------------------------------------------------------------------------------------------------------------------
    for (int x = 0; x <= 8; x++) {
    pinMode(left[x], OUTPUT);
    turnOff(left[x]);
    Serial.print(left[x]);
    Serial.print(",  ");
    if ( x == 8) {
      Serial.println("");
    }
  }
  for (int y = 0; y <= 8; y++) {
    pinMode(middle[y], OUTPUT);
    turnOff(middle[y]);
    Serial.print(middle[y]);
    Serial.print(",  ");
    if ( y == 8) {
      Serial.println("");
    }
  }
  for (int z = 0; z <= 8; z++) {
    pinMode(right[z], OUTPUT);
    turnOff(right[z]);
    Serial.print(right[z]);
    Serial.print(",  ");
    if ( z == 8) {
      Serial.println("");
    }
  }
  //---------------This Completes Programming 3 Relay Shields-----------------------------------------------------------------------
 
  // This is for the slapper button that is using an interrpt pin.
  attachInterrupt(2, slapperMode, CHANGE);
  pinMode(21, INPUT);

  
}// This is the end of the void Setup-----------------------------------------------------------------------------------------------
 //---------------------------------------------------------------------------------------------------------------------------------

//----------------------------------------------------------------------------------------------------------------------------------
//--- The loop that runs continually as long as the ardunio is on. ----------------------------------------------------------------
void loop()
{

  Serial.println("making borads");
  while(Serial.available() < 0);
  int options = Serial.read() - '0';
  //Serial.println(options);
  if(options == 1){
    INFO();
  }

  
  
  // Maintenance
  if (analogRead(maintenancePressed) >= 200) // Checks
  {
    maintenance();
  }

  // Emergency stop
  if (eStopButtonPressed())
  {
    shutdown();
  }

  // Turns on the assembly chain
  // Checks the status of the Start up Sequence
  if (!eStopButtonPressed() && !runButtonPressed())
  {
    turnOn(assemblyChainRelay);
    turnOn(hydraulicCrowderRollsRelay);
  }

  //--- Allows the program to skip delays when running -----------------------------------------------------------------------------
  if (isOff(hydraulicTankRelay))  
    // Checks to make sure the hydra;ic tank is off before entering the nested loop. This makes sure that we are not using
    // the delays after the machine has started up. Once running this section of code is skipped.
  {
    //--- Checks the status of the Press E-Stop ------------------------------------------------------------------------------------
    //--- This is the startup sequence for this section of the machine. ------------------------------------------------------------
    if (!eStopButtonPressed())
    {
      turnOn(PET4Relay);
      giveMeSomeTime();
      turnOn(PET3Relay);
      giveMeSomeTime();
      turnOn(PET2Relay);
      giveMeSomeTime();
      turnOn(PET1Relay);
      giveMeSomeTime();
      turnOn(flyingCutOffSawMotorRelay);
      giveMeSomeTime();
      turnOn(hydraulicTankRelay);
    }
  }
  //--------------------------------------------------------------------------------------------------------------------------------

  //--- Turn off run button process ------------------------------------------------------------------------------------------------
  if (!eStopButtonPressed() && runButtonPressed())  
  // This checks to make the run button has been turned off and the the e-stop has not been pressed.
  {
    turnOff(assemblyChainRelay);
    turnOff(crowderRollsFreakDriveRelay);
    turnOff(hydraulicCrowderRollsRelay);
  }
  //---------------------------------------------------------------------------------------------------------------------------------
  // Debug - Print which mode or sensor values the code is running

  //Serial.println(analogRead(fullStrokeSensor));
  
  

  //--------------------------------------------------------------------------------------------------------------------------------
  // The next section of code will instruct he cycling of the press.

  //--- End of the Press sensors ---------------------------------------------------------------------------------------------------
  if (analogRead(endPressSensor) >= 100 && analogRead(drainSensor) <= 100)
  // This checks both sensors at the end of the press to make sure they are both on.
  {
    turnOff(flyingCutOffRetractRelay);
    turnOn(bigSqueezeRelay);
    turnOn(pressTopHoldRelay);
    turnOn(pushoutRelay);

    /* We were having some issues with the spike coming down randomly. 
       This nested if statement makes it only possible if the press bar
       has been retracted as well as all the other condition from the first if statment are also true.
    */
    if (analogRead(pushoutSensor) <= 100)
    // This ensures that the press bar has been retracted before it allows the spike to come down.
    {
      turnOn(spikeHoldDownRelay);
    }
  }
  //--------------------------------------------------------------------------------------------------------------------------------

  //--- This is for the flying cut off saw -----------------------------------------------------------------------------------------
  if (isOff(flyingCutOffRetractRelay) && analogRead(flyingCutOffMoveSensor) <= 200 && isOn(spikeHoldDownRelay))  
  // checks all conditions before proceeding
  {
    /*
    This forces the ardunio to focus on the just this small loop for a small amount of time to ensure the
    flying-cut off saw comes up. The counter is adjustable for the best timing possible, but the value does
    not represent an actual time count. This also ensures the cut can only happen once and will be reset and
    availble to happen again once the board that was cut entered the press and the sensor at the front has
    reset to value for x.
    */
    for (x = 0; x <= 3; x++)
    {
      turnOn(flyingCutOffSawGuardClampRelay);
      turnOn(flyingCutOffSawUpRelay);
    }
  }

  //-------------------------------------------------------------------------------------------------------------------------------
  // This checks to see if the press bar is retracted and that saw is full stroke.
  if (isOn(pushoutRelay) && analogRead(fullStrokeSensor) >= 200)
  {
    for (x = 0; x <= 3; x++)
    {
      turnOff(flyingCutOffSawGuardClampRelay);
      turnOff(flyingCutOffSawUpRelay);

      if ( isOff(flyingCutOffSawUpRelay) && isOff(flyingCutOffSawGuardClampRelay))
      {
        turnOn(clearingRollsRelay);
        turnOn(flyingCutOffRetractRelay);
      }
      // This is looking for any reason to let the spike unclamp.
      if (isOn(clearingRollsRelay) || isOn(flyingCutOffRetractRelay) )
      {
        turnOff(spikeHoldDownRelay);
      }
    }
  }
    //------------------------------------------------------------------------------------------------------------------------------
    // Front of the Press
    // Checks the status of the sensor at the front of the press.
    // This section os looking to reset the cycling process and reseting x
    if (analogRead(speedRollsSensor) <= 100)
    {
      turnOff(spikeHoldDownRelay);
      turnOff(clearingRollsRelay);
      turnOff(pushoutRelay);
      turnOn(flyingCutOffRetractRelay);
      x = 0;
    }

    //------------------------------------------------------------------------------------------------------------------------------
    // This checks to make sure the press bar is all the way forward.
    // then it allows the machine to close and pressurize.
    if (analogRead(pushoutSensor) <= 100)
    {
      turnOff(pressTopHoldRelay);
      turnOff(bigSqueezeRelay);
    }

    //------------------------------------------------------------------------------------------------------------------------------
    //Assembley & Crowd control
    if (analogRead(runButton) > 100)       // This is the run button that will now turn ON the assembly
    {
      if (analogRead(assemblySensor) <= 100  || analogRead(drainSensor) <= 100)
      {
        turnOn(crowderRollsFreakDriveRelay);
      }
      else
      {
        turnOff(crowderRollsFreakDriveRelay);
      }
    }

    //------------------------------------------------------------------------------------------------------------------------------
  }// This is the end of the void Loop
  //--------------------------------------------------------------------------------------------------------------------------------
Controls.inoArduino
Support Code for the Press. Function calls are all here.
//--- Slapper Button -----------------------------------------------------------------------------------------
void slapperMode()
{
  if (digitalRead(21) == ON)
    turnOff(crowderRollsAirRelay);
  else
    turnOn(crowderRollsAirRelay);
}
//------------------------------------------------------------
//--- Return true if the eStop button is pressed -------------
boolean eStopButtonPressed()
{
  return (analogRead(startUpSequenceButton) < 200);
}
//------------------------------------------------------------
//--- Return true if the run button is pressed ---------------
boolean runButtonPressed()
{
  return (analogRead(runButton) < 200);
}
//------------------------------------------------------------
//--- Turn the pin ON ----------------------------------------
void turnOn(int pinNumber)
{
  digitalWrite(pinNumber, ON);
}
//------------------------------------------------------------
//--- Turn the pin OFF ---------------------------------------
void turnOff(int pinNumber)
{
  digitalWrite(pinNumber, OFF);
}
//------------------------------------------------------------
//--- Return true if the pin is ON ---------------------------
boolean isOn(int pinNumber)
{
  return (digitalRead(pinNumber) == ON);
}
//------------------------------------------------------------
//--- Return true if the pin is OFF --------------------------
boolean isOff(int pinNumber)
{
  return (digitalRead(pinNumber) == OFF);
}
//--------------------------------------------------------------------------------
// Give some time between actions to check if the e-stop button was pressed-------

boolean pln(int pinNumber)
{
  return Serial.println(analogRead(pinNumber));
}

void giveMeSomeTime()
{
  for (int i = 0; i < 4; i++)
  {
    if (eStopButtonPressed())
      shutdown();
    delay (delayTime);
    if (eStopButtonPressed())
      shutdown();
  }
}
//-----------------------------------------------------------------------------------------------------------
//--- Maintenance mode --------------------------------------------------------------------------------------
void maintenance()
{
  while ( runButtonPressed() && !eStopButtonPressed() && analogRead(maintenancePressed) >= 200 )
  {
    if (analogRead(maintenancePressed) >= 75)
    {
      Serial.println("Maintenance Mode Active");

      // This opens the press and keeps everything open to releave any kind of pressure.

      turnOff(assemblyChainRelay            );  // Turns the assembly chain off
      turnOff(crowderRollsFreakDriveRelay   );  // Turns the Freq on Crowder Rolls off
      turnOff(hydraulicCrowderRollsRelay    );  // Turns Hydraulic Crowder rolls off
      turnOff(clearingRollsRelay            );  // turn off the clearing rolls
      turnOn(bigSqueezeRelay                );  // Pulls back the squeeze
      turnOff(spikeHoldDownRelay            );  // spike clamp compress on the flying cut off
      turnOn(pressTopHoldRelay              );  // Air hold downs in the press up
      turnOn(pushoutRelay                   );  // Press bar retract
      turnOff(flyingCutOffRetractRelay      );  // turns the flying cut off retract off
      turnOff(flyingCutOffSawGuardClampRelay);  // Flying cut off clamp off
      turnOff(flyingCutOffSawUpRelay        );  // Flying cut off saw cut off

      slapperMode();  // This allows me to use the slappers while in this mode

    }
    else  // Once the swithc has been deactivated this else statment allows the code to break
      // away from the while loop it is nested into.
    {
      break;  // Gets me out of the while loop.
    }
  }
}
//-----------------------------------------------------------------------------------------------------------------------------------------------------
// Shutdown the process -------------------------------------------------------------------------------------------------------------------------------
void shutdown()
{
  turnOff(hydraulicTankRelay);
  turnOff(flyingCutOffSawMotorRelay);
  turnOff(PET4Relay);
  turnOff(PET1Relay);
  turnOff(PET2Relay);
  turnOff(PET3Relay);
  turnOff(assemblyChainRelay);
  turnOff(crowderRollsFreakDriveRelay);
}


void INFO() {
  Serial.println("Select the Sheild you want");
  Serial.println("1 = Left, 2 = Middle, 3 = Right");

  while (Serial.available() == 0);
  int sheild = Serial.read() - '0';
  switch (sheild) {

    case 1:
      Serial.println("Left Sheild");
      infoLeft();
      break;
    case 2:
      Serial.println("Middle Sheild");
      infoMiddle();
      break;
    case 3:
      Serial.println("Right Sheild");
      infoRight();
      break;
  }

}

Schematics

IMG_2233.JPG
Img 2233

Comments

Similar projects you might like

Sienci Mill One - Simple and Affordable Desktop CNC

Project tutorial by Sienci Labs

  • 17,986 views
  • 2 comments
  • 72 respects

Arduino Star Trek Tricorder (BETA)

Project in progress by Team The Trekduinos

  • 1,533 views
  • 2 comments
  • 4 respects

Multi-Dashboard Display with Arduino Controller

Project showcase by Colin O'Dell

  • 24,865 views
  • 6 comments
  • 67 respects

Arduino 101 BLE App

Project in progress by Alexis Santiago Allende

  • 10,795 views
  • 26 comments
  • 51 respects

Electronic Check-In

Project tutorial by Gergely Imreh

  • 6,196 views
  • 9 comments
  • 32 respects

Circuito Arduino Controller Pad

Project tutorial by AhmedAzouz

  • 2,688 views
  • 1 comment
  • 7 respects
Add projectSign up / Login