Button presses to re-define a set of values.

Hi All,

I am working on a much larger setup where a stepper motor is to be controlled via potentiometer feedback but need to go back to basics and understand how a push button can define some values if possible.

This is my other larger project. http://forum.arduino.cc/index.php?topic=378877.0

I though I would ask a more simpler question here and hopefully this will help me with my larger project.

I have 3 buttons.
I need to be able to read a button press and then have that button press define some variables.

so if a button state is true how do I then have it define particular code to use in a loop?

for example I have 3 button states:

if (Button1 == true)
Setting = 0;

if (Button2 == true)
Setting = 1;

if (Button3 == true)
Setting = 2;

So if button 2 is active and Setting = 1, how do use that setting to define what's to be used in the loop.

Something like this perhaps ( but in code format ).

if Setting = 0 then Delay = 5
else use
if Setting = 1 then Delay = 15
else use
if Setting = 2 then Delay = 30

if Setting = 0 then 'something' map(val, 0, 1023, 0, 1023)
else use
if Setting = 1 then 'something' map(val, 0, 1023, 0, 501)
else use
if Setting = 2 then 'something' map(val, 0, 1023, 0, 255)

And so on and so on with as many variables i need. I have the serial port reading what button is active but need to use this to define values within the loop etc.

I'm hoping that when the Setting state has been defined I can just call a simple bit of start code to select the value I need either individually or as a group like this perhaps but again in code format?

if (Button1 == true)
Setting = 0;
if Setting = 0 then Delay = 5
if Setting = 0 then 'something' map(val, 0, 1023, 0, 1023)

else

if (Button2 == true)
Setting = 1;
if Setting = 1 then Delay = 15
if Setting = 1 then 'something' map(val, 0, 1023, 0, 501)

else

if (Button3 == true)
Setting = 2;
if Setting = 2 then Delay = 30
if Setting = 2 then 'something' map(val, 0, 1023, 0, 255)

And advise would be appreciated.

Thanks

J

Maybe you should get some basic programming skills mastered.
There are examples that come with the IDE, go through them. Don't skip this!
Also, there is a lot of basic information on the site you should go through.

13 posts and you still don’t know about code tags? I don’t think it was your intention to include ???

But yeay, you’re on the right way. The checking for the buttons is just a complete separate task which sets a variable (settings in this case). After that you can just check that variable to check what to do.

Keep in mind buttons are not clean. They debounce and stuff. But as long its not a problem for you/the code to change the setting variable multiple times when you press it you’re okay.If you just set a setting to 1 when you press a button (and don’t change the variable other then with buttons) it’s not a problem to assign it 1 multiple times.

If it is a problem you want to detect when a button became pressed and you want to debounce it. But don’t worry, in that case just use a library like Bounce2 and it’s all neat and simple.

And easiest way to use a button, connect it between a pin and GND and use

pinMode(pin, INPUT_PULLUP);

The pin will now read LOW when it’s pressed and HIGH when it’s not pressed. Sounds backwards but don’t worry. So it becomes something like:

if(!digitalRead(Button1)){
  setting = 1;
}
else if(!digitalRead(Button2)){
  setting = 2;
}

I don’t know how many buttons/setting you want to use? But it it’s more then 2-3 I would use a array.

const byte ButtonPins[] = {8, 9, 10, 11};
byte setting = 0;

void setup(){
  for(byte i = 0; i < sizeof(ButtonPins); i++){
    pinMode(ButtonPins[i], INPUT_PULLUP);
  }
}

void loop(){
  checkButtons();
  
  //do your other stuff
}


void checkButtons(){
  for(byte i = 0; i < sizeof(ButtonPins); i++){
    if(!digitalRead(ButtonPins[i])){
      setting = i;
    }
  }
}

Keep in mind a array starts at 0!

Hi,

Thanks for the responses, I keep going back to the basics which I have read a couple of times now but as soon as I read it, it’s like it goes in one ear and out the next. I have completed the led, button, potentiometer, stepper motor and servo tutorials. I can figure out the terminology as I go, I guess I just need to know if the way I am looking at it is logical and possible? I’ts all slowly starting to sink in now, bit by bit i think. I am probably running before I can walk but trying to create a sketch which furfills the whole requirement from the get go is directing me towards the correct questions to ask and hopefully help in getting the right answers.

I only need 3 buttons to set 3 states with about 5 Stepper motor variables like RPM, delay, map, Steps to take, etc. This is my Stepper motor loop below which works fine now within my other larger sketch. It just doesn’t allow me to switch between the 3 states at the push of a button which is why I’m here :slight_smile:

This is how my sketch is seeing the buttons from startup.

const int RallyButton = 7;   // Setting Button on button 0
const int RoadButton = 6;    // Setting Button on button 1
const int TruckButton = 5;   // Setting Button on button 2

boolean RallyState;    // Setting Rally State
boolean RoadState;     // Setting Road State
boolean TruckState;    // Setting Truck State

int Setting = 0;    // Default setting option, 0 Rally. 1 Road, 2 Truck

int Rally_prev;
int Rally_current;
int Road_prev;
int Road_current;
int Truck_prev;
int Truck_current;

void setup()

{
  pinMode(RallyButton, INPUT);   // set up button 0 as input
  pinMode(RoadButton, INPUT);    // set up button 1 as input
  pinMode(TruckButton, INPUT);   // set up button 2 as input
}

This is my Stepper motor loop, defining the characteristics of the Motor.

stepper.setSpeed(150);
 val = map (val, 0, 1023, 0, 1023);
  if ((val - frame) != 0) {
    if ((val - frame) > 40) { // Deadzone
      stepper.step(1); // move a step toward the pot reading.
      frame++;
    }
    if ((val - frame) < -40) { // Deadzone
      stepper.step(-1); // move a step toward the pot reading.
      frame--;
    }
  }

So within this I have all the adjustable values i need for one of the 3 settings. I just need to be able to switch between them for each button selection. I will only press one button to change the setting once and then leave it at that until next power up. I just don’t know how easy it is to take that block of code and assign a button to it? If I can do it in one, great. If I have to break it down into seperate parts then I will do so…

So looking at your code and adding the third button:

if(!digitalRead(Button1)){
  setting = 1;
}
else if(!digitalRead(Button2)){
  setting = 2;
}
else if(!digitalRead(Button3)){
  setting = 3;
}

Where could I add my stepper block code. I feel like I can add it under the setting = # line but that seems like it would be too easy.

What if I were to add it like this? is this the correct road to go down?

if(!digitalRead(Button1)){
  setting = 1;
   stepper.setSpeed(150);
    val = map (val, 0, 1023, 0, 1023);
      if ((val - frame) != 0) {
        if ((val - frame) > 40) { // Deadzone
          stepper.step(1); // move a step toward the pot reading.
          frame++;
        }
        if ((val - frame) < -40) { // Deadzone
         stepper.step(-1); // move a step toward the pot reading.
          frame--;
        }
      }
    }
else if(!digitalRead(Button2)){
  setting = 2;
   stepper.setSpeed(150);
    val = map (val, 0, 1023, 0, 1023);
      if ((val - frame) != 0) {
        if ((val - frame) > 40) { // Deadzone
          stepper.step(1); // move a step toward the pot reading.
          frame++;
        }
        if ((val - frame) < -40) { // Deadzone
          stepper.step(-1); // move a step toward the pot reading.
          frame--;
        }
      }
    }
}
else if(!digitalRead(Button3)){
  setting = 3;
   stepper.setSpeed(150);
    val = map (val, 0, 1023, 0, 1023);
      if ((val - frame) != 0) {
        if ((val - frame) > 40) { // Deadzone
          stepper.step(1); // move a step toward the pot reading.
          frame++;
        }
        if ((val - frame) < -40) { // Deadzone
          stepper.step(-1); // move a step toward the pot reading.
          frame--;
        }
      }
    }
}

Thanks for your patience :smiley:

I did look into the array option but I only need to cover the few variables above so didn’t look any further.

Thanks again for your help

J

This is my full code warts and all…

// 2 Pots, 3 Buttons, Stepper motor rotation control jason187781.

#include <Stepper.h>

#define STEPS 400

Stepper stepper(STEPS, 8, 9, 10, 11);

int frame = 0;    // the initial position of the frame.

const int RallyButton = 7;   // Setting Button on button 0
const int RoadButton = 6;    // Setting Button on button 1
const int TruckButton = 5;   // Setting Button on button 2

boolean RallyState;    // Setting Rally State
boolean RoadState;     // Setting Road State
boolean TruckState;    // Setting Truck State

int Setting = 0;    // 0 Rally. 1 Road, 2 Truck

int Rally_prev;
int Rally_current;
int Road_prev;
int Road_current;
int Truck_prev;
int Truck_current;

void setup()

