Code Assistance

Hello, some of you may be familiar with a couple of other topics during which I have been asking for help and I appreciate the guidance. I am pleased to say that, as a result of that help, all the hardware is giving me the outputs/readings I would expect (mostly anyway).

I have a couple of remaining issues however, and I was just wondering if anyone would be able to have a look over my code and tell me if they can spot any obvious errors I might have missed whilst I have been debugging these last two days.

Pins 0 to 5 are connect to reed switches which are connected to ground. The readings I am getting across these switches is as I would expect (5V when no magnet is present/0V when magnet is present).
These appear to be triggering the responses that I would expect when a magnet is applied, however, I am wondering whether they aren't always correctly active. For example, either Sen1 or Sen2 would be active and sometime when Sen1 should be active I suspect that the code is checking Sen2 instead. As of yet that is only a suspicion because I can't be sure until I have fixed one hardware issue where a MOSFET needs to be replaced by a relay.

The other issue is that the P_L servo doesn't ever seem to change whereas the P_R servo seems to change whenever it feels like.

I have double checked and triple checked the wiring and can see no shorts anywhere, there are no loose connections and all the value appear to be what I would expect, when I would expect them.

I will post the code on a subsequent post because it exceeds the character limit.

Thanks in advance
Mitchell

*  
/*
 *  Track layout:
 *  
 *  S1___Sen1_                                 _Sen4___S4
 *            \                               /
 *  S2___Sen2__\____________Track____________/__Sen3___S3           
 *            P_L    Sen_L         Sen_R    P_R
 *                   
 *  Pin assignments:     
 *   ____________________________
 *  |Pin |Function  |Input/Ouput |
 *  |----+----------+------------|
 *  |0   |Sen_L     |Input       |
 *  |1   |Sen_R     |Input       |
 *  |2   |Sen1      |Input       |
 *  |3   |Sen2      |Input       |
 *  |4   |Sen3      |Input       |
 *  |5   |Sen4      |Input       |
 *  |6   |S1        |Output      |
 *  |7   |S2        |Output      |
 *  |8   |S3        |Output      |
 *  |9   |P_L       |Output      |
 *  |10  |P_R       |Output      |
 *  |11  |Track     |Output      |
 *  |12  |Direction |Output      |
 *  |13  |S4        |Output      |
 *  |============================|
 */

#include <Servo.h>
Servo P_L;
Servo P_R; 
//define Servos
int Direction = 12; //Use DPDT non-latching relay
int Track = 11;
int S1 = 6;
int S2 = 7;
int S3 = 8;
int S4 = 13;
//Assign outputs to their pins

int Sen_L = 0;
int Sen_R = 1;
int Sen1 = 2;
int Sen2 = 3;
int Sen3 = 4;
int Sen4 = 5;
//Assign digital sensors to their pins
//Use reed switches

const unsigned int maxSpeed = 100; //Maximum speed of train
const unsigned int wait = 1000; //Duration braking/acceleration
unsigned int numRepeat = 0; 
int num;
//Define variables

unsigned int pLeft = 165;
unsigned int pRight = 70;
//Point servo angle values

const unsigned int stationStopMin = 4000;
const unsigned int stationStopMax = 6000;
const unsigned int sidingStop = 5000;
//Delay constants
//Delays in milliseconds

//int cnt = 0;

void setup() {
  pinMode(Direction, OUTPUT);
  pinMode(Track, OUTPUT);
  pinMode(S1, OUTPUT);
  pinMode(S2, OUTPUT);
  pinMode(S3, OUTPUT);
  pinMode(S4, OUTPUT);
  //Define as outputs 

  pinMode(Sen_L, INPUT_PULLUP);
  pinMode(Sen_R, INPUT_PULLUP);
  pinMode(Sen1, INPUT_PULLUP);
  pinMode(Sen2, INPUT_PULLUP);
  pinMode(Sen3, INPUT_PULLUP);
  pinMode(Sen4, INPUT_PULLUP);
  //Define as inputs with pull-up resistors enabled

  P_L.attach(9);
  P_R.attach(10);
  //Attach servo control wires to their pins

  //Serial.begin(9600);
}

int Dec(const unsigned int Max, const unsigned int dly);
int Acc(const unsigned int Max, const unsigned int dly);
void SidingSet(const unsigned int pLeft, const unsigned int pRight);
//int RepeatInc(unsigned int Repeats);
unsigned int change_pRight(unsigned int pRight);
unsigned int change_pLeft(unsigned int pLeft);
void fullSiding_R(const unsigned int pRight, const unsigned int spd);
void fullSiding_L(const unsigned int pLeft, const unsigned int spd);
//int debug(int cnt);
//Define functions

