Help sought for code for ACS712 Current Sensor used with a Pump Controller



  • Hi there, just wanting to get some help to use an ACS712 current sensing module in a project i'm working on.

    It's to control our 240v 300W pump that has pressure sense to turn on and flow sense to turn off.

    I"m basically wanting to monitor when the pump is on, and how much power it uses plus the ability to turn it off if i'm away from home and it's running too much (eg if there's a leak somewhere).

    These are the specs:

    • Power node off the 240v
    • current sensor to send alert when pump is on (can set that up in my Controller running Domoticz) and off
    • recording power usage (within Domoticz)
    • relay to turn off 240v to pump if necessary

    So far I've put most of the hardware together but my issue is the code.

    The RelayActuator sketch is cool, it's a matter of finding a sketch for the ACS712 and merging the two.

    Can anyone help?


  • Hero Member

    @breimann I'm using a similar combination to achieve something similar. :D So it's doable.

    Did you already try to combine the two sketches? What doesn't work?

    I'll share my code, but it's a multi-sensor and a bit more complex: 1 ACS712, 12 SSR for 5 shutters and 2 lights and additionally a door bell.

    The readings from the ACS712 aren't precise, just google how to fix that. I just need it to distinguish between ON and OFF (120W and 0 W).

    The LIGHT_1 is the one that works together with the SSR, but I'm using a bistable relay in my central switch so the SSR only sends a short impulse of 100ms to switch the relay. In your case it needs to be constantly be powered on or off.

    // Enable debug prints to serial monitor
    //#define MY_DEBUG 
    
    
    // Enable serial gateway
    #define MY_GATEWAY_SERIAL
    
    #include <MySensors.h>
    #include <Bounce2.h>  
    
    #define SSR_ON 1
    #define SSR_OFF 0
    #define NUMBER_OF_SSR 12
    
    // How long should the relay stay active?
    #define SSR_ACTIVE_DURATION_1 100
    #define SSR_ACTIVE_DURATION_2 120000
    
    #define CURRENT_MEASURE_INTERVAL 5000
    
    #define ACS712_PIN A4
    #define MV_PER_AMP 100
    
    #define BELL_PIN A5
    
    #define CHILD_ID_COVER_1 0
    #define CHILD_ID_COVER_2 1
    #define CHILD_ID_COVER_3 2
    #define CHILD_ID_COVER_4 3
    #define CHILD_ID_COVER_5 4
    #define CHILD_ID_LIGHT_1 5
    #define CHILD_ID_LIGHT_2 6
    #define CHILD_ID_POWER_1 7
    #define CHILD_ID_POWER_2 8
    #define CHILD_ID_BELL    9
    
    
    unsigned long ssr_active_duration[] = {
      SSR_ACTIVE_DURATION_2,
      SSR_ACTIVE_DURATION_2,
      SSR_ACTIVE_DURATION_2,
      SSR_ACTIVE_DURATION_2,
      SSR_ACTIVE_DURATION_2,
      SSR_ACTIVE_DURATION_2,
      SSR_ACTIVE_DURATION_2,
      SSR_ACTIVE_DURATION_2,
      SSR_ACTIVE_DURATION_2,
      SSR_ACTIVE_DURATION_2,
      SSR_ACTIVE_DURATION_1,
      SSR_ACTIVE_DURATION_1,
    };
    
    unsigned int ssr_pins[] = {2, 3, 4, 5, 6, 7, 8, 9, A0, A1, A2, A3};
    
    unsigned long ssr_last_change[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    unsigned int ssr_status[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
    unsigned long lastCurrentMeasurement = 0;
    unsigned long lastWatts = 0;
    
    int lastSendLight1Status = 0;
    
    Bounce debouncer = Bounce(); 
    int oldValue=0;
    
    MyMessage wattMsg(CHILD_ID_POWER_1,V_WATT);
    MyMessage light1Msg(CHILD_ID_LIGHT_1, V_STATUS);
    MyMessage bellMsg(CHILD_ID_BELL,V_TRIPPED);
    
    void setup() { 
      for (int pin = 0; pin < NUMBER_OF_SSR; pin++) {
        pinMode(ssr_pins[pin], OUTPUT);
        digitalWrite(ssr_pins[pin], LOW);
      }
    
      // Init Bell button
      pinMode(BELL_PIN, INPUT);
      digitalWrite(BELL_PIN, HIGH);
    
      debouncer.attach(BELL_PIN);
      debouncer.interval(5);
    }
    
    void presentation() {
      sendSketchInfo("RelaisKeller", "2.0");
      present(CHILD_ID_COVER_1, S_COVER);
      present(CHILD_ID_COVER_2, S_COVER);
      present(CHILD_ID_COVER_3, S_COVER);
      present(CHILD_ID_COVER_4, S_COVER);
      present(CHILD_ID_COVER_5, S_COVER);
      present(CHILD_ID_LIGHT_1, S_LIGHT);
      present(CHILD_ID_LIGHT_2, S_LIGHT);
      present(CHILD_ID_POWER_1, S_POWER);
      present(CHILD_ID_BELL, S_DOOR);
    }
    
    void loop() { 
      for(int i = 0; i < sizeof(ssr_status); i++) {
        if(ssr_status[i] == SSR_ON) {
          if(ssr_last_change[i] + ssr_active_duration[i] < millis()) {
            digitalWrite(ssr_pins[i], SSR_OFF);
            ssr_status[i] = SSR_OFF;
          }
        }
      }
    
      if(lastCurrentMeasurement + CURRENT_MEASURE_INTERVAL < millis()) {
        unsigned long currentWatts = (unsigned long)readWatts();
        
        unsigned long diff = 0;
        if(currentWatts > lastWatts) {
          diff = currentWatts - lastWatts;
        } else {
          diff = lastWatts - currentWatts;
        }
    
        if(diff > 10) {
          send(wattMsg.set(currentWatts));
          if(currentWatts > 50) {
            if(lastSendLight1Status == 0) {
              send(light1Msg.set(1));
              lastSendLight1Status = 1;
            }
          } else {
            if(lastSendLight1Status == 1) {
              send(light1Msg.set(0));
              lastSendLight1Status = 0;
            }
          }
          lastWatts = currentWatts;
        }
        lastCurrentMeasurement = millis(); 
      }
    
      // Bell
      debouncer.update();
      int value = debouncer.read();
    
      if(value != oldValue) {
        send(bellMsg.set(value==HIGH ? 0 : 1));
        oldValue = value;
      }
    }
    
    float readWatts() {
      float result;
      
      int readValue;             //value read from the sensor
      int maxValue = 0;          // store max value here
      int minValue = 1024;          // store min value here
      
      uint32_t start_time = millis();
      while((millis()-start_time) < 50) //sample for 1 mSec
      {
          readValue = analogRead(ACS712_PIN);
          // see if you have a new maxValue
          if (readValue > maxValue) 
          {
              /*record the maximum sensor value*/
              maxValue = readValue;
          }
          if (readValue < minValue) 
          {
              /*record the maximum sensor value*/
              minValue = readValue;
          }
      }
       
      // Subtract min from max
      result = ((maxValue - minValue) * 5.0)/1024.0;
    
      float VRMS = (result/2.0) *0.707; 
      float AmpsRMS = (VRMS * 1000)/MV_PER_AMP;
          
      return AmpsRMS*230;
    }
    
    void receive(const MyMessage &message) {
      if(message.type == V_STATUS) {
        if(message.sensor == CHILD_ID_LIGHT_1) {
          digitalWrite(ssr_pins[message.sensor*2], SSR_ON);
          ssr_last_change[message.sensor*2] = millis();
          ssr_status[message.sensor*2] = SSR_ON;
        } else if(message.sensor == CHILD_ID_LIGHT_2) {
          digitalWrite(ssr_pins[message.sensor*2-1], message.getBool()?SSR_ON:SSR_OFF);
          ssr_last_change[message.sensor*2-1] = millis();
          ssr_status[message.sensor*2-1] = message.getBool()?SSR_ON:SSR_OFF;
        }
      } else if(message.type == V_UP) {
        digitalWrite(ssr_pins[message.sensor*2], SSR_ON);
        ssr_last_change[message.sensor*2] = millis();
        ssr_status[message.sensor*2] = SSR_ON;
        digitalWrite(ssr_pins[message.sensor*2 + 1], SSR_OFF);
      } else if(message.type == V_DOWN) {
        digitalWrite(ssr_pins[message.sensor*2], SSR_OFF);
        digitalWrite(ssr_pins[message.sensor*2 + 1], SSR_ON);
        ssr_last_change[message.sensor*2+1] = millis();
        ssr_status[message.sensor*2+1] = SSR_ON;
      } else if(message.type == V_STOP) {
        digitalWrite(ssr_pins[message.sensor*2], SSR_OFF);
        digitalWrite(ssr_pins[message.sensor*2 + 1], SSR_OFF);
      }
    }
    

  • Hero Member

    @breimann I did a battery monitor project using the acs712 a while back. in that post you should be able to find out what you need.



  • Hi @Boots33 and @TimO. Thanks for your prompt replies.

    My main issue is finding non-specific (not for a specific context) ACS712 code for mysensors.

    I've looked at your Battery monitor thread a little Boots33 and i'll have another look.

    Thankyou TimO for sharing your code. I'll have a look and see what i can understand and if it might work / how i might adapt for my context.


  • Hero Member

    @breimann If you don't need to know how much current the motor is drawing, just whether it is on or off.
    Then a simpler way to check if the pump is on might be to plug a small 5v power pack into the same point that the pump is connected to and monitor the 5v on one of the arduino digital in pins.
    This way you will not need to be mucking around with 240v.
    If you know the current draw of the pump you could then probably work out how much power it has used by timing the on time and multiplying by the draw etc.

    You could also perhaps use a magnetometer module placed on the pump to check for it being on.


  • Mod

    If you want to have a precise power reading you also have to correct for the power factor (I hope I got the English term right), you can't just multiply 240v times the amps (given that 240v are stable, because they can drop to 220v or even 210v during the day)


  • Hero Member

    @breimann thinking on this a bit more I don't know whether the details on my project will be of much use. I am measuring DC current and you will be using AC so you will likely need a different method of working out current flow.

    Also make sure you allow for the higher startup draw of your motor when selecting the ACS712.



  • @Boots33 thanks for your input. Really encouraging.

    I can't do the 5v plug pack in the power point as the pump has it's own controller which just turns itself on when it detects pressure fluctuations (ie a tap is turned on) so there's always power to the pump if that makes sense?

    Good idea though!

    Thanks for your ideas and taking the time to post your suggestions. Very much appreciated.


Log in to reply
 

Looks like your connection to MySensors Forum was lost, please wait while we try to reconnect.