{
  pinMode(RallyButton, INPUT);   // set up button 0 as input
  pinMode(RoadButton, INPUT);    // set up button 1 as input
  pinMode(TruckButton, INPUT);   // set up button 2 as input

  // set the speed of the motor to 50 RPMs
  stepper.setSpeed(150);
}
void loop()
{

  int val = analogRead(0); // Wheel Postion Read
  int frame = analogRead(1); // Frame Position Read

  // Output the values to the serial port
  Serial.print(val, DEC);
  Serial.print(",");
  Serial.print(frame, DEC);
  Serial.print(",");
  Serial.print(Setting, DEC);
  Serial.println();

  // check if the "Rally" button has been pressed
  // if yes, then set then run "true" setup as below.
  Rally_prev = Rally_current; Rally_current = digitalRead(RallyButton);
  if (Rally_prev == LOW && Rally_current == HIGH) {
    changeRallyButtonState();
  }
  if (RallyState == true)
    Setting = 0;

  // Stepper Motor Settings for Rally State.
  val = map (val, 0, 1023, 0, 1023);
  if ((val - frame) != 0) {
    if ((val - frame) > 400) { // Deadzone
      stepper.step(1); // move a step toward the pot reading.
      frame++;
    }
    if ((val - frame) < -400) { // Deadzone
      stepper.step(-1); // move a step toward the pot reading.
      frame--;
    }
  }

  // End of Rally settings state.

  RallyState = false;

  // check if the "Road" button has been pressed
  // if yes, then set then run "true" setup as below.
  Road_prev = Road_current; Road_current = digitalRead(RoadButton);
  if (Road_prev == LOW && Road_current == HIGH) {
    changeRoadButtonState();
  }
  if (RoadState == true)
    Setting = 1;

  // Stepper Motor Settings for Rally State.
  val = map (val, 0, 1023, 150, 850);
  if ((val - frame) != 0) {
    if ((val - frame) > 100) { // Deadzone
      stepper.step(1); // move a step toward the pot reading.
      frame++;
    }
    if ((val - frame) < -100) { // Deadzone
      stepper.step(-1); // move a step toward the pot reading.
      frame--;
    }
  }

  // End of Rally settings state.

  RoadState = false;

  // check if the "Truck" button has been pressed
  // if yes, then set then run "true" setup as below.
  Truck_prev = Truck_current; Truck_current = digitalRead(TruckButton);
  if (Truck_prev == LOW && Truck_current == HIGH) {
    changeTruckButtonState();
  }
  if (TruckState == true)
    Setting = 2;

  // Stepper Motor Settings for Rally State.
  val = map (val, 0, 1023, 300, 800);
  if ((val - frame) != 0) {
    if ((val - frame) > 150) { // Deadzone
      stepper.step(10); // move a step toward the pot reading.
      frame++;
    }
    if ((val - frame) < -150) { // Deadzone
      stepper.step(-10); // move a step toward the pot reading.
      frame--;
    }
  }

  // End of Rally settings state.

  TruckState = false;

  // ensures that Processing can read the values before the next values arrive
}
void changeRallyButtonState() // Rally button state logic
{
  if (RallyState == true) {
    RallyState = false;
  }
  else {
    RallyState = true;
  }
}
void changeRoadButtonState() // Road button state logic
{
  if (RoadState == true) {
    RoadState = false;
  }
  else {
    RoadState = true;
  }
}
void changeTruckButtonState() // Truck button state logic
{
  if (TruckState == true) {
    TruckState = false;
  }
  else {
    TruckState = true;
  }
}

I did some clean up.
Please read //<<<<<<<<<<< comments >>>>>>>>>>>
This is not tested in any way, just some suggestions:

EDIT:
Note: you haven’t considered switch bounce.

// 2 Pots, 3 Buttons, Stepper motor rotation control jason187781.

#include <Stepper.h>

#define STEPS 400

Stepper stepper(STEPS, 8, 9, 10, 11);

int frame = 0;    // the initial position of the frame.

const int RallyButton = 7;   // Setting Button on button 0
const int RoadButton = 6;    // Setting Button on button 1
const int TruckButton = 5;   // Setting Button on button 2

boolean RallyState;    // Setting Rally State
boolean RoadState;     // Setting Road State
boolean TruckState;    // Setting Truck State

int Setting = 0;    // 0 Rally. 1 Road, 2 Truck

int Rally_prev;
int Rally_current;
int Road_prev;
int Road_current;
int Truck_prev;
int Truck_current;

