Need help with final part of sketch. Switch Case I think?

Hi everyone.

Thanks so much to all those who have helped me here this week, and sorry to be posting so much but you've allowed me to create something so awesome! Thank you so much!

I just need one final thing that I can't seem to work out.

I think I need to use some sort of switch case? I want the last section of the code to be in a loop started by StartButton, and the top half to be what runs when the arduino starts up.

This is the section I need to start AND LOOP FOREVER when StartButton = HIGH

//KEEP THIS AT BOTTOM - EASY DRIVER CONTROL SET UP//
  
{

if(StartButton == HIGH) {
  int i;
  digitalWrite(dirpin, LOW);     // Set the direction. LOW = to motor, HIGH = away  
  for (i = 0; i<Distance; i++)         //  DISTANCE PER LOOP 22500 is the length of the track
    digitalWrite(steppin, LOW);  // 
    digitalWrite(steppin, HIGH); //
    delayMicroseconds(800); //Speed - max of 800
    delay(1000)
    digitalWrite(TimerPin, HIGH)
    delay(1000)
    digitalWrite(TimerPin, LOW)
    delay(1000)
    StepCounter++;
}
    else (StartButton == LOW); {
      Distance = 0;
    }

}

}

Here is the whole sketch, I think I need a switch case somewhere in here, but im not sure what to do or how to do it, could someone please help me know how and where to put it? OR if I'm wrong and there is an easier way to do this, please let me know! :slight_smile:

#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

int Distance = 0;
int StepCounter = 0;

// this constant won't change:
const int  SpeedControlButton = 50;    
const int  DistanceControlButton = 48; 
const int  ExposureControlButton = 46;
const int  DirectionControlButton = 44;
const int  ShutterControlButton = 42;
const int dirpin = 52;
const int steppin = 53;
const int TimerPin = 40;
const int StartButton = 7;
 
// Variables will change:
int SpeedControlCounter = 0;      // Counter for the Speed Button
int DistanceControlCounter = 0;   // Counter for the Distance Button
int ExposureControlCounter = 0;   // Counter for the Exposure Button
int DirectionControlCounter = 0;  // Counter for the Direction Button
int ShutterControlCounter = 0;
int StepSpeed = 0;

//
int SpeedButtonState = 0;         // current state of the button
int DistanceButtonState = 0;
int lastSpeedButtonState = 0;     // previous state of the button
int lastDistanceButtonState = 0;

