title: Array + Serial Monitor Problem

text:
# Question
Title: Array + Serial Monitor Problem
I've written a Arduino sketch that converts an analogue voltage to a temperature using a lookup table - code below. I've recently changed my LUT to include more values but ever since that my Serial monitor won't print out my debugging statements etc. So I limited the number of elements in the array and it was back to normal. But when I enter more debugging statements using the serial monitor, there is garbage before my statements (still readable though when I parse through it myself) or at the start nothing is printed. I've checked that the two baud rates are the same but I just find it peculiar that if I take some of my println() statements out it runs okay. Tested everything else with a "Hello World" example but in the simple exaples the monitor works fine.

```
    /*
    #####PROJECT DESCRIPTION#####
    Measures temperature with an Arduino and NTC Thermistor (10Kohms @ 25^C)                                 in a voltage divider circuit
    Since the response is non-linear, a lookup table is used since there is a non linear response
    The values in the LUT are the predicted values of the ADC at  temperature between 6^C and 40^C
    LUT has been derived from the calibration tests
    */
    //#####CONSTANTS#####
    const int constDelay = 3000; //constant delay for program
    const int constNoOfAnaloguePins = 2; //number of analogue pins that are to be read
    const int errReturn = 998; //error value that is returned ***CHECK FOR CONSITENT VALUE ACROSS FUNCTIONS***
    //#####VARIABLE DECLARATIONS#####
    float avgTempC; //float var to store average of multiple temp readings

    //#####SETUP PROCEDURE#####
    void setup()
    {
      //this is the Setup part of your project - this is for code that is run only ONCE at startup
      for (int analoguePinCounter = 0; analoguePinCounter < constNoOfAnaloguePins; analoguePinCounter++) //for loop to set up numerous analogue pins
      {
        pinMode(analoguePinCounter, INPUT);  //set pin mode of the analogue thermistor input
      }//end for
      analogReference(INTERNAL); //use the interval votlage of 1.1V for the ADC resolution
      Serial.begin(9600); //serial monitor baud rate
    }//end Setup function

    //#####LOOP PROCEDURE#####
    void loop()
    {
      //this is the main part of your project - put all continuously running code here
      for (int analoguePinCounter = 0; analoguePinCounter < constNoOfAnaloguePins; analoguePinCounter++) //for loop to take temp readings from each analogue pin
      {
        //get LPF average reading over 25 samples
        avgTempC = LPF(analoguePinCounter, 25);
        //print out the readings
        if (avgTempC < float(errReturn)) //there hasn't been any temps outside the range ***CHECK THE VALUE RETURNED FROM LPF IF ERROR***
        {
          Serial.print(analoguePinCounter);
          Serial.print(" | Average Temperature Readings = ");
          Serial.print(avgTempC, 2);
          Serial.println(" degC.");
          Serial.println("-------------------------");
        }
        else //avgTempC has returned X indicating an error
        {
          Serial.print(analoguePinCounter);
          Serial.println("**ERROR IN READING AVERAGE TEMP**");
          Serial.println("-------------------------");
          delay(10);
        }//end if
        delay(constDelay/2); //wait X/2 seconds until moving onto next sensor
      }//end for
      delay(constDelay); //wait X seconds until next loop
    }//end Loop function

    /*
    #####LOW PASS FILTER DESCRIPTION#####
    This function is a LPF for smoothing out signals or averaging
    It uses a static buffer to store the last "n" readings, and each time it is called,
    the oldest reading is discarded, the new reading is added, and the stack average
    value is returned.
    The buffer size is user-adjustable, but is constrained between 2 and 50
    An initialization function fills the entire buffer with the input value.
    This is useful when the LPF function is called for the first time.
    Note: To meet the definition of a true LPF, this function must be called         at regular intervals.
    */
    //#####LOW PASS FILTER FUNCTION#####
    float LPF(int pinAnalogue, int bufferSize)
    {
      //##PRE PROCESSOR##
      #define bufferCap 75 //maximum buffer capacity
      //##CONSTANTS##
      const int constMAXERRORS = 5; //max number of error that can occur
      const int errReturn = 998; //value return if there is an error
      //##VARIABLES##
      float tempC; //var to store instantaneous temp
      static float buffer[bufferCap]; //array to act like a 'stack' of temp values ***DOES IT NEED TO BE STATIC NOW?***
      float tempSum; //to store the sum of the temperatures
      float output; //return value of LPF which is the average of the temp readings
      int errCounter = 0; //initialise error counter to 0

      //make sure buffer size is between the range
      bufferSize = constrain(bufferSize, 2, bufferCap);

      for (int i=0; i<bufferSize; i++) //for loop to store temps in buffer array
      {
        tempC = getTempFloat(pinAnalogue); //call function to get temperature from pin
        if ((tempC > -errReturn) && (tempC < errReturn)) //no error
        {
          buffer[i] = tempC; //store temp value into array
        }
        else //error
        {
          errCounter++; //increment counter for number of erroneous readings
          i--; //decrement counter as to not skip a sample index
          if (errCounter > constMAXERRORS)
          {
            return(errReturn+1.0); //return the error value + 1
          }//end if
        }//end if
        delay(25); //allow the ADC to settle
      }//end for

      //calculate current stack average
      tempSum = 0; //initialise sum total
      for (int i=0; i<bufferSize; i++) //go through stack array
      {
        tempSum = tempSum + buffer[i]; //total up readings
      }//end for

      //average sum
      output = tempSum/bufferSize;

      return(output);
    }//end LPF function

    /*
    #####GET TEMP FLOAT DESCRIPTION#####
    This function converts a thermistor reading into a corresponding temp in ^C
    The thermistor is incorporated into a Voltage Divider Circuit:

       +Vref---[Thermistor]---+--[1.8K]---GND
                              |
                             ADC @ thermPin

    ADC Values were externally calculated from the calibration table using:           ADC = 1023*10000/(Rtherm+10000)
    The LUT is an array of integer constants containing the predicted ADC         values for all temperatures between +6^C to +40.5^C.
    The array index starts at zero, which corresponds to a temperature of         +6^C.
    A linear interpolation between the two closest entries is performed to         give a finer output resolution.
    */

    float getTempFloat (int thermPin)
    {
      //##CONSTANTS##
      /*1K8*/
      const int constLUTArraySize = 431;
      const int LUT_Therm[constLUTArraySize] = //LUT containing ADC values
      {
        223, 224, 225, 226, 227, 228, 229, 230, 231, 232,         //7^C to 7.9^C
        233, 234, 235, 236, 237, 238, 239, 240, 241, 242,
        244, 245, 246, 247, 248, 249, 250, 251, 252, 253,
        255, 256, 257, 258, 259, 260, 261, 263, 264, 265,
        266, 267, 268, 269, 271, 272, 273, 274, 275, 277,
        278, 279, 280, 281, 283, 284, 285, 286, 287, 289,
        290, 291, 292, 294, 295, 296, 297, 299, 300, 301,           //13^C to 13.9^C
        302, 304, 305, 306, 308, 309, 310, 312, 313, 314,
        315, 317, 318, 319, 321, 322, 323, 325, 326, 327,
        329, 330, 332, 333, 334, 336, 337, 338, 340, 341,
        343, 344, 345, 347, 348, 350, 351, 353, 354, 355,
        357, 358, 360, 361, 363, 364, 366, 367, 369, 370,
        371, 373, 374, 376, 377, 379, 380, 382, 383, 385,
        387, 388, 390, 391, 393, 394, 396, 397, 399, 400,
        402, 404, 405, 407, 408, 410, 411, 413, 415, 416,
        418, 419, 421, 423, 424, 426, 428, 429, 431, 433,
        434, 436, 438, 439, 441, 443, 444, 446, 448, 449,
        451, 453, 454, 456, 458, 460, 461, 463, 465, 466,
        468, 470, 472, 473, 475, 477, 479, 480, 482, 484,
        486, 488, 489, 491, 493, 495, 497, 498, 500, 502,
        504, 506, 507, 509, 511, 513, 515, 517, 519, 520,
        522, 524, 526, 528, 530, 532, 534, 535, 537, 539,
        541, 543, 545, 547, 549, 551, 553, 555, 557, 559,
        560, 562, 564, 566, 568, 570, 572, 574, 576, 578,
        580, 582, 584, 586, 588, 590, 592, 594, 596, 598,
        600, 602, 604, 606, 608, 611, 613, 615, 617, 619,
        621, 623, 625, 627, 629, 631, 633, 635, 638, 640,
        642, 644, 646, 648, 650, 652, 655, 657, 659, 661,
        663, 665, 667, 670, 672, 674, 676, 678, 680, 683,
        685, 687, 689, 691, 694, 696, 698, 700, 702, 705,
        707, 709, 711, 714, 716, 718, 720, 723, 725, 727,
        729, 732, 734, 736, 738, 741, 743, 745, 747, 750,
        752, 754, 757, 759, 761, 764, 766, 768, 771, 773,
        775, 778, 780, 782, 785, 787, 789, 792, 794, 796,
        799, 801, 803, 806, 808, 811, 813, 815, 818, 820,
        822, 825, 827, 830, 832, 834, 837, 839, 842, 844,
        847, 849, 851, 854, 856, 859, 861, 864, 866, 868,
        871, 873, 876, 878, 881, 883, 886, 888, 891, 893,
        896, 898, 901, 903, 906, 908, 911, 913, 916, 918,
        921, 923, 926, 928, 931, 933, 936, 938, 941, 943,
        946, 948, 951, 953, 956, 958, 961, 963, 966, 969,
        971, 974, 976, 979, 981, 984, 987, 989, 992, 994,
        997, 999, 1002, 1005, 1007, 1010, 1012, 1015, 1017, 1020, //40^C to 49.9^C
        1023                                                     //50^C
      };
      const int errReturn = 998; //error value that is returned
      //##VARIABLES##
      float _tempC; //intermediate results + final temperature return value
      int ADC_Lo; //the lower ADC matching value
      int ADC_Hi; //the higher ADC matching value
      float Temp_Lo; //the lower number matching temperature
      int mapTemp_Lo; //the lower number that will be entered into the map function
      float Temp_Hi; //the higher  number matching temperature
      int mapTemp_Hi; //the higher number that will be entered into the map function

      //prep ADC onto that particular analogue pin to sort out multiplexing etc
      analogRead(thermPin);
      delay(10);
      //get raw ADC value from VDR
      int thermValue = analogRead(thermPin);
      //Serial.println(thermValue);
      /*Serial.print("PinNo : ");
      Serial.println(thermPin);*/
      Serial.print("ADC : ");
      Serial.println(thermValue);
      //return dummy value if the sensor reading falls outside of the LUT
      if (thermValue < LUT_Therm[0]) //less than the least ADC value
        _tempC = -errReturn-1; //under range dummy value
      else if (thermValue > LUT_Therm[constLUTArraySize-1]) //more than the greatest ADC value
        _tempC = errReturn+1; //over range dummy value
      else //value falls in LUT range
      {
        for (int i=0; i<constLUTArraySize; i++) //step through LUT and look for a match
        {
          if (LUT_Therm[i] > thermValue) //LUT value is greater than the reading
          {
            //find the closest higher ADC value
            ADC_Hi = LUT_Therm[i];
            //record the closest higher temperature
            Temp_Hi = float(i/10) + 13.0; //convert to temp
            //get the closest lower temperature - taking the lower table boundary into account
            if (i != 0) //general case -> as long as it is not the first entry
            {
              ADC_Lo = LUT_Therm[i-1]; //store the previous array element as the low
              Temp_Lo = float(i/10) + 13.0 - 0.1; //convert to temp
            }
            else //special case -> counter = 0 ie first array entry
            {
              ADC_Lo = LUT_Therm[i]; //store the first array element
              Temp_Lo = i - float(i/10) + 13.0; //convert to temp
            }//end if
            //interpolate the temperature value for greater precision
            //NB the map function does not use floating-point math, so the int values of temp are multiplied by 100 and then result is subsequently divided by 100
            mapTemp_Lo = Temp_Lo*100;
            mapTemp_Hi = Temp_Hi*100;
            _tempC = float(map(thermValue,ADC_Lo,ADC_Hi,mapTemp_Lo,mapTemp_Hi))/100;
            break;  //exit for loop after the match is detected
          }//end if
        }//end for
      }//end if
      return(_tempC);
    }//end getTempFloat function

```

