Arduino uno not reading switch states

Basically, I have a BLDC motor and ESC controlled by the Arduino uno. I'm using a 3 state switch to control Forward/neutral/reverse. I connected the switch common connection to 5v and the other sides to pins 11 and 12. However, when I run my code, it just constantly loops my first for loop and my switch has no effect. I also have a hall sensor I'm trying to use to stop it so that's why the attachInterrupt is there, but I do not know if that is going to work yet because of the previous problem.

#include <Servo.h>
Servo ESC; // create servo object to control the ESC

boolean CTRL = false;
boolean StateA=false;
boolean StateB=false;
boolean STOP=false;
byte Pos=90;
byte FMax = 180;
byte RMax = 0;
int pos = 0;    // variable to store the servo position
void setup() {
  Serial.begin(57600);
  attachInterrupt(0, magnet_detect, RISING);   //Initialize hall sensor to interrupt pin (digital pin 2)
  
  // Attach the ESC on pin 9
  ESC.attach(9,1000,2000); // (pin, min pulse width, max pulse width in microseconds)
}

void loop() {

StateA=digitalRead(11);
StateB=digitalRead(12);

 if (StateA && !CTRL && !STOP){
    for (pos = 90; pos <= 110; pos += 1) { // goes from 90 degrees to 180 degrees
        ESC.write(pos);              // tell motor speed in variable 'pos'
        delay(200);                  // waits 200ms for the servo to reach the position
       }
  CTRL=!CTRL;
     }
 
 if (StateB && CTRL && !STOP){
     for (pos = 90; pos <= 60; pos -= 1) { // goes from 90 degrees to 0 degrees
        ESC.write(pos);              // tell motor speed in variable 'pos'
        delay(200);                  // waits 200ms for the servo to reach the position
  }
  CTRL=!CTRL;
 }
  if (StateA && CTRL && !STOP){
     ESC.write(FMax);
  }
   if (StateB && !CTRL){
      ESC.write(RMax);
  }
   if(!StateA && !StateB) {
      ESC.write(90);
      STOP = false;
   }
   if (STOP) {
      ESC.write(90);
   }
   
}
void InterruptSR() {
  STOP = !STOP;
}
void magnet_detect()   //Function to stop motor once hall sensor detects a magnet
  {
    pos <= 90;
    ESC.write(pos);
  }

Show us a good schematic of your proposed circuit.
Show us a good image of your ‘actual’ wiring.
Give links to components.


I recommend INPUT_PULLUP and connect the switch terminals to GND. Unless you have pulldown resistors the way you have it wired the inputs will float with NC.

A few observations:

  1. When I am beginning a project I write a simple sketch to test each piece of hardware. In this case write 3 sketches: one for the switch, one for the hall effect sensor, and one for the servo. That way when you test your final code you can be sure the hardware and wiring are NOT the problem if it doesn't work.
  2. You do not need an interrupt for the hall effect sensor. I would just recommend reading the sensor at the beginning of loop().
  3. 200ms for the servo to move 1 degree is excessive. 20 degrees of movement will take 4 seconds. 30 degrees will take 6 seconds the way you have it coded. If you really need it move that slow that is fine; however, your program will be completely stalled during these movements, which may or may not be a problem.

I took out the Hall sensor stuff, and tried with just the acceleration code and switches. I added a pull down resistor as well and I get no response at all. Also I know the acceleration code works just fine, I have tested this many times.

#include <Servo.h>

Servo ESC;                                  // create servo object to control the ESC

int pos = 90;                               // variable to store the servo position

int stateA = digitalRead(11);               // variables for reading the switches status 
int stateB = digitalRead(12);

void setup() {
  Serial.begin(57600);
  
  ESC.attach(9,1000,2000);                  // (attach to pin 9, min pulse width, max pulse width in microseconds)

if (stateA == LOW) {                       // if swith in forward postion run motor forward a set speed

     for (pos = 90; pos <= 110; pos += 1) { // goes from 0 degrees to 180 degrees
        ESC.write(pos);                     // tell motor speed in variable 'pos'
        delay(20);                         // waits 200ms for the servo to reach the position
   
  }

if (stateB == HIGH) {                     // if switch in rear position run motor backwards at set speed

    for (pos = 90; pos <= 60; pos -= 1) { // goes from 90 degrees to 0 degrees
      ESC.write(pos);                     // tell motor speed in variable 'pos'
      delay(200);                         // waits 200ms for the servo to reach the position


        }
}

else {                                   // motor off, mid position
   pos <= 90;
   ESC.write(pos);
     }
   
   }
}