/////
void setup() {
  pinMode(SpeedControlButton, INPUT);
  pinMode(DistanceControlButton, INPUT);
  pinMode(ExposureControlButton, INPUT);
  pinMode(DirectionControlButton, INPUT);
  pinMode(ShutterControlButton, INPUT);
  pinMode(dirpin, OUTPUT);
  pinMode(steppin, OUTPUT);
  pinMode(TimerPin, OUTPUT);
  pinMode(StartButton, OUTPUT);
  Serial.begin(9600);
  lcd.begin(16, 2);
}

 void loop() {

  // SPEED CONTROL BUTTON READING//
  // read the pushbutton input pin:
  SpeedButtonState = digitalRead(SpeedControlButton);
  // compare the buttonState to its previous state
  if (SpeedButtonState != lastSpeedButtonState) {
    // if the state has changed, increment the counter
    if (SpeedButtonState == HIGH) {
      // if the current state is HIGH then the button
      // wend from off to on:
      SpeedControlCounter++;
      Serial.println("Speed, Up");
      Serial.print("number of button pushes:  ");
      Serial.println(SpeedControlCounter);
////
      lcd.clear();
      lcd.println("Speed Up");
      lcd.println(SpeedControlCounter);
      if(SpeedControlCounter == 5) SpeedControlCounter =0;
      
    } else {
      // if the current state is LOW then the button went from on to off:
      Serial.println("off");
    }
    // Delay a little bit to avoid bouncing
    delay(50);
  }
  // save the current state as the last state,
  //for next time through the loop
  lastSpeedButtonState = SpeedButtonState;


                         ///DISTANCE CONTROL BUTTON READING
   // SPEED CONTROL BUTTON READING//
  // read the pushbutton input pin:
  DistanceButtonState = digitalRead(DistanceControlButton);
  // compare the buttonState to its previous state
  if (DistanceButtonState != lastDistanceButtonState) {
    // if the state has changed, increment the counter
    if (DistanceButtonState == HIGH) {
      // if the current state is HIGH then the button
      // wend from off to on:
      DistanceControlCounter++;
      Serial.println("Distance, Up");
      Serial.print("number of button pushes:  ");
      Serial.println(DistanceControlCounter);
////
      lcd.clear();
      lcd.println("Distance, Up");
      lcd.println(DistanceControlCounter);
      if(DistanceControlCounter == 5) DistanceControlCounter =0;
      
    } else {
      // if the current state is LOW then the button went from on to off:
      Serial.println("off");
    }
    // Delay a little bit to avoid bouncing
    delay(50);
  }
  // save the current state as the last state,
  //for next time through the loop
  lastDistanceButtonState = DistanceButtonState;

//Control Section//

{
//SPEED CONTROL//
  if (SpeedControlCounter == 1) StepSpeed = 800; 
  
  if (SpeedControlCounter == 2) StepSpeed = 2000;

  if (SpeedControlCounter == 3) StepSpeed = 4000;

  if (SpeedControlCounter == 4) StepSpeed = 10000;

  if (SpeedControlCounter == 5) StepSpeed = 100000;

//DISTANCE CONTROL//
  if (DistanceControlCounter == 1) Distance = 10; 
  
  if (DistanceControlCounter == 2) Distance = 25;

  if (DistanceControlCounter == 3) Distance = 45;

  if (DistanceControlCounter == 4) Distance = 100;

  if (DistanceControlCounter == 5) Distance = 22500;


  }


//KEEP THIS AT BOTTOM - EASY DRIVER CONTROL SET UP//
  
{

if(StartButton == HIGH) {
  int i;
  digitalWrite(dirpin, LOW);     // Set the direction. LOW = to motor, HIGH = away  
  for (i = 0; i<Distance; i++)         //  DISTANCE PER LOOP 22500 is the length of the track
    digitalWrite(steppin, LOW);  // 
    digitalWrite(steppin, HIGH); //
    delayMicroseconds(800); //Speed - max of 800
    delay(1000)
    digitalWrite(TimerPin, HIGH)
    delay(1000)
    digitalWrite(TimerPin, LOW)
    delay(1000)
    StepCounter++;
}
    else (StartButton == LOW); {
      Distance = 0;
    }

}

}

THANK YOU SO MUCH!

Several sections of your code would benefit from a switch/case:

//SPEED CONTROL//
switch (SpeedControlCounter) {
  case 1:
    StepSpeed = 800;
    break;
  case 2:
    StepSpeed = 2000;
    break;
  case 3:
    StepSpeed = 4000;
    break;
  case 4:
    StepSpeed = 10000;
    break;
  case 5:
    StepSpeed = 100000;
    break;
  default:
    Serial.print("I shouldn't be here. SpeedControlCounter = ");
    Serial.println(SpeedControlCounter);
    break;
}

Or you could use:

long StepArray[] = {800, 2000, 4000, 10000, 100000};

// more code...

    StepSpeed = StepArray[SpeedControlCounter - 1];

The use of the if statement blocks is the least efficient since, on average, you will do 2.5 unnecessary tests to get to the "right" one. The switch/case block creates a jump table, so it will be faster on average. The last version is probably the best version, since it only requires indexing into an array. You can apply similar logic elsewhere in your code.

econjack:
Several sections of your code would benefit from a switch/case:

//SPEED CONTROL//

