train control

hello

First i am sorry for any grammar mistakes but English is not my native languish
and if this is not the right sub please re-direct.
i am brand new too arduino and c+ but i do now some vba (didn't help :frowning: )
so i need some help.

The project is too drive a model train between two gates.
So i build 2 gates with a LED and a LDR.

I choose this option cause i had the LDR and LED and i want too be able to move the gates
without damaging the track.

i have a arduino mega and arduino motorshield and connect them this way.

looks confusing but its just two pairs of a LED and a LDR.
and i started with the code;

/*
  Train control
  Drive the train between two gates made of a LED and a LDR.
*/

int ledL = 32;
int ledR = 34;
int sensL = A10;
int sensR = A11;
int train = 12;
int brake = 9;
int sensLreading = analogRead;
int sensRreading = analogRead;
String state = String("Stands");


// the setup function runs once when you press reset or power the board
void setup() {
  pinMode(ledL, OUTPUT);
  pinMode(ledR, OUTPUT);
  pinMode(train, OUTPUT);
  pinMode(brake, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  sensLreading = analogRead(sensL);
  sensRreading = analogRead(sensR);
  delay(50);
  sensLreading = analogRead(sensL);
  sensRreading = analogRead(sensR);

  Serial.println(sensLreading);
  Serial.println(sensRreading);
  Serial.println(state);
  
  if (sensLreading > 200 && sensRreading > 200) {
      digitalWrite(ledL, HIGH);  //Turn left LED on  
      digitalWrite(train, HIGH); //Establishes left direction of train
      digitalWrite(brake, LOW);  //Disengage the Brake
      analogWrite(3, 200);       //Sets the speed of the train (255 is ful speed)
      state = String("goLeft");  //Sets "state"
     }

  sensLreading = analogRead(sensL);
  sensRreading = analogRead(sensR);
  delay(50);
  sensLreading = analogRead(sensL);
  sensRreading = analogRead(sensR);

  Serial.println(sensLreading);
  Serial.println(sensRreading);
  Serial.println(state);

  if (sensLreading > 200 && state == "goLeft") {
      digitalWrite(ledL, LOW);   //Turn left LED off
      digitalWrite(ledR, HIGH);  //Turn right LED on
      digitalWrite(train, LOW);  //Establishes backward direction of train
      digitalWrite(9, LOW);      //Disengage the Brake
      analogWrite(3, 200);       //Sets the speed of the train (255 is ful speed)
      state = String("goRight"); //Sets "state"
     }

  sensLreading = analogRead(sensL);
  sensRreading = analogRead(sensR);
  delay(50);
  sensLreading = analogRead(sensL);
  sensRreading = analogRead(sensR);

  Serial.println(sensLreading);
  Serial.println(sensRreading);
  Serial.println(state);

  if (sensRreading > 200 && state == "goRight") {
      digitalWrite(ledR, LOW);   //Turn right LED off
      digitalWrite(ledL, HIGH);  //Turn left LED on
      digitalWrite(train, HIGH); //Establishes forward direction of train
      digitalWrite(9, LOW);      //Disengage the Brake
      analogWrite(3, 200);       //Sets the speed of the train (255 is ful speed)
      state = String("goLeft");  //Sets "state"
     } 
}

as you can see the code for running the train comes later.
first i wanted too switch the gates.

at the start both LED`s are off so the first if statement turns on the left gate and (later)
send the train to the left gate and set "state" to "goLeft"

so when the train comes thru the gate, the value of the left LDR rise.
that should trigger the second if statement. so it turns off the left turns on the right LED
reverse the train and set state to goRight.

the Serial.println is to check what is happening.

problem 1

the led switch to right while the value of "sensL" didn`t rise above 400 or wathever value i try.

this is what serial monitor whrite;

878
886
Stands
878
886
goLeft
83 <<< (not > 400)
447
goRight

problem 2

not a problem just a question. is there a way to combine a string and the value in println
so it puts out "left 876" strings work very different than VBA and i cant find the right syntax
for this.

well that it for now :slight_smile:
Al help is appreciated

not a problem just a question. is there a way to combine a string and the value in println
so it puts out "left 876" strings work very different than VBA and i cant find the right syntax
for this.

This is easy. Just do it with two calls to print. There's no need to combine them ahead of time.

Serial.print("left ");
Serial.println(someVariableHoldingThatNumber);

Note the important difference between print and println. One takes you to the next line and the other doesn't.

yup that works :slight_smile: but there are still 2 separate commands i wanted too connect them too be very
very sure the reading 682 belongs too the left sensor. it would be very unlikely that the program
mixing the lines but with problem 1 it seems arduino having a hard time listening
too my code. :confused:

i updated the code a Little. changed pins, checked al wires remove the motor shield and
re upload and reset about 40 times :slight_smile:

and always the same result

Even after 6sec it refuse too see the value drop of the left LDR.
I heard LDR can be slow but THAT slow :o i dont think that is the case.

Finaly if it does see the value drop it ignore it and execute the if statement that clearly
say`s the value has to be greater than 200

are you sure that 200 is the right limit for the LDR's?

Try some different values.

regards

Allan

The circuit uses LEDs and LDRs. You may find the LDRs are not suitable for this use. They are not very sensitive and may not change value sufficiently to be reliably detected.

Weedpharma

your 6 second delay did nothing to help you .

what you did was to get sensorLreading.
wait 6 seconds
show what the sensorLreading was

void loop() {
  int sensLreading = analogRead(sensL);
  sensLreading = analoRead(sendL);  // second time
  int sensRreading = analogRead(sensR);
  sensRreading = analogRead(sensR);  // second time

delay(500)

Serial.print ( "left reading is = ");
Serial.print (sensLreading);
Serial.Print("  right reading is = ");  // extra spaces in front to separate from the sensLreading
Serial.println(senRreading);

then move your LED , put a tube, a straw or some cardboard around the LED and the LDR to block any extra light.
get the highest reading you can, and the lowest you can.

that would be a way to calibrate your LED to LDR values.

also, if you read the same value twice, the first time may show some effect from what was read before.
the ADC needs some time to settle. between readings.

Masters:
yup that works :slight_smile: but there are still 2 separate commands i wanted too connect them too be very
very sure the reading 682 belongs too the left sensor. it would be very unlikely that the program
mixing the lines but with problem 1 it seems arduino having a hard time listening
too my code.

Your fear is unfounded. As long as you put the two print lines back to back the end result is the same. It's actually a little faster with the two print lines. They're not going to magically get mixed up. They'll print when you tell them to.

@ Delta_g

Your right. see it as a pilot when al instruments tells something else :confused:
i was lost there :slight_smile:

@ allenhurst

i did , al readings where between +/- 80 for on, +/- 800 for off.
so between 200 and 500 should be ok.

@ weedpharma

it might not be the best way. but it seems responsive in other cases.

al i did here was removing the delay

@ dave-in-nj

what you did was to get sensorLreading.
wait 6 seconds
show what the sensorLreading was

there is some Light going up here :slight_smile:
need some time too let this sink in.

so youre saying "Serial.print (sensLreading);" is not getting the value
it just prints the last value that was read. ?

Masters:
so youre saying "Serial.print (sensLreading);" is not getting the value
it just prints the last value that was read. ?

Variables just hold a value, not any line of code. They don't magically update themselves. They just hold the last value you put in them.

see it now :slight_smile:
i updated the code in first post. and as you can see
its working fine for now.

thanks for the help

next work;

  • let the train slowly stop and start
  • actual reading of speed and direction
  • in a nice looking window on pc screen :stuck_out_tongue:

lots too do, little time. :wink:

Masters:
i updated the code in first post.

Please don't make changes to earlier Posts (other than to correct typos) as it makes a nonsense of the discussion for people reading it later and trying to learn from your experience.

Always post your new code and new comments in the correct chronological position.

If it is possible to reinstate the first Post I suggest you do so.

...R

Sorry
cant recall the first code i made.
but the main mistake is in post 3.

won`t do it again :-[

Masters:
@ dave-in-nj

there is some Light going up here :slight_smile:
need some time too let this sink in.

actually, you miised the point.

say you read A0 and is a 5 volts. and
then A1 and it is at 0.1 volts.
the buffer started at 5 and has to drain to 0.1

if you read
A1
A1

your first read of A1 will bring the buffer near to your reading.
the second time is will not have any of the values from the previous pin.

you did

A0
A1
A0
A1

no advantage in doing that.

however, if you are not experiencing any problems, then there is no need to do that at all.

Masters:
see it now :slight_smile:
i updated the code in first post. and as you can see
its working fine for now.

https://www.youtube.com/watch?v=7AsdMgpgfzs&feature=youtu.be

thanks for the help

next work;

  • let the train slowly stop and start
  • actual reading of speed and direction
  • in a nice looking window on pc screen :stuck_out_tongue:

lots too do, little time. :wink:

youtube says the video is locked

Hi,
The LDR is it inside the arch you have built, the arch is made out of what.
Is it fully opaque to light
I think you have ambient light problems, the LDR is not just sensitive to the LED but to a major part of the ambient light spectrum.
What colour is your LED and if its a normal LED it will not be emitting a beam of light, which is what you need.

Do you have the LDR and LED in light tubes?
Can you post closer pictures of your LDR and LED assemblies please?

Check your readings in a darkened room.

Tom..... :slight_smile:

I unblockt the video, i dont use utube much it seems you have to hit a publish button :astonished:
mind that the video speed is faster than real life. also i brought the speed down by pin 3 to 130
(255 = full speed in this case 12v on the motor) so it gives a much smoother impression now.

there is some Light going up here :slight_smile:

that was the part of "Variables just hold a value, not any line of code."

For reading the sensor twice...
old

void loop() {
  sensLreading = analogRead(sensL);
  sensRreading = analogRead(sensR);
  delay(50);
  sensLreading = analogRead(sensL);
  sensRreading = analogRead(sensR);

new

void loop() {
  sensLreading = analogRead(sensL);
  sensRreading = analogRead(sensL);
  delay(50);
  sensLreading = analogRead(sensR);
  sensRreading = analogRead(sensR);

See your point (i hope) but in this case, does it make a difference?.
cause i am not doing anything with "analogRead(sensL)" before i have "analogRead(sensR)".
One of them always be last read. could place the "serial.print(sensL)" between them but
its not about the print lines.
i need both value`s before any IF statement.

well its running for now, 9 of 10 times al goes right. the 10th time it does not set
ledR LOW so it stays on. makes no difference train is still going from left to right and
after 2 or 3 times the led goes on and off again.

@TomGeorge
The arch is made of plywood and a white led, no tubes just made two holes across each other and stick the LDR and LEDs in them, So there is ambient light. in darkness and full daylight the scale would be from 1024 to 0, in my case with some lamps and little daylight its 800 to 80. sufficient enough to
notice the led light is blocked as you can see in the first video.

i have rebuild the code to implement slow break and start of the train.
as you can see in this video glitch - YouTube
when the train reverse there is a glitch. for a split second it gets a high voltage.
and i see no reason why is does this.
this is the point of code where the train reverse.

      while (Speed >= 0){
        analogWrite(3, Speed);   //Sets the speed of the train to 0 (255 is ful speed)
        Speed = Speed - 2;
        delay(20);
        } 

      while (Speed <= maxSpeed){
      digitalWrite(train, LOW); //Establishes forward direction of train
      digitalWrite(9, LOW);      //Disengage the Brake
      analogWrite(3, Speed);       //Sets the speed of the train (255 is ful speed)

so to ad it al up i have to read sensor input value`s twice to get right value, stil 1 of 10 times skips
shutting off the right LED (loop is going to fast or it just ignores the command, and now this.

is this general arduino or just my board ?.

further codewise am i an the right track of building this?.

full code;

  /*
  Train control
  Drive the train between two gates made of a LED and LDR.
  */

int ledL = 32;
int ledR = 34;
int sensL = A10;
int sensR = A11;
int train = 12;
int brake = 9;
int Speed = 0;
int maxSpeed = 150;
int sensLreading = analogRead;
int sensRreading = analogRead;
String state = String("Stands");

void setup() {
  Serial.begin(9600);
  pinMode(ledL, OUTPUT);
  pinMode(ledR, OUTPUT);
  pinMode(train, OUTPUT);
  pinMode(brake, OUTPUT);  
}

void loop() {
  sensLreading = analogRead(sensL);
  sensRreading = analogRead(sensL);
  delay(20);
  sensLreading = analogRead(sensR);
  sensRreading = analogRead(sensR);
  
  if (sensLreading > 200 && sensRreading > 200) {
      digitalWrite(ledL, HIGH);  //Turn left LED on  
      digitalWrite(train, LOW);  //Establishes left direction of train
      digitalWrite(brake, LOW);  //Disengage the Brake
      while (Speed <= maxSpeed){
        analogWrite(3, Speed);   //Sets the speed of the train (255 is ful speed)
        Speed = Speed + 1;
        delay(40);
        }
      state = String("goLeft");  //Sets "state"
      }
  
  sensLreading = analogRead(sensR);
  sensRreading = analogRead(sensR);
  delay(20);
  sensLreading = analogRead(sensL);
  sensRreading = analogRead(sensL);

  if (sensLreading > 200 && state == "goLeft") {
      digitalWrite(ledL, LOW);   //Turn left LED off
      digitalWrite(ledR, HIGH);  //Turn right LED on
      while (Speed >= 0){
        analogWrite(3, Speed);   //Sets the speed of the train to 0 (255 is ful speed)
        Speed = Speed - 2;
        delay(20);
        }
      
      while (Speed <= maxSpeed){
        digitalWrite(train, HIGH);  //Establishes backward direction of train
        digitalWrite(9, LOW);      //Disengage the Brake
        analogWrite(3, Speed);   //Sets the speed of the train (255 is ful speed)
        Speed = Speed + 1;
        delay(60);
        }
      state = String("goRight"); //Sets "state"
  }

  sensLreading = analogRead(sensL);
  sensRreading = analogRead(sensR);
  delay(20);
  sensLreading = analogRead(sensL);
  sensRreading = analogRead(sensR);

  if (sensRreading > 200 && state == "goRight") {
      digitalWrite(ledR, LOW);   //Turn right LED off
      digitalWrite(ledL, HIGH);  //Turn left LED on
      while (Speed >= 0){
        analogWrite(3, Speed);   //Sets the speed of the train to 0 (255 is ful speed)
        Speed = Speed - 2;
        delay(20);
        } 

      while (Speed <= maxSpeed){
      digitalWrite(train, LOW); //Establishes forward direction of train
      digitalWrite(9, LOW);      //Disengage the Brake
      analogWrite(3, Speed);       //Sets the speed of the train (255 is ful speed)
      Speed = Speed + 1;
      delay(60);
      }
      state = String("goLeft");  //Sets "state"
  }
}

You have a huge amount of unnecessary duplication in your program. For example the code after

 if (sensLreading > 200 && state == "goLeft") {

is the same as the code after

 if (sensRreading > 200 && state == "goRight") {

When you see that you should put the code into a function and call the function whenever it is needed.

Duplication opens up scope for silly errors caused by typos and makes it very difficult to mae changes without forgetting the repeat the change somewhere else.

Also you seem to be reading the sensors all over the place - I count 3 repeats of that code. It should only be necessary to read the sensors once in every iteration of loop() - I would also put the sensor code into a function.

The other important advantage of small single-purpose functions is that you can develop and test them independently of the rest of the code.

WHILE blocks the Arduino until it completes. Unless it can complete in a few microseconds I would use IF and allow loop() to look after the iteration.

Rather than using a String to hold the state I would use a char variable and allow it the values 'L', 'R' and 'S'. It is not a good idea to use the String (capital S) class as it can cause memory corruption in the small memory on an Arduino.

...R

thanks for your advice, working on it.
it seems i learn the most of video tutorials have seen about 25 now.
but not mush to find about working with, or create your own functions.

put the code into a function and call the function whenever it is needed.

so if anyone now a good tutorial please inform me :slight_smile:

found the glitch !!!! (so happy)

while (Speed <= maxSpeed){
        analogWrite(3, Speed);   //Sets the speed of the train (255 is ful speed)
        Speed = Speed + 1;
        delay(40);
        }
        state = String("goLeft");  //Sets "state"
        }

Speed <= maxSpeed sets the speed to 151 not 150 so in the next loop (decrease speed)
it gets to -1 not 0. i guess like an int flips over to negative at 32,767.
-1 on pin 3 gives a positive 255.

did some work on it,

/*
  Train control
  Drive the train between two gates made of a LED and LDR.
*/

byte ledL = 4;                                //declare variable and value for led L pin
byte sensL = A4;                              //declare variable and value for ldr L pin
byte ledR = 5;                                //declare variable and value for led R pin
byte sensR = A5;                              //declare variable and value for ldr R pin
byte brake = 9;                               //declare variable and value for train brake pin
byte trainD = 12;                             //declare variable and value for train direction pin (High/Low)
byte trainS = 3;                              //declare variable and value for train speed pin (0 - 255)
byte cSens = A0;                              //declare variable and value for train Current Sensing pin (not used yet)

int Speed = 0;                                //declare variable and set value for Speed (0 to 255 for speed)
int maxSpeed = 200;                           //declare variable and set value for maximum speed (255 is ful speed)
int sensLreading = 0;                         //declare variable for left ldr reading value
int sensRreading = 0;                         //declare variable for right ldr reading value
int cSensreading = 0;                         //declare variable for train Current Sensing value (not used yet)
int accspeed = 40;                            //declare variable for acceleration speed
int decspeed = 2;                             //declare variable for deceleration speed
String state = String("Stands");              //declare variable and set value for state (keeps track of driving direction)

void setup() {
  Serial.begin(9600);                         //open serial port for communication
  pinMode(ledL, OUTPUT);                      //set pin 32 to output for left led
  pinMode(ledR, OUTPUT);                      //set pin 34 to output for right led
  pinMode(trainD, OUTPUT);                    //set pin 12 to output for train (direction)
  pinMode(brake, OUTPUT);                     //set pin  9 to output for train (brake)
  pinMode(trainS, OUTPUT);                    //set pin  3 to output for train (speed)
  digitalWrite(brake, LOW);                   //Disengage the Brake
}

void loop() {

  readSens();
  printReport();

  if (sensLreading > 200 && sensRreading > 200) {     //if both ldr are high value, the program just started and nothing happend yet
     digitalWrite(ledL, HIGH);                        //Turn left LED on
     digitalWrite(trainD, LOW);                       //Establishes left direction of train
     accelerate();                                    //accelerate the train
     state = String("goLeft");                        //set state (keeps track of driving direction)
     }

  readSens();
  printReport();

  if (sensLreading > 200 && state == "goLeft") {      //if left ldr is high value and state is "goleft", the train reached left gate
     digitalWrite(ledL, LOW);                         //Turn left LED off
     digitalWrite(ledR, HIGH);                        //Turn right LED on
     decelerate();                                    //decelerate the train
     digitalWrite(trainD, HIGH);                      //reverse direction of the train
     accelerate();                                    //accelerate the train
     state = String("goRight");                       //set state (keeps track of driving direction)
     }

  readSens();
  printReport();

  if (sensRreading > 200 && state == "goRight") {     //if right ldr is high value and state is "goright", the train reached right gate
     digitalWrite(ledR, LOW);                         //Turn right LED off
     digitalWrite(ledL, HIGH);                        //Turn left LED on
     decelerate();                                    //decelerate the train
     digitalWrite(trainD, LOW);                       //reverse direction of the train
     accelerate();                                    //accelerate the train
     state = String("goLeft");                        //set state (keeps track of driving direction)
     }
}

//******** functions ********

void readSens() {

  cSensreading = analogRead(cSens);      //read current sensing of motor
  cSensreading = analogRead(cSens);      //read current sensing of motor
  sensLreading = analogRead(sensL);      //read left ldr (a high value means the light is off or blockt)
  sensLreading = analogRead(sensL);      //read left ldr (a high value means the light is off or blockt)
  sensRreading = analogRead(sensR);      //read right ldr (a high value means the light is off or blockt)
  sensRreading = analogRead(sensR);      //read right ldr (a high value means the light is off or blockt)
}

void printReport() {

  Serial.println("Start Report;");                  //print "Start Report;"
  //Serial.print("sensL = ");                         //print "sensL = "
  //Serial.println(sensLreading);                     //print sensL value (for debugging purposive)
  //Serial.print("sensR = ");                         //print "sensR = "
  //Serial.println(sensRreading);                     //print sensR value (for debugging purposive)
  Serial.print("Speed = ");                         //print "speed = "
  Serial.println(Speed);                            //print speed (for debugging purposive)
  Serial.print("Current Sensing value = ");         //print "Current Sensing value = "
  Serial.println(cSensreading);                     //print Current Sensing value (for debugging purposive)
}

void accelerate() {

  while (Speed < maxSpeed) {                        //loop to accelerate to maximum speed
    readSens();                                     //read sensors
    printReport();                                  //print report
    analogWrite(trainS, Speed);                     //Sets the speed of the train (255 is ful speed)
    Speed = Speed + 1;                              //add 1 to speed
    delay(accspeed);                                //slow down the proces
    }
}

void decelerate() {

  while (Speed > 0) {                              //loop to decelerate to 0 speed
    readSens();                                    //read sensors
    printReport();                                 //print report
      if (Speed < 0) {
      Speed = 0;
      }
    analogWrite(trainS, Speed);                    //Sets the speed of the train (255 is ful speed)
    Speed = Speed - 20;                            //subtract 20 of speed
    delay(decspeed);                               //slow down the proces
    }
}

build some functions as recommanded and move some things.
but problems are increasing instead of being solved.
one of them is, program is to busy to keep track of the sensors.
its not the LDR being slow but when the train passing the sensor
program is busy with for example the print report.