Skip to content
  • MySensors
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
  1. Home
  2. My Project
  3. 12v Solar battery monitor

12v Solar battery monitor

Scheduled Pinned Locked Moved My Project
59 Posts 8 Posters 34.5k Views 15 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • Boots33B Offline
    Boots33B Offline
    Boots33
    Hero Member
    wrote on last edited by Boots33
    #38

    The best way to setup the acs712 is to put it where it is going to be mounted but have no current going through it. (you can just disconnect one power lead) it should show a reading close to zero.
    If not push the button and hold till the led flashes (may take a while depending on how much delay you are using) once the led flashes you can let go of the button and the offset to zero the reading will be applied. This offset will also be saved in the arduino eeprom so it will be reloaded if the arduino is rebooted etc.
    then the readings should be very close to zero.
    you can now reconnect and it should give you the correct reading.

    1 Reply Last reply
    0
    • aDm1NA Offline
      aDm1NA Offline
      aDm1N
      wrote on last edited by gohan
      #39

      Hallo

      Mein Englisch ist nicht so gut.
      Ich habe versucht das Projekt nach zu bauen. Den Button brauche ich (denke ich) nicht, dafür habe ich das script jedoch um 2 weitere current und voltage Sensoren erweitert. Das Ziel ist 3 mal Current und 3 mal Volt als Ergebnis zu bekommen. Ich habe 30A Sensoren und einen 30A Laderegler. Dazwischen sind jeweils 30A Sicherungen.
      Leider kommt in Domoticz aber nur ein mal Volt und 2 mal Current an. Leider habe ich auch nicht wirklich viel Ahnung vom Programmieren. Könnte hier mal jemand über den Sketch gucken um zu sehen ob ich einen Fehler darin habe?

      /*Sketch for a MySensor node to monitor a 12v battery with a solar panel for charging
       * The node monitors battery voltage,current into and out of the battery, ambient temperature and battery temperature.
       * 2 x DS18b20 dallas temperature ic's their data pins connected to arduino digital pin 3
       * 1 x ACS712 current sensor module connected to  arduino analog pin A4
       * 1 x 25v voltage sensor module connected to arduino analog pin A0
       * 1 x nRF24L01+  2.4ghz tranceiver connected as per the MySensors web site.
       * 1 x LED connected via a 330 ohm resistor to pin 6
       * 1 x push button connected to pin 5
       */
       
      #include <MySensor.h>  
      #include <SPI.h>
      #include <OneWire.h>
      #include <DallasTemperature.h>
       
      
      #define ONE_WIRE_BUS 3                       // Ds18b20 data wire is connected to digital pin 3 on the Arduino
      #define ID_S_TEMPA 0                         // First temp device
      #define ID_S_TEMPB 1                         // second temp device
      #define ID_S_MULTIMETERV1 3                   // Multimeter device for voltage measurement
      #define ID_S_MULTIMETERC1 4                   // Multimeter device for positive current measurement 
      #define ID_S_MULTIMETERC11 5                  // Multimeter device for negative current measurement
      #define ID_S_MULTIMETERV2 3                   // Multimeter device for voltage measurement
      #define ID_S_MULTIMETERC2 4                   // Multimeter device for positive current measurement 
      #define ID_S_MULTIMETERC12 5                  // Multimeter device for negative current measurement
      #define ID_S_MULTIMETERV3 6                   // Multimeter device for voltage measurement
      #define ID_S_MULTIMETERC3 7                   // Multimeter device for positive current measurement 
      #define ID_S_MULTIMETERC13 8
      #define NUM_SAMPLES 10                       // number of analog voltage samples to take per reading
      
      
      int ledPin = 6;                               // the pin for the LED
      int buttonPin = 5;                            // the input pin for offset pushbutton
      int buttonState = 0;                          // variable for reading the pin status
      unsigned long SLEEP_TIME = 30000;            // Sleep time between reads (in milliseconds)
      int lastmilli1 = 25000;                       // set to an arbitary number outside of expected current sensor range to ensure a change when first run 
      int lastmilli2 = 25000;                       // set to an arbitary number outside of expected current sensor range to ensure a change when first run 
      int lastmilli3 = 25000;                       // set to an arbitary number outside of expected current sensor range to ensure a change when first run 
      float sensitivity = 66 ;                    //change this to 185 for ACS712-5 or to 100 for ACS712-20A or to 66 for ACS712-30A
      int VQ = 0;                                  //Placeholder for quiescent voltage calculations
      int ACSPin1 = A4;                             // Analog pin number the ACS712 data pin connects to
      int ACSPin2 = A5;                             // Analog pin number the ACS712 data pin connects to
      int ACSPin3 = A3;                             // Analog pin number the ACS712 data pin connects to
      float lastTemperature[2];                    //Array to hold the last temp readings sent to gateway, only send new data if different
      int sum = 0;                                 // sum of voltage samples taken
      unsigned char sample_count = 0;              // current sample number
      int lastVoltage1 = 30000;                     // set to an arbitary number outside of expected voltage sensor range to ensure a change when first run
      int lastVoltage2 = 30000;                     // set to an arbitary number outside of expected voltage sensor range to ensure a change when first run
      int lastVoltage3 = 30000;                     // set to an arbitary number outside of expected voltage sensor range to ensure a change when first run
      int voltagePin1 = A0;                         // analog pin voltage sensor or voltage divider is connected to
      int voltagePin2 = A1;                         // analog pin voltage sensor or voltage divider is connected to
      int voltagePin3 = A2;                         // analog pin voltage sensor or voltage divider is connected to
      int voltSense1Max = 25000;                    // set to the maximum input voltage in millivolts of your voltage divider input  
      int voltSense2Max = 25000;                    // set to the maximum input voltage in millivolts of your voltage divider input
      int voltSense3Max = 25000;                    // set to the maximum input voltage in millivolts of your voltage divider input    
      OneWire oneWire(ONE_WIRE_BUS);               // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
      DallasTemperature sensors(&oneWire);         // Pass our oneWire reference to Dallas Temperature.
      
      MySensor gw;
      
      // ------ Initialize  messages -------
      MyMessage msg(0,V_TEMP);                     
      MyMessage msg_S_MULTIMETERv1(ID_S_MULTIMETERV1,V_VOLTAGE);
      MyMessage msg_S_MULTIMETERc1(ID_S_MULTIMETERC1,V_CURRENT);
      MyMessage msg_S_MULTIMETERc11(ID_S_MULTIMETERC11,V_CURRENT); 
      MyMessage msg_S_MULTIMETERv2(ID_S_MULTIMETERV2,V_VOLTAGE);
      MyMessage msg_S_MULTIMETERc2(ID_S_MULTIMETERC2,V_CURRENT);
      MyMessage msg_S_MULTIMETERc12(ID_S_MULTIMETERC12,V_CURRENT); 
      MyMessage msg_S_MULTIMETERv3(ID_S_MULTIMETERV3,V_VOLTAGE);
      MyMessage msg_S_MULTIMETERc3(ID_S_MULTIMETERC3,V_CURRENT);
      MyMessage msg_S_MULTIMETERc13(ID_S_MULTIMETERC13,V_CURRENT); 
      
      void setup()
      {
       
      sensors.begin();                                    // Start up the onewire library
      gw.begin();                                         // Startup and initialize MySensors library. Set callback for incoming messages. 
      gw.sendSketchInfo("Battery Status Sensor", "1");    // Send the sketch version information to the gateway and Controller
      
      // ------ Present all sensors to controller ------
      gw.present(ID_S_TEMPA, S_TEMP);
      gw.present(ID_S_TEMPB, S_TEMP);
      gw.present(ID_S_MULTIMETERV1,V_VOLTAGE);
      gw.present(ID_S_MULTIMETERC1,V_CURRENT);
      gw.present(ID_S_MULTIMETERC11,V_CURRENT);
      gw.present(ID_S_MULTIMETERV2,V_VOLTAGE);
      gw.present(ID_S_MULTIMETERC2,V_CURRENT);
      gw.present(ID_S_MULTIMETERC12,V_CURRENT);
      gw.present(ID_S_MULTIMETERV3,V_VOLTAGE);
      gw.present(ID_S_MULTIMETERC3,V_CURRENT);
      gw.present(ID_S_MULTIMETERC13,V_CURRENT);
      
      
      pinMode(buttonPin, INPUT_PULLUP);                     // Set buttonPin as input and turn on internal pull up resistor
      pinMode(ledPin, OUTPUT);                              // Set ledPin as output
      digitalWrite(ledPin, LOW);                            // Make sure ledPin is off
      
      // ------ load offset for current sensor
      int validCheck = gw.loadState(0);
      if (validCheck == 120){                          // check to see if valid data exists
        VQ = gw.loadState(1);                               // Load count offset into VQ
      //  Serial.print(" positive VQ offset loaded..."); Serial.println(VQ);
       }
       else if (validCheck == 125) {
        VQ = -abs(gw.loadState(1));
      //  Serial.print(" negative VQ offset loaded..."); Serial.println(VQ);
       }
      else {
      // Serial.println("VQ offset not set");
      }
      
      delay(500);  
      }
       
      void loop()
      {
      
      buttonState = digitalRead(buttonPin);
      //Serial.print("buttonstate..."); Serial.println(buttonState);
       if (buttonState == LOW) {
          VQ = determineVQ(ACSPin1);                           //Returns the offset count needed to show zero with no load
      
          
        if (VQ >= 0 && VQ < 255) {                              //check for valid data. VQ is positive number
          gw.saveState(0, 120);                               // Store 120 value  in eeprom position 0. use this to check for valid data at boot
          gw.saveState(1, VQ);                                // Store offset count in eeprom. in case of re-boot  
        }
        else if (VQ < 0 && VQ > -255) {                              // VQ is a negative number. negatives cannot be stored in eeprom
          gw.saveState(0, 125);                               // Store 125 value  in eeprom position 0. use this to check for valid data at boot
          gw.saveState(1, abs(VQ));                                // convert VQ to positive and  Store offset count in eeprom. in case of re-boot   
        }
      
        }
      
      // ------------------ Start voltage 1 readings --------------------
       
      
       sample_count = 0;
       sum = 0;
       while (sample_count < NUM_SAMPLES) {                                   // take a number of voltage samples  
        sum += analogRead(voltagePin1);
        sample_count++;
        delay(10);
       }
      //Serial.print("sum count..."); Serial.println((sum / NUM_SAMPLES));      // print the count result. will be between 0 and 1023
      int voltage1I = map(sum/NUM_SAMPLES,0,1023,0,voltSense1Max);              // map the reading and get our result in millivolts
      //Serial.print("mapped volts..."); Serial.println(voltageI / 1000.0, 1);  // convert millivolts back to volts and print. the 1 at the end determines how many decimal places to show
      
      
      if ( voltage1I != lastVoltage1) {                                         // check if we have a new value. only send data if it is different
       gw.send(msg_S_MULTIMETERv1.set(voltage1I / 1000.0, 1));                  // voltagel is in millivolts so we divide by 1000 to convert back to volts and
                                                                              // send voltage message to gateway with 1 decimal place
       lastVoltage1 = voltage1I;                                                // copy the current voltage reading for testing on the next loop 
      }
      
      //--------------------Start Current 1 readings---------------------------------
      
      int milli1 = readCurrent(ACSPin1);                                       // take a reading from the ACS712 and send to the readcurrent function
      
      //Serial.print("Milliamps..."); Serial.println(milli);                   // print the value (in milliamps) returned
      
      if ( milli1 != lastmilli1)                                               // check if value has changed
      {
       if ( milli1 > 0)                                                       // Battery is charging
       {
        gw.send(msg_S_MULTIMETERc1.set(milli1/1000.0, 1));                     // Send new data to charging amp device
        gw.send(msg_S_MULTIMETERc11.set(0));                                  // set the dis-charging amp device to zero
        lastmilli1 =  milli1;
       }
       else if (milli1 < 0)                                                  // Battery is discharging
       {
        gw.send(msg_S_MULTIMETERc1.set(0));                                  // set the charging amp device to zero
        gw.send(msg_S_MULTIMETERc11.set(abs(milli1)/1000.0, 1));             //  use abs(milli) to Send a positive number  to dis-charging amp device
        lastmilli1 =  milli1; 
       }
      else                                                                // No current flowing, set both to zero
      {
       gw.send(msg_S_MULTIMETERc1.set(0));
       gw.send(msg_S_MULTIMETERc11.set(0));
       lastmilli1 =  milli1;
      }
      }
       
      //----------------------Teperature readings start------------------------
        
        Serial.println(" Requesting temperatures...");
       
       // Fetch temperatures from Dallas sensors
        sensors.requestTemperatures();                  // call sensors.requestTemperatures() to issue a global temperature request to all devices on the bus
      
        // ------- query conversion time and sleep until conversion completed ------
        int16_t conversionTime = sensors.millisToWaitForConversion(sensors.getResolution());
        gw.sleep(conversionTime);
      
       for (int i=0; i<2; i++) {
      //  Serial.print("Temperature for Device: ");Serial.print(i);Serial.print(" is: ");
       // Serial.println(sensors.getTempCByIndex(i)); // Why "byIndex"? 
          // You can have more than one IC on the same bus. 
          // 0 refers to the first IC on the wire
      
       float temperature = static_cast<float>(static_cast<int>((sensors.getTempCByIndex(i)) * 10.)) / 10.;  // Fetch and round temperature to one decimal in celcius
      
      if (lastTemperature[i] != temperature)               // check for a changed temperature reading
        {
         gw.send(msg.setSensor(i).set(temperature,1));     // Send in the new temperature
         lastTemperature[i]=temperature;                   // Save new temperatures for next compare
        }     
      }
      
      // ------------------ Start 2 voltage readings --------------------
       
      
       sample_count = 0;
       sum = 0;
       while (sample_count < NUM_SAMPLES) {                                   // take a number of voltage samples  
        sum += analogRead(voltagePin2);
        sample_count++;
        delay(10);
       }
      //Serial.print("sum count..."); Serial.println((sum / NUM_SAMPLES));      // print the count result. will be between 0 and 1023
      int voltage2I = map(sum/NUM_SAMPLES,0,1023,0,voltSense2Max);              // map the reading and get our result in millivolts
      //Serial.print("mapped volts..."); Serial.println(voltageI / 1000.0, 1);  // convert millivolts back to volts and print. the 1 at the end determines how many decimal places to show
      
      
      if ( voltage2I != lastVoltage2) {                                         // check if we have a new value. only send data if it is different
       gw.send(msg_S_MULTIMETERv2.set(voltage2I / 1000.0, 1));                  // voltagel is in millivolts so we divide by 1000 to convert back to volts and
                                                                              // send voltage message to gateway with 1 decimal place
       lastVoltage2 = voltage2I;                                                // copy the current voltage reading for testing on the next loop 
      }
      
      //--------------------Start Current 2 readings---------------------------------
      
      int milli2 = readCurrent(ACSPin2);                                       // take a reading from the ACS712 and send to the readcurrent function
      
      //Serial.print("Milliamps..."); Serial.println(milli);                   // print the value (in milliamps) returned
      
      if ( milli2 != lastmilli2)                                               // check if value has changed
      {
       if ( milli2 > 0)                                                       // Battery is charging
       {
        gw.send(msg_S_MULTIMETERc2.set(milli2/1000.0, 1));                     // Send new data to charging amp device
        gw.send(msg_S_MULTIMETERc12.set(0));                                  // set the dis-charging amp device to zero
        lastmilli2 =  milli2;
       }
       else if (milli1 < 0)                                                  // Battery is discharging
       {
        gw.send(msg_S_MULTIMETERc2.set(0));                                  // set the charging amp device to zero
        gw.send(msg_S_MULTIMETERc12.set(abs(milli2)/1000.0, 1));             //  use abs(milli) to Send a positive number  to dis-charging amp device
        lastmilli2 =  milli2; 
       }
      else                                                                // No current flowing, set both to zero
      {
       gw.send(msg_S_MULTIMETERc2.set(0));
       gw.send(msg_S_MULTIMETERc12.set(0));
       lastmilli2 =  milli2;
      }
      }
      
      
      // ------------------ Start voltage 3 readings --------------------
       
      
       sample_count = 0;
       sum = 0;
       while (sample_count < NUM_SAMPLES) {                                   // take a number of voltage samples  
        sum += analogRead(voltagePin3);
        sample_count++;
        delay(10);
       }
      //Serial.print("sum count..."); Serial.println((sum / NUM_SAMPLES));      // print the count result. will be between 0 and 1023
      int voltage3I = map(sum/NUM_SAMPLES,0,1023,0,voltSense3Max);              // map the reading and get our result in millivolts
      //Serial.print("mapped volts..."); Serial.println(voltageI / 1000.0, 1);  // convert millivolts back to volts and print. the 1 at the end determines how many decimal places to show
      
      
      if ( voltage3I != lastVoltage3) {                                         // check if we have a new value. only send data if it is different
       gw.send(msg_S_MULTIMETERv3.set(voltage3I / 1000.0, 1));                  // voltagel is in millivolts so we divide by 1000 to convert back to volts and
                                                                              // send voltage message to gateway with 1 decimal place
       lastVoltage3 = voltage3I;                                                // copy the current voltage reading for testing on the next loop 
      }
      
      //--------------------Start Current 3 readings---------------------------------
      
      int milli3 = readCurrent(ACSPin3);                                       // take a reading from the ACS712 and send to the readcurrent function
      
      //Serial.print("Milliamps..."); Serial.println(milli);                   // print the value (in milliamps) returned
      
      if ( milli3 != lastmilli3)                                               // check if value has changed
      {
       if ( milli3 > 0)                                                       // Battery is charging
       {
        gw.send(msg_S_MULTIMETERc3.set(milli3/1000.0, 1));                     // Send new data to charging amp device
        gw.send(msg_S_MULTIMETERc13.set(0));                                  // set the dis-charging amp device to zero
        lastmilli3 =  milli3;
       }
       else if (milli3 < 0)                                                  // Battery is discharging
       {
        gw.send(msg_S_MULTIMETERc3.set(0));                                  // set the charging amp device to zero
        gw.send(msg_S_MULTIMETERc13.set(abs(milli3)/1000.0, 1));             //  use abs(milli) to Send a positive number  to dis-charging amp device
        lastmilli3 =  milli3; 
       }
      else                                                                // No current flowing, set both to zero
      {
       gw.send(msg_S_MULTIMETERc3.set(0));
       gw.send(msg_S_MULTIMETERc13.set(0));
       lastmilli3 =  milli3;
      }
      }
      gw.sleep(SLEEP_TIME);
      }
      
       
      
      /*-------------- Function to get the offset required for ACS712 to show zero with no current flowing -----------------*/
      int determineVQ(int PIN)                  
       {
        digitalWrite(ledPin, HIGH);                                      // Turn on LED to indicate offset being calculated
        delay(500);                                                      // Delay to hold LED on
        digitalWrite(ledPin, LOW);                                       // Turn off LED
        delay(150);                                                      // Delay to let readings stabilise
      //  Serial.print("estimating avg. quiscent voltage:");
        long acsCount = 0;
        for (int i=0; i<5000; i++)                                       //read 5000 samples to stabilise value
         {
          acsCount += analogRead(PIN);                                   // read the count value between 0 and 1023 and add it to acsCount
          delay(1);                                           
         }
        acsCount /= 5000;                                                      // acsCount now eaquals the average of the 5000 readings taken
      //  Serial.print(map(acsCount, 0, 1023, 0, 5000));Serial.println(" mV");   //Print the avg in millivolts
      //  Serial.print("acsCount:");Serial.println(acsCount);                               //Print the actual count value
        
        return int(acsCount - 512);                                            // return the count difference. 512 is the count for 2.5v which is what the reading should be with no current flow                           
        
      }
      
      
       /*--------------- Function to read current flowing ------------------*/
       
      int readCurrent(int PIN) 
      {
       int count = 0;
       for (int i=0; i<5; i++)                                        //read 5 analog count samples to stabilise value
        {
         count += analogRead(PIN) - VQ;                               //subtract the offset count VQ to improve accuracy
         delay(1);
       //  Serial.print("raw count..."); Serial.println(count);
        }
       /* Notes on the conversion below
        *  .00488 is the volt value per count of the arduino adc. The analog pin measures from 0 to 5 volt and then assigns the result to 
        *  a count from 0 to 1023, thats 1024 counts including zero. If we devide 5v by 1024 we get .oo488 volts for each count.  
        *  
        *  The (count/5) just gets us the average of our 5 count samples.
        *  
        *  So after the first part of the equation  (.00488 * (count/5) is complete we have converted our count reading into volts. 
        *  
        *  The ACS712 can measure current flow in both directions so it outputs a voltage of  2.5v as it's center point (when no current is flowing).
        *  To allow for this offset we must subtract the 2.5v to center our voltage reading.
        *  
        * Thats what the next part does (.00488 * (count/5)) - 2.5) After this is complete we are left with either a negative or  positive voltage
        * reading or a reading of zero for no current flow.
        * 
        * NOTE: While the ACS712 is a 5v device it does not use the full 0 to 5v for it's output. The datasheet shows the 20A version has a sensitivity of
        *  100mv per amp, so if we multiply 100mv by 20 we get 2v.  That means the 20A ACS712 has an output range from .5v to 4.5v.  
        * 
        * So to convert our reading in volts to a reading in amps we need to add the last part ((.00488 * (count/5)) - 2.5)/(sensitivity/1000).
        * The variable sensitivity is defined at the begining of the sketch and holds the ACS712 sensitvity amount, it is stored in millivolts. 
        * That is 66mv for the 30amp,  100mv for the 20amp and 185mv for the 5amp. As sensitivity is in millivolts we need to devide it by 1000 
        * to convert it back to volts so we can use it in the equation. 
        * 
        * Now we have our Amps value stored in the float amps. Integers are much easier to work with when checking for zero so we multiply by 1000 
        * to convert it to milliamps and return it as an integer.
      */
      
      //Serial.print("VQ = ..."); Serial.println(VQ);
      //Serial.print("current count..."); Serial.println(count/5);
      //Serial.print("map  milliamps..."); Serial.println(map((count/5), 102, 922, -20000, 20000));
       float amps = ((.00488 * (count/5)) - 2.5) / (sensitivity/1000);
      // Serial.print("float amps..."); Serial.println(amps, 1);
        return int (amps * 1000);                                         // convert to milliamps and return as an integer
      
      }
      Insert Code Here
      

      English:

      Hello

      My English is not that good.
      I tried to build the project. The button I need (I think) not, but I have extended the script, however, by 2 more current and voltage sensors. The goal is to get 3 times Current and 3 times Volt as a result. I have 30A sensors and a 30A charger. In between are 30A fuses.
      Unfortunately in Domoticz but only one time Volt and 2 times Current. Unfortunately I have not really much idea of ​​the programming. Could someone here over the sketch look around to see if I have a mistake in it?do i

      gohanG 1 Reply Last reply
      0
      • aDm1NA aDm1N

        Hallo

        Mein Englisch ist nicht so gut.
        Ich habe versucht das Projekt nach zu bauen. Den Button brauche ich (denke ich) nicht, dafür habe ich das script jedoch um 2 weitere current und voltage Sensoren erweitert. Das Ziel ist 3 mal Current und 3 mal Volt als Ergebnis zu bekommen. Ich habe 30A Sensoren und einen 30A Laderegler. Dazwischen sind jeweils 30A Sicherungen.
        Leider kommt in Domoticz aber nur ein mal Volt und 2 mal Current an. Leider habe ich auch nicht wirklich viel Ahnung vom Programmieren. Könnte hier mal jemand über den Sketch gucken um zu sehen ob ich einen Fehler darin habe?

        /*Sketch for a MySensor node to monitor a 12v battery with a solar panel for charging
         * The node monitors battery voltage,current into and out of the battery, ambient temperature and battery temperature.
         * 2 x DS18b20 dallas temperature ic's their data pins connected to arduino digital pin 3
         * 1 x ACS712 current sensor module connected to  arduino analog pin A4
         * 1 x 25v voltage sensor module connected to arduino analog pin A0
         * 1 x nRF24L01+  2.4ghz tranceiver connected as per the MySensors web site.
         * 1 x LED connected via a 330 ohm resistor to pin 6
         * 1 x push button connected to pin 5
         */
         
        #include <MySensor.h>  
        #include <SPI.h>
        #include <OneWire.h>
        #include <DallasTemperature.h>
         
        
        #define ONE_WIRE_BUS 3                       // Ds18b20 data wire is connected to digital pin 3 on the Arduino
        #define ID_S_TEMPA 0                         // First temp device
        #define ID_S_TEMPB 1                         // second temp device
        #define ID_S_MULTIMETERV1 3                   // Multimeter device for voltage measurement
        #define ID_S_MULTIMETERC1 4                   // Multimeter device for positive current measurement 
        #define ID_S_MULTIMETERC11 5                  // Multimeter device for negative current measurement
        #define ID_S_MULTIMETERV2 3                   // Multimeter device for voltage measurement
        #define ID_S_MULTIMETERC2 4                   // Multimeter device for positive current measurement 
        #define ID_S_MULTIMETERC12 5                  // Multimeter device for negative current measurement
        #define ID_S_MULTIMETERV3 6                   // Multimeter device for voltage measurement
        #define ID_S_MULTIMETERC3 7                   // Multimeter device for positive current measurement 
        #define ID_S_MULTIMETERC13 8
        #define NUM_SAMPLES 10                       // number of analog voltage samples to take per reading
        
        
        int ledPin = 6;                               // the pin for the LED
        int buttonPin = 5;                            // the input pin for offset pushbutton
        int buttonState = 0;                          // variable for reading the pin status
        unsigned long SLEEP_TIME = 30000;            // Sleep time between reads (in milliseconds)
        int lastmilli1 = 25000;                       // set to an arbitary number outside of expected current sensor range to ensure a change when first run 
        int lastmilli2 = 25000;                       // set to an arbitary number outside of expected current sensor range to ensure a change when first run 
        int lastmilli3 = 25000;                       // set to an arbitary number outside of expected current sensor range to ensure a change when first run 
        float sensitivity = 66 ;                    //change this to 185 for ACS712-5 or to 100 for ACS712-20A or to 66 for ACS712-30A
        int VQ = 0;                                  //Placeholder for quiescent voltage calculations
        int ACSPin1 = A4;                             // Analog pin number the ACS712 data pin connects to
        int ACSPin2 = A5;                             // Analog pin number the ACS712 data pin connects to
        int ACSPin3 = A3;                             // Analog pin number the ACS712 data pin connects to
        float lastTemperature[2];                    //Array to hold the last temp readings sent to gateway, only send new data if different
        int sum = 0;                                 // sum of voltage samples taken
        unsigned char sample_count = 0;              // current sample number
        int lastVoltage1 = 30000;                     // set to an arbitary number outside of expected voltage sensor range to ensure a change when first run
        int lastVoltage2 = 30000;                     // set to an arbitary number outside of expected voltage sensor range to ensure a change when first run
        int lastVoltage3 = 30000;                     // set to an arbitary number outside of expected voltage sensor range to ensure a change when first run
        int voltagePin1 = A0;                         // analog pin voltage sensor or voltage divider is connected to
        int voltagePin2 = A1;                         // analog pin voltage sensor or voltage divider is connected to
        int voltagePin3 = A2;                         // analog pin voltage sensor or voltage divider is connected to
        int voltSense1Max = 25000;                    // set to the maximum input voltage in millivolts of your voltage divider input  
        int voltSense2Max = 25000;                    // set to the maximum input voltage in millivolts of your voltage divider input
        int voltSense3Max = 25000;                    // set to the maximum input voltage in millivolts of your voltage divider input    
        OneWire oneWire(ONE_WIRE_BUS);               // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
        DallasTemperature sensors(&oneWire);         // Pass our oneWire reference to Dallas Temperature.
        
        MySensor gw;
        
        // ------ Initialize  messages -------
        MyMessage msg(0,V_TEMP);                     
        MyMessage msg_S_MULTIMETERv1(ID_S_MULTIMETERV1,V_VOLTAGE);
        MyMessage msg_S_MULTIMETERc1(ID_S_MULTIMETERC1,V_CURRENT);
        MyMessage msg_S_MULTIMETERc11(ID_S_MULTIMETERC11,V_CURRENT); 
        MyMessage msg_S_MULTIMETERv2(ID_S_MULTIMETERV2,V_VOLTAGE);
        MyMessage msg_S_MULTIMETERc2(ID_S_MULTIMETERC2,V_CURRENT);
        MyMessage msg_S_MULTIMETERc12(ID_S_MULTIMETERC12,V_CURRENT); 
        MyMessage msg_S_MULTIMETERv3(ID_S_MULTIMETERV3,V_VOLTAGE);
        MyMessage msg_S_MULTIMETERc3(ID_S_MULTIMETERC3,V_CURRENT);
        MyMessage msg_S_MULTIMETERc13(ID_S_MULTIMETERC13,V_CURRENT); 
        
        void setup()
        {
         
        sensors.begin();                                    // Start up the onewire library
        gw.begin();                                         // Startup and initialize MySensors library. Set callback for incoming messages. 
        gw.sendSketchInfo("Battery Status Sensor", "1");    // Send the sketch version information to the gateway and Controller
        
        // ------ Present all sensors to controller ------
        gw.present(ID_S_TEMPA, S_TEMP);
        gw.present(ID_S_TEMPB, S_TEMP);
        gw.present(ID_S_MULTIMETERV1,V_VOLTAGE);
        gw.present(ID_S_MULTIMETERC1,V_CURRENT);
        gw.present(ID_S_MULTIMETERC11,V_CURRENT);
        gw.present(ID_S_MULTIMETERV2,V_VOLTAGE);
        gw.present(ID_S_MULTIMETERC2,V_CURRENT);
        gw.present(ID_S_MULTIMETERC12,V_CURRENT);
        gw.present(ID_S_MULTIMETERV3,V_VOLTAGE);
        gw.present(ID_S_MULTIMETERC3,V_CURRENT);
        gw.present(ID_S_MULTIMETERC13,V_CURRENT);
        
        
        pinMode(buttonPin, INPUT_PULLUP);                     // Set buttonPin as input and turn on internal pull up resistor
        pinMode(ledPin, OUTPUT);                              // Set ledPin as output
        digitalWrite(ledPin, LOW);                            // Make sure ledPin is off
        
        // ------ load offset for current sensor
        int validCheck = gw.loadState(0);
        if (validCheck == 120){                          // check to see if valid data exists
          VQ = gw.loadState(1);                               // Load count offset into VQ
        //  Serial.print(" positive VQ offset loaded..."); Serial.println(VQ);
         }
         else if (validCheck == 125) {
          VQ = -abs(gw.loadState(1));
        //  Serial.print(" negative VQ offset loaded..."); Serial.println(VQ);
         }
        else {
        // Serial.println("VQ offset not set");
        }
        
        delay(500);  
        }
         
        void loop()
        {
        
        buttonState = digitalRead(buttonPin);
        //Serial.print("buttonstate..."); Serial.println(buttonState);
         if (buttonState == LOW) {
            VQ = determineVQ(ACSPin1);                           //Returns the offset count needed to show zero with no load
        
            
          if (VQ >= 0 && VQ < 255) {                              //check for valid data. VQ is positive number
            gw.saveState(0, 120);                               // Store 120 value  in eeprom position 0. use this to check for valid data at boot
            gw.saveState(1, VQ);                                // Store offset count in eeprom. in case of re-boot  
          }
          else if (VQ < 0 && VQ > -255) {                              // VQ is a negative number. negatives cannot be stored in eeprom
            gw.saveState(0, 125);                               // Store 125 value  in eeprom position 0. use this to check for valid data at boot
            gw.saveState(1, abs(VQ));                                // convert VQ to positive and  Store offset count in eeprom. in case of re-boot   
          }
        
          }
        
        // ------------------ Start voltage 1 readings --------------------
         
        
         sample_count = 0;
         sum = 0;
         while (sample_count < NUM_SAMPLES) {                                   // take a number of voltage samples  
          sum += analogRead(voltagePin1);
          sample_count++;
          delay(10);
         }
        //Serial.print("sum count..."); Serial.println((sum / NUM_SAMPLES));      // print the count result. will be between 0 and 1023
        int voltage1I = map(sum/NUM_SAMPLES,0,1023,0,voltSense1Max);              // map the reading and get our result in millivolts
        //Serial.print("mapped volts..."); Serial.println(voltageI / 1000.0, 1);  // convert millivolts back to volts and print. the 1 at the end determines how many decimal places to show
        
        
        if ( voltage1I != lastVoltage1) {                                         // check if we have a new value. only send data if it is different
         gw.send(msg_S_MULTIMETERv1.set(voltage1I / 1000.0, 1));                  // voltagel is in millivolts so we divide by 1000 to convert back to volts and
                                                                                // send voltage message to gateway with 1 decimal place
         lastVoltage1 = voltage1I;                                                // copy the current voltage reading for testing on the next loop 
        }
        
        //--------------------Start Current 1 readings---------------------------------
        
        int milli1 = readCurrent(ACSPin1);                                       // take a reading from the ACS712 and send to the readcurrent function
        
        //Serial.print("Milliamps..."); Serial.println(milli);                   // print the value (in milliamps) returned
        
        if ( milli1 != lastmilli1)                                               // check if value has changed
        {
         if ( milli1 > 0)                                                       // Battery is charging
         {
          gw.send(msg_S_MULTIMETERc1.set(milli1/1000.0, 1));                     // Send new data to charging amp device
          gw.send(msg_S_MULTIMETERc11.set(0));                                  // set the dis-charging amp device to zero
          lastmilli1 =  milli1;
         }
         else if (milli1 < 0)                                                  // Battery is discharging
         {
          gw.send(msg_S_MULTIMETERc1.set(0));                                  // set the charging amp device to zero
          gw.send(msg_S_MULTIMETERc11.set(abs(milli1)/1000.0, 1));             //  use abs(milli) to Send a positive number  to dis-charging amp device
          lastmilli1 =  milli1; 
         }
        else                                                                // No current flowing, set both to zero
        {
         gw.send(msg_S_MULTIMETERc1.set(0));
         gw.send(msg_S_MULTIMETERc11.set(0));
         lastmilli1 =  milli1;
        }
        }
         
        //----------------------Teperature readings start------------------------
          
          Serial.println(" Requesting temperatures...");
         
         // Fetch temperatures from Dallas sensors
          sensors.requestTemperatures();                  // call sensors.requestTemperatures() to issue a global temperature request to all devices on the bus
        
          // ------- query conversion time and sleep until conversion completed ------
          int16_t conversionTime = sensors.millisToWaitForConversion(sensors.getResolution());
          gw.sleep(conversionTime);
        
         for (int i=0; i<2; i++) {
        //  Serial.print("Temperature for Device: ");Serial.print(i);Serial.print(" is: ");
         // Serial.println(sensors.getTempCByIndex(i)); // Why "byIndex"? 
            // You can have more than one IC on the same bus. 
            // 0 refers to the first IC on the wire
        
         float temperature = static_cast<float>(static_cast<int>((sensors.getTempCByIndex(i)) * 10.)) / 10.;  // Fetch and round temperature to one decimal in celcius
        
        if (lastTemperature[i] != temperature)               // check for a changed temperature reading
          {
           gw.send(msg.setSensor(i).set(temperature,1));     // Send in the new temperature
           lastTemperature[i]=temperature;                   // Save new temperatures for next compare
          }     
        }
        
        // ------------------ Start 2 voltage readings --------------------
         
        
         sample_count = 0;
         sum = 0;
         while (sample_count < NUM_SAMPLES) {                                   // take a number of voltage samples  
          sum += analogRead(voltagePin2);
          sample_count++;
          delay(10);
         }
        //Serial.print("sum count..."); Serial.println((sum / NUM_SAMPLES));      // print the count result. will be between 0 and 1023
        int voltage2I = map(sum/NUM_SAMPLES,0,1023,0,voltSense2Max);              // map the reading and get our result in millivolts
        //Serial.print("mapped volts..."); Serial.println(voltageI / 1000.0, 1);  // convert millivolts back to volts and print. the 1 at the end determines how many decimal places to show
        
        
        if ( voltage2I != lastVoltage2) {                                         // check if we have a new value. only send data if it is different
         gw.send(msg_S_MULTIMETERv2.set(voltage2I / 1000.0, 1));                  // voltagel is in millivolts so we divide by 1000 to convert back to volts and
                                                                                // send voltage message to gateway with 1 decimal place
         lastVoltage2 = voltage2I;                                                // copy the current voltage reading for testing on the next loop 
        }
        
        //--------------------Start Current 2 readings---------------------------------
        
        int milli2 = readCurrent(ACSPin2);                                       // take a reading from the ACS712 and send to the readcurrent function
        
        //Serial.print("Milliamps..."); Serial.println(milli);                   // print the value (in milliamps) returned
        
        if ( milli2 != lastmilli2)                                               // check if value has changed
        {
         if ( milli2 > 0)                                                       // Battery is charging
         {
          gw.send(msg_S_MULTIMETERc2.set(milli2/1000.0, 1));                     // Send new data to charging amp device
          gw.send(msg_S_MULTIMETERc12.set(0));                                  // set the dis-charging amp device to zero
          lastmilli2 =  milli2;
         }
         else if (milli1 < 0)                                                  // Battery is discharging
         {
          gw.send(msg_S_MULTIMETERc2.set(0));                                  // set the charging amp device to zero
          gw.send(msg_S_MULTIMETERc12.set(abs(milli2)/1000.0, 1));             //  use abs(milli) to Send a positive number  to dis-charging amp device
          lastmilli2 =  milli2; 
         }
        else                                                                // No current flowing, set both to zero
        {
         gw.send(msg_S_MULTIMETERc2.set(0));
         gw.send(msg_S_MULTIMETERc12.set(0));
         lastmilli2 =  milli2;
        }
        }
        
        
        // ------------------ Start voltage 3 readings --------------------
         
        
         sample_count = 0;
         sum = 0;
         while (sample_count < NUM_SAMPLES) {                                   // take a number of voltage samples  
          sum += analogRead(voltagePin3);
          sample_count++;
          delay(10);
         }
        //Serial.print("sum count..."); Serial.println((sum / NUM_SAMPLES));      // print the count result. will be between 0 and 1023
        int voltage3I = map(sum/NUM_SAMPLES,0,1023,0,voltSense3Max);              // map the reading and get our result in millivolts
        //Serial.print("mapped volts..."); Serial.println(voltageI / 1000.0, 1);  // convert millivolts back to volts and print. the 1 at the end determines how many decimal places to show
        
        
        if ( voltage3I != lastVoltage3) {                                         // check if we have a new value. only send data if it is different
         gw.send(msg_S_MULTIMETERv3.set(voltage3I / 1000.0, 1));                  // voltagel is in millivolts so we divide by 1000 to convert back to volts and
                                                                                // send voltage message to gateway with 1 decimal place
         lastVoltage3 = voltage3I;                                                // copy the current voltage reading for testing on the next loop 
        }
        
        //--------------------Start Current 3 readings---------------------------------
        
        int milli3 = readCurrent(ACSPin3);                                       // take a reading from the ACS712 and send to the readcurrent function
        
        //Serial.print("Milliamps..."); Serial.println(milli);                   // print the value (in milliamps) returned
        
        if ( milli3 != lastmilli3)                                               // check if value has changed
        {
         if ( milli3 > 0)                                                       // Battery is charging
         {
          gw.send(msg_S_MULTIMETERc3.set(milli3/1000.0, 1));                     // Send new data to charging amp device
          gw.send(msg_S_MULTIMETERc13.set(0));                                  // set the dis-charging amp device to zero
          lastmilli3 =  milli3;
         }
         else if (milli3 < 0)                                                  // Battery is discharging
         {
          gw.send(msg_S_MULTIMETERc3.set(0));                                  // set the charging amp device to zero
          gw.send(msg_S_MULTIMETERc13.set(abs(milli3)/1000.0, 1));             //  use abs(milli) to Send a positive number  to dis-charging amp device
          lastmilli3 =  milli3; 
         }
        else                                                                // No current flowing, set both to zero
        {
         gw.send(msg_S_MULTIMETERc3.set(0));
         gw.send(msg_S_MULTIMETERc13.set(0));
         lastmilli3 =  milli3;
        }
        }
        gw.sleep(SLEEP_TIME);
        }
        
         
        
        /*-------------- Function to get the offset required for ACS712 to show zero with no current flowing -----------------*/
        int determineVQ(int PIN)                  
         {
          digitalWrite(ledPin, HIGH);                                      // Turn on LED to indicate offset being calculated
          delay(500);                                                      // Delay to hold LED on
          digitalWrite(ledPin, LOW);                                       // Turn off LED
          delay(150);                                                      // Delay to let readings stabilise
        //  Serial.print("estimating avg. quiscent voltage:");
          long acsCount = 0;
          for (int i=0; i<5000; i++)                                       //read 5000 samples to stabilise value
           {
            acsCount += analogRead(PIN);                                   // read the count value between 0 and 1023 and add it to acsCount
            delay(1);                                           
           }
          acsCount /= 5000;                                                      // acsCount now eaquals the average of the 5000 readings taken
        //  Serial.print(map(acsCount, 0, 1023, 0, 5000));Serial.println(" mV");   //Print the avg in millivolts
        //  Serial.print("acsCount:");Serial.println(acsCount);                               //Print the actual count value
          
          return int(acsCount - 512);                                            // return the count difference. 512 is the count for 2.5v which is what the reading should be with no current flow                           
          
        }
        
        
         /*--------------- Function to read current flowing ------------------*/
         
        int readCurrent(int PIN) 
        {
         int count = 0;
         for (int i=0; i<5; i++)                                        //read 5 analog count samples to stabilise value
          {
           count += analogRead(PIN) - VQ;                               //subtract the offset count VQ to improve accuracy
           delay(1);
         //  Serial.print("raw count..."); Serial.println(count);
          }
         /* Notes on the conversion below
          *  .00488 is the volt value per count of the arduino adc. The analog pin measures from 0 to 5 volt and then assigns the result to 
          *  a count from 0 to 1023, thats 1024 counts including zero. If we devide 5v by 1024 we get .oo488 volts for each count.  
          *  
          *  The (count/5) just gets us the average of our 5 count samples.
          *  
          *  So after the first part of the equation  (.00488 * (count/5) is complete we have converted our count reading into volts. 
          *  
          *  The ACS712 can measure current flow in both directions so it outputs a voltage of  2.5v as it's center point (when no current is flowing).
          *  To allow for this offset we must subtract the 2.5v to center our voltage reading.
          *  
          * Thats what the next part does (.00488 * (count/5)) - 2.5) After this is complete we are left with either a negative or  positive voltage
          * reading or a reading of zero for no current flow.
          * 
          * NOTE: While the ACS712 is a 5v device it does not use the full 0 to 5v for it's output. The datasheet shows the 20A version has a sensitivity of
          *  100mv per amp, so if we multiply 100mv by 20 we get 2v.  That means the 20A ACS712 has an output range from .5v to 4.5v.  
          * 
          * So to convert our reading in volts to a reading in amps we need to add the last part ((.00488 * (count/5)) - 2.5)/(sensitivity/1000).
          * The variable sensitivity is defined at the begining of the sketch and holds the ACS712 sensitvity amount, it is stored in millivolts. 
          * That is 66mv for the 30amp,  100mv for the 20amp and 185mv for the 5amp. As sensitivity is in millivolts we need to devide it by 1000 
          * to convert it back to volts so we can use it in the equation. 
          * 
          * Now we have our Amps value stored in the float amps. Integers are much easier to work with when checking for zero so we multiply by 1000 
          * to convert it to milliamps and return it as an integer.
        */
        
        //Serial.print("VQ = ..."); Serial.println(VQ);
        //Serial.print("current count..."); Serial.println(count/5);
        //Serial.print("map  milliamps..."); Serial.println(map((count/5), 102, 922, -20000, 20000));
         float amps = ((.00488 * (count/5)) - 2.5) / (sensitivity/1000);
        // Serial.print("float amps..."); Serial.println(amps, 1);
          return int (amps * 1000);                                         // convert to milliamps and return as an integer
        
        }
        Insert Code Here
        

        English:

        Hello

        My English is not that good.
        I tried to build the project. The button I need (I think) not, but I have extended the script, however, by 2 more current and voltage sensors. The goal is to get 3 times Current and 3 times Volt as a result. I have 30A sensors and a 30A charger. In between are 30A fuses.
        Unfortunately in Domoticz but only one time Volt and 2 times Current. Unfortunately I have not really much idea of ​​the programming. Could someone here over the sketch look around to see if I have a mistake in it?do i

        gohanG Offline
        gohanG Offline
        gohan
        Mod
        wrote on last edited by
        #40

        @aDm1N
        Do you have a log of the data being sent from the node? What mysensors library version are you using?

        1 Reply Last reply
        0
        • mrc-coreM Offline
          mrc-coreM Offline
          mrc-core
          wrote on last edited by mrc-core
          #41

          Hi. i have been working on this solar code and have made the changes to work over mysensors 2.1.1
          I'm now triyng to add a line code to monitor the voltage from the solar panels. Can anyone give me a help on this?
          I want to now the voltage watts or kws produce over my pannels. The idea is to have domoticz monitoring all data produce over the solar pannel.
          Thanks

          /*Sketch for a MySensor node to monitor a 12v battery with a solar panel for charging
           * The node monitors battery voltage,current into and out of the battery, ambient temperature and battery temperature.
           * 2 x DS18b20 dallas temperature ic's their data pins connected to arduino digital pin 3
           * 1 x ACS712 current sensor module connected to  arduino analog pin A4
           * 1 x 25v voltage sensor module connected to arduino analog pin A0
           * 1 x nRF24L01+  2.4ghz tranceiver connected as per the MySensors web site.
           * 1 x LED connected via a 330 ohm resistor to pin 6
           * 1 x push button connected to pin 5
           */
          
          // Enable debug prints to serial monitor
          #define MY_DEBUG
          
          // Enable and select radio type attached
          #define MY_RADIO_NRF24
          //#define MY_RADIO_RFM69
          
          // Enable repeater functionality for this node
          #define MY_REPEATER_FEATURE
           
          #include <MySensors.h>  
          #include <SPI.h>
          #include <OneWire.h>
          #include <DallasTemperature.h>
           
          #define ONE_WIRE_BUS 3                            // Ds18b20 data wire is connected to digital pin 3 on the Arduino
          #define ID_S_TEMP_A 0                             // First temp device
          #define ID_S_TEMP_B 1                             // Second temp device
          #define ID_S_MULTIMETERV 3                        // Multimeter device for voltage measurement
          #define ID_S_MULTIMETERC 4                        // Multimeter device for positive current measurement 
          #define ID_S_MULTIMETERC1 5                       // Multimeter device for negative current measurement
          #define NUM_SAMPLES 10                            // number of analog voltage samples to take per reading
          
          int ledPin = 6;                                   // the pin for the LED
          int buttonPin = 5;                                // the input pin for offset pushbutton
          int buttonState = 0;                              // variable for reading the pin status
          unsigned long SLEEP_TIME = 30000;                 // Sleep time between reads (in milliseconds)
          int lastmilli = 25000;                            // set to an arbitary number outside of expected current sensor range to ensure a change when first run 
          float sensitivity = 66 ;                          // change this to 185 for ACS712-5 or to 100 for ACS712-20A or to 66 for ACS712-30A
          int VQ = 0;                                       // Placeholder for quiescent voltage calculations
          int ACSPin = A4;                                  // Analog pin number the ACS712 data pin connects to
          float lastTemperature[2];                         // Array to hold the last temp readings sent to gateway, only send new data if different
          int sum = 0;                                      // sum of voltage samples taken
          unsigned char sample_count = 0;                   // current sample number
          int lastVoltage = 30000;                          // set to an arbitary number outside of expected voltage sensor range to ensure a change when first run
          int voltagePin = A0;                              // analog pin voltage sensor or voltage divider is connected to
          int voltSenseMax = 25000;                         // set to the maximum input voltage in millivolts of your voltage divider input    
          OneWire oneWire(ONE_WIRE_BUS);                    // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
          DallasTemperature sensors(&oneWire);              // Pass our oneWire reference to Dallas Temperature.
          
          // ------ Initialize  messages ------- //
          MyMessage msg(0,V_TEMP);                     
          MyMessage msg_S_MULTIMETERv(ID_S_MULTIMETERV,V_VOLTAGE);
          MyMessage msg_S_MULTIMETERc(ID_S_MULTIMETERC,V_CURRENT);
          MyMessage msg_S_MULTIMETERc1(ID_S_MULTIMETERC1,V_CURRENT); 
          
          void presentation()  
          {
            // Send the sketch version information to the gateway
            sendSketchInfo("Battery Status Sensor", "2.1.1");
          
            // Register all sensors to gw (they will be created as child devices)
            present(ID_S_TEMP_A, S_TEMP);
            present(ID_S_TEMP_B, S_TEMP);
            present(ID_S_MULTIMETERV,V_VOLTAGE);
            present(ID_S_MULTIMETERC,V_CURRENT);
            present(ID_S_MULTIMETERC1,V_CURRENT);
          }
          
          void setup()
          {
            sensors.begin();                                      // Start up the onewire library
            pinMode(buttonPin, INPUT_PULLUP);                     // Set buttonPin as input and turn on internal pull up resistor
            pinMode(ledPin, OUTPUT);                              // Set ledPin as output
            digitalWrite(ledPin, LOW);                            // Make sure ledPin is off
          
            // ------ load offset for current sensor
            int validCheck = loadState(0);
            if (validCheck == 120)                                // check to see if valid data exists
            {
              VQ = loadState(1);                                  // Load count offset into VQ
              //Serial.print(" positive VQ offset loaded..."); Serial.println(VQ);
            }
            else if (validCheck == 125) 
            {
              VQ = -abs(loadState(1));
              //Serial.print(" negative VQ offset loaded..."); Serial.println(VQ);
            }
            else 
            {
              //Serial.println("VQ offset not set");
            }
            delay(500);  
          }
           
          void loop()
          {
            buttonState = digitalRead(buttonPin);
            //Serial.print("buttonstate..."); Serial.println(buttonState);
            if (buttonState == LOW) 
            {
              VQ = determineVQ(ACSPin);                           // Returns the offset count needed to show zero with no load
              if (VQ >= 0 && VQ < 255) 
              {                                                   // check for valid data. VQ is positive number
                saveState(0, 120);                                // Store 120 value  in eeprom position 0. use this to check for valid data at boot
                saveState(1, VQ);                                 // Store offset count in eeprom. in case of re-boot  
              }
              else if (VQ < 0 && VQ > -255)                       // VQ is a negative number. negatives cannot be stored in eeprom 
              {                                                   
                saveState(0, 125);                                // Store 125 value  in eeprom position 0. use this to check for valid data at boot
                saveState(1, abs(VQ));                            // convert VQ to positive and  Store offset count in eeprom. in case of re-boot   
              }
            }
            
          //-------------------------------------------- Start voltage readings ----------------------------------------------------
            
            sample_count = 0;
            sum = 0;
            while (sample_count < NUM_SAMPLES)                     // take a number of voltage samples 
            {                     
              sum += analogRead(voltagePin);
              sample_count++;
              delay(10);
            }
           
            //Serial.print("sum count..."); Serial.println((sum / NUM_SAMPLES));        // print the count result. will be between 0 and 1023
            int voltageI = map(sum/NUM_SAMPLES,0,1023,0,voltSenseMax);                  // map the reading and get our result in millivolts
            //Serial.print("mapped volts..."); Serial.println(voltageI / 1000.0, 1);    // convert millivolts back to volts and print. the 1 at the end determines how many decimal places to show
          
            if ( voltageI != lastVoltage)                                               // check if we have a new value. only send data if it is different
            {
              send(msg_S_MULTIMETERv.set(voltageI / 1000.0, 1));                        // voltagel is in millivolts so we divide by 1000 to convert back to volts and send voltage message to gateway with 1 decimal place
              lastVoltage = voltageI;                                                   // copy the current voltage reading for testing on the next loop 
            }
          
          //---------------------------------------- Start Current readings ---------------------------------------------------------
            
            int milli = readCurrent(ACSPin);                                            // take a reading from the ACS712 and send to the readcurrent function
            //Serial.print("Milliamps..."); Serial.println(milli);                      // print the value (in milliamps) returned
            if ( milli != lastmilli)                                                    // check if value has changed
            {
              if ( milli > 0)                                                           // Battery is charging
              {
                send(msg_S_MULTIMETERc.set(milli/1000.0, 1));                           // Send new data to charging amp device
                send(msg_S_MULTIMETERc1.set(0));                                        // set the dis-charging amp device to zero
                lastmilli =  milli;
              }
              else if (milli < 0)                                                       // Battery is discharging
              {
                send(msg_S_MULTIMETERc.set(0));                                         // set the charging amp device to zero
                send(msg_S_MULTIMETERc1.set(abs(milli)/1000.0, 1));                     //  use abs(milli) to Send a positive number  to dis-charging amp device
                lastmilli =  milli; 
              }
              else                                                                      // No current flowing, set both to zero
              {
                send(msg_S_MULTIMETERc.set(0));
                send(msg_S_MULTIMETERc1.set(0));
                lastmilli =  milli;
              }
            }
           
          //--------------------------------------- Temperature readings start ------------------------------------------------------------
          
            Serial.println(" Requesting temperatures...");
            // Fetch temperatures from Dallas sensors
            sensors.requestTemperatures();                              // call sensors.requestTemperatures() to issue a global temperature request to all devices on the bus
          
            // ------- query conversion time and sleep until conversion completed ------
            int16_t conversionTime = sensors.millisToWaitForConversion(sensors.getResolution());
            sleep(conversionTime);
          
            for (int i=0; i<2; i++) 
            {
              //Serial.print("Temperature for Device: ");Serial.print(i);Serial.print(" is: ");
              //Serial.println(sensors.getTempCByIndex(i)); // Why "byIndex"? 
              // You can have more than one IC on the same bus. 
              // 0 refers to the first IC on the wire
          
              float temperature = static_cast<float>(static_cast<int>((sensors.getTempCByIndex(i)) * 10.)) / 10.;    // Fetch and round temperature to one decimal in celcius
              if (lastTemperature[i] != temperature)                                                                 // check for a changed temperature reading
              {
                send(msg.setSensor(i).set(temperature,1));                                                           // Send in the new temperature
                lastTemperature[i]=temperature;                                                                      // Save new temperatures for next compare
              }     
            }
            sleep(SLEEP_TIME);
          }
          
          /*-------------- Function to get the offset required for ACS712 to show zero with no current flowing -----------------*/
          int determineVQ(int PIN)                  
          {
            digitalWrite(ledPin, HIGH);                                             // Turn on LED to indicate offset being calculated
            delay(500);                                                             // Delay to hold LED on
            digitalWrite(ledPin, LOW);                                              // Turn off LED
            delay(150);                                                             // Delay to let readings stabilise
            //Serial.print("estimating avg. quiscent voltage:");
            long acsCount = 0;
            for (int i=0; i<5000; i++)                                              // read 5000 samples to stabilise value
            {
              acsCount += analogRead(PIN);                                          // read the count value between 0 and 1023 and add it to acsCount
              delay(1);                                           
            }
            acsCount /= 5000;                                                       // acsCount now eaquals the average of the 5000 readings taken
            //Serial.print(map(acsCount, 0, 1023, 0, 5000));Serial.println(" mV");  // Print the avg in millivolts
            //Serial.print("acsCount:");Serial.println(acsCount);                   // Print the actual count value
            return int(acsCount - 512);                                             // return the count difference. 512 is the count for 2.5v which is what the reading should be with no current flow                           
            
          }
          
          /*--------------- Function to read current flowing ------------------*/
          int readCurrent(int PIN) 
          {
           int count = 0;
           for (int i=0; i<5; i++)                                                  // read 5 analog count samples to stabilise value
            {
             count += analogRead(PIN) - VQ;                                         // subtract the offset count VQ to improve accuracy
             delay(1);
            //Serial.print("raw count..."); Serial.println(count);
            }
           
          /* Notes on the conversion below
           *  .00488 is the volt value per count of the arduino adc. The analog pin measures from 0 to 5 volt and then assigns the result to 
           *  a count from 0 to 1023, thats 1024 counts including zero. If we devide 5v by 1024 we get .oo488 volts for each count.  
           *  
           *  The (count/5) just gets us the average of our 5 count samples.
           *  
           *  So after the first part of the equation  (.00488 * (count/5) is complete we have converted our count reading into volts. 
           *  
           *  The ACS712 can measure current flow in both directions so it outputs a voltage of  2.5v as it's center point (when no current is flowing).
           *  To allow for this offset we must subtract the 2.5v to center our voltage reading.
           *  
           * Thats what the next part does (.00488 * (count/5)) - 2.5) After this is complete we are left with either a negative or  positive voltage
           * reading or a reading of zero for no current flow.
           * 
           * NOTE: While the ACS712 is a 5v device it does not use the full 0 to 5v for it's output. The datasheet shows the 20A version has a sensitivity of
           *  100mv per amp, so if we multiply 100mv by 20 we get 2v.  That means the 20A ACS712 has an output range from .5v to 4.5v.  
           * 
           * So to convert our reading in volts to a reading in amps we need to add the last part ((.00488 * (count/5)) - 2.5)/(sensitivity/1000).
           * The variable sensitivity is defined at the begining of the sketch and holds the ACS712 sensitvity amount, it is stored in millivolts. 
           * That is 66mv for the 30amp,  100mv for the 20amp and 185mv for the 5amp. As sensitivity is in millivolts we need to devide it by 1000 
           * to convert it back to volts so we can use it in the equation. 
           * 
           * Now we have our Amps value stored in the float amps. Integers are much easier to work with when checking for zero so we multiply by 1000 
           * to convert it to milliamps and return it as an integer.
          */
          
          //Serial.print("VQ = ..."); Serial.println(VQ);
          //Serial.print("current count..."); Serial.println(count/5);
          //Serial.print("map  milliamps..."); Serial.println(map((count/5), 102, 922, -20000, 20000));
            float amps = ((.00488 * (count/5)) - 2.5) / (sensitivity/1000);
          //Serial.print("float amps..."); Serial.println(amps, 1);
            return int (amps * 1000);                                         // convert to milliamps and return as an integer
          }```
          1 Reply Last reply
          0
          • mrc-coreM Offline
            mrc-coreM Offline
            mrc-core
            wrote on last edited by
            #42

            I'm working again on this system but i'm having some troubles... The code has you caan see i have already adapted it to version 2.1.1 Now on the hardware i'm building i have this:

            • 1 solar panel 10w connected to the LM2596 that converts the 12v to 5.5v that goes to the LiPo Enhanced Charger Module, here i have the 3,7v bat connected and the arduinos connected to the other power out.

            My problem is that when i have the system online the values i'm getting are not right. For the battery voltage i get 5,5v when i believe i should be getting 3,7v or 4,1v maximum.
            The charge and load are always on 0,2A or 0,0A

            I have the acs712 connected to the negative side off the battery and the Voltage sensor connected to the negative and positive side off the battery.

            What i'm i doing rong here ????

            Boots33B 1 Reply Last reply
            0
            • mrc-coreM mrc-core

              I'm working again on this system but i'm having some troubles... The code has you caan see i have already adapted it to version 2.1.1 Now on the hardware i'm building i have this:

              • 1 solar panel 10w connected to the LM2596 that converts the 12v to 5.5v that goes to the LiPo Enhanced Charger Module, here i have the 3,7v bat connected and the arduinos connected to the other power out.

              My problem is that when i have the system online the values i'm getting are not right. For the battery voltage i get 5,5v when i believe i should be getting 3,7v or 4,1v maximum.
              The charge and load are always on 0,2A or 0,0A

              I have the acs712 connected to the negative side off the battery and the Voltage sensor connected to the negative and positive side off the battery.

              What i'm i doing rong here ????

              Boots33B Offline
              Boots33B Offline
              Boots33
              Hero Member
              wrote on last edited by
              #43

              @mrc-core From your code it looks like you are using a 30A acs712 and you are still using the 25v sensor to measure the expected 4v. With only a 10w panel you might be better off with a 5A acs712 and also a voltage divider that maxes out at around 10v. This will give you a better resolution to work with right from the start.

              How are you powering the arduino? Perhaps you can do a drawing of how your project is wired together. Remember the arduino needs to have a stable 5v supply to have any chance of giving a good result.

              1 Reply Last reply
              0
              • mrc-coreM Offline
                mrc-coreM Offline
                mrc-core
                wrote on last edited by mrc-core
                #44

                Hi. sorry for my late replay....
                Here's the way i'm powering things up.
                I don't have a solar charge since last summer we had a big fire on my island and all my arduino and sensors that were outside were all damage from the fire and hot temperatures. So to fiz this problem i'm using the LM2596 to reduce the 12V from the solar panels to 5.5V so that the lipo charger can work. Above the 5v this charger will get damage.

                Some data from this charger:
                LED: Red = Charging, Green = Complete
                Input Voltage: 4.5 to 5.5V
                Battery Max Charge Voltage: 4.2V - charges a 1S Lithium Ion Polymer Battery

                This outputs a 4.2V on the load and batt connections.

                My arduino and sensors are connected to the load pins from the lipo charger as you can see on the picture.
                Thanks for your replay and help.

                0_1497281574639_Solar.png

                Boots33B 1 Reply Last reply
                0
                • mrc-coreM mrc-core

                  Hi. sorry for my late replay....
                  Here's the way i'm powering things up.
                  I don't have a solar charge since last summer we had a big fire on my island and all my arduino and sensors that were outside were all damage from the fire and hot temperatures. So to fiz this problem i'm using the LM2596 to reduce the 12V from the solar panels to 5.5V so that the lipo charger can work. Above the 5v this charger will get damage.

                  Some data from this charger:
                  LED: Red = Charging, Green = Complete
                  Input Voltage: 4.5 to 5.5V
                  Battery Max Charge Voltage: 4.2V - charges a 1S Lithium Ion Polymer Battery

                  This outputs a 4.2V on the load and batt connections.

                  My arduino and sensors are connected to the load pins from the lipo charger as you can see on the picture.
                  Thanks for your replay and help.

                  0_1497281574639_Solar.png

                  Boots33B Offline
                  Boots33B Offline
                  Boots33
                  Hero Member
                  wrote on last edited by
                  #45

                  @mrc-core The original circuit/sketch was designed for a 5v arduino and was measuring a 12v system . From your drawing it looks like you will be using a 3v arduino so at the very least you will need to change the voltage divider to give you a better resolution. As to the acs712 it is a 5v device so most likely will not even work on 3v so you may need to source some other device for current measurement. Again you would want a low current device if you are to have any chance of measuring the few milliamps you would be seeing. perhaps a google search for acs712 on 3v will produce a result.

                  mrc-coreM 2 Replies Last reply
                  0
                  • Boots33B Boots33

                    @mrc-core The original circuit/sketch was designed for a 5v arduino and was measuring a 12v system . From your drawing it looks like you will be using a 3v arduino so at the very least you will need to change the voltage divider to give you a better resolution. As to the acs712 it is a 5v device so most likely will not even work on 3v so you may need to source some other device for current measurement. Again you would want a low current device if you are to have any chance of measuring the few milliamps you would be seeing. perhaps a google search for acs712 on 3v will produce a result.

                    mrc-coreM Offline
                    mrc-coreM Offline
                    mrc-core
                    wrote on last edited by
                    #46

                    @Boots33 I'm going to change the arduino mini for an arduino nano to have the 5V still have one in the house.
                    Acs712 have already buy 2 off them just in case if i have to go back to arduino mini.

                    I was thinking on booting all my outside arduinos from this solar panel i have 2 more off them that i can connect.

                    1 Reply Last reply
                    0
                    • Boots33B Boots33

                      @mrc-core The original circuit/sketch was designed for a 5v arduino and was measuring a 12v system . From your drawing it looks like you will be using a 3v arduino so at the very least you will need to change the voltage divider to give you a better resolution. As to the acs712 it is a 5v device so most likely will not even work on 3v so you may need to source some other device for current measurement. Again you would want a low current device if you are to have any chance of measuring the few milliamps you would be seeing. perhaps a google search for acs712 on 3v will produce a result.

                      mrc-coreM Offline
                      mrc-coreM Offline
                      mrc-core
                      wrote on last edited by
                      #47

                      @Boots33 I have change to an arduino nano but still get some strange values. I'm going to make some changes over this project and see again what ill get.

                      Thanks for all the help.

                      Boots33B 1 Reply Last reply
                      0
                      • mrc-coreM mrc-core

                        @Boots33 I have change to an arduino nano but still get some strange values. I'm going to make some changes over this project and see again what ill get.

                        Thanks for all the help.

                        Boots33B Offline
                        Boots33B Offline
                        Boots33
                        Hero Member
                        wrote on last edited by
                        #48

                        @mrc-core Ok, let me know how you get on.
                        I think solar powering the nodes is a great idea, I have several nodes and three raspberry pi's running on my house solar system at the moment.

                        1 Reply Last reply
                        0
                        • U Offline
                          U Offline
                          unfadingpyro
                          wrote on last edited by
                          #49

                          I just finished setting up this sensor to monitor my solar panels. The voltage sensors is reporting correct, but i'm not sure if the current sensor is right or wired correctly.

                          This is how it is currently wired.
                          alt text

                          Is this going to give me both charge and discharge?

                          Thanks!

                          Boots33B 1 Reply Last reply
                          0
                          • U unfadingpyro

                            I just finished setting up this sensor to monitor my solar panels. The voltage sensors is reporting correct, but i'm not sure if the current sensor is right or wired correctly.

                            This is how it is currently wired.
                            alt text

                            Is this going to give me both charge and discharge?

                            Thanks!

                            Boots33B Offline
                            Boots33B Offline
                            Boots33
                            Hero Member
                            wrote on last edited by
                            #50

                            @unfadingpyro I can't see your wiring diagram.

                            1 Reply Last reply
                            0
                            • mfalkviddM Offline
                              mfalkviddM Offline
                              mfalkvidd
                              Mod
                              wrote on last edited by
                              #51

                              Me neither. This is what it looks like to me:
                              0_1523442392977_IMG_2373.PNG

                              1 Reply Last reply
                              0
                              • U Offline
                                U Offline
                                unfadingpyro
                                wrote on last edited by
                                #52

                                How about now?

                                0_1524089561728_Untitled drawing (1).jpg

                                1 Reply Last reply
                                0
                                • Boots33B Offline
                                  Boots33B Offline
                                  Boots33
                                  Hero Member
                                  wrote on last edited by Boots33
                                  #53

                                  Yes i can see your wiring now and no you are not likely to get any sort of reading with that circuit. You have the 712 wired in parallel with the charge wire, it needs to be in series instead. The load needs to be connected to the same side that the charge wire is on. So a quick re-draw of your circuit would look like this.

                                  0_1524101289797_panel wire.jpg

                                  Don't forget to add a fuse at the battery positive.

                                  The original drawing from earlier in this thread would also be ok

                                  alt text

                                  nurul amiraN 1 Reply Last reply
                                  2
                                  • U Offline
                                    U Offline
                                    unfadingpyro
                                    wrote on last edited by
                                    #54

                                    Okay. I will rewire it this weekend. Thanks!

                                    1 Reply Last reply
                                    2
                                    • U Offline
                                      U Offline
                                      unfadingpyro
                                      wrote on last edited by
                                      #55

                                      Get the sensor rewired yesterday and i am now getting the correct readings! Thanks again for the help.

                                      Boots33B 1 Reply Last reply
                                      2
                                      • U unfadingpyro

                                        Get the sensor rewired yesterday and i am now getting the correct readings! Thanks again for the help.

                                        Boots33B Offline
                                        Boots33B Offline
                                        Boots33
                                        Hero Member
                                        wrote on last edited by
                                        #56

                                        @unfadingpyro Great to hear you got it all working. Always a good feeling when a project comes together :)

                                        1 Reply Last reply
                                        0
                                        • Boots33B Boots33

                                          Yes i can see your wiring now and no you are not likely to get any sort of reading with that circuit. You have the 712 wired in parallel with the charge wire, it needs to be in series instead. The load needs to be connected to the same side that the charge wire is on. So a quick re-draw of your circuit would look like this.

                                          0_1524101289797_panel wire.jpg

                                          Don't forget to add a fuse at the battery positive.

                                          The original drawing from earlier in this thread would also be ok

                                          alt text

                                          nurul amiraN Offline
                                          nurul amiraN Offline
                                          nurul amira
                                          wrote on last edited by
                                          #57

                                          @Boots33 hi. Now, i'm working on this project for my final year project. I dont really used your overall project, i just used the concept which monitor the solar battery. I used your circuit diagram without using the transceiver and use my own code to run the project. In your opinion, is that make sense to you ?

                                          Boots33B 1 Reply Last reply
                                          0
                                          Reply
                                          • Reply as topic
                                          Log in to reply
                                          • Oldest to Newest
                                          • Newest to Oldest
                                          • Most Votes


                                          21

                                          Online

                                          11.7k

                                          Users

                                          11.2k

                                          Topics

                                          113.1k

                                          Posts


                                          Copyright 2025 TBD   |   Forum Guidelines   |   Privacy Policy   |   Terms of Service
                                          • Login

                                          • Don't have an account? Register

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • MySensors
                                          • OpenHardware.io
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular