Why are while loops working on R3 but not on R4

The below program runs as I would expect on a Uno R3 but not on the R4 The issue I am having is the when homing() is called the first while loop starts and waits for the switch to go HIGH on pin A0. When it goes HIGH it is supposed to wait until it goes LOW before moving on to the next while loop. Instead when the limit switch connected to A0 goes HIGH it moves onto the next while loop within homing(). This while loop does exactly the same and waits until A1 goes HIGH then instead of waiting until A1 goes LOW calls running().

The same program on the R3 works how I would expect.

#include <Wire.h>
#include <DS3232RTC.h>
#include <SolarPosition.h>


DS3232RTC myRTC;

#define MOTOR_ON LOW
#define MOTOR_OFF HIGH

const uint8_t digits = 3;

SolarPosition Home(15.898551, 101.539774);  // Thailand
//SolarPosition Home(52.898551, -2.539774);  // Home//RTC CODE


const int azEncoder_a = 2;  // Green - pin 2 - Digital
const int azEncoder_b = 4;  // White - pin 4 - Digital
long azEncoder = 0;

const int elEncoder_a = 3;  // Green - pin 3 - Digital
const int elEncoder_b = 5;  // White - pin 5 - Digital
long elEncoder = 0;


const int azLimitSwitchPin = A0;  // DEFINE PIN TO USE FOR AZIMUTH LIMIT SWITCH
const int elLimitSwitchPin = A1;  // DEFINE PIN TO USE FOR AZIMUTH LIMIT SWITCH
const int azMotorPinPositive = 12;
const int azMotorPinNegative = 11;
const int elMotorPinPositive = 10;
const int elMotorPinNegative = 9;

bool nightime;
bool daytime;
bool trackerAzimuthRunning = false;
bool trackerElevationRunning = false;
bool sunRising = false;

int azLimitSwitch;  // VARIABLE TO HOLD THE ABOVE VALUE
int elLimitSwitch;

int hours;
int minutes;
int seconds;
int trackerAzimuthAngle;
int trackerElevationAngle;
int start = 0;
int azimuthSun_position;
float sunElevation;
float newPosition;
float oldPosition;



void setup() {
  Serial.begin(9600);
  Wire.begin();
  pinMode(azEncoder_a, INPUT_PULLUP);
  pinMode(azEncoder_b, INPUT_PULLUP);

  pinMode(elEncoder_a, INPUT_PULLUP);
  pinMode(elEncoder_b, INPUT_PULLUP);

  attachInterrupt(digitalPinToInterrupt(2), azEncoderPinChangeA, RISING);
  attachInterrupt(digitalPinToInterrupt(3), elEncoderPinChangeB, RISING);

  pinMode(azLimitSwitchPin, INPUT);  // LIMIT SWITCH
  pinMode(elLimitSwitchPin, INPUT);  // LIMIT SWITCH


  pinMode(azMotorPinPositive, OUTPUT);
  pinMode(azMotorPinNegative, OUTPUT);
  pinMode(elMotorPinPositive, OUTPUT);
  pinMode(elMotorPinNegative, OUTPUT);

  SolarPosition::setTimeProvider(myRTC.get);
}