In this particular sketch no output is seen on the serial monitor. Has anyone come across this before or have any ideas how I could fix this?

# Answer
> 4 votes
Use the `F()` macro for all double-quoted strings you print. Change lines like this:

```
Serial.println(" degC.");

```

...to this:

```
Serial.println( F(" degC.") );

```

This will save about 100 bytes of RAM.

And as BrettAM suggested, put that table into PROGMEM:

```
  const int LUT_Therm[constLUTArraySize] PROGMEM = //LUT containing ADC values
  {
    223, 224, 225, 226, 227, 228, 229, 230, 231, 232,         //7^C to 7.9^C

```

This requires changing how you access the array, from this:

```
  if (thermValue < LUT_Therm[0]) //less than the least ADC value

```

...to this:

```
  if (thermValue < (int) pgm_read_word( &LUT_Therm[0] )) //less than the least ADC value

```

Note the cast, the function call and the ampersand wrapped around the desired array element. You must replace all uses of the array with this sequence. You can also read it once into a local `int` and then use it normally:

```
      int lut_therm = (int) pgm_read_word(LUT_Therm[i]); // read it in

      if (lut_therm > thermValue) //LUT value is greater than the reading

```

This saves almost 1000 bytes of RAM! The reported binary sketch size goes *up* by the same amount<sup>\[1\]</sup>.

I had to pull the table out from inside `getTempFloat`, to the file scope. Here's the complete sketch with those mods:

```
/*
#####PROJECT DESCRIPTION#####
Measures temperature with an Arduino and NTC Thermistor (10Kohms @ 25^C)                                 in a voltage divider circuit
Since the response is non-linear, a lookup table is used since there is a non linear response
The values in the LUT are the predicted values of the ADC at  temperature between 6^C and 40^C
LUT has been derived from the calibration tests
*/

//#####CONSTANTS#####
const int constDelay = 3000; //constant delay for program
const int constNoOfAnaloguePins = 2; //number of analogue pins that are to be read
const int errReturn = 998; //error value that is returned ***CHECK FOR CONSITENT VALUE ACROSS FUNCTIONS***

//#####VARIABLE DECLARATIONS#####
float avgTempC; //float var to store average of multiple temp readings

//#####SETUP PROCEDURE#####
void setup()
{
  //this is the Setup part of your project - this is for code that is run only ONCE at startup
  for (int analoguePinCounter = 0; analoguePinCounter < constNoOfAnaloguePins; analoguePinCounter++) //for loop to set up numerous analogue pins
  {
    pinMode(analoguePinCounter, INPUT);  //set pin mode of the analogue thermistor input
  }//end for
  analogReference(INTERNAL); //use the interval votlage of 1.1V for the ADC resolution
  Serial.begin(9600); //serial monitor baud rate
}//end Setup function

//#####LOOP PROCEDURE#####
void loop()
{
  //this is the main part of your project - put all continuously running code here
  for (int analoguePinCounter = 0; analoguePinCounter < constNoOfAnaloguePins; analoguePinCounter++) //for loop to take temp readings from each analogue pin
  {
    //get LPF average reading over 25 samples
    avgTempC = LPF(analoguePinCounter, 25);
    //print out the readings
    if (avgTempC < float(errReturn)) //there hasn't been any temps outside the range ***CHECK THE VALUE RETURNED FROM LPF IF ERROR***
    {
      Serial.print(analoguePinCounter);
      Serial.print( F(" | Average Temperature Readings = ") );
      Serial.print(avgTempC, 2);
      Serial.println( F(" degC.") );
      Serial.println( F("-------------------------") );
    }
    else //avgTempC has returned X indicating an error
    {
      Serial.print(analoguePinCounter);
      Serial.println( F("**ERROR IN READING AVERAGE TEMP**") );
      Serial.println( F("-------------------------") );
      delay(10);
    }//end if
    delay(constDelay/2); //wait X/2 seconds until moving onto next sensor
  }//end for
  delay(constDelay); //wait X seconds until next loop
}//end Loop function

/*
#####LOW PASS FILTER DESCRIPTION#####
This function is a LPF for smoothing out signals or averaging
It uses a static buffer to store the last "n" readings, and each time it is called,
the oldest reading is discarded, the new reading is added, and the stack average
value is returned.
The buffer size is user-adjustable, but is constrained between 2 and 50
An initialization function fills the entire buffer with the input value.
This is useful when the LPF function is called for the first time.
Note: To meet the definition of a true LPF, this function must be called         at regular intervals.
*/
//#####LOW PASS FILTER FUNCTION#####
float LPF(int pinAnalogue, int bufferSize)
{
  //##PRE PROCESSOR##
  #define bufferCap 75 //maximum buffer capacity
  //##CONSTANTS##
  const int constMAXERRORS = 5; //max number of error that can occur
  //##VARIABLES##
  float tempC; //var to store instantaneous temp
  static float buffer[bufferCap]; //array to act like a 'stack' of temp values ***DOES IT NEED TO BE STATIC NOW?***
  float tempSum; //to store the sum of the temperatures
  float output; //return value of LPF which is the average of the temp readings
  int errCounter = 0; //initialise error counter to 0

  //make sure buffer size is between the range
  bufferSize = constrain(bufferSize, 2, bufferCap);

  for (int i=0; i<bufferSize; i++) //for loop to store temps in buffer array
  {
    tempC = getTempFloat(pinAnalogue); //call function to get temperature from pin
    if ((tempC > -errReturn) && (tempC < errReturn)) //no error
    {
      buffer[i] = tempC; //store temp value into array
    }
    else //error
    {
      errCounter++; //increment counter for number of erroneous readings
      i--; //decrement counter as to not skip a sample index
      if (errCounter > constMAXERRORS)
      {
        return(errReturn+1.0); //return the error value + 1
      }//end if
    }//end if
    delay(25); //allow the ADC to settle
  }//end for

  //calculate current stack average
  tempSum = 0; //initialise sum total
  for (int i=0; i<bufferSize; i++) //go through stack array
  {
    tempSum = tempSum + buffer[i]; //total up readings
  }//end for

  //average sum
  output = tempSum/bufferSize;

  return(output);
}//end LPF function

/*
#####GET TEMP FLOAT DESCRIPTION#####
This function converts a thermistor reading into a corresponding temp in ^C
The thermistor is incorporated into a Voltage Divider Circuit:

   +Vref---[Thermistor]---+--[1.8K]---GND
                          |
                         ADC @ thermPin

ADC Values were externally calculated from the calibration table using:           ADC = 1023*10000/(Rtherm+10000)
The LUT is an array of integer constants containing the predicted ADC         values for all temperatures between +6^C to +40.5^C.
The array index starts at zero, which corresponds to a temperature of         +6^C.
A linear interpolation between the two closest entries is performed to         give a finer output resolution.
*/

//##CONSTANTS##
/*1K8*/
const int LUT_Therm[] PROGMEM = //LUT containing ADC values
{
  223, 224, 225, 226, 227, 228, 229, 230, 231, 232,         //7^C to 7.9^C
  233, 234, 235, 236, 237, 238, 239, 240, 241, 242,
  244, 245, 246, 247, 248, 249, 250, 251, 252, 253,
  255, 256, 257, 258, 259, 260, 261, 263, 264, 265,
  266, 267, 268, 269, 271, 272, 273, 274, 275, 277,
  278, 279, 280, 281, 283, 284, 285, 286, 287, 289,
  290, 291, 292, 294, 295, 296, 297, 299, 300, 301,           //13^C to 13.9^C
  302, 304, 305, 306, 308, 309, 310, 312, 313, 314,
  315, 317, 318, 319, 321, 322, 323, 325, 326, 327,
  329, 330, 332, 333, 334, 336, 337, 338, 340, 341,
  343, 344, 345, 347, 348, 350, 351, 353, 354, 355,
  357, 358, 360, 361, 363, 364, 366, 367, 369, 370,
  371, 373, 374, 376, 377, 379, 380, 382, 383, 385,
  387, 388, 390, 391, 393, 394, 396, 397, 399, 400,
  402, 404, 405, 407, 408, 410, 411, 413, 415, 416,
  418, 419, 421, 423, 424, 426, 428, 429, 431, 433,
  434, 436, 438, 439, 441, 443, 444, 446, 448, 449,
  451, 453, 454, 456, 458, 460, 461, 463, 465, 466,
  468, 470, 472, 473, 475, 477, 479, 480, 482, 484,
  486, 488, 489, 491, 493, 495, 497, 498, 500, 502,
  504, 506, 507, 509, 511, 513, 515, 517, 519, 520,
  522, 524, 526, 528, 530, 532, 534, 535, 537, 539,
  541, 543, 545, 547, 549, 551, 553, 555, 557, 559,
  560, 562, 564, 566, 568, 570, 572, 574, 576, 578,
  580, 582, 584, 586, 588, 590, 592, 594, 596, 598,
  600, 602, 604, 606, 608, 611, 613, 615, 617, 619,
  621, 623, 625, 627, 629, 631, 633, 635, 638, 640,
  642, 644, 646, 648, 650, 652, 655, 657, 659, 661,
  663, 665, 667, 670, 672, 674, 676, 678, 680, 683,
  685, 687, 689, 691, 694, 696, 698, 700, 702, 705,
  707, 709, 711, 714, 716, 718, 720, 723, 725, 727,
  729, 732, 734, 736, 738, 741, 743, 745, 747, 750,
  752, 754, 757, 759, 761, 764, 766, 768, 771, 773,
  775, 778, 780, 782, 785, 787, 789, 792, 794, 796,
  799, 801, 803, 806, 808, 811, 813, 815, 818, 820,
  822, 825, 827, 830, 832, 834, 837, 839, 842, 844,
  847, 849, 851, 854, 856, 859, 861, 864, 866, 868,
  871, 873, 876, 878, 881, 883, 886, 888, 891, 893,
  896, 898, 901, 903, 906, 908, 911, 913, 916, 918,
  921, 923, 926, 928, 931, 933, 936, 938, 941, 943,
  946, 948, 951, 953, 956, 958, 961, 963, 966, 969,
  971, 974, 976, 979, 981, 984, 987, 989, 992, 994,
  997, 999, 1002, 1005, 1007, 1010, 1012, 1015, 1017, 1020, //40^C to 49.9^C
  1023                                                     //50^C
};
const int constLUTArraySize = sizeof(LUT_Therm)/sizeof(LUT_Therm[0]);

float getTempFloat (int thermPin)
{
  //##VARIABLES##
  float _tempC; //intermediate results + final temperature return value
  int ADC_Lo; //the lower ADC matching value
  int ADC_Hi; //the higher ADC matching value
  float Temp_Lo; //the lower number matching temperature
  int mapTemp_Lo; //the lower number that will be entered into the map function
  float Temp_Hi; //the higher  number matching temperature
  int mapTemp_Hi; //the higher number that will be entered into the map function

  //prep ADC onto that particular analogue pin to sort out multiplexing etc
  analogRead(thermPin);
  delay(10);
  //get raw ADC value from VDR
  int thermValue = analogRead(thermPin);
  //Serial.println(thermValue);
  /*Serial.print( F("PinNo : ") );
  Serial.println(thermPin);*/
  Serial.print( F("ADC : ") );
  Serial.println(thermValue);

  //return dummy value if the sensor reading falls outside of the LUT
  if (thermValue < (int) pgm_read_word( &LUT_Therm[0] )) //less than the least ADC value
    _tempC = -errReturn-1; //under range dummy value

  else if (thermValue > (int) pgm_read_word(LUT_Therm[constLUTArraySize-1])) //more than the greatest ADC value
    _tempC = errReturn+1; //over range dummy value

  else //value falls in LUT range
  {
    int prev_lut_therm = 0;
    for (int i=0; i<constLUTArraySize; i++) //step through LUT and look for a match
    {
      int lut_therm = (int) pgm_read_word(LUT_Therm[i]);
      if (lut_therm > thermValue) //LUT value is greater than the reading
      {
        //find the closest higher ADC value
        ADC_Hi = lut_therm;
        //record the closest higher temperature
        Temp_Hi = float(i/10) + 13.0; //convert to temp
        //get the closest lower temperature - taking the lower table boundary into account
        if (i != 0) //general case -> as long as it is not the first entry
        {
          ADC_Lo = prev_lut_therm; //store the previous array element as the low
          Temp_Lo = float(i/10) + 13.0 - 0.1; //convert to temp
        }
        else //special case -> counter = 0 ie first array entry
        {
          ADC_Lo = lut_therm; //store the first array element
          Temp_Lo = i - float(i/10) + 13.0; //convert to temp
        }//end if
        //interpolate the temperature value for greater precision
        //NB the map function does not use floating-point math, so the int values of temp are multiplied by 100 and then result is subsequently divided by 100
        mapTemp_Lo = Temp_Lo*100;
        mapTemp_Hi = Temp_Hi*100;
        _tempC = float(map(thermValue,ADC_Lo,ADC_Hi,mapTemp_Lo,mapTemp_Hi))/100;
        break;  //exit for loop after the match is detected
      }//end if
      prev_lut_therm = lut_therm;
    }//end for
  }//end if
  return(_tempC);
}//end getTempFloat function

```