void loop() {
  P_L.write(pLeft);
  P_R.write(pRight);
  //Set servos to default positions
  
  SidingSet(pLeft, pRight); //Set sidings
  //Perform only at first loop instance
  
  for(;;) {
    digitalWrite(Direction, LOW); //Set direction of travel (Left-Right)
    analogWrite(Track, maxSpeed); //Write PWM to track of duty cycle maxSpeed

    while(digitalRead(Sen_L) == 1) {
    } //Wait until Sen_L is triggered
    //cnt = debug(cnt);
    Dec(maxSpeed, wait); //Decelerate train to stop
    delay(/*random(stationStopMin, stationStopMax)*/10000); //Wait between 'x' to 'y' seconds at station
    Acc(maxSpeed, wait); //Accelerate train
  
    fullSiding_R(pRight, maxSpeed); //Wait for train to enter siding
    //cnt = debug(cnt);
    digitalWrite(Track, LOW); //Turn off track (stop train)
  
    pRight = change_pRight(pRight); 
    SidingSet(pLeft, pRight);
    delay(sidingStop); //Wait for 'x' seconds before sending out next train
    Serial.println("Exit");
  
    digitalWrite(Direction, HIGH); //Reverse direction of travel (Right-Left)
    analogWrite(Track, maxSpeed); //Write PWM to track of duty cycle maxSpeed
  
    while(digitalRead(Sen_R) == 1) {
    } //Wait for Sen_R to trigger
    //cnt = debug(cnt);
    Dec(maxSpeed, wait); //Decelerate train to stop
    delay(random(stationStopMin, stationStopMax)); //Wait between 'x' to 'y' seconds at station
    Acc(maxSpeed, wait); //Accelerate train
  
    fullSiding_L(pLeft, maxSpeed); //Wait for train to enter siding
    //cnt = debug(cnt);
    digitalWrite(Track, LOW); //Turn off track (stop train)
  
    pLeft = change_pLeft(pLeft);
    SidingSet(pLeft, pRight);
    delay(sidingStop); //Wait for 'x' seconds before sending out next train
  } 
}

int Dec(const unsigned int Max, const unsigned int dly) {
  for(int i = Max; i >= 0; i--) {
    analogWrite(Track, i); //Set Track PWM to i duty cycle
    delay((float) dly/Max); //Wait for dly milliseconds (dly/max seconds per loop
  }
  //digitalWrite(Track, LOW);
  //loop until i < 0. Decrement i on each loop
}

int Acc(const unsigned int Max, const unsigned int dly) {
  for(int i = 0; i <= Max; i++) {
    analogWrite(Track, i); //Set Track PWM to i duty cycle
    delay((float) dly/Max); //Wait for dly seconds (dly/max seconds per loop
  }
  //loop until i < 0. Increment i on each loop
}

void SidingSet(const unsigned int pLeft, const unsigned int pRight) {
  if(pLeft == 165) {
    digitalWrite(S2, HIGH); //Make S2 active
    digitalWrite(S1, LOW); //Make S1 inactive
  }
  else {
    digitalWrite(S2, LOW); //Make S2 inactive
    digitalWrite(S1, HIGH); //Make S1 active
  }
  
  if(pRight == 70) {
    digitalWrite(S3, HIGH); //Make S3 active
    digitalWrite(S4, LOW); //Make S4 inactive
  }
  else{
    digitalWrite(S3, LOW); //Make S3 inactive
    digitalWrite(S4, HIGH); //Make S4 active
  }
}

//int RepeatInc(unsigned int Repeats) {
//  if(Repeats == 0) {
//   Repeats++;
//  }
//}
//Increment Repeats to 1 if it equals 0

unsigned int change_pRight(unsigned int pRight) {
  int k;
  int a;
  //Define local variables
  num = random(0,10); //Generate a random number of 0 or 1
  if(num % 2) {
    k = pRight;
    pRight = 100;
    a = 1;
  }
  else {
    k = pRight;
    pRight = 70;
    a = -1;
  }
//  Serial.println(pRight);
//
//  Serial.print("Random number: ");
//  Serial.println(num);
  
  for(;k <= pRight; k = k+a) {
    P_R.write(k);
    delay(50); //Wait 10 milliseconds on each loop
  }
  //Change point by looping until k < pRight 
  return pRight; 
}

unsigned int change_pLeft(unsigned int pLeft) {
  int k;
  int a;
  //Define local variables
  num = random(0,10); //Generate random number of 0 or 1
  if(num % 2) {
    k = pLeft;
    pLeft = 135;
    a = -1;
  }
  else {
    k = pLeft;
    pLeft = 165;
    a = 1;
  }
 
  for(;k <= pLeft; k = k+a) {
    P_L.write(k);
    delay(50); //Wait 10 milliseconds on each loop
  }
  //Change point by looping until k < pRight
  return pLeft;
}


void fullSiding_R(const unsigned int pRight, const unsigned int spd) {
  if(pRight == 70) {
    while(digitalRead(Sen3) == 1) {
    }
  }
  else {
    while(digitalRead(Sen4) == 1) {
    }
  }
  analogWrite(Track, (spd/2));
  delay(1000);
  //Wait for train to enter active siding
}

void fullSiding_L(const unsigned int pLeft, const unsigned int spd) {
  if(pLeft == 165) {
    while(digitalRead(Sen2) == 1) {
    }
  }
  else {
    while(digitalRead(Sen1) == 1) {
    }
  }
  analogWrite(Track, (spd/2));
  delay(1000);
  //Wait for train to enter active siding
}

//int debug(int cnt) {
//  Serial.print(cnt);
//  delay(2000);
//  Serial.println(": Triggered");
//
//  cnt++;
//  return cnt;
//}

Hi,
What model Arduino board are you using?
Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

If you are using a UNO or a Nano, pins 0 and 1 are Rx/Tx pins used to program the controller and my cause some program upload problems or some code input inconsistent operation.

Tom..... :slight_smile:

I have attached the circuit. I hope you can read it, it is the best I can do for the time being.

The board I am using is an ordinary Uno.

I know the symbol for the MOSFET is wrong. The source of the MOSFET is connected to +12V and the Drain to 'A'. I have compiled a separate test program, which proves that the MOSFET is operating correctly.

The SPST relays have been switched with MOSFETs - though they will be switched back to relays in the near future.

I have been powering it through a USB connection from my laptop. I wonder if this isn't supplying enough current/power to the circuit. I am going to borrow a more suitable power supply this evening and see if it works with that (any thoughts on that matter are welcome).

I have attached the MOSFET datasheet as well and will try and find the datasheet for the DPDT relay later.

Mitchell

MOSFET datasheet:

I am having problems linking the image. Doesn't meet security or something-or-other. Got to do something now, will see to it later this afternoon.

Mitchell

It is a bad idea to use pins 0 and 1 because they are used by the serial port and so you won’t be able to do any debugging printing to see what is going on.

Why are you writing the code in such an odd way? You have an endless loop in the loop function. Get rid of it and put the initial servo positions in the setup function. The loop function acts as an endless loop anyway.

Did you write this code yourself? It looks like it wasn’t written for an Arduino.

Running two servos requires good supply decoupling and you can’t power them reliably with the 5V output of an Arduino. You need at least a separate regulator, if not power source. Because without this the servos generate a lot of interference which stops the software working correctly.

I have been powering it through a USB connection from my laptop. I wonder if this isn't supplying enough current/power to the circuit.

Yes as a USB can only supply 500mA and each servo needs about 1A peak current this will be a problem.

Yes, I wrote the code myself.

Excuse the unusual use of a while loop. The reason for the while loop is that the values of pLeft and pRight kept getting reset every time the loop wrapped around to repeat itself. Adding the while loop solved this. If there is another reason and solution for this, I will readily change the code.

A reason why the code might look odd is that I am probably getting somewhat confused with other languages that I have been learning recently, however, I'm probably just not particularly great at programming.

I'm still picking things up as I go along so any feedback or advice is welcome should anyone wish to give any.

What exactly do you mean by 'It looks as if it wasn't written for an Arduino"?

As far as the Servo's go, I was informed on a previous project - for which I received advice on another topic - that I should be fine powering the SG90 servo's from the Arduino's 5V pin. Should I take that to be incorrect?

Mitchell

There was a problem during the uploading of Circuit.jpg.
Your post has been made, however the above attachment was not attached. Please use the Back button to edit your post and submit any required changes.
Your attachment has failed security checks and cannot be uploaded. Please consult the forum administrator.

It won't let me attach the image of the circuit to the post, displaying that (^^) error message each time. I'm not all too familiar with forums - any advice? Else I shan't be able to include it like requested.

A common reason why a JPG can't be uploaded is because if contains EXIF data from the camera or phone. The simple solution is to copy the file to a PNG and upload that.

Simple Image Posting Guide

...R

The reason for the while loop is that the values of pLeft and pRight kept getting reset every time the loop wrapped around to repeat itself. Adding the while loop solved this.

No it can not possibly fix that problem. I think you are mistaken.

It was the infinite for loop that made me think it was not written for an Arduino. You see this in some C programs on other processors but there is no need on an Arduino. Some Arduinos actually need to fall out of the loop function to do some “house work”, but not the Uno. Still it is good to get into the habit of doing it right.

It is all pointing to poor power supply and lack of decoupling.

As far as the Servo's go, I was informed on a previous project - for which I received advice on another topic - that I should be fine powering the SG90 servo's from the Arduino's 5V pin. Should I take that to be incorrect?

Yes absolutely rubbish. If that indeed what was said. Maybe you did not consider the context of the reply. While testing you might get away with running one servo, although it is flakey but never using two servos. Maybe you can supply a link.