void loop() {

  rtcCode();

  trackerAzimuthAngle = azEncoder / 1.67;    //This change to degrees
  trackerElevationAngle = elEncoder / 1.67;  // 6This changes to degrees
  azLimitSwitch = digitalRead(azLimitSwitchPin);
  elLimitSwitch = digitalRead(elLimitSwitchPin);

  if (newPosition > oldPosition) {
    Serial.print("THE SUN IS GOING UP");
    Serial.print('\n');
    sunRising = true;
  }

  else if (newPosition < oldPosition) {
    Serial.print("THE SUN IS GOING DOWN");
    Serial.print('\n');
    sunRising = false;
  }
  oldPosition = newPosition;
  newPosition = sunElevation;


  Serial.print("AZIMUTH LIMIT SWITCH STATUS =.....");  //0 = Closed
  Serial.print(azLimitSwitch);
  Serial.print('\n');
  Serial.print("ELEVATION LIMIT SWITCH STATUS =.....");  // 0 = Closed
  Serial.print(elLimitSwitch);
  Serial.print('\n');

  if (start < 1) {
    homing();  // This statement checks to see if the programs has just started.
  }

  Serial.print("TRACKER AZIMUTH ANGLE IS   ");
  Serial.print(trackerAzimuthAngle);
  Serial.print('\n');

  Serial.print("TRACKER ELEVATION ANGLE IS   ");
  Serial.print(trackerElevationAngle);
  Serial.print('\n');

  //ADJUST THESE TIMES FOR TESTING
  if (hours >= 6 && hours <= 21 && minutes <= 59 && seconds <= 59) {
    daytime = true;
    nightime = false;
  } else {
    nightime = true;
    daytime = false;
  }
  Serial.print("DAYTIME  ");
  Serial.print(daytime);
  Serial.print('\n');
  Serial.print("NIGHTIME  ");
  Serial.print(nightime);
  Serial.print('\n');


  // CHANGE THE BELOW FOR TESTING
  if (daytime == true) {
    azimuthRunning();
  } else {
    Serial.print("PAUSED NOT MOVING UNTIL 6AM");
    Serial.print('\n');
    Serial.print('\n');

    digitalWrite(azMotorPinPositive, HIGH);
  }
  // CHECK TO SEE IF ITS TIME TO HOME POSITIONE
  if (hours == 17 && minutes == 47 && seconds == 0) {
    homing();
  }
}
void homing() {
  digitalWrite(azMotorPinNegative, MOTOR_OFF);
  digitalWrite(azMotorPinPositive, MOTOR_OFF);
  digitalWrite(elMotorPinNegative, MOTOR_OFF);
  digitalWrite(elMotorPinPositive, MOTOR_OFF);

  //HOMING AZIMUTH

  while (digitalRead(azLimitSwitchPin) == LOW) {
    Serial.print("HOMING AZIMUTH");
    Serial.print('\n');
    digitalWrite(azMotorPinNegative, MOTOR_ON);
  }
  digitalWrite(azMotorPinNegative, MOTOR_OFF);

  while (digitalRead(azLimitSwitchPin) == HIGH) {
    Serial.print("BACKING OFF AZIMUTH");  //Change this to move motor
    Serial.print('\n');
    digitalWrite(azMotorPinPositive, MOTOR_ON);
  }
  azEncoder = 0;  // Sets the encoder back to 0 once homed
  digitalWrite(azMotorPinPositive, MOTOR_OFF);

  //HOMING ELEVATION

  while (digitalRead(elLimitSwitchPin) == LOW) {
    Serial.print("HOMING ELEVATION");
    Serial.print('\n');
    digitalWrite(elMotorPinNegative, MOTOR_ON);
  }
  digitalWrite(elMotorPinNegative, MOTOR_OFF);

  while (digitalRead(elLimitSwitchPin) == HIGH) {
    Serial.print("BACKING OFF ELEVATION");  //Change this to move motor
    Serial.print('\n');
    digitalWrite(elMotorPinPositive, MOTOR_ON);
  }
  elEncoder = 0;  // Sets the encoder back to 0 once homed
  digitalWrite(elMotorPinPositive, MOTOR_OFF);
  start++;
}

void azimuthRunning() {

  if (azimuthSun_position > trackerAzimuthAngle && daytime == true && trackerElevationRunning == false) {
    trackerAzimuthRunning = true;
    digitalWrite(azMotorPinPositive, MOTOR_ON);
    Serial.print("AZ RUNNING ");

  } else {
    trackerAzimuthRunning = false;
    digitalWrite(azMotorPinPositive, MOTOR_OFF);
    Serial.print("AZ Waiting ");
    Serial.print('\n');
  }
  if (trackerAzimuthRunning == false) {
    elevationRunning();  //Elevation Running only gets called if azimuth is not running
  }
  Serial.print('\n');
  Serial.print('\n');
  Serial.print('\n');
}

void elevationRunning() {

  if (sunRising == true) {
    elevationUp();
  } else if (sunRising == false) {
    elevationDown();
  }
}

void elevationUp() {
  if (sunElevation > trackerElevationAngle && daytime == true) {
    trackerElevationRunning = true;
    digitalWrite(elMotorPinPositive, MOTOR_ON);
    Serial.print("EL RUNNING GOING UP ");
  }

  else {
    trackerElevationRunning = false;
    digitalWrite(elMotorPinPositive, MOTOR_OFF);
    Serial.print("EL WAITING");
  }
  Serial.print('\n');
}

void elevationDown() {
  if (sunElevation < trackerElevationAngle && daytime == true) {
    trackerElevationRunning = true;
    digitalWrite(elMotorPinNegative, MOTOR_ON);
    Serial.print("EL RUNNING GOING DOWN ");
  }

  else {
    trackerElevationRunning = false;
    digitalWrite(elMotorPinNegative, MOTOR_OFF);
    Serial.print("EL GOING DOWN WAITING");
  }
  Serial.print('\n');
}

void rtcCode() {
  printTime(myRTC.get());
  Serial.print(F("Home:\t"));
  printSolarPosition(Home.getSolarPosition(), digits);
}

void azEncoderPinChangeA() {
  azEncoder += digitalRead(azEncoder_a) == digitalRead(azEncoder_b) ? -1 : 1;
}
void elEncoderPinChangeB() {
  elEncoder += digitalRead(elEncoder_a) == digitalRead(elEncoder_b) ? 1 : -1;
}

void printSolarPosition(SolarPosition_t pos, int numDigits) {
  Serial.print(F("el: "));
  Serial.print(pos.elevation, numDigits);
  Serial.print(F(" deg\t"));

  Serial.print(F("az: "));
  Serial.print(pos.azimuth, numDigits);
  Serial.println(F(" deg"));
  azimuthSun_position = (pos.azimuth);
  sunElevation = (pos.elevation);
}

void printTime(time_t t) {
  tmElements_t someTime;
  breakTime(t, someTime);

  Serial.print(someTime.Hour);
  Serial.print(F(":"));
  Serial.print(someTime.Minute);
  Serial.print(F(":"));
  Serial.print(someTime.Second);
  Serial.print(F(" UTC on "));
  Serial.print(dayStr(someTime.Wday));
  Serial.print(F(", "));
  Serial.print(monthStr(someTime.Month));
  Serial.print(F(" "));
  Serial.print(someTime.Day);
  Serial.print(F(", "));
  Serial.println(tmYearToCalendar(someTime.Year));

  hours = someTime.Hour;
  minutes = someTime.Minute;
  seconds = someTime.Second;
}


Welcome to the forum

What is keeping the limit switch pins in a known state when not activated ?

Are you suggesting setting the azLimitSwitch and elLimitSwitch pins to LOW before the program starts running?

Please post a wiring diagram showing how the switch pins are wired. Hand drawn is fine.

The switch pins cannot be left floating:

  pinMode(azLimitSwitchPin, INPUT);  // LIMIT SWITCH
  pinMode(elLimitSwitchPin, INPUT);  // LIMIT SWITCH
1 Like

[quote="mickh1, post:1, topic:1356220"]
Are they floating with this at the beginning of void loop?
azLimitSwitch = digitalRead(azLimitSwitchPin);

Read here for a possible answer of different behavior between R3 and R4.

Ciao, Ale.

If you not use a hardware pulldown, your pin are floating and might be in HIGH state at the start of the program.

1 Like

Probably. A resistor pullup or pulldown is required. This is Arduino 101.

2 Likes

The both limit switches have 10k pull up resistors wired like this

Like what?

Why have you not posted a wiring diagram?

1 Like

Sorry cant see how to post an image

Capture

See the "How to get the best out of this forum" post, for posting instructions.

1 Like

Or just paste the image into a reply

The switches are normally closed not as drawn

That should work. Use your multimeter to verify that the pin is HIGH when the switch is opened.

There is 3.3v at the pins A0 and A1
when open.

The pin voltage should be 5V when the switch is open, and 0V when it is closed.

Check that the resistor is actually connected to 5V.

The switches are connected to the 3.3v side of the R4 board.

Why?

Question for the class: what is the numerical value of AVCC0 x 0.8 when AVCC0 is 5V?

Is that value greater than, or less than 3.3V?