void loop() 
{
 

Show us a good schematic of your proposed circuit.
Show us a good image of your ‘actual’ wiring.
Give links to components.


Your sketch has multiple errors

try this sketch for testing the switches separately from anything else

trying to be quick by combining too early too many things will turn out to slow you down because there are multiple things that are wrong.

trying this then trying that without knowing it slows you down too

For all future steps take the time to do separated tests and take time to learn the basics.

This will speed up finishing your project

const byte stateA_pin = 11; // use constants for IO-pin NOT direct numbers
const byte stateB_pin = 12;

int stateA;               // variables for reading the switches status
int stateB;

unsigned long myTestTimer;

// helper-function for easy to use non-blocking timing
boolean TimePeriodIsOver (unsigned long &expireTime, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();
  if ( currentMillis - expireTime >= TimePeriod ) {
    expireTime = currentMillis; // set new expireTime
    return true;                // more time than TimePeriod) has elapsed since last time if-condition was true
  }
  else return false;            // not expired
}


void setup() {
  Serial.begin(115200); // start serial interface
  Serial.println( F("Setup-Start") );
  pinMode(stateA_pin, INPUT); 
  pinMode(stateB_pin, INPUT);
}

void loop() {
  // reading the switches status must be done INSIDE loop
  stateA = digitalRead(stateA_pin); 
  stateB = digitalRead(stateB_pin);
  
  if ( TimePeriodIsOver(myTestTimer,1000) ) {
    // if 1000 milliseconds = one second have passed by 
    Serial.print("digitalRead("); // print title and state of IO-pin to the serial monitor
    Serial.print(stateA_pin);
    Serial.print(")=stateA=");
    Serial.println(stateA);
    
    Serial.print("digitalRead(");
    Serial.print(stateB_pin);
    Serial.print(")=stateB=");
    Serial.println(stateB);
  }
}

Be the change you want to see in the world
best regards Stefan

I was able to get this to work first try, So it seems like my problem is with the if statements I made?

With the if statement formatted properly you can see how they are nested. Is this what you intended? Unless stateA==LOW you will never get to the if (stateB == HIGH). These ifs were NOT nested in your original code. This is why properly formatted and indented code is important.

if (stateA == LOW) {                       // if swith in forward postion run motor forward a set speed
  for (pos = 90; pos <= 110; pos += 1) { // goes from 0 degrees to 180 degrees
    ESC.write(pos);                     // tell motor speed in variable 'pos'
    delay(20);                         // waits 200ms for the servo to reach the position
  }
  if (stateB == HIGH) {                     // if switch in rear position run motor backwards at set speed
    for (pos = 90; pos <= 60; pos -= 1) { // goes from 90 degrees to 0 degrees
      ESC.write(pos);                     // tell motor speed in variable 'pos'
      delay(200);                         // waits 200ms for the servo to reach the position
    }
  }
  else {                                   // motor off, mid position
    pos <= 90;
    ESC.write(pos);
  }
}

That is not what I intended, It was supposed to work if stateA =/= LOW then it moves on to check stateB's condition.

So with this code, it is like you said, it will only go to next if statement when stateA == HIGH. How can I make it progress to the next if statement without needing the first if statement's condition to be met?

#include <Servo.h>

Servo ESC;                                  // create servo object to control the ESC

int pos = 90;                               // variable to store the servo position

const byte stateA_pin = 10; // use constants for IO-pin NOT direct numbers
const byte stateB_pin = 11;

int stateA;               // variables for reading the switches status
int stateB;

void setup() {
  pinMode(stateA_pin, INPUT); 
  pinMode(stateB_pin, INPUT);
  ESC.attach(9,1000,2000);                  // (attach to pin 9, min pulse width, max pulse width in microseconds)
}

void loop() 
{
  Serial.begin(115200);
  stateA = digitalRead(stateA_pin); 
  stateB = digitalRead(stateB_pin);

if (stateA == HIGH) {                       // if swith in forward postion run motor forward a set speed
  for (pos = 90; pos <= 110; pos += 1) { // goes from 0 degrees to 180 degrees
    Serial.print("digitalRead("); // print title and state of IO-pin to the serial monitor
    Serial.print(stateA_pin);
    Serial.print(")=stateA=");
    Serial.println(stateA);
    ESC.write(pos);                     // tell motor speed in variable 'pos'
    delay(20);                         // waits 200ms for the servo to reach the position
  }
  if (stateB == HIGH) {                     // if switch in rear position run motor backwards at set speed
      for (pos = 90; pos <= 110; pos += 1) { // goes from 90 degrees to 0 degrees
      Serial.print("digitalRead(");
      Serial.print(stateB_pin);
      Serial.print(")=stateB=");        Serial.println(stateB);
      ESC.write(pos);                    // tell motor speed in variable 'pos'
      delay(20);                         // waits 200ms for the servo to reach the position
      }
  }
  else {                                   // motor off, mid position
      pos <= 90;
      ESC.write(pos);
  }
}

}

Why is that in the loop function?

Why print the same state multiple times?

  if (stateA == HIGH) {                       // if swith in forward postion run motor forward a set speed
    for (pos = 90; pos <= 110; pos += 1) { // goes from 0 degrees to 180 degrees
      Serial.print("digitalRead("); // print title and state of IO-pin to the serial monitor
      Serial.print(stateA_pin);
      Serial.print(")=stateA=");
      Serial.println(stateA);
      ESC.write(pos);                     // tell motor speed in variable 'pos'
      delay(20);                         // waits 200ms for the servo to reach the position
    } // closing curly brace of for-loop

    // if-condition still INSIDE if-condition if (stateA == HIGH) {
    if (stateB == HIGH) {                     // if switch in rear position run motor backwards at set speed
      for (pos = 90; pos <= 110; pos += 1) { // goes from 90 degrees to 0 degrees
        Serial.print("digitalRead(");
        Serial.print(stateB_pin);
        Serial.print(")=stateB=");        Serial.println(stateB);
        ESC.write(pos);                    // tell motor speed in variable 'pos'
        delay(20);                         // waits 200ms for the servo to reach the position
      } // closing curly brace of for-loop
    } // closing curly brace of if (stateB == HIGH)

    
    // else still INSIDE if-condition if (stateA == HIGH) {
    else {                                   // motor off, mid position
      pos <= 90;
      ESC.write(pos);
    } // closing curly brace of else
  } // clsoing curly brace of if (stateA == HIGH) {

well this is one of the rare cases where I'm just asking back

After showing you that your second if-condition is

inside

your first if-condition

What do you think?

Be the change you want to see in the world
best regards Stefan

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.