Global variable value changing for no reason

I am making a POV(Persistence of Vision) for my cycle. Code is taken from persistenceofvision.com which site does not exist now but is available in web archive.
the code is for single strip of addressable RGB leds. I modified it to use 3 strips .i.e 1 strip 0 degrees, 2nd at 120 degrees and third at 240 degrees, to provide the image at even lower speeds.
Problem: I am finding the value of a variable at .degrees close to 120 and 240 and saving it to global variables, x120 and x240 which are not supposed to change but the x240 changes. i dont know why?

Query : I am using variable k, k120, k240. Is it possible to substitute this as

i=120;
k[i]= whatever calculations;

My Main code



const uint8_t chipled[] PROGMEM = {0};
const uint8_t numstrip[] PROGMEM = {1};    // Number of LED strips
const uint8_t numradios[] PROGMEM = {1};   // Number of Spokes(radius)
const uint8_t radio1directo[] PROGMEM = {1};
const uint8_t radio2directo[] PROGMEM = {1};
const uint8_t radio2180[] PROGMEM = {0};
const uint8_t offset1[] PROGMEM = {0};
const uint8_t offset2[] PROGMEM = {0};
const uint8_t brillo[] PROGMEM = {128};
const uint8_t animate[] PROGMEM = {0};
//const uint8_t num_leds[] PROGMEM = {30};
const uint16_t numpasos[] PROGMEM = {152}; // number of steps
const uint16_t angreducido[] PROGMEM = {152}; // angle reduced
const uint16_t sizePolarRedu[] PROGMEM = {684};
const uint8_t PolarRedu[684] PROGMEM = {0,1,0,0,2,7,0,3,7,0,4,7,0,5,7,0,6,7,0,7,7,0,8,7,0,9,0,0,10,0,0,11,0,0,12,0,0,13,0,0,14,0,0,15,0,0,16,0,0,17,0,0,18,0,0,19,0,0,20,0,0,21,0,0,22,0,0,23,0,0,24,0,0,25,0,0,26,0,0,27,0,0,28,0,0,29,0,0,30,0,2,8,0,4,2,0,5,3,0,5,7,0,6,6,0,7,4,0,7,5,0,23,5,7,24,6,7,27,4,7,27,7,7,33,8,7,33,26,7,34,25,7,34,27,7,34,28,7,35,3,7,35,24,7,36,23,7,36,29,7,37,22,7,38,21,7,40,20,7,41,19,7,43,9,7,43,18,7,45,17,7,45,29,0,47,16,7,47,28,0,48,27,0,50,15,7,50,26,0,52,25,0,53,14,7,54,24,0,56,23,0,57,13,7,59,22,0,62,1,7,62,12,7,62,21,0,66,20,0,69,11,7,71,19,0,72,9,0,77,18,0,79,3,0,80,10,7,87,17,0,108,17,7,115,2,7,116,10,0,118,18,7,122,9,7,125,19,7,126,4,0,128,11,0,130,20,7,132,10,7,135,12,0,135,21,7,139,22,7,140,11,7,141,3,7,144,23,7,145,5,0,147,24,7,150,13,0,152,25,7,153,13,7,158,4,7,158,26,7,162,11,0,164,6,0,166,27,7,167,12,7,170,10,0,175,5,7,175,9,0,175,11,7,176,8,0,176,28,7,177,7,0,181,10,7,184,16,0,185,9,7,185,15,0,187,6,7,187,8,7,188,14,0,188,16,7,189,8,0,192,15,7,194,13,0,197,7,7,197,14,7,198,9,0,202,28,0,205,8,7,206,10,0,209,27,0,211,12,0,212,9,7,212,11,0,214,26,0,217,13,7,218,10,7,219,12,7,219,25,0,222,11,7,225,24,0,230,23,0,237,22,0,241,21,0,243,20,0,244,19,0,246,18,0,248,17,0,250,16,0,253,15,0,253,17,7,1,14,0,1,16,7,1,17,0,4,13,0,4,15,7,7,12,0,8,14,7,9,11,0,10,8,0,10,9,0,10,10,0,11,5,0,11,6,0,11,7,0,12,13,7,14,4,0,15,4,7,15,12,7,16,4,0,17,11,7,18,3,0,18,10,7,19,9,7,19,16,0,20,16,7,22,2,0,22,7,7,23,16,0,24,16,7,25,6,7,29,5,7,35,4,7,37,1,0,37,17,7,44,9,0,44,18,7,47,3,7,48,19,7,50,8,7,52,20,7,54,10,0,55,21,7,58,22,7,59,11,0,60,23,7,61,9,7,63,12,0,63,24,7,65,25,7,66,13,0,67,26,7,68,27,7,69,14,0,70,28,7,71,15,0,71,29,7,72,10,7,72,30,7,73,2,7,73,16,0,74,17,0,76,18,0,77,19,0,78,20,0,80,21,0,80,22,0,81,23,0,82,24,0,83,25,0,83,26,0,84,27,0,84,28,0,85,29,0,85,30,0,89,10,0,101,9,0};

