1

I am using an Arduino for the first time to control the level crossing gates on my model railway using an LDR and two servos. I want to have a train run over a photo resistor (LDR). On this event, the gates should close. When the train has passed over, there should be a delay and then the gates should open. The code presented here is simplified to just open the gates and close them without the required delays. As the LDR sends constant readings, the servos should only respond on the initial change as I don't want to manage servos pulling or pushing on gates once they have moved.

I have tried using a global to hold the gate state. I have now changed the code to pass a variable around.

#include <Servo.h>
Servo myservo;
int sensorPin = A0; // select the input pin for LDR
int sensorValue = 0; // variable to store the value coming from the sensor
int pos = 1;
int barState;

void setup() {
  Serial.begin(9600); //sets serial port for communication
  myservo.attach(9);
  barState = 0;
}

int upMove(int bs)

bs = 0;
for (pos = 0; pos <= 60; pos += 1) { // goes from 0 degrees to 60 degrees
  // in steps of 1 degree
  myservo.write(pos);              // tell servo to go to position in variable 'pos'
  delay(30);                       // waits 30ms for the servo to reach the position

}
return bs;
}

int downMove(int bs)
{

  bs = 1;
  for (pos = 60; pos >= 0; pos -= 1) { // goes from 60 degrees to 0 degrees
    // in steps of 1 degree
    { myservo.write(pos);              // tell servo to go to position in variable 'pos'
      delay(30);                    // waits 30ms for the servo to reach the position
    }
    return bs;
  }

  int up(int bs)

  {
    if ( bs = 1) {
      bs =  upMove(bs);
    }
    return bs;
  }

  int down(int bs)

  {
    bs = downMove(bs);
  }
  return bs;
}

void loop() {
  { sensorValue = analogRead(sensorPin);                    //define photocellReading as pin 0 input from LDR
    sensorValue = map(sensorValue, 0, 1023, 0, 179);      //map the LDR input to a value between 1-180 so the servo can understand it
    if (sensorValue > 90)         //if the LDR is showing less than half light intensity
    {
      up(barState);
    }
    else if (sensorValue <= 90)   //if the LDR is showing more than half light intensity
    {
      down(barState);   //then tell the servo to rotate forwards at a steady rate
    }
  }
}

The code is working for Up but not for Down. Up works once but Down continually resets and operates the servo.

Kentaro Okuda
  • 1,557
  • 2
  • 12
  • 16
  • 1
    You have code in `up` to make sure that it's not constantly moved, but you don't seem to have similar code in `down`. – Thomas Jager May 07 '19 at 18:01
  • 1
    `for (pos = 0; pos <= 60;..` will do __61__ steps, not 60. Use `<60`. – Paul Ogilvie May 07 '19 at 18:26
  • 1
    `for (pos = 60; pos >= 0;..` will also do 61 steps. Use `pos>0`. – Paul Ogilvie May 07 '19 at 18:29
  • 1
    `if ( bs = 1)` _assigns_ to `bs`. It does not _test_ `bs`. Use `if (bs==1)` – Paul Ogilvie May 07 '19 at 18:31
  • OT: For ease of readability and understanding: 1) Please consistently indent the code. Indent after every opening brace '{'. Unindent before every closing brace '}'. Suggest each indent level be 4 spaces. 2) insert a blank line around code blocks: `for` `if` `else` `while` `do...while` `switch` `case` `default`. 3) do not insert random blank lines – user3629249 May 07 '19 at 19:42

1 Answers1

0

I have honed the code to make it a bit simpler. It now operates as expected except that it continues to operate the servo instead of just once for each change of the LDR

#include <Servo.h>
Servo myservo;
int sensorPin = A0; // select the input pin for LDR
int sensorValue = 0; // variable to store the value coming from the sensor
int pos = 1;
int barState;

void setup() {
  Serial.begin(9600); //sets serial port for communication
  myservo.attach(9);
  barState = 0;
}

void upMove()
{
Serial.print( " In upMove ");Serial.println(barState);

for (pos = 0; pos <= 60; pos += 1) { // goes from 0 degrees to 60 degrees
  // in steps of 1 degree
  myservo.write(pos);              // tell servo to go to position in variable 'pos'
  delay(30);                       // waits 30ms for the servo to reach the position
barState = 0;
}
}

void downMove()
{
Serial.print( " In downMove ");Serial.println(barState);

for (pos = 60; pos >= 0; pos -= 1) { // goes from 0 degrees to 60 degrees
  // in steps of 1 degree
  myservo.write(pos);              // tell servo to go to position in variable 'pos'
  delay(30);                       // waits 30ms for the servo to reach the position
barState = 0;
}


}

void up()

  {
    Serial.print( " In UP 1 ");Serial.println(barState);
    {
     if (barState = 1) upMove();
    }
    Serial.print( " In UP 2 ");Serial.println(barState);
  }

void down()
{
    Serial.print( " In DOWN 1 ");Serial.println(barState);
 {
     if (barState = 1) downMove();
  }

    Serial.print( " In DOWN 2 ");Serial.println(barState);

}

void loop() {
  { sensorValue = analogRead(sensorPin);                    //define photocellReading as pin 0 input from LDR
    sensorValue = map(sensorValue, 0, 1023, 0, 179);      //map the LDR input to a value between 1-180 so the servo can understand it
    if (sensorValue > 90)         //if the LDR is showing less than half light intensity
    {
      up();
    }
    else if (sensorValue <= 90)   //if the LDR is showing more than half light intensity
    {
      down();   //then tell the servo to rotate forwards at a steady rate
    }
  }
}
  • Use `==` (double equals) when comparing values, currently the code assigns `barState` with the value of 1 and always return true. – Eran W May 07 '19 at 19:17
  • Suggest `barState` be an enum with values: movingDown, downStopped, movingUP, upStopped. Then when the 'bar' finishes moving, then change its' state to the appropriate `stopped` condition. Then the function(s) that move the bar can check if the bar is already in the final state and therefore, do nothing.. The analog state of the sensor can be used to change the state if the final state is not already reached, else do nothing – user3629249 May 07 '19 at 19:47
  • Double equals == fixed the problem. It now works as expected. Many thanks for the heads up. I should have known as that is a Smalltalk thing as well - Smalltalk is my main language. – LongHairedDavid May 08 '19 at 11:45