Detect if 230V AC is on

Hi

I have an automatic pump system that sometimes runs longer than needed.

My idea is to use a "sensor" that reads if 230V AC is on, connect it to an esp32 Wroom.

If 230V AC runs longer than 120 sec, switch off 230V to the pump system, wait 10 minutes, switch on 230V to the pump system, using an SSR for 230V AC.

I have SSR, Optocoupler, passive components and sensors SEN0211 and WSC1500.

I don't know if I need a sensor mentioned above or use a rectifier bridge and some capacitors and a optocoupler.

Please advice me to a "simple" and safe system.

M

To detect if 230V AC is on, you can use a voltage detection circuit with a step-down transformer or optocoupler for isolation. This ensures safety while providing a signal to indicate the presence of voltage, which can be used for further processing in your system.

If you have that with clamp sensor, should be safe and simple.

Use a phone charger to detect 230V AC.

3 Likes

FIRST! Tell us if the 230 volt circuit is hard wired to the pump or does it have a plug on a cord the plugs into a 230 volt outlet.

Hi

Wow, lots of tips, thanks!

Here is what I have

Idea:

Parts

Sensor connections


Backside sensor

So can this be done?

Sensor has VCC: Use 5 or 3.3V?
Dout: Is that I2C? or something else
Aout: Analog out, to a analog GPIO?

"Code":
SSR always on
if 230V AC = HIGH more than 2 min switch OFF SSR, switch ON SSR after 10 min
Repeat

By the way, the pump is for a cleaning system of my Koi pond. If it runs to long, the pond will be dry. So this is kind of important, I hope to have this running in a day or 2.

Thanks

It has a cord with a plug that goes into the old pump automation from Filtreau.

On of the outlets is controlling the pump. But it sometimes dont switch it off

I see. Can you make or find something to go between the controller outlet and the pump plug so you can tell if the pump is off or not? A box or and extension cord or a transformer or?

Yes, exactly.
if power on > 2 min then power off for 10 min

Then maybe your Filtreau unit is bad. I would replace it before it completely fails and causes pump damage.

1 Like

I'd tend to focus initially on solving the problem of the existing controller keeping the motor running for "too long". Is it a timing adjustment issue or is there a level switch somewhere or what?

1 Like

The picture, incidentally, is lovely. Is that carp/gold fish leaping out of the water or is it a strange optical effect?

1 Like

I have a new one, this "mistake" happens with months between. Supplier cant find mistake on it, and I cant reproduce the error, it suddenly happens...

Now I make a system to control it so I can sleep at night.

And I don't like to make "extra" systems that is vital to my koi's, but what else can I do?

Thanks, its a carp, we call it koi.
Fish is in the water. Water is clear, and maybe a lucky shot.

There is a sensor (floater that triggers a read relay). I cant find errors on it when I test it....
When I test it, the system works, if pump runs too long it stops the system. But this is not happening all the time, this is what my system tries to fix.

After I take the power of the system, it starts working.... until it hick up one more time....

Filtreau is obviously an unreliable product. Buy a different unit from a different manufacturer.
Your choice but you are treating the symptom and the the real cause of the problem.

1 Like

I have made a code that reads AC (RMS) and control a SSR.
I will test it later today.

GPIOs is always interesting, I start with
5 for sensor Aout and
34 for SSR, works with 3.3V

The sensor will get 5V supply

The function calculateRMS is the one I'm not sure about, I have a 1 phase 230V 50Hz, IT net (Norway+Albania...) no neutral.
Any input from you to my code?

#define SSR_PIN  5  // GPIO pin connected to the SSR  
#define WCS1500_PIN 34  // ADC pin connected to the WCS1500 current sensor - marked Aout on sensor
#define WCS_ZERO_POINT 2048  // Middle point of WCS1500 sensor (approx 2.5V mapped to 12-bit ADC)

// Timing constants
#define SAMPLE_DURATION 200  // Sampling duration in milliseconds
#define RMS_THRESHOLD 100    // Adjust based on expected current (RMS value from ADC)