Note the technique for declaring the `LUT_Therm` array, using the empty `[]` brackets (line 135).

That's followed by the `const int` array size (line 182) that is "calculated" from the array declaration: (Total array size) / (size of one array element). If you ever change the lookup table, you don't have to count the elements by hand. Let the compiler do it for you! :)

---

\[1\] Although the IDE reports an increased binary sketch size, the total uploaded size is unchanged:
```
PROGMEM keyword   text    data     bss
No                5948     894     483
Yes               6810      32     483

```

As you can see, the 862 bytes for this table move from the `data` section to the `text` section. The uploaded HEX files are identical at 93,737 bytes.

# Answer
> 4 votes
You have likely run out of RAM.

You have 431 integers in the look-up table alone. That equates to 862 bytes of SRAM. You also have a buffer of 75 floats, which equates to 300 bytes. This is in addition to all your other variables and function calls.

The Arduino Uno only has 2KB of SRAM.

Solutions:
1) Move your LUT to Flash (ie. program space) using the PROGMEM keyword (just before the equals sign):

```
const int LUT_Therm[constLUTArraySize] PROGMEM = //LUT containing ADC values

```

2) Use an Arduino with a greater amount of SRAM.

* Arduino Mega - 8KB SRAM
* Arduino ZERO - 32KB SRAM
* Arduino Due - 96KB SRAM
* Arduino MKR 1000/1010/1400/ZERO - 32KB SRAM

# Answer
> 2 votes
I went through your program and found a few bugs you may want to fix. I think only one of these (wastage of RAM) is really related to your problem, but anyway, here it goes:

Fist, there are two issues with `LPF()`. The description states that this is a rolling average low-pass filter. This is erroneous: a rolling average would take a *single reading*, then report the average of the last *n* readings. This function, in contrast, takes *n* readings and reports their average. This makes a big difference: a rolling average would need to store the last *n* values in static memory, while your function does this for no good reason. You are just wasting 300 bytes of RAM.

Here is a reimplementation of `LPF()` that does the same thing as yours without wasting RAM. I changed its name to be more consistent with it's real purpose:

```
/*
 * Take 'count' temperature readings from 'pin' and return their average.
 * Returns NaN (not a number) if too many readings where in error.
 */
float getAvgTemp(int pin, int count)
{
  const int MAXERRORS = 5; // max number of errors that can occur
  float temp;              // current temperature reading
  float tempSum = 0;       // sum of temperatures
  int errCounter = 0;      // number of erroneous readings

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

    // Try to get a valid reading.
    do {
      temp = getTempFloat(pin);
      if (isnan(temp))
        errCounter++;
      delay(25); // allow the ADC to settle
    } while (isnan(temp) && errCounter <= MAXERRORS);

    // Too many errors: return an error.
    if (errCounter > MAXERRORS)
      return NAN;

    tempSum += temp;
  }

  return tempSum / count;
}

```

Here I use NaN (not a number) as an error indicator, as it is semantically clearer than a random out-of-range value.

There are also a few errors in `getTempFloat()`:

* `pgm_read_word(LUT_Therm[constLUTArraySize-1])` and `pgm_read_word(LUT_Therm[i])` will not work: you have to pass `pgm_read_word()` the *address* where to read.
* `float(i/10)` does not do what you want: it computes `i/10` as an integer division (i.e. discarding the fractional part), and *then* it converts the result to a float. If you want a floating point division, you should make sure that at least one of the arguments is a float. The usual idiom is `i/10.0`.

Here is a version of `getTempFloat()` with these problems fixed, and also somewhat simplified:

```
float getTempFloat(int pin)
{
  int i, lutval, prev_lutval;

  // Take an analog reading.
  analogRead(pin);  // dummy reading to settle the MUX
  delay(10);
  int adc = analogRead(pin);
  Serial.print(F("ADC: "));
  Serial.println(adc);

  // Find i such that adc lies between LUT[i-1] and LUT[i].
  for (i = 0; i < constLUTArraySize; i++) {
    prev_lutval = lutval;
    lutval = pgm_read_word(&LUT_Therm[i]);
    if (lutval >= adc) break;
  }

  // Special case: adc == LUT[0].
  if (i == 0 && adc == lutval)
    return 13.0;

  // Report an error if out of range.
  if (i == 0 || i == constLUTArraySize)
    return NAN;

  // Return interpolated temperature.
  float fraction = float(adc - prev_lutval) / (lutval - prev_lutval);
  return 13.0 + (i-1 + fraction) / 10.0;
}

```

---

## Addendum

I have noticed a few more problems and inconsistencies with your program.

### Powering the thermistor from the internal reference

In `setup()`, you write

> analogReference(INTERNAL); //use the interval votlage of 1.1V for the ADC resolution

and then, in a comment further down you have the schematic

> +Vref---\[Thermistor\]---+--\[1.8K\]---GND

This suggests you are powering the voltage divider from the internal voltage reference of the MCU. You should not do that, as the datasheet states: “Note that V<sub>REF</sub> is a high impedance source, and only a capacitive load should be connected in a system.”

### Relationship between ADC reading and thermistor resistance

In the same comment as above, you wrote:

> ADC = 1023\*10000/(Rtherm+10000)

Actually, the factor is 1024, not 1023. Again, see the datasheet. And the number `10000` should be `1800`, i.e. the resistance you have put between the ADC input and GND. I understand that you may have simply changed the value and forgotten to update one of the comments. But you should consider a misleading comment as a bug, especially if it's not consistent with the actual code.

For this kind of measurement, you get the best precision if the pulldown resistor has a value close to the resistance of the thermistor. The comment at the beginning of the program says your thermistor has 10 kΩ @ 25°C. This means that, if you are mostly interested in the range around 25°C, a 10 kΩ pulldown is better than 1.8 kΩ.

### Relationship between array index and temperature

The comment before the LUT says:

> The array index starts at zero, which corresponds to a temperature of +6^C

Then, the very first line of the LUT has the comment

> //7^C to 7.9^C

And later on, the implementation of `getTempFloat()` assumes index 0 means 13°C. You should sort this out and make everything consistent.

BTW, your LUT values go all the way up to 1023. A reading of 1023 would mean the ADC voltage is higher than 1022.5/1024×V<sub>REF</sub>. Which in turn would imply the thermistor has a resistance lower than 14.6 Ω (assuming a 10 kΩ pulldown). I find this dubious.

### Removal of the LUT

Since your program is meant to run very slowly (`constDelay = 3000`), you can afford doing complex computations in it. You can get the same precision with a way smaller LUT if you use a higher order interpolation. For a function sampled at constant steps, the Catmull–Rom spline is easy to implement and is way better than linear interpolation.

Or you can remove the LUT altogether and use an analytical expression instead. If you derived the LUT from such an expression, why not use it in the program? If the LUT derives from experimental data, you can try to do an empirical fit, i.e. an arbitrary function that closely fits the data. The most obvious (though maybe not the best) empirical function would be a polynomial. Below is an example of such a function that reproduces you LUT with good accuracy using a 6th degree polynomial. It assumes the first LUT entry is for a temperature of 7°C:

```
float getTempFloat(int pin)
{
    const float T0 = 7;   // temperature at beginning of range
    int adc = analogRead(pin);
    float x = (adc-223.) / (1023.-223.) * 2 - 1;  // scale to [-1:1]
    if (x < -1 || x > 1) return NAN;              // out of range
    float y = 1.474 - x*(0.533 - x*(0.732 - x*0.458));
    return T0 + 26.107 + x*(19.287 - x*(3.596 - x*y));
}

```

Actually this may be even more accurate than your LUT-based function, as that LUT is made of integer values whereas the calibration curve should obviously be continuous.

---
Tags: arduino-uno, serial, c++, sram
---


# Question
Title: Is it possible to replace this delay with millis()? (And issue with other millis loop)
I am working on updating a project and I have a thread over in the Arduino forum which helped me out, but I'm a bit stuck, and there isn't much activity going on there.

This code is for use with a one wire temperature sensor, however, each time it retrieves data for the sensor, it has a 750ms delay as seen here:

```
ds.reset();
ds.select(addr);
ds.write(0x44, 1);        // start conversion, with parasite power on at the end

delay(750);     // maybe 750ms is enough, maybe not
// we might do a ds.depower() here, but the reset will take care of it.

present = ds.reset();
ds.select(addr);
ds.write(0xBE);         // Read Scratchpad

```

Now, I'm going to be using a momentary button as a toggle, but for this I need to debounce it, using a delay. With the 750ms delay present for the temperature sensor, that just isn't feasible, it makes it too unpredictable and difficult to use.

I need to replace this delay with a `millis` counter, but I'm not sure if I can without hanging up the rest of the script. I gave it a try like so, but it completely screwed up the reading.

```
if (owcurrentMillis - owpreviousMillis >= owinterval) {
owpreviousMillis = owcurrentMillis;
present = ds.reset();
ds.select(addr);
ds.write(0xBE);         // Read Scratchpad
}

```

I then tried it like so, and the readout does still work, however, I have an LED which lights up when the temperature has "Stabilized", which it's supposed to check every one second, but that has stopped working, and it's basically instant making it useless. I don't know why that `millis` loop does not work though, it was only working due to the 750ms delay.

```
if (owcurrentMillis - owpreviousMillis >= owinterval) {
owpreviousMillis = owcurrentMillis;
ds.reset();
ds.select(addr);
ds.write(0x44, 1);        // start conversion, with parasite power on at the end
}

```

Here is the bit of code controlling the LED illumination.

```
if (currentMillis - previousMillis >= interval) {  //If it has been 20 seconds, check to turn LED on
previousMillis = currentMillis;
if ((delta < 00.03) && (delta > -00.03)) {      //If temperature hasn't changed by +/- .05 turn led on.
  digitalWrite(A0, HIGH);
}
}
if (delta >= 00.06) {                             //If temperature has changed by more than .1 turn LED off
digitalWrite(A0, LOW);
}
if (delta <= -00.06) {
digitalWrite(A0, LOW);                         // If temperature has changed by more than -.1 turn LED off
}

```

I think if I can get that one to work properly, instead of messing up like it is now I should be good, then I just need the 50ms delay to debounce the button which will trigger what I need, I just can't figure out why it will not work.

You can see the version which works best here (with the 750ms delay in place):

```
#include <OneWire.h>
#include <LiquidCrystal.h>
#include <SPI.h>
#include <SD.h>
const int chipSelect = 10;

OneWire  ds(9);                               //Onewire + lcd setup
LiquidCrystal lcd(6, 7, 5, 4, 3, 2);
float lasttemp;                              //Variable for last temperature
float delta;                                 //Variable for temperaturechange
long previousMillis = 0;
const long interval = 1000;                       //Check once every 20 seconds

const long sdinterval = 5000;
long sdpreviousMillis = 0;

File myFile;

void setup(void) {
  pinMode(A0, OUTPUT);
  pinMode(A3, OUTPUT);

  Serial.begin(115200);                       //Start serial + LCD/Light test
  lcd.begin(8, 2);
  lcd.setCursor(0,0);
  lcd.print("STARTING");
  lcd.setCursor(0, 1);
  lcd.print("VER. 1.2");
  digitalWrite(A0, HIGH);
  digitalWrite(A3, LOW);
  delay(1000);
  digitalWrite(A0, LOW);
  digitalWrite(A3, HIGH);
  lcd.clear();                                //End of LCD/Light test

  if (!SD.begin(10)) {                       // Check for SD card
    digitalWrite(A3, LOW);
    lcd.setCursor(0,0);
    lcd.print("SD CHECK");
    lcd.setCursor(0,1);
    lcd.print("  FAIL  ");
    delay(1000);
    lcd.clear();
    digitalWrite(A3, HIGH);
  } else {
    delay(1000);
    digitalWrite(A3, LOW);
    lcd.setCursor(0,0);
    lcd.print("SD CHECK");
    lcd.setCursor(0,1);
    lcd.print("  PASS  ");
    delay(1000);
    lcd.clear();
    digitalWrite(A3, HIGH);
  }
}

void loop(void) {

  unsigned long sdcurrentMillis = millis();
  unsigned long currentMillis = millis();
{
  }

  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius, fahrenheit;

  if ( !ds.search(addr)) {
    Serial.println("No more addresses.");
    Serial.println();
    ds.reset_search();
    delay(250);
    return;
  }

  Serial.print("ROM =");
  for( i = 0; i < 8; i++) {
    Serial.write(' ');
    Serial.print(addr[i], HEX);
  }

  if (OneWire::crc8(addr, 7) != addr[7]) {
    Serial.println("CRC is not valid!");
    return;
  }
  Serial.println();

  // the first ROM byte indicates which chip
  switch (addr[0]) {
  case 0x10:
    Serial.println("  Chip = DS18S20");  // or old DS1820
    type_s = 1;
    break;
  case 0x28:
    Serial.println("  Chip = DS18B20");
    type_s = 0;
    break;
  case 0x22:
    Serial.println("  Chip = DS1822");
    type_s = 0;
    break;
  default:
    Serial.println("Device is not a DS18x20 family device.");
    return;
  }

  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1);        // start conversion, with parasite power on at the end

  delay(1000);     // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.

  present = ds.reset();
  ds.select(addr);
  ds.write(0xBE);         // Read Scratchpad

  Serial.print("  Data = ");
  Serial.print(present, HEX);
  Serial.print(" ");
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
    Serial.print(data[i], HEX);
    Serial.print(" ");
  }
  Serial.print(" CRC=");
  Serial.print(OneWire::crc8(data, 8), HEX);
  Serial.println();

  // Convert the data to actual temperature
  // because the result is a 16 bit signed integer, it should
  // be stored to an "int16_t" type, which is always 16 bits
  // even when compiled on a 32 bit processor.
  int16_t raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // "count remain" gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  }
  else {
    byte cfg = (data[4] & 0x60);
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
    //// default is 12 bit resolution, 750 ms conversion time
  }

  celsius = (float)raw / 16.0;
  fahrenheit = celsius * 1.8 + 32.0;
  Serial.print("  Temperature = ");
  Serial.print(celsius);
  Serial.print(" Celsius, ");
  Serial.print(fahrenheit);
  Serial.println(" Fahrenheit");

  delta = celsius - lasttemp;                       //Create value to check how much temperature has changed

  if (currentMillis - previousMillis >= interval) {  //If it has been 20 seconds, check to turn LED on
    previousMillis = currentMillis;
    if ((delta < 00.03) && (delta > -00.03)) {      //If temperature hasn't changed by +/- .05 turn led on.
      digitalWrite(A0, HIGH);
    }
  }
  if (delta >= 00.06) {                             //If temperature has changed by more than .1 turn LED off
    digitalWrite(A0, LOW);
  }
  if (delta <= -00.06) {
    digitalWrite(A0, LOW);                         // If temperature has changed by more than -.1 turn LED off
  }

    if (sdcurrentMillis - sdpreviousMillis >= sdinterval) {  //Write to SD card every 5 seconds.
    sdpreviousMillis = sdcurrentMillis;
    digitalWrite(A3, LOW);
    myFile = SD.open("Log.txt", FILE_WRITE);
    myFile.print(celsius);
    myFile.println(" C ");
    myFile.close();
    digitalWrite(A3, HIGH);
  }

  lcd.setCursor(0, 0);
  lcd.print(celsius);
  lcd.print(" C ");
  lcd.setCursor(0, 1);
  lcd.print(fahrenheit);
  lcd.print(" F ");
  lasttemp = celsius;
  }

```

and this is the one I'm working on as I write this, with the illumination delay messing up:

```
#include <OneWire.h>
#include <LiquidCrystal.h>
#include <SPI.h>
#include <SD.h>

unsigned long owpreviousMillis = 0;
const long owinterval = 750;
//---------------------------------------------------------------------------------- One wire temperature sensor stuff
OneWire  ds(9);                 //Setting one wire bus pin
byte i;
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
float celsius, fahrenheit;      //Variables for celsius and farenheit conversions
long previousMillis = 0;
float lasttemp;                 //Variable for last temperature
float delta;                    //Variable for temperaturechange
const long interval = 1000;     //Check once every 1 second

//---------------------------------------------------------------------------------- End of one wire temperature sensor stuff.

LiquidCrystal lcd(6, 7, 5, 4, 3, 2); //Defining pins for the LCD

//---------------------------------------------------------------------------------- SD card stuff
const int chipSelect = 10;              //Setting SD chip select pin (obviously)
File myFile;
long sdpreviousMillis = 0;
const long sdinterval = 5000;           //SD card write interval

//-----------------------------------------------------------------------------------End of pre-setup

void setup(void) {
  pinMode(A2, INPUT);
  pinMode(A0, OUTPUT);    //Green LED for temperature stability indication
  pinMode(A3, OUTPUT);    //Red LED for sd card activity indication
  Serial.begin(115200);
//------------------------- Testing LCD and LED's, displaying version number and checking for SD card.
  lcd.begin(8, 2);
  lcd.setCursor(0,0);
  lcd.print("STARTING");
  lcd.setCursor(0, 1);
  lcd.print("VER. 1.5");
  digitalWrite(A0, HIGH);
  digitalWrite(A3, LOW);
  delay(1000);
  digitalWrite(A0, LOW);
  digitalWrite(A3, HIGH);
  lcd.clear();

  if (!SD.begin(10)) {                    // Check for SD card
    digitalWrite(A3, LOW);
    lcd.setCursor(0,0);
    lcd.print("SD CHECK");
    lcd.setCursor(0,1);
    lcd.print("  FAIL  ");
    delay(1000);
    lcd.clear();
    digitalWrite(A3, HIGH);
  } else {
    delay(1000);
    digitalWrite(A3, LOW);
    lcd.setCursor(0,0);
    lcd.print("SD CHECK");
    lcd.setCursor(0,1);
    lcd.print("  PASS  ");
    delay(1000);
    lcd.clear();
    digitalWrite(A3, HIGH);
  }
//----------------------------------- Setting up one wire temperature sensor.
  if ( !ds.search(addr)) {
    Serial.println("No more addresses.");
    Serial.println();
    ds.reset_search();
    delay(250);
    return;
  }
  Serial.print("ROM =");
  for( i = 0; i < 8; i++) {
    Serial.write(' ');
    Serial.print(addr[i], HEX);
  }
  if (OneWire::crc8(addr, 7) != addr[7]) {
    Serial.println("CRC is not valid!");
    return;
  }
  Serial.println();

  // the first ROM byte indicates which chip
  switch (addr[0]) {
  case 0x10:
    Serial.println("  Chip = DS18S20");  // or old DS1820
    type_s = 1;
    break;
  case 0x28:
    Serial.println("  Chip = DS18B20");
    type_s = 0;
    break;
  case 0x22:
    Serial.println("  Chip = DS1822");
    type_s = 0;
    break;
  default:
    Serial.println("Device is not a DS18x20 family device.");
    return;
  }

}
//----------------------------------------------------------------------------- End of setup.

void loop(void) {

  unsigned long sdcurrentMillis = millis();
  unsigned long currentMillis = millis();
  unsigned long owcurrentMillis = millis();

  if (owcurrentMillis - owpreviousMillis >= owinterval) {
    owpreviousMillis = owcurrentMillis;
    ds.reset();
    ds.select(addr);
    ds.write(0x44, 1);        // start conversion, with parasite power on at the end
    }

  present = ds.reset();
  ds.select(addr);
  ds.write(0xBE);         // Read Scratchpad

  Serial.print("  Data = ");
  Serial.print(present, HEX);
  Serial.print(" ");
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
    Serial.print(data[i], HEX);
    Serial.print(" ");
  }
  Serial.print(" CRC=");
  Serial.print(OneWire::crc8(data, 8), HEX);
  Serial.println();

  // Convert the data to actual temperature
  // because the result is a 16 bit signed integer, it should
  // be stored to an "int16_t" type, which is always 16 bits
  // even when compiled on a 32 bit processor.
  int16_t raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // "count remain" gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  }
  else {
    byte cfg = (data[4] & 0x60);
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
    //// default is 12 bit resolution, 750 ms conversion time
  }

  celsius = (float)raw / 16.0;
  fahrenheit = celsius * 1.8 + 32.0;
  Serial.print("  Temperature = ");
  Serial.print(celsius);
  Serial.print(" Celsius, ");
  Serial.print(fahrenheit);
  Serial.println(" Fahrenheit");

  delta = celsius - lasttemp;                       //Create value to check how much temperature has changed

  if (currentMillis - previousMillis >= interval) {  //If it has been 20 seconds, check to turn LED on
    previousMillis = currentMillis;
    if ((delta < 00.03) && (delta > -00.03)) {      //If temperature hasn't changed by +/- .05 turn led on.
      digitalWrite(A0, HIGH);
    }
  }
  if (delta >= 00.06) {                             //If temperature has changed by more than .1 turn LED off
    digitalWrite(A0, LOW);
  }
  if (delta <= -00.06) {
    digitalWrite(A0, LOW);                         // If temperature has changed by more than -.1 turn LED off
  }

    if (sdcurrentMillis - sdpreviousMillis >= sdinterval) {  //Write to SD card every 5 seconds.
    sdpreviousMillis = sdcurrentMillis;
    digitalWrite(A3, LOW);
    myFile = SD.open("Log.txt", FILE_WRITE);
    myFile.print(celsius);
    myFile.println(" C ");
    myFile.close();
    digitalWrite(A3, HIGH);
  }

  lcd.setCursor(0, 0);
  lcd.print(celsius);
  lcd.print(" C ");
  lcd.setCursor(0, 1);
  lcd.print(fahrenheit);
  lcd.print(" F ");
  lasttemp = celsius;
  }

```

This is the post on the Arduino forum which sort of explains what I'm doing a bit better, if it does not make sense: Best way to set up a button to toggle a second function? (millis issue now).

**Edit/update**

Alright, so I think it has to do with how I structured that bit of the code, it seems like the arguments to turn the LED off weren't in the if statement which used the delay, so changed it to this, and unfortunately now it is on constantly, but I think I am on the right track.

```
if (currentMillis - previousMillis >= interval) {  //If it has been 20 seconds, check to turn LED on
previousMillis = currentMillis;
if ((delta < 00.03) && (delta > -00.03)) {       //If temperature hasn't changed by +/- .05 turn led on.
  digitalWrite(A0, HIGH);
} else {
  if ((delta >= 00.06) && (delta <= -00.06)) {
    digitalWrite(A0, LOW);
  }
}
}

```

It seems like this should work but perhaps there's an issue with having two `if` statements set up on top of each other like that. I also gave it a try like this, to no avail.

```
(currentMillis - previousMillis >= interval) {  //If it has been 20 seconds, check to turn LED on
previousMillis = currentMillis;
if ((delta < 00.03) && (delta > -00.03)) {       //If temperature hasn't changed by +/- .05 turn led on.
  digitalWrite(A0, HIGH);
} else {
  if (delta >= 00.06){
    digitalWrite(A0, LOW);
  } else {
  if (delta <= -00.06){
   digitalWrite(A0, LOW);
  }
 }
}
}

```

**Edit/update**

Quick clarification, I managed to get rid of the delay and use millis instead but it introduced an issue with the LED which indicates stable temperature not working (being lit most of the time, and then flashing off/on fairly quickly as the temperature changes, instead of remaining off until it stabilizes again). It seems to be ignoring the delay I have it waiting for.

Now, after going through it a lot, it seems like this is how I need it set up. It checks if the interval has been reached, if so, it checks if the temperature has changed less than *x* amount, if so it lights the LED.

However, if the temperature has changed more than that, it checks if it exceeds *y* amount, and if so turns the light off.

I have tried reversing these and it has had no effect, it just seems like the boolean arguments aren't working and I don't know why, but at least the delay issue is solved.

```
if (currentMillis - previousMillis >= interval) {  //If it has been 20 seconds, check to turn LED on
previousMillis = currentMillis;
if ((delta < 00.03) && (delta > -00.03)) {       //If temperature hasn't changed by +/- .05 turn led on.
  digitalWrite(A0, HIGH);
} else if ((delta >= 00.06) || (delta <= -00.06)) {
    digitalWrite(A0, LOW);
  }
}

```

# Answer
Currently, your algorithm for reading the temperature in `loop()` looks like:

```
request_temperature_conversion();
delay(1000);
float temp = read_temperature();
report_temperature_to_user(temp);

```

If you take care to send the first request in `setup()`, then you can roll these pieces around so that your `loop()` code looks like:

```
delay(1000);
float temp = read_temperature();
report_temperature_to_user(temp);
request_temperature_conversion();

```

And that's the trick: you send the new request in the same loop iteration. Once you do that, it becomes quite simple to remove the delay and use `millis()` instead. Your compete loop code could then look like:

```
void loop() {
  uint32_t now = millis();

  if (now - last_temp_read >= temp_read_interval) {
    float temp = read_temperature();
    report_temperature_to_user(temp);
    request_temperature_conversion();  // make request now, will read next time
    last_temp_read = now;
  }

  if (now - last_led_update >= led_update_interval) {
    update_led_display();
    last_led_update = now;
  }

  if (now - last_SD_card_write >= SD_card_write_interval) {
    write_data_to_log_file();
    last_SD_card_write = now;
  }
}

```
> 2 votes

---
Tags: millis
---


title: VirtualWire send function

text:
# Question
Title: VirtualWire send function
I am a little confused on how exactly VirtualWire's "send" function works. After looking at the code, the process I gathered is the following.

1. In the Arduino IDE, call `vw_send()` with the right parameters.
2. Inside this method, it will start to encode the message and create the packet.
3. Then before the function returns, it calls `vw_tx_start()`.
4. Inside that function, it enables the transmitter hardware and sets the variable "vw\_tx\_enabled" equal to true. Then this function returns, followed by the immediate return of `vw_send()`. So there is no where in this flow where the message is actually being sent.

However, the actual transmission of the message happens inside `vw_Int_Handler()`. But this function is never called in `vw_send()` or `vw_tx_start()`. So the only way this could be happening is if there was some sort of multi-threading correct? Because by setting vw\_tx\_enabled to true, the transmission process would begin inside vw\_Int\_Handler.

Can someone explain/clarify this?

Moreover, this library uses digitalWrite to transmit the bits. Wouldn't it just be faster to toggle the bits at the registry level?

Lastly, in VirtualWire, they send a 36 bit preamble, I assume this is for synchorinzation purposes. So if I want to send 128 byte packet length, how much of a preamble should I use? I believe the reason for VirtualWire only transmitting 27 byte packet length is because the 36 bit preamble will only keep the data synchronized for that long. So is there a certain formula used to determine the preamble size?

# Answer
> 1 votes
> However, the actual transmission of the message happens inside vw\_Int\_Handler(). But this function is never called in vw\_send() or vw\_tx\_start(). So the only way this could be happening is if there was some sort of multi-threading correct? Because by setting vw\_tx\_enabled to true, the transmission process would begin inside vw\_Int\_Handler.

The `vw_Int_Handler` function is called from the interrupt handler of one of the timer modules in the chip. Yes, you could say it was some form of multi-threading in that it happens interleaved with the main processing of your sketch.

> Moreover, this library uses digitalWrite to transmit the bits. Wouldn't it just be faster to toggle the bits at the registry level?

Yes it would, but it would be less portable. VirtualWire has been written to work on a wide range of chips, and doing low-level port access would make the code about 1000x more complex, having to include special code for each and every chip it runs on. Easier (though less efficient) to just use `digitalWrite()`.

> Lastly, in VirtualWire, they send a 36 bit preamble, I assume this is for synchorinzation purposes. So if I want to send 128 byte packet length, how much of a preamble should I use? I believe the reason for VirtualWire only transmitting 27 byte packet length is because the 36 bit preamble will only keep the data synchronized for that long. So is there a certain formula used to determine the preamble size?

VirtualWire uses a coding system called 4b/6b (actually a sub-set of 5b/6b coding). In that system it takes 6 *symbols* to transmit 4 *bits*. It is a way of encoding the clock into the signal in a reasonably efficient manner.

The encoding system means that there can never be 36 alternating 1/0 bits in a message. That unique stream is used as the synchronisation because it can't be confused with anything else. From then on it's just data encoded as 4b/6b. The limit on how much data can be transmitted in one packet is a purely arbitrary value. Since this is a low-speed protocol to low-power devices it is expected that they will have limited RAM, and so limited space to receive data. So small packets are the default.

The numbers in use, incidentally, have been chosen because they fit into the 4b/6b coding scheme quite nicely. For instance 36 symbols of preamble is equivalent to 24 bits of data. The packet size is 30 bytes, three bytes of which are used for control information (checksum, byte count, etc), leaving 27 bytes of actual payload. 30 bytes is 240 bits, which is, in 4b/6b, 360 symbols. 360 symbols could be packed cleanly into 45 bytes for simple transmission (pre-encoding from binary to 4b/6b before transmission).

Other values won't fit quite so neatly.

---
Tags: library, communication, softwareserial, virtualwire
---


title: Zeroing a Vernier force probe

text:
# Question
Title: Zeroing a Vernier force probe
For a class assignment I have been tasked with zeroing a Vernier force probe by typing a command into the serial monitor. I am having trouble writing the code for this algorithim. I was hoping to give the monitor the command and have it save the analogread as a variable which I can later subtract from future reads. Does anyone know if I can save the analogread value without it being updated in a loop? If, so how?

# Answer
Not sure if this is what you mean, but:

```
const int FP = 0;  // force probe analog pin
const int OFFSET = 10; // your deadband depending on your sensors consistency too
int init_read = 0;  // initial read
int curr_read = 0;  // this will be constantly updated till zeroing is done

void setup(){
  Serial.begin(9600);
  //the rest of your setup()
}

void loop(){
  if (Serial.available() && (Serial.read() == 'z')){  // if you sent anything with the monitor and if 'z' is present
    init_read = analogRead(FP); // initial read from sensor before 'zeroing' begins
    while (abs(curr_read - init_read) < OFFSET){ // here you indicate the condition that would mean the probe has been zeroed
      // make your adjustments or whatever
      curr_read = analogRead(FP);  // take a new reading and check in the next iteration
    }
    Serial.print("Zeroing is done.");
  }
}

```

`z` is the command you send from the serial monitor to begin zeroing.
> 1 votes

---
Tags: arduino-uno, documentation
---


# Question
Title: How to define a SoftwareSerial object inside a class?
I have a header file called Rhino.h with class Rhino. I want to pass RX and TX pin numbers to this object class, and with this, define a SoftwareSerial object to be used inside the Rhino class. The code in my header file looks like this (there are more number of functions like gotoPos() which I have omitted for brevity purpose):

```
#include "Arduino.h"

class Rhino
{
public:
    Rhino(int rx,int tx):serial(rx,tx){}

    void gotoPos(int pos)
    {
        serial.write(pos);
    }
private:
    SoftwareSerial serial;
}

```

And my Arduino code looks like this:

```
#include <Rhino.h>
Rhino motor1(9,10);
void setup()
{
    motor1.gotoPos(10);
}
void loop() {}

```

I get this as error:

```
Arduino: 1.0.6 (Windows NT (unknown)), Board: "Arduino Uno"
S:\Program Files (x86)\Arduino\hardware\tools\avr\bin\avr-g++ -c -g -Os -Wall -fno-exceptions -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -MMD -DUSB_VID=null -DUSB_PID=null -DARDUINO=106 -IS:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino -IS:\Program Files (x86)\Arduino\hardware\arduino\variants\standard -IS:\Program Files (x86)\Arduino\libraries\Rhino C:\Users\Samvrit\AppData\Local\Temp\build2516495983752907071.tmp\Test2.cpp -o C:\Users\Samvrit\AppData\Local\Temp\build2516495983752907071.tmp\Test2.cpp.o

In file included from Test2.ino:6:
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:740: error: 'SoftwareSerial' does not name a type
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h: In constructor 'Rhino::Rhino(int, int)':
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:16: error: class 'Rhino' does not have any field named 'serial'
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h: In member function 'void Rhino::init()':
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:21: error: 'serial' was not declared in this scope
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h: In member function 'void Rhino::reset()':
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:30: error: 'serial' was not declared in this scope
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h: In member function 'void Rhino::autoCalibrate()':
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:37: error: 'serial' was not declared in this scope
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h: In member function 'void Rhino::sendCmd(String)':
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:46: error: 'serial' was not declared in this scope
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h: In member function 'void Rhino::sendCmd(char*)':
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:58: error: 'serial' was not declared in this scope
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h: In member function 'void Rhino::rotate(int)':
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:76: error: 'serial' was not declared in this scope
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h: In member function 'void Rhino::stopMotor()':
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:88: error: 'serial' was not declared in this scope
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h: In member function 'void Rhino::gotoPos(float)':
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:103: error: 'serial' was not declared in this scope
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h: In member function 'void Rhino::gotoAngleDeg(float)':
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:123: error: 'serial' was not declared in this scope
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h: In member function 'void Rhino::gotoAngleRad(float)':
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:143: error: 'serial' was not declared in this scope
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h: In member function 'void Rhino::gotoAngleDegC(float)':
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:164: error: 'serial' was not declared in this scope
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h: In member function 'void Rhino::gotoAngleRadC(float)':
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:185: error: 'serial' was not declared in this scope
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h: In member function 'void Rhino::gotoRel(long int)':
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:218: error: 'serial' was not declared in this scope
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h: In member function 'void Rhino::gotoRelDeg(float)':
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:253: error: 'serial' was not declared in this scope
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h: In member function 'void Rhino::gotoRelRad(float)':
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:289: error: 'serial' was not declared in this scope
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h: In member function 'void Rhino::setSFGain(int)':
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:306: error: 'serial' was not declared in this scope
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h: In member function 'void Rhino::setP(int)':
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:322: error: 'serial' was not declared in this scope
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h: In member function 'void Rhino::setI(int)':
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:338: error: 'serial' was not declared in this scope
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h: In member function 'void Rhino::setD(int)':
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:355: error: 'serial' was not declared in this scope
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h: In member function 'void Rhino::setSpeed(int)':
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:372: error: 'serial' was not declared in this scope
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h: In member function 'void Rhino::setI2CAddr(int)':
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:389: error: 'serial' was not declared in this scope
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h: In member function 'void Rhino::setPos(int)':
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:406: warning: unused variable 'curr_pos'
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:415: warning: unused variable 'curr_pos'
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:426: error: 'serial' was not declared in this scope
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h: In member function 'int Rhino::getPos()':
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:474: error: 'serial' was not declared in this scope
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h: In member function 'float Rhino::getAngleDeg()':
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:501: error: 'serial' was not declared in this scope
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h: In member function 'float Rhino::getAngleRad()':
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:528: error: 'serial' was not declared in this scope
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h: In member function 'int Rhino::getSpeed()':
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:555: error: 'serial' was not declared in this scope
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h: In member function 'int Rhino::getRotSpeed()':
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:582: error: 'serial' was not declared in this scope
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h: In member function 'int Rhino::getI2CAddr()':
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:609: error: 'serial' was not declared in this scope
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h: In member function 'int Rhino::getSFGain()':
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:636: error: 'serial' was not declared in this scope
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h: In member function 'int Rhino::getP()':
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:663: error: 'serial' was not declared in this scope
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h: In member function 'int Rhino::getI()':
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:690: error: 'serial' was not declared in this scope
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h: In member function 'int Rhino::getD()':
S:\Program Files (x86)\Arduino\libraries\Rhino/Rhino.h:717: error: 'serial' was not declared in this scope

```