void setup()
{
  // <<<<<<<<<<<<<<<<<<<<<<<<< May need INPUT_PULLUP in the next three lines >>>>>>>>>>>>>>>>>>>>>
  pinMode(RallyButton, INPUT);   // set up button 0 as input
  pinMode(RoadButton,  INPUT);   // set up button 1 as input
  pinMode(TruckButton, INPUT);   // set up button 2 as input

  // set the speed of the motor to 50 RPMs
  stepper.setSpeed(150);
}
void loop()
{
  int val = analogRead(0); // Wheel Postion Read
  int frame = analogRead(1); // Frame Position Read

  // Output the values to the serial port
  Serial.print(val, DEC);
  Serial.print(",");
  Serial.print(frame, DEC);
  Serial.print(",");
  Serial.print(Setting, DEC);
  Serial.println();

  //----------------------------------------------------------------
  // check if the "Rally" button has been pressed
  // if yes, then set then run "true" setup as below.
  Rally_prev = Rally_current; 
  Rally_current = digitalRead(RallyButton);

  if (Rally_prev == LOW && Rally_current == HIGH) 
  {
    //changeRallyButtonState();
    RallyState = !RallyState;
  }

  if (RallyState == true)
  {
    Setting = 0;
  }
  
  //<<<<<<<<<<<<<<<<<< Should the next line be with the previous if? >>>>>>>>>>>>>>
  // Stepper Motor Settings for Rally State.
  //<<<<<<<<<< Why, it is already 0-1023? >>>>>>>>>>>>>>
  val = map (val, 0, 1023, 0, 1023);

  if ((val - frame) != 0) 
  {

    if ((val - frame) > 400) 
    { // Deadzone
      stepper.step(1); // move a step toward the pot reading.
      frame++;
    }
    else if ((val - frame) < -400) 
    { // Deadzone
      stepper.step(-1); // move a step toward the pot reading.
      frame--;
    }
  }// End of Rally settings state.

  RallyState = false;

  //----------------------------------------------------------------
  // check if the "Road" button has been pressed
  // if yes, then set then run "true" setup as below.
  Road_prev = Road_current; 
  Road_current = digitalRead(RoadButton);

  if (Road_prev == LOW && Road_current == HIGH) 
  {
    //changeRoadButtonState();
    RoadState = !RoadState;
  }

  if (RoadState == true)
  {
    Setting = 1;
  }

  //<<<<<<<<<<<<<<<<<< Should the next line be with the previous if? >>>>>>>>>>>>>>
  // Stepper Motor Settings for Rally State.
  val = map (val, 0, 1023, 150, 850);

  if ((val - frame) != 0) 
  {

    if ((val - frame) > 100) 
    { // Deadzone
      stepper.step(1); // move a step toward the pot reading.
      frame++;
    }
    else if ((val - frame) < -100) 
    { // Deadzone
      stepper.step(-1); // move a step toward the pot reading.
      frame--;
    }
  }// End of Rally settings state.

  RoadState = false;

  //----------------------------------------------------------------
  // check if the "Truck" button has been pressed
  // if yes, then set then run "true" setup as below.
  Truck_prev = Truck_current; 
  Truck_current = digitalRead(TruckButton);

  if (Truck_prev == LOW && Truck_current == HIGH) 
  {
    //changeTruckButtonState();
    TruckState = !TruckState;
  }

  if (TruckState == true)
  {
    Setting = 2;
  }

  //<<<<<<<<<<<<<<<<<< Should the next line be with the previous if? >>>>>>>>>>>>>>
  // Stepper Motor Settings for Rally State.
  val = map (val, 0, 1023, 300, 800);

  if ((val - frame) != 0) 
  {

    if ((val - frame) > 150) 
    { // Deadzone
      stepper.step(10); // move a step toward the pot reading.
      frame++;
    }
    else if ((val - frame) < -150) 
    { // Deadzone
      stepper.step(-10); // move a step toward the pot reading.
      frame--;
    }
  }// End of Rally settings state.

  TruckState = false;

  // ensures that Processing can read the values before the next values arrive
}//END of loop()

//---------------------------------------------------------

//void changeRallyButtonState() // Rally button state logic
//{
//  if (RallyState == true) {
//    RallyState = false;
//  }
//  else {
//    RallyState = true;
//  }
//}
//void changeRoadButtonState() // Road button state logic
//{
//  if (RoadState == true) {
//    RoadState = false;
//  }
//  else {
//    RoadState = true;
//  }
//}
//void changeTruckButtonState() // Truck button state logic
//{
//  if (TruckState == true) {
//    TruckState = false;
//  }
//  else {
//    TruckState = true;
//  }
//}

Here is a bit of code to handle 2 switches .
You can easily add more switches as needed.
You may want to incorproate it into your sketch:

/*SwitchManager skeleton 
 LarryD
 
 This is sketch is to introduce new people to the SwitchManager library written by Nick Gammon
 
 The library handles switch de-bouncing and provides timing and state change information in your sketch.
 The SwitchManager.h file should be placed in your libraries folder, i.e.
 C:\Users\YouName\Documents\Arduino\libraries\SwitchManager\SwitchManager.h
 You can download the library at:
 http://gammon.com.au/Arduino/SwitchManager.zip    Thank you Nick!
 
 In this example we have 2 normally open (N.O.) switches connected to the Arduino - increment and decrement.
 The increment switch will also be used as a "Reset" switch if pressed for more than two seconds.
 The two switches are connected between GND (0 volts) and an Arduino input pin.
 The library enables pull-up resistors for your switch inputs.
 Pushing a switch makes its pin LOW. Releasing a switch makes its pin HIGH.
 
 The SwitchManager library provides 10ms de-bounce for switches. 
 i.e. enum { debounceTime = 10, noSwitch = -1 };
 If you need more time, edit the SwitchManager.h file
 i.e. enum { debounceTime = 50, noSwitch = -1 }; //here it is changed to 50ms
 */

