Laststate or else?

Hi everyone ,

I have many question , i'm obviously not really good to code......

This is what im trying to do :slight_smile:
I have an arduino with a motor shield r3 to control an electric linear actuator .
I have a npn NO sensor in the middle position
i have two input from a "computer"
input 1 switch to high to get it retracted
input 2 switch to high to extend
when input 1 and 2 are high it needs to go in the middle , same when input 1 and 2 are low

this is the non working code i have so far :



int section1 = 5; // input  section 1
int section2 = 6;// input  section 2
int millieu = 7;

int pwm = 3;
int sens = 12;

int lastState ;


void setup() {
  pinMode (section1, INPUT);
  pinMode (section2, INPUT);
  pinMode (millieu, INPUT);
  pinMode (pwm, OUTPUT);
  pinMode (sens, OUTPUT);
  lastState = 3 ;
 
}

void loop() {
  if (digitalRead(section1) == HIGH) {

    analogWrite(pwm, 255);
    digitalWrite(sens, HIGH);
    lastState = 1;



  } else if (digitalRead(section2) == HIGH) {

    analogWrite(pwm, 255);
    digitalWrite(sens, LOW);
    lastState = 2;
  }

    else if (digitalRead(section1) == HIGH && digitalRead(section2) == HIGH && digitalRead(millieu) == LOW )
    {
      analogWrite(pwm, 0);
    }

   else {

    if (digitalRead(millieu) == LOW) {
      analogWrite(pwm, 0);
      //digitalWrite(sens, LOW);
      //lastState = 1;
      return;
    }

    switch (lastState) {
      case 1:
        analogWrite(pwm, 255);
        digitalWrite(sens, LOW);


        break;

      case 2:
        analogWrite(pwm, 255);
        digitalWrite(sens, HIGH);


        break;

      default :

        analogWrite(pwm, 255);
        digitalWrite(sens, HIGH);
        //delay (8000);
        lastState = 1;


        break;


    }

Anyone could guide me plse ?

In what way does the sketch not work ?

Have you got pulldown resistors on the inputs to keep them at a known (LOW) state except when activated by taking them HIGH ?

Looking at the code I notice that it will always detect when section1 or section2 are HIGH before testing whether both are HIGH. In other words, if either are HIGH it will never test for both. Put the combined test first

1 Like

It would help enormousness if you could include a schematic of your circuit. The code is only half the story.

When it is time to go to the middle position, how do you know which direction to go?

It looks like the "sens" output sets the direction of travel. Is that correct? If so, the name 'sens' seems to be a poor choice.

Why use a PWM output and analogWrite() when you only ever use full-on (255) or full-off (0)?

No id doesnt work , when both are high or low it goes all the way in one direction....
I did not put resistor , maybe i should , i look into that

Where on the computer are the signals coming from ?

It's not exactly from a computer it's from a tractor equipement , so it comes from a 12v relay driver

My problem being when input 1 and 2 are high but not in the middle its going one side and stay there....

No wonder when the first thing in loop() is

if (digitalRead(section1) == HIGH)
{
  analogWrite(pwm, 255);
  digitalWrite(sens, HIGH);
  lastState = 1;
}

The sketch never gets to the code that tests whether both inputs are HIGH

This was pointed out in post #2

How can make it so it's cheking all parameter without getting stuck on one condition ?
I did put in first but it still doesnt work

if (digitalRead(section1) == HIGH && digitalRead(section2) == HIGH && digitalRead(millieu) == LOW )
    {
      analogWrite(pwm, 0);
    }

first but it still doesnt work

That is a very poor description of the problem

Whenever you make a change to your code post the new version in a new reply here and explain any problems in full

tractor?? sounds dangerous, I'm IN!!

try this..

//renamed some vars from really old english..
//i understood it though.. :)
const int BTN_RETRACT = 5; //retract button
const int BTN_EXTEND = 6;// extend button
const int SEN_MIDDLE = 7;//middle sensor

const int LIN_ACT = 3;//linear activator
const int CTL_DIRECTION = 12;//was sens

#define STATE_RET 1
#define STATE_EXT 2
#define STATE_MID 3
#define STATE_STOP 4

//vars to track samples
bool Retract = false;
bool Extend = false;
bool InMiddle = false;

//0=before 1=at 2=after
byte MidPosition = 0;

int lastState = 0;
//millis from last sample
unsigned long lastSample = 0;
//sampling rate in millis
int SampleRate = 100;


void setup() {
 // Serial.begin(115200);
  pinMode (BTN_RETRACT, INPUT);
  pinMode (BTN_EXTEND, INPUT);
  pinMode (SEN_MIDDLE, INPUT);
  pinMode (LIN_ACT, OUTPUT);
  pinMode (CTL_DIRECTION, OUTPUT);
  lastState = 3 ;//start in middle
 // Serial.println("Ready..");
 
}

void SampleInputs()
{

   unsigned long currMilli = millis();
   if (currMilli-lastSample>=SampleRate)
   {
     lastSample = currMilli;
     Retract = digitalRead(BTN_RETRACT);
     Extend = digitalRead(BTN_EXTEND);
     InMiddle = digitalRead(SEN_MIDDLE);

     if (InMiddle){
       MidPosition = 1;
     }else {
          switch (lastState){
            case STATE_RET: MidPosition = 0;break;
            case STATE_EXT: MidPosition = 2;break;
          }

     }


   }

}

void loop() {

     SampleInputs();

     int newState;
     if ((Retract&&Extend)||(!Retract&&!Extend)){
       newState = STATE_MID;
     }else
     if (Retract){
       newState = STATE_RET;
     } else
     if (Extend){
       newState = STATE_EXT;
     }
      //if we're moving to mid and we're there, STOP
      if (newState==STATE_MID && InMiddle) newState = STATE_STOP; 

       lastState = newState;

    switch (lastState) {
      case STATE_RET: //retract
       // Serial.println("Retracting");
        digitalWrite(CTL_DIRECTION, LOW);
        analogWrite(LIN_ACT, 255);
        break;

      case STATE_EXT: //extend
       // Serial.println("Extending");
        digitalWrite(CTL_DIRECTION, HIGH);
        analogWrite(LIN_ACT, 255);
        break;

      case  STATE_MID: //go middle
     //  Serial.println("Middle");
      if (MidPosition==0)
       {digitalWrite(CTL_DIRECTION, HIGH);}
       else
       {digitalWrite(CTL_DIRECTION, HIGH);}
       analogWrite(LIN_ACT, 255);
        break;
      case  STATE_STOP: //stop
      //  Serial.println("Stop");
       digitalWrite(CTL_DIRECTION, LOW);
       analogWrite(LIN_ACT, 0);
        break;
    }
     // delay(1000); used for debuging slows the serial prints down..

    }

play with it here..

Without keeping track of which side of middle you are on, there is no way to know if you should extend or retract.

Here is my first guess at how it has to be done. Each time the center is passed, keep track of which side of center the actuator is on (EXTENDED or RETRACTED). Then, when it comes time to head for center, we know which way to go.

const int RetractPin = 5;  // input  section 1
const int ExtendPin = 6;   // input  section 2
const int MiddleSensorPin = 7;

const int MotorPowerPin = 3;
const int MotorDirectionExtendPin = 12;

boolean LastCentered = false;

enum Positions
{
  UNKNOWN,
  RETRACTED,
  CENTERED,
  EXTENDED
} Position = UNKNOWN;

enum Directions
{
  STOPPED,
  RETRACTING,
  CENTERING,
  EXTENDING
} Direction = STOPPED;

void setup()
{
  pinMode(RetractPin, INPUT);
  pinMode(ExtendPin, INPUT);
  pinMode(MiddleSensorPin, INPUT_PULLUP);  // Open Collector

  if (digitalRead(MiddleSensorPin) == LOW)
  {
    Position = CENTERED;
    LastCentered = true;
  }

  digitalWrite(MotorPowerPin, LOW);  // Off
  pinMode(MotorPowerPin, OUTPUT);
  pinMode(MotorDirectionExtendPin, OUTPUT);
}

void Extend()
{
  digitalWrite(MotorDirectionExtendPin, HIGH);
  digitalWrite(MotorPowerPin, HIGH);
  Direction = EXTENDING;
}

void Retract()
{
  digitalWrite(MotorDirectionExtendPin, LOW);
  digitalWrite(MotorPowerPin, HIGH);
  Direction = RETRACTING;
}

void loop()
{
  boolean retract = digitalRead(RetractPin) == HIGH;
  boolean extend = digitalRead(ExtendPin) == HIGH;
  boolean centered = digitalRead(MiddleSensorPin) == LOW;

  if (centered != LastCentered)
  {
    // The middle sensor has changed state
    LastCentered = centered;

    // If the center sensor just went active
    if (centered && Direction == CENTERING)
    {
      digitalWrite(MotorPowerPin, LOW);  // Off
      Position = CENTERED;
      Direction = STOPPED;
    }

    // If the center sensor just went inactive
    // (we just passed center)
    if (!centered && Direction == RETRACTING)
      Position = RETRACTED;

    if (!centered && Direction == EXTENDING)
      Position = EXTENDED;
  }

  if (retract == extend)
  {
    // Head to the middle
    if (Position == RETRACTED)
    {
      Extend();
      Direction = CENTERING;
    }

    if (Position == EXTENDED)
    {
      Retract();
      Direction = CENTERING;
    }
  }
  else if (retract)
  {
    Retract();
  }
  else if (extend)
  {
    Extend();
  }
}

Curious too..
what happens if you over or under drive a linear actuator?
do they have built in stops?
kind of thinking they don't or maybe all are not the same, so depends on actuator..

I sure hope that this model has internal limit switches that turn off the motor when the limits are reached.

lol, so i guess, i was kind of thinking right, not all do..
and if it doesn't results in a damaged actuator and a very heavy bail of hay drops on @tinybear ..
hope he's ok!!

LOL , i'm still alive , have been away for the weekend , thx a lot for the code , i'm gonna work to understand it and test it .
Yes the actuator have limit switches so no worries for that part

I tried your code , just changed from low to high for sensor as i will use a npn instead

const int RetractPin = 5;  // input  section 1
const int ExtendPin = 6;   // input  section 2
const int MiddleSensorPin = 7;

const int MotorPowerPin = 3;
const int MotorDirectionExtendPin = 12;

boolean LastCentered = false;

enum Positions
{
  UNKNOWN,
  RETRACTED,
  CENTERED,
  EXTENDED
} Position = UNKNOWN;

enum Directions
{
  STOPPED,
  RETRACTING,
  CENTERING,
  EXTENDING
} Direction = STOPPED;

void setup()
{
  pinMode(RetractPin, INPUT);
  pinMode(ExtendPin, INPUT);
  pinMode(MiddleSensorPin, INPUT_PULLUP);  // Open Collector

  if (digitalRead(MiddleSensorPin) == HIGH)
  {
    Position = CENTERED;
    LastCentered = true;
  }

  digitalWrite(MotorPowerPin, LOW);  // Off
  pinMode(MotorPowerPin, OUTPUT);
  pinMode(MotorDirectionExtendPin, OUTPUT);
}

void Extend()
{
  digitalWrite(MotorDirectionExtendPin, HIGH);
  digitalWrite(MotorPowerPin, HIGH);
  Direction = EXTENDING;
}

void Retract()
{
  digitalWrite(MotorDirectionExtendPin, LOW);
  digitalWrite(MotorPowerPin, HIGH);
  Direction = RETRACTING;
}

void loop()
{
  boolean retract = digitalRead(RetractPin) == HIGH;
  boolean extend = digitalRead(ExtendPin) == HIGH;
  boolean centered = digitalRead(MiddleSensorPin) == HIGH;

  if (centered != LastCentered)
  {
    // The middle sensor has changed state
    LastCentered = centered;

    // If the center sensor just went active
    if (centered && Direction == CENTERING)
    {
      digitalWrite(MotorPowerPin, LOW);  // Off
      Position = CENTERED;
      Direction = STOPPED;
    }

    // If the center sensor just went inactive
    // (we just passed center)
    if (!centered && Direction == RETRACTING)
      Position = RETRACTED;

    if (!centered && Direction == EXTENDING)
      Position = EXTENDED;
  }

  if (retract == extend)
  {
    // Head to the middle
    if (Position == RETRACTED)
    {
      Extend();
      Direction = CENTERING;
    }

    if (Position == EXTENDED)
    {
      Retract();
      Direction = CENTERING;
    }
  }
  else if (retract)
  {
    Retract();
  }
  else if (extend)
  {
    Extend();
  }
}

It works on most scenario but one , when it retract and pin 5 get back to LOW it doesnt reach center , it stays retracted , i still quite new to arduino and programming , i cant pin point where the problem is
It works the other way around though

When first turned on the Arduino has no way of knowing the position of the actuator. Only by passing through the center does it know if it is on the RETRACTED side of the center or the EXTENDED side of the center. Without knowing that, there is no way to know which way to go to get back to CENTERED.

If something different is happening, I can help you add Serial output to the sketch to determine why it won't center after a retract.

It's very likely going to be center at restart

It seems like it doesnt see or store when it passes middle on the retract way but it weird that it works on extend .

How does serial output works ?