#include <avr/pgmspace.h>
#include "FastLED.h"
#include <SoftwareSerial.h>
SoftwareSerial BT(7,8); //10 RX, 11 TX

#define DATA_PIN1 9     //   0 Degrees
#define DATA_PIN2 10    // 120 degrees
#define DATA_PIN3 11    // 240 degrees
#define LED_TYPE WS2812B
# define NUM_LEDS 30



CRGB leds[NUM_LEDS];     // original value 141
CRGB leds120[NUM_LEDS];
CRGB leds240[NUM_LEDS];

unsigned int numled;
int angAux = 0;
int anginicio = 360;
int kinicial = 0;
int angulo;          // angle 0
int angulo120;
int angulo240;
unsigned int ang = 360;
unsigned int ang120 = 0;
unsigned int ang240 = 0;
unsigned int k = 0;
unsigned int k120 = 0;
unsigned int k240 = 0;
unsigned int x120 = 0; 
unsigned int x240 = 0;

bool pasa = false;  // Hall sensor detect
bool cambiaLed = false; // change LED
long tiempoDibujo = 0;  // time drawing
long periodo = 0;      // period
long periodoini = 0;  // initial period
long previoustime = 0;
long tiempo = 0;       // time
long contaseconds = 0; // consist seconds


long tvariable = 0;
int tiempoescritura = 700; // writing time
byte LedColour = 0;
byte vred = 0;
byte vgreen = 0;
byte vblue = 0;

int contaang = 0;
long tiempoanimate = 0;



void set_led(){
  
  vred = 0;
  vgreen = 0;
  vblue = 0;

  if(LedColour == 4 || LedColour == 6 || LedColour == 7 || LedColour == 1) {
    vblue = 255;
  }
  if(LedColour == 3 || LedColour == 5 || LedColour == 6 || LedColour == 1) {
    vgreen = 255;
  }
  if(LedColour == 2 || LedColour == 5 || LedColour == 7 || LedColour == 1) {
    vred = 255;
  }  
}

void precompute(){
 unsigned int x = 0 ;
 unsigned int angle = 0;
 unsigned int angular;

 angular = pgm_read_byte(PolarRedu + x);
  if (x / 3 >= pgm_read_word_near(angreducido + 0)) {
    angular += 255;
  }
  for (angle = 0; angle < 360; angle++) {       
    while (angular == angle){ 
      if(angle >= 120 && x120 == 0){ 
       x120 = x;
      }
      if(angle >= 240 && x240 == 0){
       x240 = x;
      }
      if(x120 != 0 && x240 != 0){
        return;
        
      }
      x += 3;
      if (x >= pgm_read_word_near(sizePolarRedu + 0)) {
        angular = 999;
      }
      else{
        angular = pgm_read_byte(PolarRedu + x); // value in the array PolarRedu at position value of k
        if (x / 3 >= pgm_read_word_near(angreducido + 0)) {
          angular += 255;
        }
      }
    } 
  }
}

void get_value(){
k120 = x120;
k240 = x240;
}

void pasaIman() {
  pasa = true;
}