# Answer
> 2 votes
In your header file, I dont see where you included `SoftwareSerial.h`; this may be a part of why you got those errors. Also you need to end the class definition with a semi-colon, like you were advised in a comment.

That said, you could just pass a pointer to a `SoftwareSerial` object to your `Rhino` constructor. In your library header:

```
#include "Arduino.h"
#include <SoftwareSerial.h>

class Rhino {
  private:
    SoftwareSerial * serial;

  public:
    Rhino(SoftwareSerial * ss);
    // other prototypes
};

```

In your .cpp source:

```
#include "Rhino.h"  // assuming thats what you named the header

Rhino::Rhino(SoftwareSerial * ss){
  serial = ss;
 }

void Rhino::begin(uint32_t baud){
  serial->begin(baud);
}

void Rhino::gotoPos(int pos)
{
  serial->write(pos);  // must use the structure pointer operator
}

```

In your Arduino sketch:

```
#include "Rhino.h"
#include <SoftwareSerial.h>

SoftwareSerial ss(2,3);
Rhino rhino(&ss);  // pass a pointer to ss

void setup(){
  rhino.begin(9600);
  rhino.gotoPos(50);
}

```

# Answer
> 6 votes
Personally I wouldn't go down this route. Instead I would pass a `Stream` object (as a pointer or a reference) to the constructor and use that. Then it is up to your sketch to define what that `Stream` object is and initialize it.

That way if you want to use the same class on a hardware UART instead of a `SoftwareSerial` you just change the sketch, not the library.

So you would initialize as something like this:

```
SoftwareSerial mySerial(6, 7);
Rhino myRhino(mySerial);

void setup() {
    mySerial.begin(9600);
    myRhino.gotoPos(34);
}

```

Your Rhino class would look something like this:

```
class Rhino {
    private:
        Stream *_dev;

    public:
        Rhino(Stream *dev) : _dev(dev) {}
        Rhino(Stream &dev) : _dev(&dev) {}
        void gotoPos(int pos);
};

void Rhino::gotoPos(int pos) {
    _dev->write(pos);
}

```

The double constructors, one with a pointer and one with a reference, allow the simplicity of passing an object as in the example, or as a pointer, which could be done with the `new` operator all in one step. I like the way shown in the example though since it is nice and clean.

Of course, because you now have a *pointer* to your stream object, you need to use the pointer dereference operator instead of the normal `.`:

```
_dev->write(pos);

```

Changing to a hardware UART is then as simple as, for example:

```
Rhino myRhino(Serial);

```

Heck, you could even send it through the internet since an Ethernet or WiFi `Client` is also a `Stream` object.

# Answer
> 0 votes
You need to import the SoftwareSerial library into your Rhino.h file, since you are using that class in your header file. Perhaps you are also in need of a forward declaration. Inside your Rhino.h file, include SoftwareSerial library, and then above `class Rhino`, type `class SoftwareSerial;`. This effectively lets the compiler know that Software Serial is being used. More information on forward declarations can be found here.

Modified Code:

```
#include "Arduino.h"
#include "SoftwareSerial.h"

class SoftwareSerial; //this might be unnecessary, but doesn't hurt to have it.
class Rhino
{
public:
Rhino(int rx,int tx):serial(rx,tx){}

void gotoPos(int pos)
{
    serial.write(pos);
}
private:
    SoftwareSerial serial;
}

```

---
Tags: c++, motor, library, softwareserial, uart
---


# Question
Title: Adafruit Neopixel Library- only the first 16 LEDs respond
I am using Adafruit Neopixel Library to work with a strand of 21 RGB LEDs. AT this point only the first 16 light up. It is not a soldering problem, battery issue or a short. This troubleshooting page suggests to

> "confirm that the number of LEDs in the LPD8806() constructor match the number of LEDs in the strip (both will be 32 if using the strandtest example and a single meter of LEDs)."

But looking at the library code below, I am not certain where to modify. Adafruit\_Neopixel master zip has 2 files, which contain source code. One is Adafruit\_Neopixel.cpp and the other Adafruit\_Neopixel.h.

Thank you.

# Answer
> When something works, but not completely, it's often due to power issues.

Embedded things, microcontrollers/Arduino are fairly robust and "logical". Hence, if your Arduino program works today, it'll work tomorrow.

Analog devices, or electricity is (in my eyes) often a bit vague. A chip can get enough power to run, but not enough to work properly.

**The NeoPixel**

Adafruit has an extremely elaborated tutorial/userguide.

> Powering the NeoPixels

This also seems to fit your problem.

You could try powering the strip from the middle. Since your voltage isn't stable, your amperage might not be as high and the resistance may be a little big. It's actually quite impressive that it works.

> Each NeoPixel can draw up to 60 milliamps at full brightness.

2000mAh does not mean it can (always) deliver 2000mA. It depends on the "C" or discharge rating of the battery. So if your battery is rated 0.5 C it'll only be able to supply 1000mA (for 2 hours).

60\*21 would be well over 1000mA, actually 60\*16 is just below 1mA, so this would fit your problem.

> The voltage of a battery depends on how much charge it has.

Check google for: "LiPo voltage drop"

> If all else fails

There is a chance that that particular LED is broken. The signal will not continue to the other LED's and thus the light of the strip will end there. Try to drive the LED's behind the LED that fails. (With the power supply closer).

I'm also not sure if you can supply 3.7V and then use 5V logic. Things like that would often break a microcontroller (when running on 3.3V, you usually can't receive 5V?)
> 5 votes

# Answer
You don't modify the library at all. The page refers to the *constructor* which is the last line here:

```
#include <Adafruit_NeoPixel.h>

#define PIN 6

Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, PIN, NEO_GRB + NEO_KHZ800);

```

So that would send to 60 NeoPixels. Change the 60 to however-many you have.

To compare, try running my library here. That doesn't use the Adafruit library. Use the minimal demo code, and change PIXELS to be 21.

```
#include <SPI.h>
#include <NeoPixels_SPI.h>

const unsigned int PIXELS = 8; // Number of pixels in the string

void setup ()
  {
  ledsetup();
  showColor (PIXELS, 0xB2, 0x22, 0x22);  // firebrick
  } // end of setup

void loop ()
  {
  } // end of loop

```

Note that you connect the NeoPixels data to pin D11 of your Uno in this case.

---

> @Paul 2000mAh at 3.7V Lipo battery

---

> according to the comment in the main question he's powering 21 LED's off a "2000mAh at 3.7V Lipo battery"

Yes, well let's look at the specs:

If you lose 0.2V over the first 8 LEDs you are under spec for the voltage.
> 3 votes

# Answer
With most led strips you can supply power from both ends if you are experiencing voltage drop.

You can do this with two separate power supply units if you don't have one unit that is capable of powering the entire strip.

I'm not sure if power is your entire problem, but if it is you could try this solution.

If it's a problem with the Neopixel library You could also try the excellent FastLED library and see if that helps you sort out your issues.
> 0 votes

---
Tags: arduino-uno, adafruit, rgb-led, neopixel
---


title: Turning all LEDs on (FAST.LED)

text:
# Question
Title: Turning all LEDs on (FAST.LED)
In Fast.Led lib for arduino there is a code to turn off all leds

```
FastLED.clear ();

```

Is there also a shortcut to turn all LEDs ON, and with a specific color

# Answer
You can use fill\_solid.

For example

```
fill_solid( leds, NUM_LEDS, CRGB(50,0,200));

```

Or

```
fill_solid( leds, NUM_LEDS, CRGB::Red);

```
> 10 votes

---
Tags: arduino-nano, adafruit
---


# Question
Title: Arduino UNO stuck in Setup function when interfacing UNO with ESP8266 module
Following is my code that i am trying to use it with Arduino Uno with ESP8266 module but my code stucked in setup function why is that.

```
#include "ESP8266.h"
#include <SoftwareSerial.h>
SoftwareSerial mySerial(12,13);
#define SSID        "abcd"
#define PASSWORD    "87654321"
#define HOST_NAME   "www.baidu.com"
#define HOST_PORT   (80)

ESP8266 wifi(mySerial);

void setup(void)
{
    Serial.begin(9600);
    Serial.print("setup begin\r\n");

    Serial.print("FW Version:");
    Serial.println(wifi.getVersion().c_str());

    if (wifi.setOprToStationSoftAP()) {
        Serial.print("to station + softap ok\r\n");
    } else {
        Serial.print("to station + softap err\r\n");
    }

//    if (wifi.joinAP(SSID, PASSWORD)) {
//        Serial.print("Join AP success\r\n");
//
//        Serial.print("IP:");
//        Serial.println( wifi.getLocalIP().c_str());
//    } else {
//        Serial.print("Join AP failure\r\n");
//    }
    delay(500);
    if (wifi.disableMUX()) {
        Serial.print("single ok\r\n");
    } else {
        Serial.print("single err\r\n");
    }

    Serial.print("setup end\r\n");

}

void loop(void)
{
    uint8_t buffer[1024] = {0};

    if (wifi.createTCP(HOST_NAME, HOST_PORT)) {
        Serial.print("create tcp ok\r\n");
    } else {
        Serial.print("create tcp err\r\n");
    }

    char *hello = "GET / HTTP/1.1\r\nHost: www.baidu.com\r\nConnection: close\r\n\r\n";
    wifi.send((const uint8_t*)hello, strlen(hello));

    uint32_t len = wifi.recv(buffer, sizeof(buffer), 10000);
    if (len > 0) {
        Serial.print("Received:[");
        for(uint32_t i = 0; i < len; i++) {
            Serial.print((char)buffer[i]);
        }
        Serial.print("]\r\n");
    }

    if (wifi.releaseTCP()) {
        Serial.print("release tcp ok\r\n");
    } else {
        Serial.print("release tcp err\r\n");
    }

    while(1);

}

```

**On Serial Monitor i get the following continuously**

```
setup begin
FW Version:0018000902
to station + softap ok
singl

```

