Automation coding to mimic Ladder Logic

Joined
Jul 7, 2008
Messages
3,963
Location
Missouri
I am refining the automation on one of my production machines, a resistance brazer. I have a big SSR coming to replace the contact switch since it is being turned off under load, and I imagine the switch won't last very long. While upgrading that part I figured it useful to integrate all functions into an arduino controlled sequence. The basic code I have hacked together is as follows:

Code:
int footswitchPin = 1;                 // footswitch  connected to digital pin 1
int HlimitPin = 2;			// high limit switch NO connected to pin 2
int LlimitPin = 3;			// low limit switch NO connected to pin 3
int motorPin = 4;                       // motor control output connected to pin 4 
int powerPin = 5;                       // transformer control output connected to pin 5
int resetPin = 6;                          // reset button connected to pin 6
int motorvar = 0;                       // variable for storage of motor state

//digitalRead shortcuts
int footswitch = digitalRead(footswitchPin);
int Hlimit = digitalRead(HlimitPin);
int Llimit = digitalRead(LlimitPin);
int reset = digitalRead(resetPin);
int power = digitalRead(powerPin);


// set variable functions
void setup()
{
  pinMode(footswitchPin, INPUT);      // sets footswitchPin as input
  pinMode(HlimitPin, INPUT);          // sets HlimitPin as input 
  pinMode(LlimitPin, INPUT);          // sets LlimitPin as input
  pinMode(resetPin, INPUT);           // sets reset as input
  
  pinMode(motorPin, OUTPUT);          // sets motorPin as output
  pinMode(powerPin, OUTPUT);          // sets powerPin as output
  
}


                                       // home position function
int high()
{
if (Hlimit != HIGH) 
{
  digitalWrite (motorPin, HIGH);
}
else 
{
  digitalWrite (motorPin, LOW);
}
}
                                      // low position function 
int low()
{
  if (Llimit != HIGH)
{
  digitalWrite (motorPin, HIGH);
}
else
{
  digitalWrite (motorPin, LOW);
  digitalWrite (powerPin, HIGH);
  delay (250);
  digitalWrite (powerPin, LOW);
  delay (100);
  high ();
}
}



                                      //main loop
void loop()
{
                                     // footswitch OFF
if (reset == HIGH)
{
  digitalWrite (powerPin, LOW);
  delay (250);
  high();
}
if (power == LOW && footswitch == LOW && Llimit == LOW && Hlimit == LOW)
{
   high();
}
if (footswitch == LOW && Hlimit == HIGH)
{
  digitalWrite (motorPin, LOW);
  digitalWrite (powerPin, LOW);
}
if (footswitch == LOW && Llimit == HIGH)
{
  digitalWrite (powerPin, LOW);
  digitalWrite (motorPin, LOW);
}

                                             //footswitch ON
if (footswitch == HIGH && Hlimit == HIGH)
{
  low();
}
if (footswitch == HIGH && Llimit == HIGH)
{
  low();
}
}



I think all cases are covered, and I threw in some extra IF statements to cover irregular states. I think a few more statements are needed to ensure the high() and low() functions operate properly, as there may be a problem where the footpedal is pressed and the loop kicks back into high() mode as soon as it releases. The pedal input is momentary on and I want to control everything with one shot input. Ideally we would want {Hlimit HIGH && pedal HIGH} to execute and wait for a second pedal HIGH input before executing the low() {else} portion of code, to prevent a long pedal press from running through the entire high() to low() {else} sequence without pause. I'm trying to figure out how to force each function to loop until a specific state is reached, I think the 'while' function could be the trick.


This is my first code for a functional machine, other than making a simple strobe for our lathe and setting up PLC years ago in college.


What do you guys think?
 
it would probably be useful to list what the machine needs to do


Loop start
read inputs, reset machine to home position
wait for input
Footpedal switch closed
lower braze head until
limit switch L
wait for input
footpedal switch closed
turn on braze machine
timer delay
Turn off braze machine
Timer delay (wait for inductive kickback to settle)
raise braze head until
Limit switch H
loop
 
Hardware wise, can I suggest you isolate the physical switches from the CPU pins. A transistor, an opto, all the way up to the plugin Opto-22 modules.

Software wise, you need to debounce those switch inputs.
The quick & dirty solution is probably just a great big delay at the end of the loop.

I'm a bit rusty, but I don't see why your high() & low() functions are declared as returning int, when there is no return statement, and the calling statement doesn't test for a return value.
Surely they should be declared as
void high() & void low()

The Arduino forum is probably a better bet for help with this.

Amanda
 
I suck at coding, but I did figure that declaring it as void would be the way to go.

Thanks for the input, I'll head over the the arduino forum if I can't figure it out after a bit. I know it will take a lot more coding to get the inputs debounced and isolated.
 
I didn't want to use the debounce header available for the aruduino compiler, as I didn't understand the concept fully. I also dislike the idea of using delays for debouncing. So I made my own debouncer that waits for MAX number of consistent inputs before changing state of the switch. It is set to three right now, unlikely to be triggered by noise. If I have issues with with electrical interference I will install an RC filter on the switches too. In the future it could be easier to use an array to store the information, I'll look into that down the road.


Seems ready to go now, I should have the hardware to complete the project within a few days.

Code:
int footswitchPin = 1;          // footswitch  connected to digital pin 1
int HlimitPin = 2;		// high limit switch NO connected to pin 2
int LlimitPin = 3;		// low limit switch NO connected to pin 3
int motorPin = 4;               // motor control output connected to pin 4 
int powerPin = 5;               // transformer control output connected to pin 5
int resetPin = 6;               // reset button connected to pin 6

int FS=0;                       // footswitch debouncing storage integer
int HL=0;                       // Highlimit switch debouncing storage integer
int LL=0;                       // Lowlimit switch debouncing storage integer
int RS=0;                       // Reset switch debouncing storage integer

#define MAX 3                        // debounce max number
bool footswitchD;                    // footswitch debounced state
bool HlimitD;                        // high limit switch debounced state
bool LlimitD;                        // low limit switch debounced state
bool resetD;                         // reset switch debounced state[/b]


//digitalRead shortcuts
int footswitch = digitalRead(footswitchD);
int Hlimit = digitalRead(HlimitD);
int Llimit = digitalRead(LlimitD);
int reset = digitalRead(resetD);
int power = digitalRead(powerPin);


// set variable functions
  pinMode(footswitchPin, INPUT);      // sets footswitchPin as input
  pinMode(HlimitPin, INPUT);          // sets HlimitPin as input 
  pinMode(LlimitPin, INPUT);          // sets LlimitPin as input
  pinMode(resetPin, INPUT);           // sets reset as input
  
  pinMode(motorPin, OUTPUT);          // sets motorPin as output
  pinMode(powerPin, OUTPUT);          // sets powerPin as output
  


 //Debounce code
if (FS <=0){FS=0;}
if (FS >= MAX){FS= MAX;}
if (footswitchPin = 0){--FS;}  
else {++FS;}
if (FS=0){digitalWrite (footswitchD,LOW);}
if (FS=MAX){digitalWrite (footswitchD, HIGH);}

if (HL <=0){HL=0;}
if (HL >= MAX){HL= MAX;}
if (HlimitPin = 0){--HL;}  
else {++HL;}
if (HL=0){digitalWrite (HlimitD,LOW);}
if (HL=MAX){digitalWrite (HlimitD, HIGH);}

if (LL <=0){LL=0;}
if (LL >= MAX){LL= MAX;}
if (footswitchPin = 0){--LL;}  
else {++LL;}
if (LL=0){digitalWrite (LlimitD,LOW);}
if (LL=MAX){digitalWrite (LlimitD, HIGH);}

if (RS <=0){RS=0;}
if (RS >= MAX){RS= MAX;}
if (resetPin = 0){--RS;}  
else {++RS;}
if (RS=0){digitalWrite (resetD,LOW);}
if (RS=MAX){digitalWrite (resetD, HIGH);}
 
Interesting debounce method.

I think the following line is wrong:
if (FS=0){digitalWrite (footswitchD,LOW);}

because footswitchD is a boolean variable, not an I/O pin.

I believe it should be:
if (FS=0){footswitchD = false;} // true & false should be globally defined as part of the Arduino package.


You can use the 'millis' inbuilt counter to do timing, rather than use delay.
The Arduino site appears to be down right now, but there's a blinking led example that shows how to implement it.

Here's a cut & paste from the last project I was working on;
Code:
void loop() {

  loop_time = millis();

  // main loop code runs every second
  if (loop_time - last_loop_time > 1000)
  {
    // do your digital reads here

  last_loop_time = loop_time;
   }

  else
  {
    // do other stuff here, like digital writes
  }

obviously, you wouldn't use one whole second to debounce switches, but maybe 10mS would be a good ballpark figure to start.

Amanda
 
I wasn't sure if the low and high values would translate right for the bool, from my reading I could put a low, 0, or false and it should all work the same.

Good catch on the = VS == use. I should have caught that this morning but didn't remember it on the new chunk of code.


Thanks for pointing those out!
 
Back
Top