switch (SpeedControlCounter) {
  case 1:
    StepSpeed = 800;
    break;
  case 2:
    StepSpeed = 2000;
    break;
  case 3:
    StepSpeed = 4000;
    break;
  case 4:
    StepSpeed = 10000;
    break;
  case 5:
    StepSpeed = 100000;
    break;
  default:
    Serial.print("I shouldn't be here. SpeedControlCounter = ");
    Serial.println(SpeedControlCounter);
    break;
}




Or you could use:



long StepArray[] = {800, 2000, 4000, 10000, 100000};

// more code...

StepSpeed = StepArray[SpeedControlCounter - 1];




The use of the if statement blocks is the least efficient since, on average, you will do 2.5 unnecessary tests to get to the "right" one. The *switch/case* block creates a jump table, so it will be faster on average. The last version is probably the best version, since it only requires indexing into an array. You can apply similar logic elsewhere in your code.

That is actually very helpful, Thank you! I have adjusted a bunch of the code using this now.

I just still can't seem to get the end section to perform in its own loop, which I think is the main problem. I want to be able to change all of the motordriver area's values and then hit start and have just this

//KEEP THIS AT BOTTOM - EASY DRIVER CONTROL SET UP//
  
{

if(StartButton == HIGH) {
  int i;
  digitalWrite(dirpin, LOW);     // Set the direction. LOW = to motor, HIGH = away  
  for (i = 0; i<Distance; i++)         //  DISTANCE PER LOOP 22500 is the length of the track
    digitalWrite(steppin, LOW);  // 
    digitalWrite(steppin, HIGH); //
    delayMicroseconds(800); //Speed - max of 800
    delay(1000)
    digitalWrite(TimerPin, HIGH)
    delay(1000)
    digitalWrite(TimerPin, LOW)
    delay(1000)
    StepCounter++;
}
    else (StartButton == LOW); {
      Distance = 0;
    }

}

}

Run in its own loop, what would be the best way of going about this?

Thanks again for help! :slight_smile:

Unless I misunderstand, you only need to change the "if" to "while". The else can be removed, since you know that if the loop was broken StartButton is LOW.

while(StartButton == HIGH) {
  int i;
  digitalWrite(dirpin, LOW);     // Set the direction. LOW = to motor, HIGH = away 
  for (i = 0; i<Distance; i++)         //  DISTANCE PER LOOP 22500 is the length of the track
    digitalWrite(steppin, LOW);  //
    digitalWrite(steppin, HIGH); //
    delayMicroseconds(800); //Speed - max of 800
    delay(1000)
    digitalWrite(TimerPin, HIGH)
    delay(1000)
    digitalWrite(TimerPin, LOW)
    delay(1000)
    StepCounter++;
}

Distance = 0;

There are several approaches. I did not look thoroughly at the code, but you can place the code that runs once in setup(); you can even wait till the start button is pressed in setup. In that case loop() only contains the part that you want to loop.

Alternative, think slightly different. Because the last part of the code seems to need variables that are set in the first code, you can use a flag to indicate that the first part is completed.

void loop()
{
  static bool fComplete = false;

  if(fComplete == false)
  {
    // first part of code
    ...
    ...

    fComplete  = true;
  }

  if(fComplete == true && digitalRead(StartButton == HIGH)
  {
    // last part of your code
    ...
    ...
  }
}

Note that this means that you have to keep the start button pressed. If that is not what you want, you can add another flag to remember that the start button was pressed

void loop()
{
  static bool fComplete = false;
  static bool fStarted = false;

  if(fComplete == false)
  {
    // first part of code
    ...
    ...

    fComplete  = true;
  }

  if(digitalRead(StartButton) == HIGH)
  {
    fStarted = true;
  }

  if(fComplete == true && fStarted == true)
  {
    // last part of your code
    ...
    ...
  }
}

You can add extra code that sets fComplete and fStarted to false, e.g. when the start button is released (LOW) so the first part is executed again. That depends on your needs.

PS
Please note that buttons might require debouncing; they can toggle a few times in quick succession. That's specially the case when you check for high and later check for low.

Thank you so much for your help!! Finally finished and its working well enough for now! Thank you!!