Programming industrial automation process

Hello all,

First to introduce myself: I am an automotive engineer with limited programming skills.
I am new to arduino but determined to make this project work.
As the project stands now I have an arduino mega, an external 5v power supply, 24v power supply, 8 channel relay board and 8 channel opto-coupler.

The project I am working on is an unwinding table: this table grips material and while it is clamping, a heat wire is applied that "welds" the material together. Then the material is pulled forward after which it is cut off by another hot wire that should go out after x seconds. Then the clamping plate goes up and back again to the beginning. This schematically looks like this.

I got it working by simply controlling the relays via different delays. The goal is to make it work through sensors.
This is the code with the simple delays:

#define clamp 6
#define linear 7
#define cut 8
 

void setup() {
 pinMode(6,OUTPUT);
  pinMode(7,OUTPUT);
pinMode(8,OUTPUT);
}
void loop() {
digitalWrite(cut,LOW);
delay(500);
digitalWrite(clamp,HIGH);
delay(1500);
digitalWrite(linear,HIGH);
delay(4000);
digitalWrite(clamp,LOW);
delay(1000);
digitalWrite(cut,HIGH);
delay(1000);
digitalWrite(linear,LOW);
delay(4000);
}

This makes it move exactly like it should, but there are no safety features possible hence I want to use sensors for moving to the next step. First video shows how it moves

There are 2 sensors on each cylinder at the end stops.
To read the sensors I used an opto coupler because the sensors work on 24 volts. The code to read it and drive a relay looks like this: (this was a standard piece of code that I modified a bit)

int input_pin = 5;
int led_pin = 9;
#define clamp 6
void setup()
{
  pinMode(6,OUTPUT);
    pinMode( input_pin , INPUT_PULLUP);
    pinMode( led_pin , OUTPUT);
    Serial.begin(9600);
}
void loop()
{
    int i = digitalRead( input_pin );
//    digitalWrite(led_pin);
    
    Serial.println(i);
    

    if (i == LOW) { // check if the input is LOW (no detection)
 digitalWrite(clamp, HIGH); // turn LED OFF
 } else {
 digitalWrite(clamp, LOW); // turn LED ON
 }
}

The intention is that the system will work by means of the sensors that must be active in certain steps in the process in order to proceed to the next step. (see excel picture)
Video down below is to show the setup with a sensor.

I wanted to tackle this project on my own but it is more difficult than I anticipated for. From what I have seen the best way to make this work is by a state machine. Because a state machine is pretty advanced (at least for me) I was hoping to get some tips and tricks or good example code that I can use.

Hope some of you can help me.
Thanks in advance

Not really. You already described the steps that become states of the state machine. Use a switch statement to select the current state, check conditions for a state transition and do what's required when switching to the new state.

may be a timeout will be needed as well on top of the sensors in case the detection goes wrong. This is handled as an event in your time machine, just like the sensors.

Look up state machines and blink without delay. You have a nice simple flow but of course you can’t have delays if you monitor sensors. You can probably think of all sorts of ways to detect problems and what sort of action you might take in each instance.

a more complete state machine has a number of stimuli and has transitions from any state to any other state. what you have is more of a sequencer.

a sequencer can easily be maintained with a switch statement. each state waits for some stimuli, your opto-coupler sensors, performs some action and then advances the state.

an action may also involve a delay or possibly waiting for a sensor before returning and advancing state

it's hard (for me) to tell what your code is doing because it's not obvious whether LOW/HIGH activates a relay and what exactly the relay is doing.

you don't describe what the sensors are. i also assume you need a start button (and very likely a STOP! button if not the start)

some more detail would be helpful

State machines are very simple and all you need to do is define the states as you have in your flow. You can then fix them in a variable in your code. A very simple example is 3 states
On
Off
Paused

Variable State=0 or 1, or 2

If state = 0 then On, 1 then off, 2 then paused
Write a function for detecting state changes eg button push or sensor reading, then;

Eg if state 0 and buttonPushed state =1

I hope my pseudo code makes sense and is only bones of it

Remember to build in a hardware fail safe button if risk of injury. Ie a cut power physical button!

Something like this:

would become this

bool cutGood = false;
digitalWrite(cut, LOW);
unsigned long cutStart = millis();
while(millis() - cutStart < 500)
{
   if (digitalRead(cutDoneSensor) == ACTIVE))
  {
    cutGood = true;
    break;
  }
}
if (cutGood)
{
  // Go to next operation
 }
else
{
  // Stop and display error
}

Each operation should be its own function returning true or false depending on success or failure. Then you can basically program the behavior by grouping operations however you want to.

HTH

thanks all for the feedback.

In the meantime I have moved on and programmed the beginning of the state machine I think...

I used this video for inspiration: https://www.youtube.com/watch?v=qFIvx1Sdjv8&ab_channel=MakerAtPlayCoding

I have now written one step and found out that it is a lot of work to digital read the sensors in every step of the process. So I thought I'd create a void function for that (also to make it more readable), but it just doesn't work. do you see where it goes wrong? I have now excluded the readSensors code in the code.

