body:
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?

title: Array + Serial Monitor Problem

Answers: 3

body:
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

body:
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[1].

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.

body:
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 VREF 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×VREF. 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](https://en.wikipedia.org/wiki/Cubic_Hermite_spline#Interpolation_on_the_unit_interval_without_exact_derivatives)
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.


body: I'm using an Ethernet shield with the built-in Ethernet library. I obtain an IP address using DHCP, and call `Ethernet.maintain()` periodically to ensure that the DHCP lease is renewed as required. So far I've never seen this fail, but `maintain()` can return error codes for renew fail and rebind fail and I assume that I should be handling them. What conditions would cause these errors to occur, and what's the best practise for recovering from them? Is it enough to call `Ethernet.maintain()` repeatedly until it returns cleanly, should I call `Ethernet.begin()` to reinitialise the Ethernet shield, or would it be best to reset both the Arduino and Ethernet shield using the watchdog timer?

title: How to recover from DHCP Renewal and Rebind failures?

Answers: 1

body:
Possible causes:

 - The DHCP server might be down.
 - Or it might have lost its state (but I think they try really hard to preserve the list of leases).
 - Or some other cause which makes the server unavailable/unwilling to renew the lease.

Solutions:

  - If you can wait, you can retry, but otherwise I'd just say try to obtain a new lease, unless for some reason you *really* want to stick to the IP from the previous lease.

  - If you control the server and your network is kinda stable, you could assign a fixed IP to your device configure the server to associate it with the MAC address you gave to your device. In general, when the network setup is really stable, this might be preferable, since other entities on the network will probably cache the IP of your device and use it, should the DNS fail as well (ex: dnsmasquerade works both as dhcp server and dns). Similarly, your device doesn't have to worry anymore of the DHCP lease, because it's permanent.


body:
I have an Arduino Uno connected to the Adafruit Motorshield v2. I have it hooked up to a stepper motor(27BYJ-48). I am trying to make the motor do one complete revolution. However, the number of steps I specify to the stepper motor(200 in the code) doesn't affect the motor steps. For example, the 2200 step in this code, is roughly one rotation and is completely unaffected by change the steps/revolution specified when instantiating the motor. How do I get the motor to do one exact revolution?

 Here is the code on the arduino:

    #include <Wire.h>
    #include <Adafruit_MotorShield.h>
    #include "utility/Adafruit_MS_PWMServoDriver.h"

    Adafruit_MotorShield AFMS = Adafruit_MotorShield();
    Adafruit_StepperMotor *myMotor = AFMS.getStepper(200, 2);

    void setup() {
      Serial.begin(9600);           // set up Serial library at 9600 bps
      Serial.println("Stepper test!");

      AFMS.begin();  // create with the default frequency 1.6KHz

      myMotor->setSpeed(2000);  // 10 rpm
    }

    void loop() {
      Serial.println("Single coil steps");
      myMotor->step(2200, FORWARD, DOUBLE);
      myMotor->step(2200, BACKWARD, DOUBLE);
    }

Edit:
Wiring:
[![Wiring from Motorshield to Stepper][1]][1]

[![enter image description here][2]][2]

  [1]: https://i.stack.imgur.com/U8Vo5.png
  [2]: https://i.stack.imgur.com/EnOvw.png

title: Stepper Motor not Stepping Properly

Answers: 2

body:
Ok so I'm not familiar with the sheild or API (or motor lol) but going off the spec sheets etc

Leave the red wire disconnected [see 1] and try this code and report back what happens:

      #include <Wire.h>
      #include <Adafruit_MotorShield.h>
      #include "utility/Adafruit_MS_PWMServoDriver.h"

      Adafruit_MotorShield AFMS = Adafruit_MotorShield();
      Adafruit_StepperMotor *myMotor = AFMS.getStepper(64, 2); // 64 steps pr revolution
                                                               // Using M3 and M4 of shield

      void setup()
      {
        AFMS.begin();  // create with the default frequency 1.6KHz
        myMotor->setSpeed(30);  // 30 rpm, so 1 full turn every 2sec
      }

      void loop()
      {
        // 64 steps per motor shaft revolution,
        // 64 revolutions of motor per output shaft revolution
        myMotor->step(4096, FORWARD, DOUBLE);    // Should be 1 rev in one direction
        myMotor->step(4096, BACKWARD, DOUBLE);   // and 1 rev in other direction
      }

[1] : your motor is unipolar ([wikipedia on unipolar and bipolar motors](https://en.wikipedia.org/wiki/Stepper_motor#Unipolar_motors)), according to its documentation. The red wire is the central tap, and useless in this context.

body:
I also tested 27BYJ-48 stepper motor with [instructables][1] source code. It works but I had the same "complete revolution" problem.
They compute on their website that a revolution contains 4096 steps.

As @James said, indeed, there is gearing inside the stepper motor.
The problem is the gearing could be different for the exact same reference !
Everything is described here : [28BYJ-48][2]

  [1]: http://www.instructables.com/id/BYJ48-Stepper-Motor/
  [2]: https://grahamwideman.wikispaces.com/Motors-+28BYJ-48+Stepper+motor+notes


body:
Arduino IDE is throwing this error when uploading sketches - **avrdude: stk500_recv(): programmer is not responding**

The problem arose just after I uploaded a blink sketch to my Arduino Mini, which worked absolutely fine. After the successful upload I tried to upload a different sketch and got the error.

I thought I had destroyed the boot loader somehow and was about to get out the Bus Pirate for ICSP but I decided to try another Arduino Mini I had lying around (albeit from another manufacturer) and got the same error.

So I'm convinced it's a driver issue as I successfully uploaded a sketch (it still runs as we speak!) then just magically without changing **ANYTHING** I can no longer upload.

In a futile attempt to get back to work I've done the following:
Switched the RX-TX lines (clearly not the issue as the first upload worked)
Used a different FTDI cable
used a  different programmer
(FTDI 5V/3.3V USB to TTL Basic FT232 FIO Programmer)
(USB to TTL Serial UART RS232 Adaptor (PL2303HX)
I'm fairly certain these use different drivers - FTDI and Prolific

Please help me I'm about to murder something :'(

[Screencaps of error and device manager - Imgur][1]

  [1]: https://i.stack.imgur.com/BBQoV.jpg

Answers: 3

body:
Is it this?

"To upload a new sketch to the Arduino Mini, you need to press the reset button on the board immediately before pressing the upload button in the Arduino environment."

https://www.arduino.cc/en/Guide/ArduinoMini

body:
> Is it this?
>
>"To upload a new sketch to the Arduino Mini, you need to press the reset button >on the board immediately before pressing the upload button in the Arduino >environment."
>
>https://www.arduino.cc/en/Guide/ArduinoMini

You sir, are a hero.

I don't even know how I accidentally did this sequence to upload the first sketch... Perhaps I plugged the USB to Serial UART in to the USB port and quickly pressed upload? Having got the first sketch on there really mixed me up :/

Solution:

1. Click upload sketch - It will show 'Compiling Sketch'
2. Immediately after clicking upload, hold the reset button down on the Arduino mini
3. Release the reset button when 'Compiling Sketch' turns in to 'Uploading'

body:
 avrdude: stk500_recv(): programmer is not responding

I have the same problem (Arduino uno)
I reset the Arduino several times, but finally i fixed the problem.
so you must change the pic of the arduino and make sure it was instilled correctly on the arduino board.

hope it work...


body:
I have seen some tutorials on ultrasonic range detector sensor.

In that, what is the meaning of the word `pulseIn`?

title: What is pulseIn in programming Arduino?

Answers: 1

body:
`pulseIn()` is used to Reads a pulse (either HIGH or LOW) on a pin. For example, if value is HIGH, `pulseIn()` waits for the pin to go HIGH, starts timing, then waits for the pin to go LOW and stops timing. Returns the length of the pulse in microseconds or 0 if no complete pulse was received within the timeout.

The timing of this function has been determined empirically and will probably show errors in shorter pulses. Works on pulses from 10 microseconds to 3 minutes in length. Please also note that if the pin is already high when the function is called, it will wait for the pin to go LOW and then HIGH before it starts counting. This routine can be used only if interrupts are activated. Furthermore the highest resolution is obtained with short intervals.

**Syntax**

    pulseIn(pin, value)
    pulseIn(pin, value, timeout)

**Parameters**

*pin:* the number of the pin on which you want to read the pulse. (int)

*value:* type of pulse to read: either HIGH or LOW. (int)

*timeout (optional):* the number of microseconds to wait for the pulse to be completed: the function returns 0 if no complete pulse was received within the timeout. Default is one second (unsigned long).

**Returns**

The length of the pulse (in microseconds) or 0 if no pulse is completed before the timeout (unsigned long).

For additional information and example code, visit: https://www.arduino.cc/en/Reference/PulseIn, hope this help you to understand the meaning of `pulseIn()`.


body:
[![enter image description here][1]][1]What to add on this code to check my pins state during run? And how can i trigger error using Visual basic when 1 of my pin is disconnected?

    String input = "";

    void setup(){

    Serial.begin(9600); // Sets up communication with the serial port

    pinMode(6,OUTPUT);
    pinMode(7,OUTPUT);
    pinMode(8,OUTPUT);
    pinMode(9,OUTPUT);
    pinMode(10,OUTPUT);
    pinMode(11,OUTPUT); // for start of program operation
    pinMode(12,OUTPUT); // for stop of program operation

    digitalWrite(6,LOW);
    digitalWrite(7,LOW);
    digitalWrite(8,LOW);
    digitalWrite(9,LOW);
    digitalWrite(10,LOW);

    digitalWrite(11,LOW);
    digitalWrite(12,LOW);

    }

    void loop(){

    int recipe;
    //Serial.print("Enter recipe number: ");

    while(Serial.available()==0){    // Waits for data from serial port
    }

    while(Serial.available() > 0){
    int data = Serial.read();
      // convert the incoming byte to a char
      // and add it to the string
    input += (char)data;

    recipe = input.toInt()+'0';    //recipe=0 if not a digit
    if(recipe == '0')
      recipe = data;

    if(data == '\n'){
      //Serial.print("Recipe: ");
      //Serial.println(recipe);
      //Serial.print("String: ");
      //Serial.println(input);
      input = "";
    }
    }

    if(recipe == 's'){
    digitalWrite(11,HIGH);
    delay(1000);
    digitalWrite(11,LOW);

    digitalWrite(6,LOW);
    digitalWrite(7,LOW);
    digitalWrite(8,LOW);
    digitalWrite(9,LOW);
    digitalWrite(10,LOW);
    }

    else if(recipe == 't'){
    digitalWrite(12,HIGH);
    delay(1000);
    digitalWrite(12,LOW);

    digitalWrite(6,LOW);
    digitalWrite(7,LOW);
    digitalWrite(8,LOW);
    digitalWrite(9,LOW);
    digitalWrite(10,LOW);
    }

    else if(recipe>'0' && recipe<'32'){

    recipe = recipe-'0';
    char binary[7] = {0}; // This is where the binary representation will be stored
    recipe += 32; // Adding 32 so that there will always be 6 digits in the string
    itoa(recipe,binary,2); // Convert recipe to a string of base 2 and save it in array 'binary'
    char* signals = binary + 1; // Get rid of the most significant digit to get the 5 bits

    //Serial.print(signals); // Print out the signals in binary

    int i;
    for(i=0; i<5; i++){
      if(signals[i] == '0')
        signals[i] = '1';
      else
        signals[i] = '0';
      digitalWrite(i+6, signals[i]-'0'); // write to pin; converts the bit of the string to HIGH or LOW
      //Serial.print(signals[i]);
    }

    }
    else
    loop();

    }

  [1]: https://i.stack.imgur.com/VoSVn.jpg

title: How to check if all pins are connected on my board to make sure Arduino sends the correct pattern number on my tool

Answers: 1

body:
As mentioned in a comment, your code has some fundamental flaws. **Do not** call `loop()` from within `loop()`! Aside from the code errors, your question has a legitimate element.

Testing the tri-state behaviour of an input pin will let you know if it is genuinely high, genuinely low, or floating (disconnected). The technique was given in [this answer](https://arduino.stackexchange.com/questions/12951/testing-tri-state-pin-erroneous-results-with-internal-pullup/12955#12955) to similar problem I was encountering.

In short:

Connect a large (1MOhm) resistor to each input between the pin and ground, then for each pin:

- Turn off internal pullup;
- Read value of input pin;
- Turn on internal pullup;
- Read value again.

If the value changes from the first to the second `digitalRead()`, the input was not connected to anything. If the value remains the same then it is a genuine value from a connected device.


body:
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][1] (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][2] 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)][3].

**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);
      }
    }

  [1]: https://www.dropbox.com/s/0hcz09ba433h80j/Temp sensor device.txt?dl=0
  [2]: https://www.dropbox.com/s/90a07yeegjvznjr/Temp sensor device new.txt?dl=0
  [3]: http://forum.arduino.cc/index.php?topic=388521.0