setup begin FW Version:0018000902 to station + softap ok singl

# Answer
> 1 votes
> It's always a good idea to put a serial output in the setup of your code.

It seems that your Arduino resets itself.

But why?

I believe the problem would be with too little power for your ESP8266 and Arduino. When the ESP8266 wants to create a network connection, it takes a little more current, possibly leaving your Arduino without enough current to run on itself.

So your Arduino would shut down since the ESP8266 takes up all the current. Creating some kind of bootloop on your Arduino.

Please tell us how you powered the devices and how you connected them. You might try using a separate power supply or a big capacitor on the Arduino's 5V+GND.

---
Tags: arduino-uno, programming, arduino-ide, esp8266
---


title: Motors settings

text:
# Question
Title: Motors settings
I'm trying to build my own 3D printer with a guide but I've got a problem with two of my CD/DVD motors: I don't know which settings to set in Marlin (`configuration.h`) because I can't find any datasheet for them.

So, I tried to set some values by my own, but I'm a little lost. That's why I'm asking for some help!

I'm using an **Arduino Mega 2560** (with Marlin firmware), a **RAMPS 1.4** and **x4 A4988 modules**.

* The 1st motor has "**7810200082AC**" engraved on front and "**D5X08VF1D**" printed on the back.
* The 2nd motor has "**05Z20P2B**" and "**092KPL201ACP**" printed on the back.

If I wasn't clear or some information is missing, please tell me!

# Answer
> 0 votes
I don't know your exact setup, but when it comes to steppers, you just need to know a few things:

* Meter the coils to get an impression, how much current you can induce.
* Limit the current on your driver as low as possible (\<= 0.25 A possible?)
* Test
* Heighten the current, if the motor doesn't turn or stalls

Your motors are quite small, so I would assume, they run with less than 0.25 A at 12 V or 0.125 A at 24 V and so on.

If you limit the current, nothing can go wrong at all. Check the heat from time to time and make sure, your drivers lowers the current, whenever the given axis stands still.

When it comes to to resolution, I would not recommend to use more than 1/4 steps, which would result in 4\*48/round steps on a standard stepper and provides very good resolution plus smooth motor action.

---
Tags: arduino-mega, motor, stepper
---


# Question
Title: Risks of ftdi_eeprom? - TX always high after flashing
I flashed an Arduino Nano compatible with ftdi\_eeprom and the following config:

```
vendor_id=0x0403    # Vendor ID
product_id=0x6001   # Product ID

max_power=0     # Max. power consumption: value * 2 mA. Use 0 if self_powered = true.

###########
# Strings #
###########
manufacturer="FTDI"     # Manufacturer
product="Arduino Nano"  # Product
serial="arduino_1"      # Serial

###########
# Options #
###########
self_powered=false  # Turn this off for bus powered
remote_wakeup=false # Turn this on for remote wakeup feature
use_serial=true     # Use the serial number string

# Normally out don't have to change one of these flags
BM_type_chip=true       # Newer chips are all BM type
in_is_isochronous=false     # In Endpoint is Isochronous
out_is_isochronous=false    # Out Endpoint is Isochronous
suspend_pull_downs=false    # Enable suspend pull downs for lower power
change_usb_version=false    # Change USB Version
usb_version=0x0200      # Only used when change_usb_version is enabled

########
# Misc #
########

filename="eeprom.new"   # Filename, leave empty to skip file writing

```

My corresponfing `udev` rules work and I get `/dev/arduino_1` after connecting.

However. After the flash, everything seems to work, But: The TX-LED is constantly on. Even, when the device is not sending. Why?

**Update & solution**

First, I removed this line, because it threw warning messages (outdated)

```
# BM_type_chip=true         # Newer chips are all BM type

```

Then I studied the schematics of the Nano and figured out, that `RX` and `TX` LEDs are indeed connected to `CBUS0` and `CBUS1`. So, I added two lines to my config

```
  cbus0=RXLED
  cbus1=TXLED

```

Which had the effect, that now both `RX` and `TX` where constantly on. So, I finally read the manual which says on page 11, that the commands in question need a trailing `#`. I updated my config again:

```
cbus0=RXLED#
cbus1=TXLED#

```

**Extra:**

Indeed, I had to install `ftdi_eeprom` to get the job done

```
 apt-get remove ftdi-eeprom
 apt-get install swig libusb-1.0-0-dev libconfuse-dev doxygen
 git clone https://github.com/legege/libftdi.git
 cd libftdi.git
 cmake .
 make
 make install
 ftdi_eeprom/ftdi_eeprom --flash-eeprom myconfig.conf

```

# Answer
The `ftdi_eeprom` utility re-writes the entire EEPROM, not just the selected bits you have chosen. That includes the "CBUS" pin configurations.

You need to check on the Nano's schematic which LED is connected to which `CBUSx` pin on the FTDI and set it accordingly. You do that in your config using:

```
cbus0=TXLED
cbus1=RXLED

```

for example.

Possible settings for the CBUS pins are:

* TXDEN
* PWREN
* RXLED
* TXLED
* TXRXLED
* SLEEP
* CLK48
* CLK24
* CLK12
* CLK6
* IO\_MODE
* BITBANG\_WR
* BITBANG\_RD
* SPECIAL

Except CBUS4 which only has the functions:

* TXDEN
* PWRON
* RXLED
* TXLED
* TX\_RX\_LED
* SLEEP
* CLK48
* CLK24
* CLK12
* CLK6

There is a chance that your pre-packages version of `ftdi_eeprom` doesn't support those settings, so you will need to download and compile the latest version from source from here: https://github.com/legege/libftdi

Also during testing I accidentally changed the VID of one of my boards thus rendering it unresponsive. I did that by omitting the `0x` from the VID and PID numbers. Extreme care should be exercised using thin utility. I have submitted a patch to allow the specification of a default VID for recovery from such situations.
> 1 votes

---
Tags: arduino-nano, ftdi
---


# Question
Title: My Arduino Nano clone doesn't show in the serial this simple code. Why?
Here is the code:

```
void setup() {
  Serial.print("hi");
}
void loop() {
}

```

The product is in here.

I also installed the drivers.

# Answer
You haven't "started" the serial interface. Before you use the serial you need to tell it to initialize the hardware and how fast you want to communicate.

You need to add, for instance,

```
Serial.begin(9600);

```

to your `setup()` function before you do your `Serial.print()`.
> 1 votes

---
Tags: arduino-nano
---


# Question
Title: Why can't I see the serial plot with the following code for arduino?
```
const int GSR=A0;
int threshold=0;
int sensorValue;

void setup(){
  long sum=0;
  Serial.begin(9600);
  delay(1000);

  for(int i=0;i<500;i++)
  {
  sensorValue=analogRead(GSR);
  sum += sensorValue;
  delay(5);
  }
  threshold = sum/500;
   Serial.print("threshold =");
   Serial.println(threshold);
  }

void loop(){
  int temp;
  sensorValue=analogRead(GSR);
  Serial.print("sensorValue=");
  Serial.println(sensorValue);
  temp = threshold - sensorValue;
  }

```

# Answer
> 3 votes
The serial plotter requires just numbers and nothing else.

It can't understand the data in the format:

```
sensorValue=49

```

It just expects:

```
49

```

Remove the line

```
Serial.print("sensorValue=");

```

and it will start working.

---
Tags: arduino-nano
---


# Question
Title: How to exclude a ino/pde file from Arduino projects
I would like to be able to exclude from the auto-including process of the current project (without renaming the extension or delete it) a sketch with `pde` or `ino` extension that is used in certain circumstances only.

How can I do this?

I currently use Visual Micro to manage projects on Arduino.

# Answer
> 1 votes
One possible approach is to guard the body of that sketch with an `#ifdef ... #endif` pair, and use Visual Micro's “Project Properties” to define (or not) a preprocessor symbol. \[If the .ino or .pde in question is used as a `#include` file, you would instead guard all the `#include` instances.\]

Refer to the “Project Defines” page at visualmicro.com for how to define a preprocessor symbol and its value. \[Via: Tools \> Options \> Visual Micro \> Compiler \> Show Build Properties\] Also see How do I add additional compiler switches in Visual Studio.

If necessary, you can use other tests besides `#ifdef` to control compilation. The first link above shows the following example.

```
#if USBPORT > 3
....your code here....
#endif

```

---
Tags: arduino-uno, programming, sketch, visualstudio, ino
---


# Question
Title: Arduino SoftwareSerial not receiving data from Neo-6M GPS module
I am trying to hook up my Neo-6M GPS module to my Arduino Uno but am having some trouble getting GPS data out of it.

The code being used was taken from the TinyGPS library. I have set the SoftwareSerial ports in the constructor to 2 and 3 (check images at bottom for reference). I set to the boad rate of the software serial so that it matches that of the Neo-6M. The datasheet for the module can be found here.

The output that comes out of the Arduino serial monitor looks like this:

A new line is added to this every second, and when the line is added the TX light on the Arduino blinks. The 'Chars RX' 0 would indicate that the SoftwareSerial isn't reading any data at all from the module. I can't for the life of me figure out why this is happening! Any help would be much appreciated.

```
#include <SoftwareSerial.h>
#include <TinyGPS.h>

/* This sample code demonstrates the normal use of a TinyGPS object.
   It requires the use of SoftwareSerial, and assumes that you have a
   4800-baud serial GPS device hooked up on pins 4(rx) and 3(tx).
*/

TinyGPS gps;
SoftwareSerial ss(2, 3);

static void smartdelay(unsigned long ms);
static void print_float(float val, float invalid, int len, int prec);
static void print_int(unsigned long val, unsigned long invalid, int len);
static void print_date(TinyGPS &gps);
static void print_str(const char *str, int len);

void setup()
{
  Serial.begin(115200);

  Serial.print("Testing TinyGPS library v. "); Serial.println(TinyGPS::library_version());
  Serial.println("by Mikal Hart");
  Serial.println();
  Serial.println("Sats HDOP Latitude  Longitude  Fix  Date       Time     Date Alt    Course Speed Card  Distance Course Card  Chars Sentences Checksum");
  Serial.println("          (deg)     (deg)      Age                      Age  (m)    --- from GPS ----  ---- to London  ----  RX    RX        Fail");
  Serial.println("-------------------------------------------------------------------------------------------------------------------------------------");

  ss.begin(9600);
}

void loop()
{
  float flat, flon;
  unsigned long age, date, time, chars = 0;
  unsigned short sentences = 0, failed = 0;
  static const double LONDON_LAT = 51.508131, LONDON_LON = -0.128002;

  print_int(gps.satellites(), TinyGPS::GPS_INVALID_SATELLITES, 5);
  print_int(gps.hdop(), TinyGPS::GPS_INVALID_HDOP, 5);
  gps.f_get_position(&flat, &flon, &age);
  print_float(flat, TinyGPS::GPS_INVALID_F_ANGLE, 10, 6);
  print_float(flon, TinyGPS::GPS_INVALID_F_ANGLE, 11, 6);
  print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
  print_date(gps);
  print_float(gps.f_altitude(), TinyGPS::GPS_INVALID_F_ALTITUDE, 7, 2);
  print_float(gps.f_course(), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2);
  print_float(gps.f_speed_kmph(), TinyGPS::GPS_INVALID_F_SPEED, 6, 2);
  print_str(gps.f_course() == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(gps.f_course()), 6);
  print_int(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0xFFFFFFFF : (unsigned long)TinyGPS::distance_between(flat, flon, LONDON_LAT, LONDON_LON) / 1000, 0xFFFFFFFF, 9);
  print_float(flat == TinyGPS::GPS_INVALID_F_ANGLE ? TinyGPS::GPS_INVALID_F_ANGLE : TinyGPS::course_to(flat, flon, LONDON_LAT, LONDON_LON), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2);
  print_str(flat == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(TinyGPS::course_to(flat, flon, LONDON_LAT, LONDON_LON)), 6);

  gps.stats(&chars, &sentences, &failed);
  print_int(chars, 0xFFFFFFFF, 6);
  print_int(sentences, 0xFFFFFFFF, 10);
  print_int(failed, 0xFFFFFFFF, 9);
  Serial.println();

  smartdelay(1000);
}

static void smartdelay(unsigned long ms)
{
  unsigned long start = millis();
  do
  {
    while (ss.available())
      gps.encode(ss.read());
  } while (millis() - start < ms);
}

static void print_float(float val, float invalid, int len, int prec)
{
  if (val == invalid)
  {
    while (len-- > 1)
      Serial.print('*');
    Serial.print(' ');
  }
  else
  {
    Serial.print(val, prec);
    int vi = abs((int)val);
    int flen = prec + (val < 0.0 ? 2 : 1); // . and -
    flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
    for (int i=flen; i<len; ++i)
      Serial.print(' ');
  }
  smartdelay(0);
}

static void print_int(unsigned long val, unsigned long invalid, int len)
{
  char sz[32];
  if (val == invalid)
    strcpy(sz, "*******");
  else
    sprintf(sz, "%ld", val);
  sz[len] = 0;
  for (int i=strlen(sz); i<len; ++i)
    sz[i] = ' ';
  if (len > 0)
    sz[len-1] = ' ';
  Serial.print(sz);
  smartdelay(0);
}

static void print_date(TinyGPS &gps)
{
  int year;
  byte month, day, hour, minute, second, hundredths;
  unsigned long age;
  gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
  if (age == TinyGPS::GPS_INVALID_AGE)
    Serial.print("********** ******** ");
  else
  {
    char sz[32];
    sprintf(sz, "%02d/%02d/%02d %02d:%02d:%02d ",
        month, day, year, hour, minute, second);
    Serial.print(sz);
  }
  print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
  smartdelay(0);
}

static void print_str(const char *str, int len)
{
  int slen = strlen(str);
  for (int i=0; i<len; ++i)
    Serial.print(i<slen ? str[i] : ' ');
  smartdelay(0);
}

```

