number of button press's runs different VOID functions, Ideas?

I am using a Arduino to run my boys train set.

Im having trouble figuring out how to change the trains direction using 1 button only on the controller to scroll through 4 Void *** commands.

1 TrainStop,
2 Clockwise,
3 TrainStop,
4 AntiClockwise, then back to TrainStop again,. there are 2 train stops so the train doesn’t destroy itself if its still moving when selecting clock and anticlock

I have had a look through google and im struggling to find the right function to do this, I think button count would be the best way? count up to 4 then the 5th press goes back to

If you have a suggestion on the code type that would be great, im happy to search google to find code that i can adapt to suit though i have struggled so far. (that how most of this was written)

Info on the trainset up.

I have made a controller with a potentiometer to control the trains speed. The controller also has 2 buttons which go to 1 analog pin. both buttons have different resistances allowing the buttonstate to be a output of 1 or 2 depending on which button is pressed.

The code i have so far allows the train to travel in 1 pre-written direction with variable speed.

Many thanks

const int sensorA = 2; //sensor A on trainset
const int IN1=9; // train motor pin 1
const int IN2=10; // train motor pin 2
const int ENA=6; // train speed PWM
const int LAmber=3; // left amber light on controller
const int RAmber=4; // right amber light on controller
const int RedLight=5; // red light on controller
const int SpeedDial=A1; // manual speed potentiometer on controller
const int CButton=A0; // multiple button on controller
const int CBUTTON1 = 1; //right button on controller using A0 pin
const int CBUTTON2 = 2; //left button on controller

 //controller button value
const int CBUTTON1LOW = 1000;
const int CBUTTON1HIGH = 1024;
const int CBUTTON2LOW = 850;
const int CBUTTON2HIGH = 970;

// Variables will change:
int speedSensorValue = 0; // speed dial controller input value
int trainSpeed = 0;
int ledState = LOW; // ledState used to set the LEDs on the controller
int buttonState;             // the current reading from the input A0 controller pin
int lastButtonState = LOW;   // the previous reading from the input A0 controller pin

//Millis setup
unsigned long previousMillis = 0;        // will store last time LED on controller was updated
const long interval = 1000;           // interval at which to blink (milliseconds)
long lastDebounceTime = 0;  // the last time the output controller pin was toggled
long debounceDelay = 50;    // the debounce time; increase if the output flickers( for controller)

// speed settings
int trainSpeedMax = 180; // max speed of train
int trainStallSpeed = 55; // slowest speed of train before stalling
int trainStop = trainStop; // train stop, no value

void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
 
  // make the pushbutton's pin an input:
  pinMode(IN1,OUTPUT); //motor pin 1
  pinMode(IN2,OUTPUT); //motor pin 2
  pinMode(CButton, INPUT_PULLUP); // sets analog pin for input on controller
}


// train direction here and light LED on controller
void AntiClockwise(){
digitalWrite(IN1,HIGH); // Backwards / anticlockwise
digitalWrite(IN2,LOW);
pinMode(RAmber,OUTPUT); //Flashes LED to show direction of train
}

// train direction here and light LED on controller
void Clockwise(){
digitalWrite(IN1,LOW); // forward / clockwise
digitalWrite(IN2,HIGH);
pinMode(LAmber,OUTPUT); //Flashes LED to show direction of train
}

// train direction here and light LED on controller
void StopDead(){
digitalWrite(IN1,LOW); // turns off motor controller
digitalWrite(IN2,LOW);
pinMode(RedLight,OUTPUT); // Lights LED to show the motor is off

}

// fade to start the train moving - something that im looking to but haven't got it to work as i want it yet
void trainFadeStart (){ //name of function to fade the train to start
    for (int fadeValue = trainStallSpeed ; fadeValue <= trainSpeed; fadeValue += 1) { //fade function to speed up the train from its lowest speed to trainSpeed
       analogWrite(ENA, fadeValue); //make the train fade up to the trainspeed value listed in settings
      delay(30);}{ // wait for 30 milliseconds
      analogWrite(ENA,trainSpeed); //once fade is complete, delay then run at trainspeed value
  }
  
}

// fade to stop the train moving - something that im looking to but haven't got it to work as i want it yet
void trainFadeStop(){ //name of function to fade the train to a stop
    for (int fadeValue = trainSpeed ; fadeValue >= trainStallSpeed; fadeValue -= 1) { //fade function to slow down the train from trainSpeed to slowest
        analogWrite(ENA,fadeValue);//make the train fade down to the trainStallSpeed value listed in settings
        delay(30);
        analogWrite(ENA,trainStop); //once fade is complete, delay then run at trainStop value
            }
}


void loop() {

// button selection on the controller
 // read the state of the switch into a local variable:
   int reading = analogRead(CButton);   
   int tmpButtonState = LOW;             // the current reading from the input pin
   
   if(reading>CBUTTON2LOW && reading<CBUTTON2HIGH){
     //Read switch 2
     tmpButtonState = CBUTTON2;
   }else if(reading>CBUTTON1LOW && reading<CBUTTON1HIGH){
     //Read switch 1
     tmpButtonState = CBUTTON1;
   }else{
     //No button is pressed;
     tmpButtonState = LOW;
   }

   // check to see if you just pressed the button 
   // (i.e. the input went from LOW to a buttonState)

   // If the switch changed, due to noise or pressing:
   if (tmpButtonState != lastButtonState) {
     // reset the debouncing timer
     lastDebounceTime = millis();
   } 

   if ((millis() - lastDebounceTime) > debounceDelay) {
     // whatever the reading is at, it's been there for longer
     // than the debounce delay, so take it as the actual current state:
     buttonState = tmpButtonState;
     Serial.println(buttonState);
   }

   // save the reading.  Next time through the loop,
   // it'll be the lastButtonState:
   lastButtonState = tmpButtonState;
   
   // don't know if i can use this, would need it to run VOID AntiClockwise and continue to run
//   switch(buttonState){
//     case CBUTTON1:
//     digitalWrite(ledPin, buttonState>0);
//     break;
//     case CBUTTON2:
//     digitalWrite(ledPin, buttonState>0);
//     break;
     
        

// check to see if it's time to blink the LED; that is, if the difference between the current time and last time you blinked the LED is bigger than the interval at which you want to blink the LED.
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }

    // set the LED with the ledState of the variable:
    digitalWrite(LAmber, ledState);
    digitalWrite(RAmber, ledState);
    digitalWrite(RedLight, ledState);
      }


// read the analog A0 on controller and output to variable trainSpeed
 speedSensorValue = analogRead(SpeedDial);
  // map it to the range of the analog out:
 trainSpeed = map(speedSensorValue, 0, 1023, trainStop, trainSpeedMax); //trainstop/trainspeedmax are preset at the top of the code


//just so the train will travel round the track
  AntiClockwise(); //direction around track
        analogWrite(ENA,trainSpeed); //runs the variable speed of the train

  }

mg_evolution: 4 Void *** commands.

The correct term is function. void is the return value type, in this case meaning that the function doesn't return a value.

mg_evolution: I think button count would be the best way? count up to 4 then the 5th press goes back to

Yep, just increment the button press count global variable on each press and then use a switch/case statement with that variable to determine which of your functions to call.

mg_evolution: // fade to stop the train moving - something that im looking to but haven't got it to work as i want it yet void trainFadeStop(){ //name of function to fade the train to a stop    for (int fadeValue = trainSpeed ; fadeValue >= trainStallSpeed; fadeValue -= 1) { //fade function to slow down the train from trainSpeed to slowest        analogWrite(ENA,fadeValue);//make the train fade down to the trainStallSpeed value listed in settings        delay(30);        analogWrite(ENA,trainStop); //once fade is complete, delay then run at trainStop value            } }

Should be:

void trainFadeStop() { //name of function to fade the train to a stop
  for (int fadeValue = trainSpeed; fadeValue >= trainStallSpeed; fadeValue -= 1) { //fade function to slow down the train from trainSpeed to slowest
    analogWrite(ENA, fadeValue); //make the train fade down to the trainStallSpeed value listed in settings
  }
  delay(30);
  analogWrite(ENA, trainStop); //once fade is complete, delay then run at trainStop value
}

You should always use Tools > Auto Format on your code. Not only will it make it easier for us on the forum to read, the automatic indentation will allow you to spot bugs quickly.

Brill many thanks,

I'll take a look at the button count and get the Auto Format done.

Im new to this, cheers for the guidance.

pert:

void trainFadeStop() { //name of function to fade the train to a stop

for (int fadeValue = trainSpeed; fadeValue >= trainStallSpeed; fadeValue -= 1) { //fade function to slow down the train from trainSpeed to slowest
   analogWrite(ENA, fadeValue); //make the train fade down to the trainStallSpeed value listed in settings
 }
 delay(30);
 analogWrite(ENA, trainStop); //once fade is complete, delay then run at trainStop value
}

This actually will not work correctly because it will fade to a stop too fast to be noticeable. In essence you need to do this:

void trainFadeStop() { //name of function to fade the train to a stop
  for (int fadeValue = trainSpeed; fadeValue >= trainStallSpeed; fadeValue -= 1) { //fade function to slow down the train from trainSpeed to slowest
    analogWrite(ENA, fadeValue); //make the train fade down to the trainStallSpeed value listed in settings
    delay(30);  //the length of this delay determines the how fast the fade happens
  }
  delay(30);
  analogWrite(ENA, trainStop); //once fade is complete, delay then run at trainStop value
}

The problem with using delay is it blocks any other code from running, so any presses of the button that occur while trainFadeStop() is running will be ignored. The better way to do this is demonstrated in File > Examples > 02.Digital > BlinkWithoutDelay. So a non-blocking implementation would look something like:

const int ENA = 6; // train speed PWM pin
const int trainSpeedMax = 180; // max speed of train
const int trainStallSpeed = 55; // slowest speed of train before stalling
const int trainStop = 0; // train stop
const byte trainFadeStopInterval = 20; // (ms)delay between each speed level
const byte trainFadeStopFinishDelay = 30; // (ms)delay between end of fade and stop

boolean trainFadeStopActive = false;
int trainSpeed;
byte trainFadeStopDelay;
unsigned long trainFadeStopTimestamp;

void setup() {
  pinMode(ENA, OUTPUT);
  trainSpeed = trainSpeedMax;
  trainFadeStop();
}

void loop() {
  updateTrainFadeStop();  // updateTrainFadeStop() must be called regularly
}

void trainFadeStop() {  // fades the train to a stop
  trainFadeStopActive = true;
  trainFadeStopDelay = trainFadeStopInterval;
}

boolean updateTrainFadeStop() {
  if (trainFadeStopActive == true) {
    if (millis() - trainFadeStopTimestamp >= trainFadeStopDelay) {  // it's time for the next speed level
      trainSpeed = trainSpeed - 1;  // reduce speed
      if (trainSpeed == trainStallSpeed) {  // time for finish delay
        trainFadeStopDelay = trainFadeStopFinishDelay;
      }
      else if (trainSpeed < trainStallSpeed) {
        trainSpeed = trainStop;
        trainFadeStopActive = false;  // disable trainFadeStop
      }
      analogWrite(ENA, trainSpeed);
      trainFadeStopTimestamp = millis();
    }
    return false; // trainFadeStop is not complete
  }
  return true;  // trainFadeStop is not active
}