Pool level controller with AC solenoid valve (solved)

New to this forum and also rather new to Arduino and electronics stuff.
Hope you could help me.

I have build a water level controller for automatically filling a pool when the water level comes too low.

Basic setup:
Arduino Nano, float switch, transformer (220-12/24V), Rainbird solenoid valve (24V AC).
The transformer is a (2x12V/24V) 600mA.
I have tapped 1x12V for powersupply to the Nano (bridge rectifier, smoothing capacitor 470uF and a buck converter ending up with 7V DC feeding the Nano at Vin.
Also tapped 24 V for the solenoid valve (brand Rainbird, actually meant for watering/irrigation), 24 V AC, 30.39 Ohm, Inrush current: 0.41A (9.9VA) at 60Hz, Holding current: 0.14A (3.43VA) at 60Hz. btw, I am actually at 50 Hz. These valves are rather sturdy and reliable.

Basically the sketch opens/closes the valve based on float switch status with securities built in to avoid on/off cycling due to waves (minimum filling time 30 seconds) and closing the valve when filling time surpasses a maximum period if something is blocked or broken (10 minutes). Actual status (filling, full, alarm) are indicated by three LEDs.

The valve is operated by a stnadard Arduino compatible mechanical relay with optocoupler.
The setup works perfectly. However when I connect the solenoid then strange things happen.
( I have seen https://forum.arduino.cc/index.php?topic=186879.0 but this refers to a DC solenoid)

When filling starts (relay on, solenoid on) and the float switch is set to status full the sketch allows a 30 seconds waiting time and the status shall change to "full". this works without the solenoid but when the solenoid is connected I hear the relay clicking after 30 seconds, the filling LED is off for a split second but then switches to ON again immediately.

My analysis is that possibly the following is the culprit:
The switching of of the solenoid creates an inductive spike in the transformer which in some way propagates through the bridge rectifier and buck converter to the Nano which gets messed up.
Because the solenoid is 24V AC a diode solution cannot work.
Would it be a solution to add an R-C snubber parallel to the relay and if so, what values for R and C.?

Hope to get some guidance.

After reading the "How to use the forum" post, please follow the directions and post a hand drawn wiring diagram, and the code, using code tags.

I suspect your transformer may also be an issue as it is only 600 mA.

It could be that the last item is putting it at a tipping point for the supply which means something is not getting all the current it needs. Note CURRENT and not VOLTAGE as they are two different beasts.

Could you also take a few moments to Learn How To Use The Forum.
Other general help and troubleshooting advice can be found here.
It will help you get the best out of the forum in the future.

I have attached the circuit, drawn as good as I can. I left out the signaling LEDs.
Hope that makes things clearer. I will upload the sketch once things are solved and all is working.

I have found out that the solenoid is rated 3 W so it should take some 125 mA at 24 V.
I thought this would be sufficiently within the limits of the transformer (500 mA) and would leave the required current for the Nano, one LED and the relay to function well.

Will read the forum rules :wink:

(mod edit)

By your drawing, you are using the Nano 5 volt regulator to power the relay. Why? The nano regulator does not have enough current capacity to power the relay.


Thanks for the suggestions sofar. I am going to redraw the circuit with separate supply to the Nano and to the relay. The transformer will then only serve the solenoid.
I have seen also that the inrush current for the solenoid is around 410 mA which is just under the 500 mA max current of the transformer.

One question remains for now: WOuld is be requires or wise to put a RC-snubber parallel to the relay to reduce or eliminate the electric equivalent of "waterhammer"?

Based on your suggestions (thanks) I have redrawn the circuit and implemented a separate power supply for the Arduino and the relay.
It now works as it should. Passed the test sofar.
It is my first project and first coding for the Arduino. Sure the code may be optimized and improved. Your suggestions are welcome.

// Variables that do not change
const byte switchPin = 8;         //floating switch
const byte relayPin = 2;          //relay turns trigger signal - active high;
const byte blueLedPin = 5;        //LED on if filling condition
const byte greenLedPin = 4;       //LED on if floating switch on full (closed)
const byte redLedPin = 6;         //LED for error

int switchState;
unsigned long switchTime;
unsigned long currentTime = millis();
unsigned long previousTime = 0 ;  // for blinking red LED
const long blinkInterval = 1000;  //Interval for blinking red LED
int redLedState = LOW;

//time setting with maxPeriodMin.
//minPeriodMin is used to avoid the relay to switch on and off in short times
//for example due to little waves. Default is 1 (minute) filling time.
int minPeriodMin = 1;

//maxPeriodMin is used in case of error, which can be cable failure or floating switch obstruction.
//if maxPeriod surpasses the limit then it is supposed that overfilling will occur.Default is 15 (minutes).
//Relay turns in OFF state and red LED starts blinking
int maxPeriodMin = 10;
//int maxPeriodMin = 1;
long minPeriod;
long maxPeriod;

void setup ()
  Serial.begin (9600);
  minPeriod = minPeriodMin *60L*1000;
  maxPeriod = maxPeriodMin * 60L * 1000;
  pinMode (relayPin, OUTPUT);            // Define port as output
  pinMode (switchPin, INPUT);            // Define port as input, on is HIGH)
  pinMode (blueLedPin, OUTPUT);          // Define port as output
  pinMode (greenLedPin, OUTPUT);         // Define port as output
  pinMode (redLedPin, OUTPUT);
  switchState = digitalRead (switchPin);
  Serial.println (switchState); // 1 = open, (filling)
  Serial.println (minPeriodMin);
  Serial.println (maxPeriodMin);
  Serial.println (minPeriod);
    Serial.println (maxPeriod);


void loop () {

  while (switchState == LOW) {
    digitalWrite (relayPin , LOW );        //close relay
    digitalWrite (blueLedPin, LOW);        //set blue LED OFF
    digitalWrite (greenLedPin, HIGH);      //set green LED ON
    digitalWrite (redLedPin, LOW);         //set red LED to OFF
    switchState = digitalRead (switchPin); //continue reading switchPin till it is != 1
    if (switchState != 0) {
      switchTime = millis();               //memorize time of state change of the switch
  // If the above condition is not true:
  // Filling will start now. Calculate the period after change of switchstate.
  // as long as the difference is <= minPeriod the filling must go on
  while ((millis() - switchTime) <= minPeriod) {
    digitalWrite (relayPin , HIGH );   //open relay
    digitalWrite (blueLedPin, HIGH);   //set blue LED to ON
    digitalWrite (greenLedPin, LOW);   //set green LED to OFF
    digitalWrite (redLedPin, LOW);     //set red LED to OFF

  // After minPeriod has passed switchstate is checked. If switchState is 1 then the following if-part will be passed.
  // and it will loop back to beginning of void-loop. If switchState is still 0 (filling state) then a control on
  // maxPeriod is made
  switchState = digitalRead (switchPin);

  if (switchState == 1 && ((millis() - switchTime) >= maxPeriod)) {
    //Filling time surpasses the maxPeriod hence error condition occurs.
    //Relay must go OFF, blueLed must go off.

    digitalWrite (relayPin , LOW );   //close relay
    digitalWrite (blueLedPin, LOW);   //set blue LED
    //the redLed must go to blinking. The following code is from BlinkingLedWithoutDelay
    if (millis() - previousTime >= blinkInterval) {
      previousTime = millis();
      if (redLedState == LOW)
        redLedState = HIGH;
      else {
        redLedState = LOW;
      digitalWrite (redLedPin, redLedState);