AnalogRead problem



  • I have troubleshot this for over a week but can't figure it out.
    My A1 & A2 wont analogRead anything except 1023, however my battery sensing works on A4. I'm using a SlimNode pcb, an AtMega328 barebone with 8mhz bootloader. The pcb is powered by 18650 with protection board (gets power from mains when lights are on and charges). The A2 has a thermistor in a voltage divider config (VCC3V3 - R10k - A2 - thermistor - GND) and reading the voltage at A2 is 1.73'ish and 3.3 at VCC.
    Sketch:

    #define MY_DEBUG                             // Enable debug prints to serial monitor
    #define MY_RADIO_RF24 // Enable and select radio type attached
    #define MY_TRANSPORT_WAIT_READY_MS 3000  //set how long to wait for connection to establish before moving on. in milliseconds
    #define MY_NODE_ID 21
    #define MY_BAUD_RATE 57600
    
    #define DOOR 3
    #define DHT_DATA_PIN 5
    #define CHILD_ID_HUM 0
    #define CHILD_ID_TEMP 1
    #define THMR_PIN A2 // A2/16 pin
    #define LED 7
    
    #define SENSOR_TEMP_OFFSET 0
    
    #include <SPI.h>
    #include <MySensors.h>  
    #include <DHT.h>
    
    int BATTERY_SENSE_PIN = A4;
    float lastTemp;
    float lastHum;
    uint8_t nNoUpdatesTemp;
    uint8_t nNoUpdatesHum;
    bool metric = true;
    unsigned long previousMillis = 0;
    long sleepTime;
    int oldBatteryPcnt = 0;
    
    MyMessage msgHum(CHILD_ID_HUM, V_HUM);
    MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
    MyMessage msgTempSau(THMR_PIN, V_TEMP);
    MyMessage msgDoor(DOOR, V_TRIPPED);
    DHT dht;
    
    void presentation()  
    { 
      sendSketchInfo("SaunaTempsDoor", "v29032020");
    
      // Register all sensors to gw (they will be created as child devices)
      present(CHILD_ID_HUM, S_HUM, "Shower Hum");
      present(CHILD_ID_TEMP, S_TEMP, "Shower Temp");
      present(THMR_PIN, S_TEMP, "Sauna Temp");
      present(DOOR, S_DOOR);
      metric = getControllerConfig().isMetric;
    
    }
    
    void setup()
    {
     dht.setup(DHT_DATA_PIN); // set data pin of DHT sensor
     sleep(2000);
    // pinMode(THMR_PIN, INPUT);
     pinMode(DOOR, INPUT_PULLUP);
     pinMode(LED, OUTPUT);
    // pinMode(BATTERY_SENSE_PIN, INPUT);
    
       for (int i=0; i<6; i++){
        digitalWrite(LED, HIGH);
        delay(200);
        digitalWrite(LED, LOW);
        delay(200);
      }
     analogReference(INTERNAL);
    }
    
    void loop()      
    {  
     // Check the door
      bool doorState = !digitalRead(DOOR);
      Serial.print("Sauna door: ");
      Serial.println(doorState);
      send(msgDoor.set(doorState?"1":"0"));  // Send tripped value to gw
    
     // Check DHT-sensor
     delay(300);
     dht.readSensor(true);
     
      float temperature = dht.getTemperature();
        if (isnan(temperature)) {
        Serial.println("Failed reading temperature from DHT!");
        } 
        else {
        lastTemp = temperature;
        send(msgTemp.set(temperature, 2));
        Serial.print("Shower T: ");
        Serial.println(temperature);
        }
    
      float humidity = dht.getHumidity();
        if (isnan(humidity)) {
        Serial.println("Failed reading humidity from DHT");
        } 
        else {
        lastHum = humidity;
        send(msgHum.set(humidity, 1));
        Serial.print("Shower H: ");
        Serial.println(humidity);
        } 
    
    // Read the thermistor
      int _nominal_resistor = 10000;
      int _nominal_temperature = 25;
      int _b_coefficient = 3950;
      int _series_resistor = 10000;
      delay(10);
      float adcT1 = analogRead(THMR_PIN);
      Serial.println(adcT1);
      float reading1 = (1023 / adcT1)  - 1;
      reading1 = _series_resistor / reading1;
      float temperatureS;
      temperatureS = reading1 / _nominal_resistor;     // (R/Ro)
      temperatureS = log(temperatureS);                  // ln(R/Ro)
      temperatureS /= _b_coefficient;                   // 1/B * ln(R/Ro)
      temperatureS += 1.0 / (_nominal_temperature + 273.15); // + (1/To)
      temperatureS = 1.0 / temperatureS;                 // Invert
      temperatureS -= 273.15;                         // convert to C
      send(msgTempSau.set((int16_t)temperatureS, 2));
        Serial.print("Sauna T: ");
        Serial.print(temperatureS);
        Serial.println(" C");
    
    if (temperatureS > 40){
        sleepTime = 300000; // 5min when sauna is hot
        Serial.println("Sauna warm, sleeptime 5min");
        }
        else {
        sleepTime = 1800000; // 30min sleep when sauna is <40C
        Serial.println("Sauna off, sleeping 30min");
        }
    
    
        // get the battery Voltage
        int sensorValue = analogRead(BATTERY_SENSE_PIN);
        // 1M & 200k => Vmax = 6.6 Volts => Volts per bit = 0.00645161290323
        float batteryV  = sensorValue * 0.00645161290323;
        Serial.print("Battery Voltage: ");
        Serial.print(batteryV);
        Serial.print(" V   ");
    
        float batteryPcnt = ( (batteryV - 3) / 1.25) * 100;
        Serial.print("Battery percent: ");
        Serial.print(batteryPcnt);
        Serial.println(" %");
        if (oldBatteryPcnt != batteryPcnt) {
            sendBatteryLevel(batteryPcnt);
            oldBatteryPcnt = batteryPcnt;
        }
     digitalWrite(LED, HIGH);
     delay(50);
     digitalWrite(LED, LOW);
    sleep(1, CHANGE, sleepTime);   // Wake to door switch or sleeptime
    
    }
    

    And debug from serial (NO errors etc along the way, sketch uses 60%mem)

    17205 MCO:SLP:WUP=1
    17209 TSF:TRI:TSB
    Sauna door: 0
    17219 TSF:MSG:SEND,21-21-9-0,s=3,c=1,t=16,pt=0,l=1,sg=0,ft=0,st=OK:0
    17555 TSF:MSG:SEND,21-21-9-0,s=1,c=1,t=0,pt=7,l=5,sg=0,ft=0,st=OK:24.00
    Shower T: 24.00
    17573 TSF:MSG:SEND,21-21-9-0,s=0,c=1,t=1,pt=7,l=5,sg=0,ft=0,st=OK:16.0
    Shower H: 16.00
    1023.00
    17604 TSF:MSG:SEND,21-21-9-0,s=16,c=1,t=0,pt=7,l=5,sg=0,ft=0,st=OK:-273.00
    Sauna T: -273.15 C
    Sauna off, sleeping 30min
    Battery Voltage: 4.31 V   Battery percent: 104.77 %
    17627 TSF:MSG:SEND,21-21-9-0,s=255,c=3,t=0,pt=1,l=1,sg=0,ft=0,st=OK:104
    17696 MCO:SLP:MS=1800000,SMS=0,I1=1,M1=1,I2=255,M2=255
    17707 TSF:TDI:TSL
    

    The reading from battery is correct (almost: multimeter says 4.23 at battery) how to fix this?

    Why are my analogReads failing (I already switched from A1 to A2 just in case). I have checked the wiring twenty times.



  • @MasMat analogRead returns an int, not a float



  • Same result float => int change in the sketch.

    Tried to reupload bootloader but got a problem, same with another atmega328. Will investigate that next.



  • @MasMat said in AnalogRead problem:

    analogReference(INTERNAL);

    Won't that set the analog reference to the 1.1V internal source? If so then the analog read range of 0-1023 will be mapped to 0-1.1V. Anything over 1.1 will be seen as 1.1V - But maybe I'm wrong....???



  • I investigated the bootloader problem, I use 1.8.1 definitions that made those problems disappear. But still, the A2 (THMR_PIN) reads 1023 but the battery sense on A4 works.

    EDIT: now I get what you mean: it also changes the reference for the whole ADC...from 3.3 to 1.1V! Any ideas for changing the resistors? I would want to use the same thermistor as I only have two wires going to the sauna. OR is there a way to change the reference for A2 read and go back after it's been read?



  • Yes, you can change between references.

    analogReference(DEFAULT);
    

    Be aware that after you changed the reference the first 52 reads have to be discarded.



  • @electrik ..and then just adjust the volts/bit for 3.3 rather than 1.1v, correct? (i.e x3). That fixed it, thank you.
    BUT presented a weird problem. The analogRead gives a proper value but the math then is not working and I cant figure it out. I did the calculations myself and get a proper result:

    int _nominal_resistor2 = 10000;
      int _nominal_temperature2 = 25;
      int _b_coefficient2 = 3950;
      int _series_resistor2 = 10000;
      int adcTmm = analogRead(THMR_PIN);
      Serial.println(adcTmm);
      float readingSau = (1023 / adcTmm)  - 1;
      readingSau = _series_resistor2 / readingSau;
      float temperatureS = readingSau / _nominal_resistor2;     // (R/Ro)
      temperatureS = log(temperatureS);                  // ln(R/Ro)
      temperatureS /= _b_coefficient2;                   // 1/B * ln(R/Ro)
      temperatureS += 1.0 / (_nominal_temperature2 + 273.15); // + (1/To)
      temperatureS = 1.0 / temperatureS;                 // Invert
      temperatureS -= 273.15;                         // convert to C
      send(msgTempSau.set((int16_t)temperatureS, 2));
        Serial.print("Sauna T: ");
        Serial.print(temperatureS);
        Serial.println(" C");
    

    But still the serial monitor shows:

    7409 MCO:SLP:WUP=1
    7413 TSF:TRI:TSB
    Sauna door: 1
    7430 TSF:MSG:SEND,21-21-10-0,s=3,c=1,t=16,pt=0,l=1,sg=0,ft=0,st=OK:1
    7966 TSF:MSG:SEND,21-21-10-0,s=1,c=1,t=0,pt=7,l=5,sg=0,ft=0,st=OK:29.00
    Shower T: 29.00
    7989 TSF:MSG:SEND,21-21-10-0,s=0,c=1,t=1,pt=7,l=5,sg=0,ft=0,st=OK:87.0
    Shower H: 87.00
    536
    8005 TSF:MSG:SEND,21-21-10-0,s=16,c=1,t=0,pt=7,l=5,sg=0,ft=0,st=OK:-273.00
    Sauna T: -273.15 C
    Sauna off, sleeping 30min
    Battery Voltage: 4.22 V   Battery percent: 97.70 %
    8028 TSF:MSG:SEND,21-21-10-0,s=255,c=3,t=0,pt=1,l=1,sg=0,ft=0,st=OK:97
    8097 MCO:SLP:MS=1800000,SMS=0,I1=1,M1=1,I2=255,M2=255
    8108 TSF:TDI:TSL
    

    I changed variable names to account there wouldnt be overlap with DHT library & dht part of sketch.



  • These kind of issues are usually caused by an overflow somewhere, or memory being full

    Edit:
    Also check if you're using the right log function... There are two log functions, the log base 10 and the log base 2



  • @electrik Thanks I'll check those.
    I added a lot of serial.Print's to debug where it goes south and it appears to ruin already at the first division after the analogRead (I started receiving 530's analogRead at room temp). So probably something else completely that's rotten. I'll try another machine with another Arduino IDE. It should work now that the original question is answered.
    So I'll consider this solved. Thanks again!



  • @MasMat
    The integer division might be the cause. Please try to force conversion to floating point:

      float readingSau = (1023.f / adcTmm)  - 1.f;
    

  • Mod

    @MasMat Try changing

    float readingSau = (1023 / adcTmm)  - 1;
    

    To

    float readingSau = (1023.0 / float(adcTmm) )  - 1;
    

    You are mixing integer and floating point math.



  • @Yveaux and @boum You two beat me by 2hrs.
    @user2684 whose code this is (cudos to him, have used this bit on a number of sensors!) had probably figured that out and I screwed myself when I changed the original analogRead to int.

    Now the whole thing works 100%


Log in to reply
 

Suggested Topics

  • 3
  • 3
  • 2
  • 2
  • 24
  • 1

1
Online

11.2k
Users

11.1k
Topics

112.5k
Posts