Subloop causes PWM D10 D11 on nano to output 0, yet serial monitor shows values

Hi Everyone,
Day number 15 of trying to get some code up and running and its come full circle and still not working! I was hoping someone could let me know why my fade subloop is shutting down my D10 and D11 pin PWM signal?
I have moved the 2 gauges connected to D10 and D11 to D3 and D5 and the problem follows the pins not the gauges. If I remove the call to go to the fade subloop all the outputs operate my gauges correctly.
No matter what condition this is in when I look at the outputs in the serial monitor it always shows the expected values, even when the 2 out of 6 gauges is not moving. While in the serial monitor I can move the 6 pots and see the expected changes on the inputs and the outputs the only difference is with the fade loop running the physical gauges on D10 and D11 stay at 0.
When I start putting in // lines into the fade subloop both of the below items shut down the D10 and D11 again the serial monitor still shows the correct values:

 for (int i=0; i<3; i++){                                                     //Loop so each of the 3 color values can be checked and adjusted
          if (timer[currentLED].counterTarget[i] > timer[currentLED].counter[i]){   //Check to see if the target is larger than the counter
            timer[currentLED].counter[i] = (timer[currentLED].counter[i] +15);      //Increase timer by 1, 0-255
            if (timer[currentLED].counter[i] >= 255){                               //Can run past target if increment is not divisible
              timer[currentLED].counter[i] = 255;
            }
          }
         if (timer[currentLED].counterTarget[i] < timer[currentLED].counter[i]){    //Check to see if the target is less than the counter
            timer[currentLED].counter[i] = (timer[currentLED].counter[i] -15);      //Decrease counter by 1, 255-0
            if (timer[currentLED].counter[i] <= 0){
              timer[currentLED].counter[i] = 0;
          }
         }
pixels.setPixelColor(currentLED, timer[currentLED].counter[0], timer[currentLED].counter[1], timer[currentLED].counter[2]);  //Set the new color
      pixels.show();                                                                //Push the color to the LEDs

I had a similar (but not the same) problem when trying to use the fast.LED library so I switched to adafruit. I thought maybe it was the milli entries but I have removed those with no change.

Below is the code:

//Gauge Puzzle June 7 LEDs working 2 outputs dead

//  INCLUDES
#include <Adafruit_NeoPixel.h>                                        //Neopixel Library 
// CONSTANTS
#define NUM_LEDS 6                                                    //Number of LEDs
#define DATA_PIN 2                                                    //LED Data pin
#define BRIGHTNESS 50                                                 //LED Brightness setting 0-155
int numOutputs = 8;                                                   //Total outputs required for win, only 6 needed for gauges
int numInputs = 8;                                                    //Pot input number
const byte meterPins[] = {3, 5, 6, 9, 10, 11};                        //mV Gauge pins
const byte sliderPins[] = {A0, A1, A2, A3, A4, A5, A6, A7};           //Pot pins
const int targetValues[] = {0, 0, 0, 0, 0, 0, 0, 0};  //Win conditions
const int tolerance = 4;                                              //Target value +-
int y = 0;                                                            //Test Int for win condition to wipe gauges
const byte smoothInterval = .1;                                       //Timing for LED update
struct timer {                                                        //Struct to hold each LED timing counter and target
  uint32_t previousMillis;
  int counter[3];
  byte counterTarget[3];
} timer[NUM_LEDS]= {                                                         //Tried 50 different ways to do this this is the only way I dont get errors
  { 0,  {255,0,0}, {255,0,0}  },
  { 0,  {255,0,0}, {255,0,0}  },
  { 0,  {255,0,0}, {255,0,0}  },
  { 0,  {255,0,0}, {255,0,0}  },
  { 0,  {255,0,0}, {255,0,0}  },
  { 0,  {255,0,0}, {255,0,0}  },
};


// GLOBALS
int inputValues[8] = {};                                              // 10-bit input values from the ADC have values in the range (0-1023)
int outputValues[8] = {};                                             // 8-bit output values to pass to AnalogWrite PWM output have values in the range (0-255)
bool isSolved = false;                                                //Win codition
Adafruit_NeoPixel pixels(NUM_LEDS, DATA_PIN, NEO_GRB + NEO_KHZ800);   //Declare Neopixel Object

void setup() {
  Serial.begin(9600);                                                 //Initilize serial
  pixels.begin();                                                     //Initilize Neopixel object
  pixels.setBrightness(BRIGHTNESS);                                   //Set LED brighness
  for(int i=0; i<NUM_LEDS; i++){                                      //Set the initial colors of the LED to Red
  pixels.setPixelColor(i, 255, 0, 0);
  }
  pixels.show();                                                      //Push changes to LEDs
  for(int i=0; i<6; i++) {                                            //Initialise the output pins
    pinMode(meterPins[i], OUTPUT); 
  }
}

void fade(byte currentLED){                                                         //Subloop to handle the LED fade
  //uint32_t currentMillis = millis();
  //if (millis() - timer[currentLED].previousMillis > smoothInterval)               //Set time when LED counters should be changed
    //{
    //timer[currentLED].previousMillis = currentMillis;                             //Reset timer as sub loop conditions have beed activated
       for (int i=0; i<3; i++){                                                     //Loop so each of the 3 color values can be checked and adjusted
          if (timer[currentLED].counterTarget[i] > timer[currentLED].counter[i]){   //Check to see if the target is larger than the counter
            timer[currentLED].counter[i] = (timer[currentLED].counter[i] +15);      //Increase timer by 1, 0-255
            if (timer[currentLED].counter[i] >= 255){                               //Can run past target if increment is not divisible
              timer[currentLED].counter[i] = 255;
            }
          }
         if (timer[currentLED].counterTarget[i] < timer[currentLED].counter[i]){    //Check to see if the target is less than the counter
            timer[currentLED].counter[i] = (timer[currentLED].counter[i] -15);      //Decrease counter by 1, 255-0
            if (timer[currentLED].counter[i] <= 0){
              timer[currentLED].counter[i] = 0;
          }
         }
      //}
      //Serial.print(currentLED);                                                  //Debug
      //Serial.print("-");
      //Serial.print(timer[currentLED].counterTarget[0]);
      //Serial.print(",");
      //Serial.print(timer[currentLED].counter[0]);
      //Serial.print("   ");
      //Serial.print(timer[currentLED].counterTarget[1]);
      //Serial.print(",");
      //Serial.print(timer[currentLED].counter[1]);
      //Serial.print("   ");
      //Serial.print(timer[currentLED].counterTarget[2]);
      //Serial.print(",");
      //Serial.print(timer[currentLED].counter[2]);
      //Serial.println("");
      pixels.setPixelColor(currentLED, timer[currentLED].counter[0], timer[currentLED].counter[1], timer[currentLED].counter[2]);  //Set the new color
      pixels.show();                                                                //Push the color to the LEDs
    }
  }


void loop() {
  for(int i=0; i<numInputs; i++){
    for(int x=0; x<2; x++) {                                        // Clear ADC by taking 2 additional reads before accepting
      analogRead(sliderPins[i]);
      delay(5);
    }
    inputValues[i] = analogRead(sliderPins[i]);                     //Assigning inputvalues 1:1 relationship for testing, move to custom rules below when working
    //Serial.print(i);                                              //Debug input values
    //Serial.print("-");
    //Serial.print(inputValues[i]);
    //Serial.print(",");
    //if(i>(numOutputs-2)){
    //Serial.println("");
    //}
  }
  for(int i=0; i<numOutputs; i++){                                  //Assigning the analog read to outputs, assigning all 8 but only 6 assined to PWM pins
    outputValues[i] = inputValues[i];
  }
  
  //Setting up custom paramters/relationships                        //Setting up custom rules for inputs
  //outputValues[0] = (inputValues[0] + inputValues[1]/ 5.5);
  //outputValues[1] = (inputValues[1] - inputValues[2]);
  //outputValues[2] = (inputValues[2]);
	//outputValues[3] = (inputValues[3]);
  //outputValues[4] = (inputValues[4]);
  //outputValues[5] = (inputValues[5]);
  
  bool allMetersCorrect = true;                                       //Check outputs vs tragets
	for(int i=0; i<numOutputs; i++){                                    
    outputValues[i] = inputValues[i] >> 2;                            //map 10 to 8 bit
    //Serial.print(i);                                                //Debug output values
    //Serial.print("-");
    //Serial.print(outputValues[i]);
    //Serial.print(",");
    //if(i>(numOutputs-2)){
    //Serial.println("");
    //}
    if(abs(outputValues[i] - targetValues[i]) > tolerance) {          //Check to see if all conditions are met
      allMetersCorrect = false;
    }
    if((abs(outputValues[i] - targetValues[i]) > tolerance) && (i<6)){ //Set wrong matches to a target color of Red limiting to 0-5
      timer[i].counterTarget[0] = {255};
      timer[i].counterTarget[1] = {0};
      timer[i].counterTarget[2] = {0};
      //Serial.print("Output");
      //Serial.print(i);                                                 //debug counter target
      //Serial.print("-");
      //Serial.print(timer[i].counterTarget[0]);
      //Serial.print(",");
      //Serial.print(timer[i].counterTarget[1]);
      //Serial.print(",");
      //Serial.print(timer[i].counterTarget[2]);
      //Serial.print(",");
      //Serial.println("");  
    }
      else {                                                           //if the matches were not inccorect they must match and LED turns traget color to Green should also be limited to 0-6
      timer[i].counterTarget[0] = {0};
      timer[i].counterTarget[1] = {255};
      timer[i].counterTarget[2] = {0};
         }
    if (i<6){
    fade(i);                                                           //Run fade subroutine to fade the LEDs to the target colors set above but only pushes 6 numbers to subroutine
    }
	}
    //Serial.println("");
  for (int i=0; i<6; i++){                                             //Write inputs 1-6 to the output PWM pins
    analogWrite(meterPins[i], outputValues[i]);
    Serial.print(i);                                                   //Debug meter values
    Serial.print("-");
    Serial.print(outputValues[i]);
    Serial.print(",");
    if(i>(4)){
    Serial.println("");
    }
    }
	if(allMetersCorrect && !isSolved) {                                  //If the inputs match target the all meters = true so is solved can be set to true
    //Serial.println("Solved!");                                       //Debug
    isSolved = true;
    //y = y+20;                                                        //Test guage wipe may need to add dely to stop gauge bounce when returned to zero
    //if(y >= 850){
      //y=0;
      //}
    //for(int i=0; i<6; i++){
      //outputValues[i] = y;
     }
  else if(isSolved && !allMetersCorrect) {                             // If the puzzle had been solved, but now the meters are no longer correct.  May want to lock out puzzle on solved
    //Serial.println("Unsolved!");
    isSolved = false;
  }
  //delay(500);
}

Any help on this would be greatly appreciated, I am days into this and just can not get past the finish line.

Thank you!

There are multiple places where you have commented out closing braces. This is one place:

for(int i=0; i<numOutputs; i++){

There are several code sections where the braces are not balanced, suggesting your code isn’t doing exactly what you think it should be doing.

Control-T is your friend.

I believe you have the possibility for writing past the bounds of 'timer' array right here:

    if ((abs(outputValues[i] - targetValues[i]) > tolerance) && (i < 6)) { //Set wrong matches to a target color of Red limiting to 0-5
      timer[i].counterTarget[0] = {255};
      timer[i].counterTarget[1] = {0};
      timer[i].counterTarget[2] = {0};
      //Serial.print("Output");
      //Serial.print(i);                                                 //debug counter target
      //Serial.print("-");
      //Serial.print(timer[i].counterTarget[0]);
      //Serial.print(",");
      //Serial.print(timer[i].counterTarget[1]);
      //Serial.print(",");
      //Serial.print(timer[i].counterTarget[2]);
      //Serial.print(",");
      //Serial.println("");
    }
    else {                                                           //if the matches were not inccorect they must match and LED turns traget color to Green should also be limited to 0-6
      timer[i].counterTarget[0] = {0};
      timer[i].counterTarget[1] = {255};
      timer[i].counterTarget[2] = {0};
    }

If 'i' is greater or equal to 6 you fall into the else block, where you write to timer[6] and timer[7] counterTarget arrays; however, the timer array has only 6 elements.

Note that the input and output arrays follow this. If you add up the bytes that are getting corrupted it would probably clobber the end of your input array and the middle of your output array.

1 Like

OMG thank you! I had no idea this existed.

Todd thank you so much. I have no idea why that part of the logic was messing up my brain. You are 110 percent right. What a strange symptom for that mess up.

The journey to get to this point has been epic, this forum is a life saver.

const byte smoothInterval = .1;
..this is new to me : .1 as integer ??

Lol yes that happened. I am not using that anymore as I took out the timing commands running via Millis and using the counter size instead.
Put in .1 to try and reproduce some of the errors I was getting to rule out a few things.

The solution was jamming 8 values in a 6 value array.

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