// Timers
unsigned long powerSenseStartTime = 0;  // Timer for detecting x minutes of continuous power
unsigned long ssrOffStartTime = 0;      // Timer for the 10-minute off delay
unsigned long offDuration = 10*1000;    // test 10 sec    //10 * 60 * 1000; // 10 minutes in milliseconds
unsigned long pumpMaxRuntime = 10*1000; // test 10 sec // 2 * 60 * 1000;

bool isSSROn = true;

void setup() {
  pinMode(SSR_PIN, OUTPUT);
  digitalWrite(SSR_PIN, HIGH);  // Default state: SSR is ON
  Serial.begin(115200);
}

void loop() {
  float rmsValue = calculateRMS();  // Calculate RMS current
  bool currentDetected = (rmsValue > RMS_THRESHOLD);

  // Debugging: Log the RMS value
  Serial.print("RMS Value: ");
  Serial.println(rmsValue);

  // Handle SSR control based on current detection
  if (currentDetected) {
    if (powerSenseStartTime == 0) {
      powerSenseStartTime = millis();  // Start timing the 2-minute power sense
    }
    if (millis() - powerSenseStartTime >= pumpMaxRuntime) {
      if (isSSROn) {
        Serial.println("Power detected for 2 minutes. Turning off SSR for 10 minutes.");
        digitalWrite(SSR_PIN, LOW);  // Turn off SSR
        isSSROn = false;
        ssrOffStartTime = millis();  // Start the 10-minute off timer
      }
    }
  } else {
    // Reset the power sensing timer if no current is detected
    powerSenseStartTime = 0;
  }

  // Manage the 10-minute off duration
  if (!isSSROn && millis() - ssrOffStartTime >= offDuration) {
    Serial.println("10 minutes elapsed. Turning SSR back ON.");
    digitalWrite(SSR_PIN, HIGH);  // Turn SSR back ON
    isSSROn = true;
    powerSenseStartTime = 0;  // Reset power sensing timer
  }
}

// Function to calculate RMS current
float calculateRMS() {
  unsigned long startTime = millis();
  unsigned long sumOfSquares = 0;
  unsigned int sampleCount = 0;

  while (millis() - startTime < SAMPLE_DURATION) {
    int adcValue = analogRead(WCS1500_PIN);
    int offsetValue = adcValue - WCS_ZERO_POINT;  // Center the waveform around zero
    sumOfSquares += offsetValue * offsetValue;   // Accumulate the square of the value
    sampleCount++;
    delayMicroseconds(1000);  // Sample every 1 ms (adjust as needed)
  }

  float meanSquare = (float)sumOfSquares / sampleCount;  // Mean of squared values
  return sqrt(meanSquare);  // RMS value
}

I completely Agree, fixing symptoms is not the best approach, but there is not much other to buy, and I will not build a new one.

Hi

Code is compiling and I can make it work but maybe some calibration I don't understand

Measurement
No load, no 230V connected = RMS between 70 and1100
No load, connected to 230V + earth= RMS ca 1451
Load 450 W = RMS 1399

NB measures under may differ from numbers above because this was the first readings but I hope it gives some input to you.

1: Expected RMS to increase, maybe wire in WCS1500 shall change direction
2: Diff RMS load/no load = 52, this number don't make sense for me.

Can I ask you to give me a tip so I manage to read 450W RMS?

running code:

#define SSR_PIN  5  // GPIO pin connected to the SSR
#define WCS1500_PIN 34  // ADC pin connected to the WCS1500 current sensor
#define WCS_ZERO_POINT 2048    // Middle point of WCS1500 sensor (adjust based on calibration)

// Constants
#define SAMPLE_FREQUENCY 2000  // Sampling rate in Hz (2000 samples per second)
#define SAMPLE_DURATION 1000   // Integration window in milliseconds (1 second)
#define RMS_THRESHOLD 1500      // Adjust based on motor's typical current in ADC units

// Timers
unsigned long powerSenseStartTime = 0;  // Timer for detecting 2 minutes of continuous power
unsigned long ssrOffStartTime = 0;     // Timer for the 10-minute off delay
unsigned long offDuration = 10 * 1000;  // test 10 sec    //10 * 60 * 1000; // 10 minutes in milliseconds
unsigned long pumpMaxRuntime = 10 * 1000; // test 10 sec // 2 * 60 * 1000;