//#include "Fsm.h"


#define S1 22      //sensor linear begin
#define S2 23      //sensor linear end
#define S3 24      //sensor clamp up
#define S4 25      //calmp down
#define S5 26      //cutting up        
#define S6 27      //cutting down
#define S7 28      // INO start
#define S8 29      //emergency stop
#define S9 30      //extra sensor

#define clamp 5     //clamp relay
#define linear 6   //linear relay
#define cut 7     //cut relay
#define weldingWire 8    //welding wire relay
#define cuttingWire 9  //cuttin wire relay



   enum  MachineState 
{
        
        step1,    //  deactivate cut relay
        step2,    //  activate welding wire and relay linear
        step3,    //activate cutting wire and cut relay
        step4     // 
    };

    
int CurrentMachineState = 0;
//int startSignal = false;


void setup(){
pinMode( S1 , INPUT_PULLUP);
pinMode( S2 , INPUT_PULLUP);
pinMode( S3 , INPUT_PULLUP);
pinMode( S4 , INPUT_PULLUP);
pinMode( S5 , INPUT_PULLUP);
pinMode( S6 , INPUT_PULLUP);
pinMode( S7 , INPUT_PULLUP);
pinMode( S8 , INPUT_PULLUP);
pinMode( S9 , INPUT_PULLUP);


pinMode(clamp,OUTPUT);
pinMode(linear,OUTPUT);
pinMode(cut,OUTPUT);
pinMode(weldingWire,OUTPUT);
pinMode(cuttingWire,OUTPUT);
pinMode(13,OUTPUT);
   
Serial.begin(9600);
digitalWrite(weldingWire, HIGH);
digitalWrite(clamp, LOW);
digitalWrite(cuttingWire, LOW);
digitalWrite(linear, LOW);
digitalWrite(linear,LOW);

}

// Events




//actions
/*void readSensors(){
 s1 = digitalRead(S1);
 s2 = digitalRead(S2);
 s3 = digitalRead(S3);
 s4 = digitalRead(S4);
 s5 = digitalRead(S5);
 s6 = digitalRead(S6);
 s7 = digitalRead(S7);
 s8 = digitalRead(S8);
 s9 = digitalRead(S9);
}*/

void ledOn(){
digitalWrite(13,HIGH);}

void start(){
Serial.println("Step 1");
digitalWrite(weldingWire, HIGH);
digitalWrite(clamp, HIGH);
digitalWrite(cuttingWire, HIGH);
digitalWrite(linear, LOW);

CurrentMachineState = step1;
//readSensors();
}

void delayStart(){
Serial.println("waiting for start");
digitalWrite(weldingWire, LOW);
digitalWrite(clamp, LOW);
digitalWrite(cuttingWire, LOW);
digitalWrite(linear, LOW);
digitalWrite(linear,LOW);




CurrentMachineState = start;
}



void loop() {
//   readSensors();
checkStart();


}

bool checkStart(){
  //readSensors();

  int s1 = digitalRead( S1 );
 int s4 = digitalRead( S4 );
int s6 = digitalRead( S6 );
 int s7 = digitalRead (S7);
  Serial.print("sensor 1  ");
  Serial.println(int(s1));
  
   Serial.print("sensor 4    ");
  Serial.println(int(s4));
  
   Serial.print("sensor 6    ");
   Serial.println(int(s6));
   
    Serial.print("sensor 7    ");
  Serial.println(int(s7));
  
  if ((s1) == false && (s4) == false && (s6)==false && (s7)==false)
  {start(); //startSignal = true;
  }  
  else {
   delayStart();
  }
  
  
   
  }

No. What makes you think that it doesn't work?

  1. When you post code, please remember to Ctrl-t before you cut and paste. That formats the code nicely, making it much easier to read.
  2. That read sensors routine is flawed because you try to read all your sensors into undeclared variables. The scope of the ints s1, etc. declared within one function is such that they're not visible to the read sensors function.
    C

when I include the readSensor part and exclude the int "S1 read "in the checkStart i get the errors that s1 is not declared. See code below.
@camysca
I tried the ctrl-t but it does not work I think

  1. I think that is correct, only thing is: I do not know how to fix it...

#define S1 22      //sensor linear begin
#define S2 23      //sensor linear end
#define S3 24      //sensor clamp up
#define S4 25      //calmp down
#define S5 26      //cutting up        
#define S6 27      //cutting down
#define S7 28      // INO start
#define S8 29      //emergency stop
#define S9 30      //extra sensor

#define clamp 5     //clamp relay
#define linear 6   //linear relay
#define cut 7     //cut relay
#define weldingWire 8    //welding wire relay
#define cuttingWire 9  //cuttin wire relay



enum  MachineState
{

  step1,    //  deactivate cut relay
  step2,    //  activate welding wire and relay linear
  step3,    //activate cutting wire and cut relay
  step4     //
};


int CurrentMachineState = 0;
//int startSignal = false;