title: Is it possible to replace this delay with millis()? (And issue with other millis loop)

Answers: 1

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

<!-- language-all: lang-c++ -->

    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;
      }
    }


body:
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?

title: VirtualWire send function

Answers: 1

body:
> 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](https://en.wikipedia.org/wiki/8b/10b_encoding#5b.2F6b)). 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.


body:
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

title: How to define a SoftwareSerial object inside a class?

Answers: 3

body:
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.][1]

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;
    }

  [1]: https://stackoverflow.com/questions/4757565/c-forward-declaration

body:
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.

body:
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);
    }


body:
The documentation for [`attachInterrupt()`](https://www.arduino.cc/en/Reference/AttachInterrupt) says:

> ... `millis()` relies on interrupts to count, so it will never increment inside an ISR. Since `delay()` requires interrupts to work, it will not work if called inside an ISR. `micros()` works initially, but will start behaving erratically after 1-2 ms. ...

How does `micros()` differ from `millis()` (except of course for their precision)? Does the above warning mean that using `micros()` inside an interrupt routine is always a bad idea?

Context - I want to [measure low pulse occupancy](https://arduino.stackexchange.com/q/22120/19445), so I need to trigger my routine when my input signal changes and record the current time.

title: Using millis() and micros() inside an interrupt routine

Answers: 4

body:
The quoted phrase is *not* a warning, it is merely a statement about how things work.

There's nothing intrinsically wrong with using `millis()` or `micros()` within a properly-written interrupt routine.

On the other hand, doing anything at all within an improperly-written interrupt routine is by definition wrong.

An interrupt routine that takes more than a few microseconds to do its job is, in all likelihood, improperly written.

In short:  A properly-written interrupt routine will not cause or encounter issues with `millis()` or `micros()`.

*Edit:*  Regarding “why micros() "starts behaving erratically"”, as explained in an “[examination of the Arduino micros function ](https://ucexperiment.wordpress.com/2012/03/17/examination-of-the-arduino-micros-function/)” webpage,  `micros()` code on an ordinary Uno is functionally equivalent to

    unsigned long micros() {
      return((timer0_overflow_count << 8) + TCNT0)*(64/16);
    }

This returns a four-byte unsigned long comprised of the three lowest bytes from `timer0_overflow_count` and one byte from the timer-0 count register.

The `timer0_overflow_count` is incremented about once per millisecond by the `TIMER0_OVF_vect` interrupt handler, as explained in an [examination of the arduino millis function ](https://ucexperiment.wordpress.com/2012/03/16/examination-of-the-arduino-millis-function/) webpage.

Before an interrupt handler begins, AVR hardware disables interrupts.  If (for example) an interrupt handler were to run for five milliseconds with interrupts still disabled, at least four timer 0 overflows would be missed.  [Interrupts written in C code in the Arduino system are not reentrant (capable of correctly handling multiple overlapping executions within the same handler) but one could write a reentrant assembly language handler that reenables interrupts before it begins a time-consuming process.]

In other words, timer overflows don't “stack up”; whenever an overflow occurs before the interrupt from the previous overflow has been handled, the `millis()` counter loses a millisecond, and the discrepancy in `timer0_overflow_count` in turn makes `micros()` wrong by a millisecond too.

Regarding “shorter than 500 μs” as an upper time limit for interrupt processing,  “to prevent blocking the timer interrupt for too long”, you could go up to just under 1024 μs (eg 1020 μs) and `millis()` still would work, most of the time.  However, I regard an interrupt handler that takes more than 5 μs as a sluggard, more than 10 μs as slothful, more than 20 μs as snail-like.

body:
It is not *wrong* to use `millis()` or `micros()` within an interrupt routine.

It *is* wrong to use them incorrectly.

The main thing here is that while you are in an interrupt routine "the clock isn't ticking".  `millis()` and `micros()` won't change (well, `micros()` will initially, but once it goes past that magic millisecond point where a millisecond tick is required it all falls apart.)

So you can certainly call on `millis()` or `micros()` to find out the current time within your ISR, but don't expect that time to change.

It is that lack of change in the time that is being warned about in the quote you provide.  `delay()` relies on `millis()` changing to know how much time has passed. Since it doesn't change `delay()` can never finish.

So essentially `millis()` and `micros()` will tell you the time *when your ISR was called* no matter when in your ISR you use them.

body:
The other answers are very good, but I want to elaborate on how `micros()` works. It *always* reads the current hardware timer (possibly `TCNT0`) which is constantly being updated by the hardware (in fact, every 4 µs because of the prescaler of 64). It then adds in the Timer 0 overflow count, which is updated by a timer overflow interrupt (multiplied by 256).

Thus, even inside an ISR, you can rely on `micros()` updating. However *if you wait too long* then you miss the overflow update, and then the result returned will go down (i.e you will get 253, 254, 255, 0, 1, 2, 3 etc.)

This is `micros()` - slightly simplified to remove defines for other processors:

<!-- language-all: lang-C++ -->

    unsigned long micros() {
     unsigned long m;
     uint8_t oldSREG = SREG, t;
     cli();
     m = timer0_overflow_count;
     t = TCNT0;
     if ((TIFR0 & _BV(TOV0)) && (t < 255))
      m++;
     SREG = oldSREG;
     return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
    }

The code above allows for the overflow (it checks the TOV0 bit) so it can cope with the overflow while interrupts are off but only **once** - there is no provision for handling two overflows.

---

**TLDR;**

* Don't do delays inside an ISR
* If you must do them, you can time then with `micros()` but not `millis()`. Also `delayMicroseconds()` is a possibility.
* Don't delay more than 500 µs or so, or you'll miss a timer overflow.
* Even short delays may cause you to you miss incoming serial data (at 115200 baud you will get a new character every 87 µs).

body: You should never do anything inside an ISR except set a flag saying you got the interrupt, and return.


body:
Using two boards of similar architecture I would like to send the contents of a struct from the sending board to the receiving board. I am using UART to transfer.

My plan was to populate an array with the starting structs data. Transfer that, than un-package the array onto the receiving boards struct.

I'm not sure this is a possible option. Unpacking the array seems sort of rigid, as I would be assigning each struct variable to the array index. It might work but I'm not really convinced I should do it this way.

Here's what my sending sketch looks like.

Send:

    typedef struct NWK_DataReq_t
    {
     uint8_t      state;
     uint8_t      options;
    } NWK_DataReq_t;

    //Instance struct
    NWK_DataReq_t dataRequest;

    void setup()
    {
      //Give it some values
      dataRequest.state = 2;
      dataRequest.options = 4;

      Serial.begin(9600);
    }

    void loop()
    {
      //set variable array to struct length
      uint8_t payload[sizeof(dataRequest)];

      //copy struct to variable array
      memcpy(payload,&dataRequest,sizeof(dataRequest));

      //send each item of struct, now contained in payload array
      for(int i=0;i < sizeof(payload);i++)
      {
        //Serial.print(i);
        //Serial.print(":");
        Serial.println(payload[i]);
      }

      Serial.println("");
      delay(1000);
    }

Receive:

    typedef struct NWK_DataReq_t
    {
     uint8_t      state;
     uint8_t      options;
    } NWK_DataReq_t;

    //Instance struct
    NWK_DataReq_t dataRequest;
    uint8_t incomingPayload[sizeof(dataRequest)];

    void setup()
    {
      Serial.begin(9600);
      Serial.print("Recieve started");
    }

    void loop()
    {

      if (Serial.available())
      {
        //add incoming data to array
        for(int i=0;i<sizeof(dataRequest);i++)
        {
          uint8_t incomingByte = Serial.read();
          incomingPayload[i] = incomingByte;
        }
      }

      //set array values to structs
      for (int i= 0;i < sizeof(dataRequest);i++)
      {
        structIndexPosition = incomingPayload[i];
      }
    }

structIndexPosition is not attached as I wasn't sure how I might index the struct, or if this is an okay approach.

title: Transfer a struct's data to an external struct via serial?

Answers: 4

body:
*Why go over the bridge for water?*

It is possible to access the data in the struct as a character pointer. No need to transfer to a buffer etc.

    void loop()
    {
      ...
      ...
      const char* dp = (const char*) &dataRequest;
      for (int i = 0; i < sizeof(dataRequest); i++) Serial.print(*dp++);
      Serial.println();
      delay(1000);
      ...
      ...
     }
It might be hard to extrapolate how to receive this?

    void loop()
    {
      if (Serial.available() > sizeof(dataRequest)) {
         char* dp = (char*) &dataRequest;
         for (int i = 0; i < sizeof(dataRequest); i++) *dp++ = Serial.read();
         Serial.read();
         ...
         ...
      }
    }

The Serial.println() and extra Serial.read() could be replaced by a "frame marker" and/or a check-sum.

Cheers!

body:
I think you are over-complicating it to send two bytes. Just send them as straight ASCII with a newline after, and decode it on the receiving end.

eg.

    42,87

However if the question was just an example of something much more complex, then you may need to do more work. You need to have the receiving end know when a packet of data starts, and ends, and preferably have some validation that it wasn't corrupted.  If you want to pursue that idea, see my [thread about sending data via RS485](http://www.gammon.com.au/forum/?id=11428) which has a library that does that sort of thing.

body:
The simplest possible way of sending the struct's data is:

    Serial.write((const uint8_t *)&myData, sizeof(myData));

Get the address of myData, cast it to an unsigned int pointer, and starting at that address write the number of bytes specified by `sizeof(myData)`. That will transfer the raw data of the struct through the serial with no messing with copying of data into other arrays, assigning pointers, etc.

However: it won't work.

Sending raw binary data over serial like that, where serial has no concept of anything other than bytes, it is just not possible to know where in the stream of data you are. Which of the myriad of bytes coming in is which within a struct?  Who can tell?

So you need to write a protocol. A method whereby one end tells the other end "This is the start of the data.  This is the data.  This is the end of the data."  But also you need to be able to say "This bit, that looks the same as the 'start of the data' message is actually a bit of the data, not the start of the data".  You see, it's quite an involved task really.

body:
[![enter image description here][1]][1]If you couldn't run this code like me then all you have to do is cut the:"
struct package
{
};
typedef struct package Package;
Package data; "
And paste it into the "void loop" and it should work fine.
P/s: Thank you very much for this helpful video, but hope you will update this in the future ( i guess the update had changed something in the Arduino codes)

  [1]: https://i.stack.imgur.com/1YnS7.png


body: 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?

title: Zeroing a Vernier force probe

Answers: 1

body:
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.