Mis relés se vuelven locos... o hacen que se vuelva loco mi Atmega328

Buenos días.

Llevo algunos meses trabajando en un proyecto que me trae loco. Se trata de controlar el riego del jardín, en el que tengo dos zonas, por lo que tengo dos electroválvulas, una para cada zona.
Estas electroválvulas son de 9V DC de esas raritas que abren y cierran invirtiendo la polaridad y no necesitan tensión para mantenerlas abiertas.
El caso es que cuando pruebo mi prototipo en la mesa de operaciones, funciona correctamente, pero si le conecto los solenoides (Electropválvulas) empiezan a ocurrir cosas raras. Parece como si la activación de una electroválvula indujera en el resto del circuito algún pico o bajada de tensión y empiezan a sonar anárquicamente hasta que se estabilizan, encendiéndose y apagándose. Esto me hizo probar el uso de una alimentación alternativa para el circuito de activación (Dibujo 2), pero me pasa lo mismo. Os pego el esquema por si alguien me puede echar un cable.
Hay algunos elementos que podéis ignorar. El ESP8266 es para poderlo activar por wifi, pero hace lo mismo que los pulsadores. Sin él me pasa lo mismo. También empecé con un arduino UNO con el mismo resultado. Finalmente elegí hacerlo con un Atmega328 directamente y nada cambia.
Sólo me queda pensar que los dos circuitos no son tan independientes.... No sé si probar con reles de estado sólido, que he leído que funcionan mejor.

Perdonad por el Fritzing, que seguro que no es muy estándar. Las hago solo para mi documentación.

Os anexo también el código del Atmega, no os pongo el código del ESP8266 porque no afecta al caso. (Pero si alguien lo cree necesario lo añado).

#include <SoftwareSerial.h>
//Variables y constantes
//long tiempo_Maximo = 18000000;
long tiempo_Maximo = 15000000;

long tiempo_Maximo_Seguridad = 112500000;
long tiempo = 0;
long tiempo_Seguridad = 0;
int tiempo_Corto = 100;
//pines


int pin_R1 = 12;
int pin_R2 = 4;
int pin_R3 = 13;
int boton_apagado = 5;
int boton_derecha = 6;
int boton_izquierda = 7;

// Semáforos
SoftwareSerial SerialESP (2, 3); //rx, tx
char data;

boolean inicio = true;

bool debug = true;

//******************************************************************
void setup() {
SerialESP.begin(9600);

pinMode(pin_R1, OUTPUT);
pinMode(pin_R2, OUTPUT);
pinMode(pin_R3, OUTPUT);
pinMode(boton_apagado, INPUT);
pinMode(boton_derecha, INPUT);
pinMode(boton_izquierda, INPUT);

if (debug) Serial.begin(9600);
apaga_todo();

inicio = true;
tiempo = 0;
tiempo_Seguridad = 0;
if (debug) pintar();
}

// the loop function runs over and over again forever
void loop() {
//if (debug) pintar();
tiempo_Seguridad++;
if (inicio) {
bucle_inicio();
}
if (digitalRead(boton_apagado) == HIGH) {
inicio = false;
apaga();
while (digitalRead(boton_apagado) != LOW) {}
}
if (digitalRead(boton_derecha) == HIGH) {
inicio = false;
enciende_Ev_1();
while (digitalRead(boton_derecha) != LOW) {}
}
if (digitalRead(boton_izquierda) == HIGH) {
inicio = false;
enciende_Ev_2();
while (digitalRead(boton_izquierda) != LOW) {}
}

// Leo del puerto SerieESP
checkSerialCom();

// por seguridad
if (tiempo_Seguridad > tiempo_Maximo_Seguridad) {
apaga_todo();
apaga();
tiempo_Seguridad = 0;
}
}

void checkSerialCom() {
if (SerialESP.available() > 0) {
if (debug) Serial.print("Leo Puerto Serie: ");
while (SerialESP.available() > 0) {
data = (char)SerialESP.read();
if (debug) Serial.print(data);
if (data == 'A') {
apaga_todo();
apaga();
tiempo_Seguridad = 0;
}
if (data == 'E') {
inicio = true;
tiempo = 0;
}
if (data == 'D') {
inicio = false;
enciende_Ev_1();
}
if (data == 'I') {
inicio = false;
enciende_Ev_2();
}
}
if (debug) Serial.println("");
}
}

void bucle_inicio() {
if (tiempo == 0) enciende_Ev_1();
else if (tiempo == tiempo_Maximo) {
//pintar();
enciende_Ev_2();
}
tiempo++;
if (tiempo > tiempo_Maximo * 2) {
inicio = false;
apaga();
}
}

void enciende_Ev_1() {
apaga();
delay(tiempo_Corto);
digitalWrite(pin_R1, HIGH);
delay(tiempo_Corto);
digitalWrite(pin_R1, LOW);
}

void enciende_Ev_2() {
apaga();
delay(tiempo_Corto);
digitalWrite(pin_R3, HIGH);
delay(tiempo_Corto);
digitalWrite(pin_R3, LOW);
}

void apaga() {
digitalWrite(pin_R2, HIGH);
delay(tiempo_Corto);
digitalWrite(pin_R2, LOW);
}

void apaga_todo() {
digitalWrite(pin_R1, LOW);
digitalWrite(pin_R2, LOW);
digitalWrite(pin_R3, LOW);
}

void pintar() {
Serial.print("Tiempo: ");
Serial.print(tiempo);
Serial.print(" inicio: ");
Serial.print(inicio);
Serial.print(" tiempo_Seguridad: ");
Serial.println(tiempo_Seguridad);
}

Ruido y mucho.

Si sigo tu esquema en frizting:

  • Tanto el reset como el oscilador los veo conectado en el negativo de la entrada del regulador, preferiblemente ponlos a la salida. Ya, GND es GND en ambos lados, pero importa.

  • Pon un par de condesadores de 100nF tanto a la entrada y la salida del 7805 para filtrar ruidos provenientes de la alimentación (ahora ves porque te digo que pongas los GND a la salida), colocalos de forma que esten todo lo cerca posible del regulador.

  • A ser posible aisla los selenoides usando otra fuente que no tenga mucho contacto con la de los 5 voltios que alimentan los micros (atmega y esp).

  • Dado que las válvulas tienes que cambiar la polaridad, un diodo antiparalelo no te vale, así que busca unos varistores de 18 voltios y colocalos, en el cable de los solenoides.

  • No uses una protoboard. Usa una placa de agujeros o haz tu propia PCB.

  • En el circuito de reset puedes colocar ademas de la resistencia PULL-UP, un condendasor y un diodo con el cátodo a positivo.

  • Si aún así sigue habiendo ruido, pues un filtro RC/LC a la entrada de la alimentación del atmega no vendria mal. Para el ESP tampoco.

Creo que ya tienes por donde empezar...