void setup() {
//Para resetear
pinMode(A2, INPUT);
digitalWrite(A2, LOW);

//Serial.begin(9600);
FastLED.addLeds<LED_TYPE, DATA_PIN1, RGB>(leds, NUM_LEDS + pgm_read_byte(offset1 + 0)); // LED TYpe WS2812b
FastLED.addLeds<LED_TYPE, DATA_PIN2, RGB>(leds120, NUM_LEDS + pgm_read_byte(offset1 + 0));
FastLED.addLeds<LED_TYPE, DATA_PIN3, RGB>(leds240, NUM_LEDS + pgm_read_byte(offset1 + 0));
FastLED.setBrightness(pgm_read_byte(brillo + 0));
FastLED.setCorrection( TypicalLEDStrip );
attachInterrupt(digitalPinToInterrupt(2), pasaIman, RISING);
memset(leds, 0, NUM_LEDS * 3);     
memset(leds120, 0, NUM_LEDS * 3);
memset(leds240, 0, NUM_LEDS * 3);
FastLED.show();
precompute();
}

void loop() {
  

  if (pasa == true) {
    pasa = false;
    tiempo = micros();
    periodoini = tiempo - previoustime;
    periodo = tiempo - previoustime - tvariable ;
    //periodo teorico //Theoretical Period
    tiempoDibujo = periodo / 360;
    if (tiempoDibujo < 0) tiempoDibujo = 0;
    previoustime = tiempo;
    get_value(); // get value of k120=252 & k240=432
    k = 0;
    //k120 = 252;
    //k240 = 432
    angulo = pgm_read_byte(PolarRedu + k);  // value in the array PolarRedu at position value of k
    angulo120 = pgm_read_byte(PolarRedu + k120);
    angulo240 = pgm_read_byte(PolarRedu + k240);
    if (k / 3 >= pgm_read_word_near(angreducido + 0)) {
      angulo += 255;
    } 
    contaang=0;
    for (ang = 0; ang < 360; ang++) {
      contaang++;                   // value 1 to 360
      cambiaLed = false;
      ang120 = ang + 120;
      if(ang120 >= 360) ang120 -= 360;
      ang240 = ang + 240;
      if(ang240 >= 360) ang240 -= 360;
      if(angulo == ang || angulo120 == ang120 || angulo240 == ang240) { 
        cambiaLed = true;
        // set leds
        while(angulo == ang){
          if (pgm_read_byte(radio1directo + 0) == 1) {
            // PolarRedu=0; k= 0,3,6,9,12...+3..675,678,681(3 less than PolarRedu[684])
            numled = pgm_read_byte(PolarRedu + k + 1) - 1 + pgm_read_byte(offset1 + 0);
          } 
          else {
            //inverso es cero // inverse is zero
            numled = NUM_LEDS - pgm_read_byte(PolarRedu + k+1) + pgm_read_byte(offset1 + 0);
          }
          LedColour = pgm_read_byte(PolarRedu + k + 2); 
          set_led();
          leds[numled].r = vred;
          leds[numled].g = vgreen;
          leds[numled].b = vblue;

          k += 3;
          if (k >= pgm_read_word_near(sizePolarRedu + 0)) {
            angulo = 999;
          }
          else{
            angulo = pgm_read_byte(PolarRedu + k); // value in the array PolarRedu at position value of k
            if (k / 3 >= pgm_read_word_near(angreducido + 0)) {
              angulo += 255;
            }
          }
        }

         // Set leds120
        while(angulo120 == ang120){
          if (pgm_read_byte(radio1directo + 0) == 1) {
            numled = pgm_read_byte(PolarRedu + k120 + 1) - 1 + pgm_read_byte(offset1 + 0);
          } 
          else {
            //inverso es cero // inverse is zero
            numled = NUM_LEDS - pgm_read_byte(PolarRedu + k120 + 1) + pgm_read_byte(offset1 + 0); // No readings
          }
          LedColour = pgm_read_byte(PolarRedu + k120 + 2); 
          set_led();
          leds120[numled].r = vred;
          leds120[numled].g = vgreen;
          leds120[numled].b = vblue;

          k120 += 3;
          if(k120 > pgm_read_word_near(sizePolarRedu + 0)){
            k120 -= (pgm_read_word_near(sizePolarRedu + 0) + 3);
          }
          if (k120 == pgm_read_word_near(sizePolarRedu + 0)) {
          }
          //else if(k120 == x120){
          else if(k120 == 252){
            angulo120 = 999;
          }
          else{
           angulo120 = pgm_read_byte(PolarRedu + k120); // value in the array PolarRedu at position value of k120
            if (k120 / 3 >= pgm_read_word_near(angreducido + 0)) {
              angulo120 += 255;
            }
          }
        }

         // Set leds240
        while(angulo240 == ang240){
          if (pgm_read_byte(radio1directo + 0) == 1) {
            numled = pgm_read_byte(PolarRedu + k240 + 1) - 1 + pgm_read_byte(offset1 + 0);
          } 
          else {
            //inverso es cero // inverse is zero
            numled = NUM_LEDS - pgm_read_byte(PolarRedu + k240 + 1) + pgm_read_byte(offset1 + 0); // No readings
          }
          LedColour = pgm_read_byte(PolarRedu + k240 + 2); 
          set_led();
          leds240[numled].r = vred;
          leds240[numled].g = vgreen;
          leds240[numled].b = vblue;

          k240 += 3;
          if(k240 > pgm_read_word_near(sizePolarRedu + 0)){
            k240 -= (pgm_read_word_near(sizePolarRedu + 0) + 3);
          }
//////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
          BT.println(k240);
          BT.println(x240); // Value should always be 432
          BT.println("=====");
          if (k240 == pgm_read_word_near(sizePolarRedu + 0)) {
			// Do Nothing
          }
          //else if(k240 == x240){
          else if(k240 == 432){
            angulo240 = 999;
          }
          else{
            angulo240 = pgm_read_byte(PolarRedu + k240); // value in the array PolarRedu at position value of k
            if (k240 / 3 >= pgm_read_word_near(angreducido + 0)) {
              angulo240 += 255;
            }
          }
        }     
      } 

      if (cambiaLed == true) { // ChangeLED
        FastLED.show();
        if (tiempoDibujo > tiempoescritura) {
          delayMicroseconds(tiempoDibujo - tiempoescritura);
        }
      } 
      else {
        if (tiempoDibujo > tiempoescritura) {
          delayMicroseconds(tiempoDibujo + tiempoescritura * pgm_read_word_near(numpasos + 0) / (360 - pgm_read_word_near(numpasos + 0)));
        } 
        else {
          delayMicroseconds(tiempoDibujo * 360 / (360 - pgm_read_word_near(numpasos + 0)));
        }
      }
      if (pasa == true) {
        //para que se sume a tvariable algo que se supone positivo
        //To add somthing that is considered positive to the variable
        tvariable += (micros() - previoustime) * 360 /contaang - periodoini;
        if (tvariable > 500000 || tvariable < -500000) {
          tvariable = 0;
        }
        return;
      }
    } // End for (ang = 0; ang < 360 ; ang++)
    //para que se sume a tvariable algo negativo
    // To add a negative value to a variable
    tvariable += (micros() - previoustime) - periodoini;
    if (tvariable > 500000 || tvariable < -500000) {
      tvariable = 0;
    }
  } // endif (pasa == true)
} // end of void