void setup() {
  pinMode( S1 , INPUT_PULLUP);
  pinMode( S2 , INPUT_PULLUP);
  pinMode( S3 , INPUT_PULLUP);
  pinMode( S4 , INPUT_PULLUP);
  pinMode( S5 , INPUT_PULLUP);
  pinMode( S6 , INPUT_PULLUP);
  pinMode( S7 , INPUT_PULLUP);
  pinMode( S8 , INPUT_PULLUP);
  pinMode( S9 , INPUT_PULLUP);


  pinMode(clamp, OUTPUT);
  pinMode(linear, OUTPUT);
  pinMode(cut, OUTPUT);
  pinMode(weldingWire, OUTPUT);
  pinMode(cuttingWire, OUTPUT);
  pinMode(13, OUTPUT);

  Serial.begin(9600);
  digitalWrite(weldingWire, HIGH);
  digitalWrite(clamp, LOW);
  digitalWrite(cuttingWire, LOW);
  digitalWrite(linear, LOW);
  digitalWrite(linear, LOW);

}

// Events




//actions
void readSensors() {
  s1 = digitalRead(S1);
  s2 = digitalRead(S2);
  s3 = digitalRead(S3);
  s4 = digitalRead(S4);
  s5 = digitalRead(S5);
  s6 = digitalRead(S6);
  s7 = digitalRead(S7);
  s8 = digitalRead(S8);
  s9 = digitalRead(S9);
}

void ledOn() {
  digitalWrite(13, HIGH);
}

void start() {
  Serial.println("Step 1");
  digitalWrite(weldingWire, HIGH);
  digitalWrite(clamp, HIGH);
  digitalWrite(cuttingWire, HIGH);
  digitalWrite(linear, LOW);

  CurrentMachineState = step1;
  //readSensors();
}

void delayStart() {
  Serial.println("waiting for start");
  digitalWrite(weldingWire, LOW);
  digitalWrite(clamp, LOW);
  digitalWrite(cuttingWire, LOW);
  digitalWrite(linear, LOW);
  digitalWrite(linear, LOW);




  CurrentMachineState = start;
}



void loop() {
  checkStart();


}

bool checkStart() {
  readSensors();
  /*
    int s1 = digitalRead( S1 );
    int s4 = digitalRead( S4 );
    int s6 = digitalRead( S6 );
    int s7 = digitalRead (S7);*/

  Serial.print("sensor 1  ");
  Serial.println(int(s1));

  Serial.print("sensor 4    ");
  Serial.println(int(s4));

  Serial.print("sensor 6    ");
  Serial.println(int(s6));

  Serial.print("sensor 7    ");
  Serial.println(int(s7));

  if ((s1) == false && (s4) == false && (s6) == false && (s7) == false)
  { start(); //startSignal = true;
  }
  else {
    delayStart();
  }



}

s1 has not been declared in the posted code. How to fix, is to properly declare s1.

Consider giving those variables more descriptive names when you do declare them. s1, s2, s3 etc are not very helpful for us or you to understand what the code is doing.

1 Like

and put the whole set in an array to shorten the code and make debugging easier.

I agree, but I have an Excle table where is listed where every sensor is listed. I tought it would be better to use short names in the arduino code to make it easy to read. Also in the #define part is listed what sensor is where.

I'm sure that if you know what you are doing it is easier. For now I will be happy if my readSensors part is working as I intend it to do. I still have trouble with declaring s1.

In the code with the readSensors part excluded I write:

bool checkStart() {
    int s1 = digitalRead( S1 );
    int s4 = digitalRead( S4 );
    int s6 = digitalRead( S6 );
    int s7 = digitalRead (S7);

and here it works. I also tried to write the readSensors function like this:

void readSensors() {
  int s1 = digitalRead(S1);
  int s2 = digitalRead(S2);
  int s3 = digitalRead(S3);
  int s4 = digitalRead(S4);
  int s5 = digitalRead(S5);
  int s6 = digitalRead(S6);
  int s7 = digitalRead(S7);
  int s8 = digitalRead(S8);
  int s9 = digitalRead(S9);

but that does also not work.

Keep in mind I am new to programming so mayby I am asking really stupid questions :flushed:

as a bool

bool s1;
voiding setp()
{
}

as an int

int s1;
voiding setp()
{
}

as a float

float s1;
voiding setp()
{
}

What trouble are you having with declaring a variable?

Here is a tutor on declaring variables in c++

Also you might need to learn about variable scope.

Variable Scope in C++.

This is where your problem lies, I think. Declaring the ints withIn readsensor is pointless, because when you exit readsensor the variables are destroyed - they don't exist for other functions to see them. Read the variable scope info. You have options, but it would be better if we don't tell you what to do, as that short-circuits the learning.
C

1 Like

This means that your code does not compile, not that it doesn't work.

The compiler error message clearly indicates your problem: you have to declare the sensor value variables at global scope, outside any function. Then the variables are usable everywhere, in any function.

A point of style (and good coding practice). This is meaningless.

This

(s1 == false)

Is very useful and avoids an entire class of errors relating to order of operations.

1 Like