#include <SwitchManager.h>             
//object instantiations
SwitchManager myIncSwitch;
SwitchManager myDecSwitch;

unsigned long currentMillis;
unsigned long heartBeatMillis;
unsigned long heartFlashRate  = 500UL; // time the led will change state       
unsigned long incShortPress   = 500UL; // 1/2 second
unsigned long incLongPress    = 2000UL;// 2 seconds 
unsigned long decShortPress   = 500UL; // 1/2 second

const byte heartBeatLED       = 13;
const byte incSwitch          = 4; //increment switch is on Arduino pin 4
const byte decSwitch          = 5; //decrement switch is on Arduino pin 5

int myCounter;

//======================================================================

void setup()
{
  Serial.begin(9600);

  //gives a visual indication if the sketch is blocking
  pinMode(heartBeatLED, OUTPUT);  

  myIncSwitch.begin (incSwitch, handleSwitchPresses); 
  myDecSwitch.begin (decSwitch, handleSwitchPresses);
  //the handleSwitchPresses() function is called when a switch changes state

} //                   E N D  O F  s e t u p ( )

//======================================================================

void loop()
{
  //leave this line of code at the top of loop()
  currentMillis = millis();

  //***************************
  //some code to see if the sketch is blocking
  if (CheckTime(heartBeatMillis, heartFlashRate, true))
  {
    //toggle the heartBeatLED
    digitalWrite(heartBeatLED,!digitalRead(heartBeatLED));
  }

  //***************************
  //check to see what's happening with the switches
  //"Do not use delay()s" in your sketch as it will make switch changes unresponsive 
  //Use BlinkWithoutDelay (BWD) techniques instead.
  myIncSwitch.check ();  
  myDecSwitch.check (); 

  //***************************
  //put other non-blocking stuff here


} //                      E N D  O F  l o o p ( )


//======================================================================
//                          F U N C T I O N S
//======================================================================


//                        C h e c k T i m e ( ) 
//**********************************************************************
//Delay time expired function
//parameters:
//lastMillis = time we started
//wait = delay in ms
//restart = do we start again  

boolean CheckTime(unsigned long  & lastMillis, unsigned long wait, boolean restart) 
{
  //has time expired for this task?
  if (currentMillis - lastMillis >= wait) 
  {
    //should this start again? 
    if(restart)
    {
      //yes, get ready for the next iteration
      lastMillis += wait;  
    }
    return true;
  }
  return false;

} //                 E N D   o f   C h e c k T i m e ( )


//                h a n d l e S w i t c h P r e s s e s( )
//**********************************************************************

void handleSwitchPresses(const byte newState, const unsigned long interval, const byte whichPin)
{
  //  You get here "ONLY" if there has been a change in a switches state.

  //When a switch has changed state, SwitchManager passes this function 3 arguments:
  //"newState" this will be HIGH or LOW. This is the state the switch is in now.
  //"interval" the number of milliseconds the switch stayed in the previous state
  //"whichPin" is the switch pin that we are examining  

  switch (whichPin)
  {
    //***************************
    //are we dealing with this switch?
  case incSwitch: 

    //has this switch gone from LOW to HIGH (gone from pressed to not pressed)
    //this happens with normally open switches wired as mentioned at the top of this sketch
    if (newState == HIGH)
    {
      //The incSwitch was just released
      //was this a short press followed by a switch release
      if(interval <= incShortPress) 
      {
        Serial.print("My counter value is = ");
        myCounter++;
        if(myCounter > 1000)
        {
          //limit the counter to a maximum of 1000
          myCounter = 1000; 
        }
        Serial.println(myCounter);
      }

      //was this a long press followed by a switch release
      else if(interval >= incLongPress) 
        //we could also have an upper limit
        //if incLongMillis was 2000UL; we could then have a window between 2-3 seconds
        //else if(interval >= incLongMillis && interval <= incLongMillis + 1000UL) 
      {
        //this could be used to change states in a StateMachine
        //in this example however, we will just reset myCounter
        myCounter = 0;
        Serial.print("My counter value is = ");
        Serial.println(myCounter);
      }

    }

    //if the switch is a normally closed (N.C.) and opens on a press this section would be used
    //the switch must have gone from HIGH to LOW 
    else 
    {
      Serial.println("The incSwitch was just pushed");
    } 

    break; //End of case incSwitch

    //*************************** 
    //are we dealing with this switch?
  case decSwitch: 

    //has this switch gone from LOW to HIGH (gone from pressed to not pressed)
    //this happens with normally open switches wired as mentioned at the top of this sketch
    if (newState == HIGH)
    {
      //The decSwitch was just released
      //was this a short press followed by a switch release
      if(interval <= decShortPress) 
      {
        Serial.print("My counter value is = ");
        myCounter--;
        if(myCounter < 0) 
        {
          //don't go below zero
          myCounter = 0;
        }
        Serial.println(myCounter);
      }

    }

    //if the switch is a normally closed (N.C.) and opens on a press this section would be used
    //the switch must have gone from HIGH to LOW
    else 
    {
      Serial.println("The decSwitch switch was just pushed");
    } 

    break; //End of case decSwitch

    //*************************** 
    //Put default stuff here
    //default:
    //break; //END of default

  } //End switch (whichPin)

} //      E n d   o f   h a n d l e S w i t c h P r e s s e s ( )