Hex and Proteus files.zip (34.6 KB)

Why all of below defined as arrays if each of them contains a single value?

1 Like
if(angle >= 240 && x240 == 0){
       x240 = x;
      }

What do you mean it shouldn't change? Here, under certain conditions, you change it.

1 Like

To add to the comment from @b707, there is no need to save a single const value in PROGMEM, the compiler would ordinarily just substitute the value into the code whenever it is used and never store it to begin with.

1 Like

This as per the original code generated by the site. I have to do code optimisation. Work in progress. But only after this hurdle is solved

I am calling that function only once in setup and assigning values to global variable x120 & x240. In the loop I am calling get_values() where I set
k120=x120;
k240=x240;
Then only value of k,k120,k240 changes. Nowhere in the loop does the value of x120 and/or x240 changes.
Surprisingly the code to set led120 and led 240 is similar but only x240 changes even if I change
If(k240==x240) to if(k240==432)

Once everything works in simulation and actual hardware, I will do the code optimisation. At present I am using only 1/3 the rom and less than 50 percent sram. I am using Arduino Nano.

The first thing I would check is that you are never writing outside the bounds of the led arrays. That is a very common cause of a seemingly unrelated variable changing value.

2 Likes

Did you first test the code to make sure it runs correctly (on your platform) exactly as written?

