Global declared variable reverting to declared value in loop

I have an int variable declared as global that is changed in the loop via a select case list. It only has 2 values, 1 and -1. When i change it to -1 due to a case, it reverts to 1 again before the loop is completed. Being global it 'should' retain its current value until changed again, but doesn't. The codec is long because I am using an LCD display, stepper motor, IR remote and receiver. The value of the rotationDir variable is used to preset the motor for CW or CCW rotation. Here's my tragedy...


//www.elegoo.com
//2016.12.12
// Include libraries
#include <LiquidCrystal.h>
#include "Stepper.h"
#include "IRremote.h"
#include <dht_nonblocking.h>
// Define types
#define STEPS  32   // Number of steps per revolution of Internal shaft
#define DHT_SENSOR_TYPE DHT_TYPE_11

/*----- Variables, Pins -----*/
const int receiver = 12; // Signal Pin of IR receiver to Arduino
static const int DHT_SENSOR_PIN = 14; //Signal pin of DHT sensor
const int stepsPerRev = 2048;
const int Position1 = 0;
const int Position2 = 100;
const int Position3 = 950;
const int Position4 = 1500;
const int Position5 = 1700;
const int Position6 = 2000;

int rotationDir = 1; //Start with anticlockwise rotation
int startPosition = 0;  //Keeps count of the absolute position of the turntable. Movement works with positionDelta from this count.
int newPosition = 0; // Radial position to advance to
int wasPosition = 0; // Radial position currently occupied. is copied from newPosition once the motor starts moving
int positionDelta = 0; // How far to move from current position to the next 
int setPosition; // Distance to home 

/*-----( Declare objects )-----*/
// Setup of proper sequencing for Motor Driver Pins
// In1, In2, In3, In4 in the sequence 1-3-2-4

Stepper small_stepper(STEPS, 2, 4, 3, 5);
IRrecv irrecv(receiver);    // create instance of 'irrecv'
decode_results results;     // create instance of 'decode_results'
DHT_nonblocking dht_sensor( DHT_SENSOR_PIN, DHT_SENSOR_TYPE ); // Call non-blocking type for Humdity & Temperature sensor 
LiquidCrystal lcd(6, 7, 8, 9, 10, 11); // initialize the library with the numbers of the lcd interface pins

void setup()
{
  irrecv.enableIRIn(); // Start the receiver
  Serial.begin(9600);
  Serial.println("Ready"); // Signal that the program is working 
  small_stepper.setSpeed(200); //Max is 500
  lcd.begin(16, 2);   // set up the LCD's number of columns and rows:
}

/*---- Take measurements every 4 seconds in the background ----*/
static bool measure_environment( float *temperature, float *humidity )
{
  static unsigned long measurement_timestamp = millis( );
  if ( millis( ) - measurement_timestamp > 9000ul )
  {
    if ( dht_sensor.measure( temperature, humidity ) == true )
    {
      measurement_timestamp = millis( );
      return ( true );
    }
  }

  return ( false );
}

void loop()
{
  float temperature;
  float humidity;
  if ( measure_environment( &temperature, &humidity ) == true )
  {
    lcd.setCursor(0, 0);
    lcd.print( "T=" );
    lcd.print( temperature, 1 );
    lcd.print( " C H=" );
    lcd.print( humidity, 0 );
    lcd.print( "%" );
    Serial.print( "T=" );
    Serial.print( temperature, 1 );
    Serial.print( "C H=");
    Serial.print( humidity, 1 );
    Serial.println( "%" );

  }
  if (irrecv.decode(&results)) // have we received an IR signal?
  {
    Serial.print("Input received "); Serial.println(results.value);
  switch(results.value)
    {
    case 0xFF629D: positionDelta = -stepsPerRev / 2; Serial.println("Go about clockwise"); break;   //VOL+
    case 0xFF22DD: positionDelta = 128 * rotationDir; Serial.println("Small correction"); break;    //Fast Back
    case 0xFFC23D: positionDelta = 64 * rotationDir; Serial.println("Smaller correction");          //Fast Forward
    case 0xFFE01F: rotationDir = -1; Serial.println("Preset clockwise rotation"); break;            //DOWN
    case 0xFFA857: positionDelta = stepsPerRev / 2; Serial.println("Go about anticlockwise"); break; //VOL-
    case 0xFF906F: rotationDir = 1; Serial.println("Preset anticlockwise rotation"); break;         //UP
    case 0xFFB04F: startPosition = 0; Serial.println("Reset start Position"); setPosition=0; break; //ST/RPT
    case 0xFF6897: newPosition = 0; Serial.println("Going home"); setPosition = 0; break;           // Return to start position  break;
    case 0xFF30CF: newPosition = Position1; Serial.println("Position 1"); setPosition = 1; break;
    case 0xFF18E7: newPosition = Position2; Serial.println("Position 2"); setPosition = 2; break;
    case 0xFF7A85: newPosition = Position3; Serial.println("Position 3"); setPosition = 3; break;
    case 0xFF10EF: newPosition = Position4; Serial.println("Position 4"); setPosition = 4; break;
    case 0xFF38C7: newPosition = Position5; Serial.println("Position 5"); setPosition = 5; break;
    case 0xFF5AA5: newPosition = Position6; Serial.println("Position 6"); setPosition = 6; break;
    case 0xFFFFFFFF: Serial.print(results.value); Serial.println(" REPEAT");break;  
  
    default: 
      Serial.println(" other button : ");
      Serial.println(results.value);
    }// End Case
    Serial.print("Rotation "); Serial.println(rotationDir);
    Serial.print("New position "); Serial.println(newPosition);
    Serial.print("Old position "); Serial.println(wasPosition);
    if (!positionDelta) positionDelta = newPosition - wasPosition;
    Serial.print("Position change "); Serial.println(positionDelta);
    startPosition = startPosition + positionDelta;
    if(startPosition > stepsPerRev) startPosition = startPosition - stepsPerRev;
    Serial.print("Steps to home "); Serial.println(startPosition);
    lcd.setCursor(0, 1);
    lcd.print("Pos: ");
    lcd.print(setPosition);
    lcd.setCursor(8, 1);
    if (rotationDir = 1) lcd.print("CCW"); 
    else 
    if (rotationDir = -1) lcd.print("CW");
    small_stepper.step(positionDelta);
    wasPosition = newPosition;
    newPosition = 0;
    positionDelta = 0;
    digitalWrite(2, LOW);
    digitalWrite(3, LOW);
    digitalWrite(4, LOW);
    digitalWrite(5, LOW);

  }
    results.value = 0; 
    irrecv.resume(); // receive the next value
    delay(500); // de-bounce

}/* --end main loop -- */