//======================================================================
//                      E N D  O F  C O D E
//======================================================================

Thanks LarryD,

Will try it out and see what happens :slight_smile:

Thanks also for the switch sketch, I will learn alot just going through each one and looking up what and how it works.

Cheers

J

This is a good case for using structs. Structs allow you to bundle together a number of variables into a set that you can use as a group.

There's no need to worry about debounce if you have three separate buttons - you don't need to count the clicks.

Also, I'll use a reference rather than having an array and an index.

struct Settings {
  const char *name;
  int high;
  int low;
};

struct Settings rally = {"Rally", 23, 45};
struct Settings road = {"Road", 19, 58};
struct Settings truck = {"Truck/Camper", 7, 54};

struct Settings &setting = rally;

void loop() {
  if(digitalRead(rallyPin)==LOW) setting = rally;
  if(digitalRead(roadPin)==LOW) setting = road;
  if(digitalRead(truckPin)==LOW) setting = truck;

  Serial.print(setting.name);
  Serial.print(" - high: ");
  Serial.print(setting.high);
  Serial.print("; low: ");
  Serial.print(setting.low);
  Serial.println();
}

First thing I spotted:

val = map (val, 0, 1023, 0, 1023);

Really?

Jason187781:
What if I were to add it like this? is this the correct road to go down?

It is certainly not!

First of all, now the loop is only run when you keep pressing the button. I thought you wanted to switch between settings and after that let it run?

Second, setting a variable setting to something is pretty useless if you never use it isn’t it?

And third, do you see repetition in your code?

Also I spotted something. You do frame++ and frame–. But that’s useless… First of all because you made frame a variable inside loop so it gets destroyed and initialized every time the loop runs. So it saves nothing. And you read a sensor into it every single loop. So you can remove it…

But yeah, code. I what thinking something like:

// 2 Pots, 3 Buttons, Stepper motor rotation control jason187781.

#include <Stepper.h>

#define STEPS 400

//For all the motor settings
typedef struct StepperSetting{
  unsigned int min;
  unsigned int max;
  unsigned int deadzone;
  byte stepSize;
};

//For easy acces to the modes, can just call them mRally, mRoad and mTruck now
enum modes_t{mRally, mRoad, mTruck};

//Setting for the stepper as min, max, deadzone, stepSize
const StepperSetting Modes[] = {{0, 1023, 400, 1},    //Rally
                          {150, 850, 100, 1},   //Road
                          {300, 800, 150, 10}}; //Truck


Stepper stepper(STEPS, 8, 9, 10, 11);

//Sensors
const byte WheelPin = A0;
const byte FramePin = A1;

//buttons
const byte RallyButton = 7;   // Setting Button on button 0
const byte RoadButton = 6;    // Setting Button on button 1
const byte TruckButton = 5;   // Setting Button on button 2

modes_t mode = mRally;    


void setup(){
  pinMode(RallyButton, INPUT_PULLUP);   // set up button 0 as input
  pinMode(RoadButton, INPUT_PULLUP);    // set up button 1 as input
  pinMode(TruckButton, INPUT_PULLUP);   // set up button 2 as input

  // set the speed of the motor to 50 RPMs
  stepper.setSpeed(150);
}
void loop(){
  updateMode();
  

  unsigned int wheel = analogRead(WheelPin); // Wheel Postion Read
  unsigned int frame = analogRead(FramePin); // Frame Position Read
  
  updateStepper(wheel, frame);

  // Output the values to the serial port
  Serial.print(wheel, DEC);
  Serial.print(",");
  Serial.print(frame, DEC);
  Serial.print(",");
  Serial.print(mode, DEC);
  Serial.println();
  
}

void updateMode(){
  if(!digitalRead(RallyButton)){
    mode = mRally;
  }
  else if(!digitalRead(RoadButton)){
    mode = mRoad;
  }
  else if(!digitalRead(TruckButton)){
    mode = mTruck;
  }
}