# Answer
> 2 votes
Gray wire should be plug on pin2. `SoftwareSerial ss(2, 3);` means pin2 for Receive(RX) and pin3 for Transmit(TX). The Transmit(TX) on Neo-6M should be connected to Receive(RX) on Arduino.

---
Tags: serial, gps
---


# Question
Title: How do I run a loop for a specific amount of time?
I currently have a `for` loop that loops 300 times and then moves on.

Instead, I'd like that loop to run for a specific number of minutes, instead.

Here's the current loop, for reference.

```
for(int i = 1; i<300; i++){
  if (kill() == true){ break; }

  strip.setPixelColor(1, strip.Color(random(100,255),random(100,255),random(100,255)));
  strip.show();

  tone(TONE, notes[random(0,3)]);
  delay(100);
}

```

Also, I have an RTC that's used elsewhere in the app, so real actual time is available for use if it makes sense to do that...though I'd love to know of a way to do it without an RTC module for future projects.

# Answer
Here is an example that will run for 5 minutes. Note that the loop will begin executing anytime before the time limit is up, including 1 msec before; it can't cut-off something happening at the 5-minute mark, meaning the timing precision will be limited to the duration of the code in the loop.

Update: My first suggestion had a bug related to the 50-some-odd days roll-over period of the millis() clock. This one is more robust:

```
uint32_t period = 5 * 60000L;       // 5 minutes

for( uint32_t tStart = millis();  (millis()-tStart) < period;  ){
   doStuff();
   moreStuff();
}

```
> 10 votes

# Answer
Using this example:

http://playground.arduino.cc/Code/ElapsedMillis

You could try something like:

```
#include <elapsedMillis.h>

elapsedMillis timeElapsed;
unsigned int interval = 60000; //one minute in ms

while(timeElapsed < interval){
    //do stuff
}

```

Depending on how accurate you want to be, you might want to opt for a similar method using the RTC.
> 3 votes

# Answer
You can use a variable that is incremented each time you perform the loop, then you need only to change the loop from using a `for` to a `while`.

For example:

```
   int incremented_variable = 0;
   int incremented_value = 100;
   int max_value = 1000;

   while(incremented_variable < max_value){
   if (kill() == true){ break; }

   strip.setPixelColor(1, strip.Color(random(100,255),random(100,255),random(100,255)));
   strip.show();

   tone(TONE, notes[random(0,3)]);

   delay(100);
   incremented_variable = incremented_variable + incremented_value;
   }

```

---

**EDIT:** I have just read your update on the question.

You can then use a while with a boolean flag that help you to end the loop or if you prefer, you can keep track of the time by calling the method: `millis()`.
> 2 votes

---
Tags: arduino-uno, time
---


# Question
Title: Link Arduinos over 5 acre laser tag field
I am building a laser tag system with an Arduino in each gun.

I want the guns to be linked during game play for many different reasons:

1. Start/Stop game
2. Nearby teammates
3. When a flag is captured
4. etc.

I don't know how to link the guns to one another during game play because the field may be large (e.g. a park). Wifi has too short of a range, cellular would cost, linking to a phone via bluetooth would drain the phone battery (and require each player have a smart phone to play).

Can you think of another way to link the guns? Radio transmitters?

Thanks!

# Answer
> 4 votes
You can use nRF24L01+

The chips offer:

* Really high range with power amplifier (1km open field radius (776 acres if I'm right) , but fairly high power consumption 100-150mA @ 3.3V)
* High range with PCB antenna (50-80m open field, low power consumption 14mA peak)
* Low cost (0.8£-6£ a piece)
* Many easy to use libraries available, possible to create a mesh network
* High usable voltage range (direct Li-Po for example without step-up)

---
Tags: arduino-uno, wifi
---


# Question
Title: Accelerometer Interrupt Meaning - Wakeup Function
I am working with an LSM9DS1 IMU, and now specifically trying to program a wakeup feature into the system. My idea is to set the accelerometer at the lowest possible read rate, then when the accelerometer value exceeds a predefined level, to have the system wake up.

When programming the sensor, there is a register called INT\_GEN\_CFG\_XL that has a "6-Direction detection for interrupt." I was wondering what this means. Does this perhaps calculate the magnitude of acceleration, and see if that goes above a predefined value? I can see the other interrupt generators are for 1-direction of each of the three axes, but I can't interrupt this one.

Here is a link to the device datasheet

# Answer
The INT\_GEN\_CFG\_XL 6-Direction detection interrupt apparently is aimed at detecting change of direction of travel, rather than an axis-combined acceleration level.

See the LSM303 discussion at Polulu.com. That page includes a link to App Note CD00290365.pdf for the LIS3DH. Here is what that app note says, on page 27:

> There are two possible configurations for the 6D direction function:
>
> > • 6D movement recognition: In this configuration the interrupt is generated when the device moves from a direction (known or unknown) to a different known direction. ...
> > • 6D position recognition: In this configuration the interrupt is generated when the device is stable in a known direction. ...

With the LSM9DS1 that you are using, you can leave OR enabled, set separate X,Y,Z threshholds in INT\_GEN\_THS\_X\_XL, INT\_GEN\_THS\_Y\_XL, INT\_GEN\_THS\_Z\_XL, and set the “Enable interrupt generation on accelerometer's X axis high event” (sim. for Y and Z) bits in the INT\_GEN\_CFG\_XL register.
> 2 votes

---
Tags: sensors, interrupt, accelerometer, sleep
---


# Question
Title: Piezo connection causing RTC to go haywire
When I connect a piezo (to pin 8), it causes the output of my RTC to go haywire and throw `165` errors into the results.

```
2016/3/25 13:36:4
2016/3/25 13:36:4
2016/3/25 13:36:4
2016/3/25 13:36:4
2016/3/25 13:36:4
2016/3/25 13:36:4
2016/3/25 13:36:4
2016/3/25 13:36:4
2165/165/165 165:37:4 // Connected piezo
2016/3/25 13:36:4
2165/165/45 13:36:4
2165/165/165 25:36:4
2016/3/25 13:36:4
2165/165/45 13:36:4
2016/3/25 13:36:4
2165/165/45 13:36:4
2165/165/165 165:165:4
2016/3/25 13:36:4
2016/3/25 13:36:4
2016/3/25 13:36:4
2165/165/165 37:36:4
2016/3/25 13:36:4
2165/165/27 13:36:4
2016/3/25 13:36:4
2165/165/165 25:36:4
2016/3/25 13:36:4
2016/3/25 13:36:4
2165/165/165 25:36:4
2016/3/25 13:36:4
2016/3/25 13:36:4
2016/3/25 13:36:4
2016/3/25 13:36:4
2016/3/25 13:36:4
2165/165/165 25:36:4
2165/165/165 25:36:4
2016/3/25 13:36:4
2016/3/25 13:36:4
2165/165/165 25:36:4

```

Here's my current layout...

Worth noting:

* Disconnecting the piezo instantly solves the problem.
* Connecting to any other pins also caused the issue.

Here is the Fritzing diagram

and schematic

Here's the full code...

```
#include <Adafruit_NeoPixel.h>
#include <Wire.h>
#include "RTClib.h"

RTC_DS1307 rtc;

#define PIN 6
#define TONE 8
const int buttonPin = 7;

long fadeTime = 1 * 60000L; // X minutes
int colorStops = 256;
int delaySpeed = fadeTime / colorStops;
int notes[] = {262,294,330,349};
int switchState = 1;         // variable for reading the pushbutton status
int timeHour = 13;
int timeMinute = 20;
uint32_t alarmLength = 5 * 60000L; // 5 minutes

Adafruit_NeoPixel strip = Adafruit_NeoPixel(4, PIN, NEO_RGB);

void setup() {
  Serial.begin(57600);

  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }
  if (! rtc.isrunning()) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(__DATE__, __TIME__));
  }

  pinMode(buttonPin, INPUT_PULLUP); // initialize the pushbutton pin as an input

  strip.begin();
  strip.show();
}

void loop() {
  DateTime now = rtc.now();

  Serial.print(now.year(), DEC);
  Serial.print('/');
  Serial.print(now.month(), DEC);
  Serial.print('/');
  Serial.print(now.day(), DEC);
  Serial.print(" ");
  Serial.print(now.hour(), DEC);
  Serial.print(':');
  Serial.print(now.minute(), DEC);
  Serial.print(':');
  Serial.print(now.second(), DEC);
  Serial.println();

  if (now.hour() == timeHour && now.minute() == timeMinute && now.second() == 00){
    // Fade in light
    for(int i = 1; i<colorStops; i++){
      if (kill() == true){ break; }

      for(int np = 0;np<strip.numPixels(); np++){
        strip.setPixelColor(np, strip.Color(i,i,0));
      }
      strip.show();
      delay(delaySpeed);
    }

    // Play tone after light fully bright
    for( uint32_t tStart = millis();  (millis()-tStart) < alarmLength; ){
      if (kill() == true){ break; }

      for(int np = 0;np<strip.numPixels(); np++){
        strip.setPixelColor(np, strip.Color(random(100,255),random(100,255),random(100,255)));
      }
      strip.show();

      tone(TONE, notes[random(0,3)]);
      delay(100);
    }

    noTone(TONE);

    for(int np = 0;np<strip.numPixels(); np++){
      strip.setPixelColor(np, strip.Color(0,0,0));
    }
    strip.show();
  }
}

bool kill() {
  if (digitalRead(buttonPin) == LOW) {
    noTone(TONE);

    for(int np = 0;np<strip.numPixels(); np++){
      strip.setPixelColor(np, strip.Color(0,0,0));
    }
    strip.show();
    return true;
  }
  else {
    return false;
  }
}

```

# Answer
Add

```
pinMode(TONE,OUTPUT);

```

to `setup()` to fix the problem.
> 2 votes

---
Tags: arduino-uno, rtc, piezo
---