I can't find a stepwise debug tool in my IDE Arduino 1.8.19 so if there's another approach or IDE i can use i'd be grateful for the help. I'm happy to use use a bool variable but the if test will be a doosey.

You are missing a break statement in one of the case statements. Is that intentional?

Your very poor choice of code formatting makes it hard to spot.

For debugging, the most popular Arduino option is to sprinkle Serial.print() statements around, to report values of variables where you suspect things are going awry.

 if (rotationDir = 1) 
else if (rotationDir = -1)

From the if structure reference:

Beware of accidentally using the single equal sign (e.g. if (x = 10) ). The single equal sign is the assignment operator, and sets x to 10 (puts the value 10 into the variable x). Instead use the double equal sign (e.g. if (x == 10) ), which is the comparison operator, and tests whether x is equal to 10 or not. The latter statement is only true if x equals 10, but the former statement will always be true.

== or = ?

Oopsie :wink:

if (rotationDir == 1) lcd.print("CCW"); 
else 
if (rotationDir == -1) lcd.print("CW");

No, a typo. Thanks. It's right in the sensitive area, too.Interesting that the compiler didn't pick that up. I have changed and loaded corrected code but no joy.

It is perfectly valid to leave out break. Execution continues through the next "case".

The faulty if statements pointed out above are a problem.

... and following remarks. That's right! code works now and the motor turns in the right direction. Thanks heaps, community.

If you have compiler warnings enabled you will get a warning for those mistakes in the if structures. Go to File, Preferences and enable All compiler warnings.

warning: suggest parentheses around assignment used as truth value [-Wparentheses]
if (rotationDir = 1) lcd.print("CCW");
~~~~~~~~~~^
: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
else if (rotationDir = -1) lcd.print("CW");

You should pay attention to all warnings and try to resolve them. They are not harmless.

Just wanted to let you know i accept your comments on code formatting and the Serial.print() debug tool. I have been a lone ranger in the code and basically use comments as reminders, not clues for those who follow. Do you know a reference I can use for good formatting?

Good point - I use the warnings but had the option at default.

The IDE autoformat tool (ctrl-T or Tools, Auto Format does a nice job of indenting the code in a standard fashion.

Put only one statement per line.

 case 0xFF30CF: newPosition = Position1; Serial.println("Position 1"); setPosition = 1; break;

Is hard to read, especially if you have to horizontal scroll to read it.

 case 0xFF30CF: 
      newPosition = Position1; 
      Serial.println("Position 1"); 
      setPosition = 1; 
      break;

Is, in my opinion, much easier to follow and missing ; will be easier to see.

I put all my { and } on their own lines. Makes the statement blocks easier to follow. And I use curly brackets even if a block is only one line.

if (!positionDelta) 
{
       positionDelta = newPosition - wasPosition;
}

I don't know of any reference. Probably others will. This is just stuff that I have picked up over the years.

I don't use verbose output just warnings. I find it distracting. If I have an error, I can always go to preferences and check and re-compile if I need to.

I suggest you read about the F-Makro and put all fix texts which should get printed in a F-Makro to safe SRAM

Serial.println(F("Preset anticlockwise rotation"));

All good points. I do all my coding on a widescreen PC and try anyway to make it as compact as possible. Clearly it also makes things unclear. I've been doing code since 1973 (1st year Uni) and am always ready to learn.

I guess in those days there were no wide screens, just 80 character punched cards (and a 1 day turn around - only to discover a minor syntax error forcing another day wait . . .)

Me too. FORTRAN. Punch cards. A box of donuts to the computer lady got my code ran a bit faster.

Very interesting... I have implemented the macro on all my text alerts and it reduced the global variables count from 43% of dynamic memory to 25%. Remarkable. Thanks

I watched a few of my BE Elec friends fall down the rabbit hole and decided after SYD11 and FORTRAN that I wanted to pursue real engineering with real things, like as it turned out process automation. A few years later i saw the risk of becoming a dinosaur and took it up again with Lotus 123. So many things have changed and so many are the same.

I went into the Navy in '74, worked on cars after I got out and never touched a computer of any kind till I bought a Timex ZX81 in '82. Been a hobbyist ever since.

Example for coding style: Google C++ Style Guide