1 Like

Since the link you provided is useless, how does one view this "web archive"?

How do you know it changes? How does it change and when?

Optimizing the code for clarity and reading might accelerate the troubleshooting process.

Edit: Calling something like this in setup() and loop() doesn't indicate changes:

void reportX(void) {
  static int oldX240 = -999;
  if (oldX240 != x240) {
    Serial.print("x240 change from:");
    Serial.print(oldX240);
    Serial.print(" to:");
    Serial.print(x240);
    oldX240 = x240;
    Serial.println();
  }
  static uint16_t last = 0;
  uint16_t now = millis();
  if (now - last > 200) {
    last = now;
    Serial.print(".");
  }
}
x240 change from:-999 to:0 
x240 change from:0 to:432
...............................................................................................................................................................................................................................................................................................................

Yes it works

If you compile the code given by me. I have mentioned in the loop under set led240. I have used BT.println(k240) and BT.println(x240). You can use Serial.println instead. The value of x240 changes there. It is steady until k240=684 then it changes. x120 doesn't change. The code of set led120 is similar to set led240

Are you trying to read element 684 of an array whose index goes from 0 to 683?

Worse is writing out of bounds.

With thse bits jammed in approprate places:

      Serial.print(k240);
      Serial.print(' ');
      Serial.print(x240); // Value should always be 432
      Serial.println("=====");

and this:

          if(numled >= NUM_LEDS){
            Serial.print("OutOfBounds");
          }
          leds240[numled].r = vred;
          leds240[numled].g = vgreen;
          leds240[numled].b = vblue;

I see:

672 432=====
675 432=====
678 432=====
681 432=====
684 432=====
OutOfBounds0 0=====
3 0=====
6 0=====
9 0=====
12 0=====
15 0=====
18 0=====

The leds240[] array is before the x240 global in the listing.

It looks like the obfuscated math here is also confused:

          if (pgm_read_byte(radio1directo + 0) == 1) {
            numled = pgm_read_byte(PolarRedu + k240 + 1) - 1 + pgm_read_byte(offset1 + 0);
          }
          else {
            //inverso es cero // inverse is zero
            numled = NUM_LEDS - pgm_read_byte(PolarRedu + k240 + 1) + pgm_read_byte(offset1 + 0); // No readings
          }
1 Like

You were right. On your suggestion I checked and found that I was writing outside the bounds of the led array.

User david_2018 suggeted that I may be writing outside the bounds of the led array and by the time I could confirm it, you were much faster in detecting it. Thanks, working on rectification. Until I figure it out can you answer my second question.
Can I replace k120/x120 with i=120; k[i]= some calculation

Syntactically, no.

What are you aiming to accomplish?

Instead of the repetive code/commands create one common function to call to set led, set led120 and set led240.
On your suggestion I made a change in the code.

if (pgm_read_byte(radio1directo + 0) == 1) {
            numled = pgm_read_byte(PolarRedu + k240 + 1) - 1 + pgm_read_byte(offset1 + 0);
          }
          else {
            //inverso es cero // inverse is zero
            numled = NUM_LEDS - pgm_read_byte(PolarRedu + k240 + 1) + pgm_read_byte(offset1 + 0); // No readings
          }
if(numled < NUM_LEDS){
set_leds();
leds240[numled].r = vred;
leds240[numled].g = vgreen;
leds240[numled].b = vblue;
}

Did this for all leds,leds120,led240

Instead of using k,k120,k240 I could create an array. Unsigned int k[3]. I can use k[0] instead of k, k[1] as k120 and k[2] as k240.
If I have

PolarRedu1[684]{0,1,2.....}
PolarRedu2[339]{5,6,7,8,......}

How to access This array like k[3] array?