void updateStepper(unsigned int wheel, unsigned int frame){
  wheel = map (wheel, 0, 1023, Modes[mode].min, Modes[mode].max);
  if ((wheel - frame) != 0) {
    if ((wheel - frame) > Modes[mode].deadzone) { // Deadzone
      stepper.step(Modes[mode].stepSize); // move a step toward the pot reading.
      //frame++; //doesnt do a thing
    }
    if ((wheel - frame) < -Modes[mode].deadzone) { // Deadzone
      stepper.step(-Modes[mode].stepSize); // move a step toward the pot reading.
      //frame--;
    }
  }
}

It’s untested but do you get the idea now?

And I changed pinMode to INPUT_PULLUP to make it easy aka don’t need external resistors.

And yeah, didn’t debouce. But it’s okay to set a mode multiple times because of debounce. So you don’t really need the state change part.

[edit] The reference option is very need as well instead of the array + enum I used :slight_smile: Like it even better! But yeah, struct is a cool thing

Thanks for the info and tips guys,

I appreciate the sketch is messy, I’m making noob errors and then fixing them one by one at the moment. I just muck about with values to see what happens and then figure out why. It may be backwards but it seems to stick in my head better with trial and error faffing.

I put septillion’s code into the Arduino and reading thru it can see what your getting at.

It’s a much cleaner call for values within the Stepper motor loop so that’s perfect. I feel I can add more variables to this myself now and increase the reference. Possibly add a few Led’s to show what button is active etc?

However I know you mentioned it’s untested so I tested it this morning before work. I only had 5-10mins so havn’t really taken a detailed look but it’s not behaving as I suspect it should.

The motor turns but none of the seperate values appear to be doing anything? It is reading a difference between each pot value because when i rotate potA past potB it changes direction. But there is no Deadzone or any other selections kicking in upon button presses? so the motor just keeps going, stuttering briefly as the pot values match?

There’s a weird result when one of the pot’s is rotated far from the other. The stepper motor appears to speed up, not gradually but in around 3 speed settings? I guess this is something in the stepper library i’m not familiar with?

Also, when I add the serial read line to check out the pot values and buttons, nothing comes up and the stepper motor appears to stutter like mad?

I’m sure it’s a quick fix.

Will take a look later myself with a view to fully understanding the logic and let you know if I get anywhere.

Thanks again.

J

Indeed east fix. Change the struct to

//For all the motor settings
typedef struct StepperSetting{
  int min;
  int max;
  int deadzone;
  byte stepSize;
};

Why it goes wrong is a bit harder. made deadzone a unsigned int (because I don’t think you want a negative deadzone…) but you kind of do when you use it as -Mode[mode].deadzone for the negative side. And the compiler treats deadzone still as a unsigned type so making it negative is not possible resulting is a wrap around. Declaring it as a int fixes this but now you have to keep in mind to not assign a negative number to deadzone because that will flip everything. Your code assumes a positive value for deadzone all the time.

Another way to fix to problem would have been to cast the unsigned int to a signed int:

if ((wheel - frame) < -(int)Modes[mode].deadzone) { // Deadzone

But I think that’s easier to forget then making the variable signed.

Hope it works now :slight_smile:

Adding a mode LED is pretty simple

const byte ModeLedPins[] = {2, 3, 4};

//as part of the setup make them output_iterator
void setup(){
  for(byte i = 0; i < sizeof(ModeLedPins); i++){
    pinMode(ModeLedPins[i], OUTPUT);
  }
}

//function to call from loop
void updateModeLeds(){
  //Run over all the leds
  for(byte i = 0; i < sizeof(ModeLedPins); i++){
    //i == mode is only true (high) when i is the selected mode 
    //thus turns on that led, false/low otherwise to turn off the rest
    digitalWrite(ModeLedPins[i], i == mode);
  }
}
[code]

Hi all,

Tried a few combinations of the updated code examples and it's still doesn't appear to be registering button presses to change settings and the Motor movement doesn't seem to be manipulated by any of the variables?

I spent most of yesterday night going thru the sketch to see if I could figure out what was going wrong but don't seem to be able to spot it? I didn't want to jump back on here with my bad news. I can see how the structure works and it looks like it should work perfectly. I did spot a potential issue with there being no negative symbol before Modes on the stepper moter second part but that didn't help when trying it that way? The only thing I am unsure of is if the button type or layout is what you expect it is with regards to Pull up ect? I have attached the wiring diagram to the first post to see if this makes any difference.

Look forward to any further advice regarding this setup. I'm just annoyed with myself that I can't see it or have picked up what !

I was also thinking about cycling between each motor setting with one button and sybolising this with an array of led's. Perhaps it may be easier and less hardware and logic hungry to have this as a second option. This way I'm not limited by the ammount of settings I can add if I need more than 3 further down the line?

Cheers :slight_smile:

First of all, did you read (and understand) what I wrote about the switch? That is should be connected between the pin and GND?

[Reading further]

Jason187781:
I have attached the wiring diagram to the first post to see if this makes any difference.

Never edit your starting post this far in the discussion. Just add info like that to the reply :wink: Keeps everything clear.

But back to the question, ahh. I see you didn’t understand my comment about the switch :wink: Just rewire them as I said. That way you can leave out the 3 (pull down) resistors :wink: Less components = less to solder = less to buy = simpler :slight_smile:

Jason187781:
I was also thinking about cycling between each motor setting with one button and sybolising this with an array of led’s. Perhaps it may be easier and less hardware and logic hungry to have this as a second option. This way I’m not limited by the ammount of settings I can add if I need more than 3 further down the line?

Only small changes to the code needed. Biggest difference, then you have to worry about debounce and state change :wink: But instead of each button that assigned a set value to mode you just increment mode each time the button becomes pushed (state change). And of course set it back to 0 when you’re out of modes. Can help you with that but first fix this problem :wink:

[/quote]

Jason187781:
I did spot a potential issue with there being no negative symbol before Modes on the stepper moter second part

I don’t see it, can you help me? Line number or something?

And the code I used to debug it:

// 2 Pots, 3 Buttons, Stepper motor rotation control jason187781.

#include <Stepper.h>

#define STEPS 400

//For all the motor settings
typedef struct StepperSetting{
  int min;
  int max;
  int deadzone;
  byte stepSize;
};

//For easy acces to the modes, can just call them mRally, mRoad and mTruck now
enum modes_t{mRally, mRoad, mTruck};

//Setting for the stepper as min, max, deadzone, stepSize
const StepperSetting Modes[] = {{0, 1023, 400, 1},    //Rally
                          {150, 850, 100, 1},   //Road
                          {300, 800, 150, 10}}; //Truck


Stepper stepper(STEPS, 8, 9, 10, 11);

//Sensors
const byte WheelPin = A0;
const byte FramePin = A1;

//buttons
const byte RallyButton = 7;   // Setting Button on button 0
const byte RoadButton = 6;    // Setting Button on button 1
const byte TruckButton = 5;   // Setting Button on button 2

modes_t mode = mRally;   


void setup(){
  pinMode(RallyButton, INPUT_PULLUP);   // set up button 0 as input
  pinMode(RoadButton, INPUT_PULLUP);    // set up button 1 as input
  pinMode(TruckButton, INPUT_PULLUP);   // set up button 2 as input

  // set the speed of the motor to 50 RPMs
  stepper.setSpeed(150);
  Serial.begin(115200);
}
void loop(){
  updateMode();
 

  unsigned int wheel = analogRead(WheelPin); // Wheel Postion Read
  unsigned int frame = analogRead(FramePin); // Frame Position Read
 
  updateStepper(wheel, frame);

  // Output the values to the serial port
  Serial.print(wheel, DEC);
  Serial.print(",");
  Serial.print(frame, DEC);
  Serial.print(",");
  Serial.print(mode, DEC);
  Serial.println();
  delay(1000);
 
}

void updateMode(){
  if(!digitalRead(RallyButton)){
    mode = mRally;
  }
  else if(!digitalRead(RoadButton)){
    mode = mRoad;
  }
  else if(!digitalRead(TruckButton)){
    mode = mTruck;
  }
}


void updateStepper(unsigned int wheel, unsigned int frame){
  debugModes();
  
  wheel = map (wheel, 0, 1023, Modes[mode].min, Modes[mode].max);
  if ((wheel - frame) != 0) {
    if ((wheel - frame) > Modes[mode].deadzone) { // Deadzone
      stepper.step(Modes[mode].stepSize); // move a step toward the pot reading.
      //frame++; //doesnt do a thing
    }
    if ((wheel - frame) < -Modes[mode].deadzone) { // Deadzone
      stepper.step(-Modes[mode].stepSize); // move a step toward the pot reading.
      //frame--;
    }
  }
}

void debugModes(){
  Serial.print("mode ");
  Serial.println(mode);
  Serial.print("min ");
  Serial.println(Modes[mode].min);
  Serial.print("max ");
  Serial.println(Modes[mode].max);
  Serial.print("deadzone ");
  Serial.print(Modes[mode].deadzone);
  Serial.print(" ");
  Serial.println(-Modes[mode].deadzone);
  Serial.print("stepsize ");
  Serial.print(Modes[mode].stepSize);
  Serial.print(" ");
  Serial.println(-Modes[mode].stepSize);
}

Note: Because I used a very rude delay() to limit the serial to the serial monitor you have to press a button for more then 1 second. But this is fully due to the delay() and there should not be a delay() in the final program.