bool isSSROn = true;

// for å lese 2 siffer i filnavn (versjonsnr
#include <cstring>
#include <cstdlib>
#include <iostream>

void setup() {
  pinMode(SSR_PIN, OUTPUT);
  digitalWrite(SSR_PIN, HIGH);  // Default state: SSR is ON
  Serial.begin(115200);
  PrintFileNameDateTime();
}

void loop() {
  float rmsCurrent = calculateRMS(SAMPLE_DURATION, SAMPLE_FREQUENCY);  // Calculate RMS current
  bool currentDetected = (rmsCurrent > RMS_THRESHOLD);   // org >

  // Debugging: Log the RMS current
//  Serial.print("RMS treshold: ");  Serial.println(RMS_THRESHOLD);
  Serial.print("RMS Current:  ");  Serial.println(rmsCurrent);

  // Handle SSR control based on current detection
  if (currentDetected) {
    //Serial.print(".");
    if (powerSenseStartTime == 0) {
      powerSenseStartTime = millis();  // Start timing the 2-minute power sense
    }
    if (millis() - powerSenseStartTime >= pumpMaxRuntime) {
      if (isSSROn) {
        Serial.println("Current detected for 2 minutes. Turning off SSR for 10 minutes.");
        digitalWrite(SSR_PIN, LOW);  // Turn off SSR
        isSSROn = false;
        ssrOffStartTime = millis();  // Start the 10-minute off timer
      }
    }
  } else {
    // Reset the power sensing timer if no current is detected
    powerSenseStartTime = 0;
  }

  // Manage the 10-minute off duration
  if (!isSSROn && millis() - ssrOffStartTime >= offDuration) {
    Serial.println("10 minutes elapsed. Turning SSR back ON.");
    digitalWrite(SSR_PIN, HIGH);  // Turn SSR back ON
    isSSROn = true;
    powerSenseStartTime = 0;  // Reset power sensing timer
  }
}


// ******************************************************


// Function to calculate RMS current over a specified duration
float calculateRMS(unsigned long durationMs, unsigned int frequencyHz) {
  unsigned long sampleInterval = 1000000 / frequencyHz;  // Microseconds between samples
  unsigned long startTime = millis();
  unsigned long sumOfSquares = 0;
  unsigned int sampleCount = 0;

  while (millis() - startTime < durationMs) {
    int adcValue = analogRead(WCS1500_PIN);
    int offsetValue = adcValue - WCS_ZERO_POINT;  // Center the waveform around zero
    sumOfSquares += offsetValue * offsetValue;   // Accumulate the square of the value
    sampleCount++;
    delayMicroseconds(sampleInterval);  // Wait for the next sample
  }

  float meanSquare = (float)sumOfSquares / sampleCount;  // Mean of squared values
  return sqrt(meanSquare);  // RMS value
}



void PrintFileNameDateTime() {
  Serial.println("    Kompileringsinformasjon:");
  Serial.print  ("    Filnavn kode:     ");  Serial.println(__FILE__);    // Makroer
  Serial.print  ("    Kompileringsdato: ");  Serial.println(__DATE__);
  Serial.print  ("    Klokkeslett:      ");  Serial.println(__TIME__);
  int mottagerVersjon = getVersionNumber(__FILE__);
//  Serial.print  ("    MotagerVersjon print file:      ");  Serial.println(mottagerVersjon);
}


// Funksjon som henter versjonsnummeret fra filnavnet
int getVersionNumber(const char* filePath) {
  const char* dotPos = strrchr(filePath, '.');  // Finn posisjonen til det siste punktumet i filbanen
  if (dotPos != nullptr && (dotPos - filePath) >= 2) {  // Hvis punktumet finnes og det er minst to tegn før punktumet
    char versionStr[3]; // 2 sifre + nullterminator
    versionStr[0] = *(dotPos - 2);
    versionStr[1] = *(dotPos - 1);
    versionStr[2] = '\0';
    return atoi(versionStr);  // Konverter til heltall
  }
  return 0;  // Returner 0 hvis versjonsnummeret ikke kan bestemmes
}

Simple might be reading a NO contact off a small 'ice cube' 230V rated relay with its coil wired in parallel with the pump.