Soil Sensor analog values differ on Uno vs Pro Mini



  • Working towards my sensor network and seeing a bit of an odd difference when moving from my Uno board over to the Pro Mini.

    I have the Soil Sensor (3.3v powered) setup to output Analog values and am reading that via A0 pin on the Uno. The base line value I get is 682, as I add water that value drops. However when I move that sensor over to the Pro Mini (3.3v) and run the exact same sketch I get a base line value of 1023, as I add water it drops. I swapped in another Pro Mini just to rule that out and it also registers 1023 as the baseline output.

    So I guess the question is, which one is correct? My initial take is that the Pro Mini is giving me bad values as it is maxed at 1023 - am I overlooking a setting on the pro mini?

    I removed all other sensors including the radio and am using this bare bones sketch between the two:
    <pre><code>
    #define SOIL_SENSOR_ANALOG_PIN A0
    void setup()
    {
    Serial.begin(115200);
    }

    void loop()
    {
    int soil = analogRead(SOIL_SENSOR_ANALOG_PIN);
    Serial.print("SOIL:");
    Serial.println(soil);

    delay(1000);
    }

    </code></pre>

    Thanks!


  • Hero Member

    @murdog You write the Pro Mini is powered at 3.3 V but you do not write how the Uno is powered but I guess it is powered at 5 V.

    If so, that can explain things I think.



  • @daulagari Yes Uno is powered via USB@5v, but the soil sensor is connected to the 3.3v regulated supply.


  • Admin

    Did you try setting pit to input mode?

    pinMode(SOIL_SENSOR_ANALOG_PIN, INPUT);


  • @hek I was playing around with it alot last night and yes that is one of the things I did try before doing a read, but still 1023. I will confirm again when home. Any ideas of what I should be seeing for the baseline on the soil sensor?


  • Hero Member

    @murdog said:

    Yes Uno is powered via USB@5v, but the soil sensor is connected to the 3.3v regulated supply.

    So is the full-ADC scale (1023) not the same as the voltage supply?

    682/1023 * 5 Volt = 3.33 Volt and that would clip the 3.3 V ADC of the Pro Mini so therefore it is giving 1023.


  • Hero Member

    OK, the soil sensor is connected to a 3.3v regulated supply.

    But the Arduino sounds like it's still running at 5v, and by default the ADC reference is VCC. So at full scale soil sensor reading of 3.3v will be only about 2/3 of that 5v reference. (but 100% of a 3.3v reference).

    So they are both right, just using different ADC references.

    The 5V reference is probably fine, you lose a little bit of resolution (less than one bit) but soil moisture sensors are not exactly precise.

    If it mattered, you can connect the 3.3v supply to the Aref input and set the ADC to use Aref as it's reference, in which case you'll get the full resolution 0..1023 for 0..3.3v. In this case I probably wouldn't bother.



  • @Zeph @daulagari Awesome thanks guys, that makes perfect sense!


  • Hero Member

    @murdog: You should probably also have a look at the New library to read Arduino VCC supply level without resistors for battery powered sensor nodes that do not use a voltage regulator but connect directly to the batteries thread.

    If you want to make the code generic, you should have the code measure the VCC and scale the measured value according to what you read for VCC.


  • Mod

    @daulagari Finally someone who appreciates my little library 😉 👍


  • Hero Member

    Can you please share your sketch? I have tried modifying the digital version of the sketch to analog but I have no idea what to write in the sensor type.


  • Hero Member

    Managed to make it a humidity sensor, which is probably close enough. Here is my sketch:
    #include <SPI.h>
    #include <MySensor.h>

    #define ANALOG_INPUT_SOIL_SENSOR A0
    #define CHILD_ID 0 // Id of the sensor child

    MySensor gw;
    MyMessage msg(CHILD_ID, V_HUM);
    int lastSoilValue = -1;

    void setup()
    {
    gw.begin();

    // Send the sketch version information to the gateway and Controller
    gw.sendSketchInfo("Soil Moisture Sensor - analog", "1.0");
    // sets the soil sensor analog pin as input
    pinMode(ANALOG_INPUT_SOIL_SENSOR, INPUT);
    // Register all sensors to gw (they will be created as child devices)
    gw.present(CHILD_ID, S_HUM);
    }

    void loop()
    {
    // Read analog soil value
    int soilValue = analogRead(ANALOG_INPUT_SOIL_SENSOR);

    if (soilValue != lastSoilValue) {
    Serial.println(soilValue);
    gw.send(msg.set(static_cast<int>(static_cast<float>(1023 - soilValue))/1023*100)); // Send the relative moisture. this will probably work only on nano or uno as I used 1023
    lastSoilValue = soilValue;
    }
    // Power down the radio and arduino until analog input changes.
    gw.sleep(1000);
    }


  • Hero Member

    Oh, sleep should probably be set to 3600000 or more to get long sleep periods between measurements as I don't think soil moisture should be measured every second....



  • @Moshe-Livne said:

    Managed to make it a humidity sensor, which is probably close enough. Here is my sketch:
    #include <SPI.h>
    #include <MySensor.h>

    #define ANALOG_INPUT_SOIL_SENSOR A0
    #define CHILD_ID 0 // Id of the sensor child

    MySensor gw;
    MyMessage msg(CHILD_ID, V_HUM);
    int lastSoilValue = -1;

    void setup()
    {
    gw.begin();

    // Send the sketch version information to the gateway and Controller
    gw.sendSketchInfo("Soil Moisture Sensor - analog", "1.0");
    // sets the soil sensor analog pin as input
    pinMode(ANALOG_INPUT_SOIL_SENSOR, INPUT);
    // Register all sensors to gw (they will be created as child devices)
    gw.present(CHILD_ID, S_HUM);
    }

    void loop()
    {
    // Read analog soil value
    int soilValue = analogRead(ANALOG_INPUT_SOIL_SENSOR);

    if (soilValue != lastSoilValue) {
    Serial.println(soilValue);
    gw.send(msg.set(static_cast<int>(static_cast<float>(1023 - soilValue))/1023*100)); // Send the relative moisture. this will probably work only on nano or uno as I used 1023
    lastSoilValue = soilValue;
    }
    // Power down the radio and arduino until analog input changes.
    gw.sleep(1000);
    }

    hello ,

    i want to do same , but can you explaind the calcul is made ?

    for now i use light sensor sketch with analog input , but i ant to modify by /10 for having a moisture meter reading value 0to100% or maybe there is a S_Percentage come in next version of mysensors ?

    i use domotiz with gateway and for now only Light sensor work for read analog value .

    thanks


  • Hero Member

    @fred97 , i also use domoticz. If you read this thread form the start, you will see that the arduino converts the moisture reading to something in the range 0-1023 (or 682 if you use mini pro). 1023 is 0 moisture, 0 is 100% moisture. so, moisture content is (1023 - reading)/1023*100.

    Hope this answers your question!

    Moshe



  • thanks you ,

    i have try your sketch but don't work send only O

    send: 2-2-0-0 s=0,c=1,t=1,pt=2,l=2,st=ok:0
    444
    send: 2-2-0-0 s=0,c=1,t=1,pt=2,l=2,st=ok:0
    470
    send: 2-2-0-0 s=0,c=1,t=1,pt=2,l=2,st=ok:0
    1023
    send: 2-2-0-0 s=0,c=1,t=1,pt=2,l=2,st=ok:0
    

    i think the problem is inside converter in percentage ....

    240 when is in water and 1023 when completly dry .


  • Hero Member

    @fred97 did you change anything in the calculation? the values in the println seems correct. do not remove the static casts - they are essential.


  • Contest Winner

    @Moshe-Livne said:

    Serial.println(soilValue);
    gw.send(msg.set(static_cast<int>(static_cast<float>(1023 - soilValue))/1023*100))

    how about just using the map() function...

    Serial.println(soilValue);
    gw.send(msg.set(map(soilValue, 0, 1023, 0 ,100));
    

  • Hero Member

    @BulldogLowell would have used it if I knew it existed.... would it work is reverse? (1023,0, 0, 100)?


  • Contest Winner

    @Moshe-Livne

    Try it!!

    int soilValue = 250;
    
    void setup() 
    {
      Serial.begin(115200);
      Serial.println(map(soilValue, 1023,0,100,0));
    }
    
    void loop() 
    {
      
    }
    

    have you run into 123dcircuits yet?

    Screen Shot 2015-05-24 at 6.26.37 AM.png


  • Hero Member

    @BulldogLowell not yet!!! my first encounter with arduino was only a few weeks ago.... so much to learn! the wood are lovely dark and deep, but i have promises to keep....



  • hello

    it's working but is not inverted 👍

    314
    send: 2-2-0-0 s=0,c=1,t=1,pt=4,l=4,st=ok:30
    294
    send: 2-2-0-0 s=0,c=1,t=1,pt=4,l=4,st=ok:28
    287
    send: 2-2-0-0 s=0,c=1,t=1,pt=4,l=4,st=ok:28
    299
    send: 2-2-0-0 s=0,c=1,t=1,pt=4,l=4,st=ok:29
    313
    send: 2-2-0-0 s=0,c=1,t=1,pt=4,l=4,st=ok:30
    1023
    send: 2-2-0-0 s=0,c=1,t=1,pt=4,l=4,st=ok:100
    

    100 is when is dry and 220/250 is when the sensor is in water .
    i just need little more help for invert value , 100 = in water and 0 when is dry

    thx


  • Contest Winner

    @fred97

    @BulldogLowell said:

    gw.send(msg.set(map(soilValue, 0, 1023, 0 ,100));

    like this:

    gw.send(msg.set(map(soilValue, 100, 250, 0, 100));
    

    it maps 100 to zero and 250 to 100

    Let me know if that works for you.

    or... you can try this to bound the returned value by zero and 100:

    gw.send((max(min(map(soilValue, 100,250,0,100), 100), 0)));
    

    confusing but is is mapping the value, and limiting to 100 and then making sure it is at least zero (i.e. non-negative).

    or just:

    gw.send(constrain(map(soilValue, 100,250,0,100), 0, 100));
    


  • gw.send(msg.set(map(soilValue, 100, 250, 0, 100)));```
    
    

    you have forget one ) at last .

    sensor started, id 2
    send: 2-2-0-0 s=255,c=0,t=17,pt=0,l=5,st=ok:1.4.1
    send: 2-2-0-0 s=255,c=3,t=6,pt=1,l=1,st=ok:0
    read: 0-0-2 s=255,c=3,t=6,pt=0,l=1:M
    send: 2-2-0-0 s=255,c=3,t=11,pt=0,l=25,st=ok:Soil Moisture Sensor - an
    send: 2-2-0-0 s=255,c=3,t=12,pt=0,l=3,st=ok:1.0
    send: 2-2-0-0 s=0,c=0,t=7,pt=0,l=5,st=ok:1.4.1
    1023
    send: 2-2-0-0 s=0,c=1,t=1,pt=4,l=4,st=ok:615
    285
    send: 2-2-0-0 s=0,c=1,t=1,pt=4,l=4,st=ok:123
    

    250 is when is in water and 1023 is dry , it's alway inverted , i can test 2 other exemple because there is a problem in sketch maybe ;or ) when is try this

    gw.send((max(min(map(soilValue, 100,250,0,100), 100), 0)));
    

    and for other 2 exemple i can send to arduino compiling error

    sketch_may24a.ino: In function 'void loop()':
    sketch_may24a:31: error: no matching function for call to 'MySensor::send(long int)'
    C:\Program Files (x86)\Arduino\libraries\MySensors/MySensor.h:142: note: candidates are: bool MySensor::send(MyMessage&, bool)
    

  • Contest Winner

    @fred97

    Post your entire sketch.



  • #include <SPI.h>
    #include <MySensor.h>
    
    #define ANALOG_INPUT_SOIL_SENSOR A0
    #define CHILD_ID 0 // Id of the sensor child
    
    MySensor gw;
    MyMessage msg(CHILD_ID, V_HUM);
    int lastSoilValue = -1;
    
    void setup()
    {
    gw.begin();
    
    // Send the sketch version information to the gateway and Controller
    gw.sendSketchInfo("Soil Moisture Sensor - analog", "1.0");
    // sets the soil sensor analog pin as input
    pinMode(ANALOG_INPUT_SOIL_SENSOR, INPUT);
    // Register all sensors to gw (they will be created as child devices)
    gw.present(CHILD_ID, S_HUM);
    }
    
    void loop()
    {
    // Read analog soil value
    int soilValue = analogRead(ANALOG_INPUT_SOIL_SENSOR);
    
    if (soilValue != lastSoilValue) {
    Serial.println(soilValue);
    gw.send(msg.set(map(soilValue, 100, 250, 0, 100)));
    lastSoilValue = soilValue;
    }
    // Power down the radio and arduino until analog input changes.
    gw.sleep(1000);
    }
    

    is the same sketch but i have changed only

    gw.send(msg.set(static_cast<int>(static_cast<float>(1023 - soilValue))/1023*100)); // Send the relative moisture. this will probably work only on nano or uno as I used 1023
    

    by this

    gw.send(msg.set(map(soilValue, 100, 250, 0, 100)));
    

    i don't understand why is alway inverted ??


  • Contest Winner

    @fred97 said:

    i don't understand why is alway inverted ??

    try to use this:

    gw.send(msg.set(constrain(map(soilValue, 1023, 250, 0, 100),0,100)));
    

    it maps 1023 to zero and 250 to 100... that is what you want, yes?

    #include <SPI.h>
    #include <MySensor.h>
    
    #define ANALOG_INPUT_SOIL_SENSOR A0
    #define CHILD_ID 0 // Id of the sensor child
    
    MySensor gw;
    MyMessage msg(CHILD_ID, V_HUM);
    int lastSoilValue = -1;
    
    void setup()
    {
      gw.begin();
    
      // Send the sketch version information to the gateway and Controller
      gw.sendSketchInfo("Soil Moisture Sensor - analog", "1.0");
      // sets the soil sensor analog pin as input
      pinMode(ANALOG_INPUT_SOIL_SENSOR, INPUT);
      // Register all sensors to gw (they will be created as child devices)
      gw.present(CHILD_ID, S_HUM);
    }
    
    void loop()
    {
      // Read analog soil value
      int soilValue = analogRead(ANALOG_INPUT_SOIL_SENSOR);
    
      if (soilValue != lastSoilValue) {
        Serial.println(soilValue);
        gw.send(msg.set(constrain(map(soilValue, 1023, 250, 0, 100),0,100)));
        lastSoilValue = soilValue;
      }
      // Power down the radio and arduino until analog input changes.
      gw.sleep(1000);
    }
    


  • thanks you very much work great !


 

329
Online

8.2k
Users

9.1k
Topics

96.7k
Posts