Pulsador con relé. Accionar un telerruptor mediante un relé

Hola a todos.
Llevo poco tiempo con el Arduino y me parece un mundo apasionante a la vez que un poco complicado.

Me pueden ayudar a programar el arduino para que cuando reciba el caracter 'a' a través del puerto serie encienda y apague un led una única vez, sin entrar en bucle.
Quiero integrar el arduino en el sistema de iluminación de una vivienda de manera que a través de un relé se cierre y abra simulando el pulsador de la vivienda y conectado al un telerruptor encienda y apague las luces.

Dejo el códido que he estado utilizando, pero este entra en bucle y no me sirve.

Muchas gracias a todos....

const int ledPin =  13;
int estado = 0;


void setup(){
 pinMode(13,OUTPUT);
 Serial.begin(9600);
 delay(1000);

}


void loop(){



if(Serial.available()>0){           
       estado = Serial.read();      
}
if (estado == 'a') {
digitalWrite(13,HIGH);
delay(100);
digitalWrite(13,LOW);

 }


if(estado== 'b' ){
      digitalWrite(13,HIGH);
}

if(estado== 'c' ){
      digitalWrite(13,LOW);
}

delay(1000);
}

Hola
yo creo que entenderias mejor el codigo y como funciona su buscas en google ACTIVAR LED POR SERIAL entonces cambias el led por un reled y ya estaria.

lo del bucle es porque tienes que hacer un setup apagandolo y luego el loop como tu quieras
saludos

Hola sondagalega gracias por ayudarme.
El tema es que voy a conectar la salida del relé a la entrada de un DIMMER que regula las lamparas a 220V.
Este dimmer funciona de la siguiente manera. Con una pulsación enciende y con otra apaga. Si pulsas y mantienes la pulsación regula la intensidad de la luz.
Por eso con el caracter 'a' quiero conseguir la pulsación para encender y apagar, con el 'b' y 'c', regularía la intensidad.
Lo que no consigo es crear la pulsación sin que entre en bucle.

Muchas gracias por todo!!

El problema es que la variable estado es global y "recuerda" su valor siempre que no se vuelva a cambiar. La condición del if...

if(Serial.available()>0){           
    estado = Serial.read();
}

... sólo se cumple si hay algún dato del puerto serie pendiente de ser leído. Esto ocurre cuando recibe la letra que le envías (supongamos una 'a’), la lee del puerto serie y se guarda en la variable estado. Continúa el programa y como es una 'a' manda el pulso. Termina la fución loop() y vuelve a empezar de nuevo. Llega otra vez al if, pero esta vez la condición no se cumple porque no hay datos pendientes de leer en el puerto serie. Así que no se "actualiza" la variable estado, con lo que mantiene el último valor recibido, la 'a', y vuelve a mandar un pulso. Así continuará hasta que se le mande algo que no sea una 'a'. ¿Posible solución? Quitar el if y dejar sólo la asignación...estado = Serial.read();... y así la variable pasará a valer -1 si no hay más datos en el puerto serie.

Solucionado… Eliminando

if(Serial.available()>0){

Se consigue que no entre en bucle y que se encienda una única vez el led durante el tiempo establecido.

Muchísimas gracias por todo!!!

entonces, ya lo resolviste?

tonyzuky:
Solucionado... Eliminando

if(Serial.available()>0){

Se consigue que no entre en bucle y que se encienda una única vez el led durante el tiempo establecido.

Muchísimas gracias por todo!!!!!

Pero esa no debería ser la solución, no tienes que quitar el if que controla si hay un dato en el puerto serie.
Lo que hay que hacer es vaciar la variable estado.

estado="";
if(Serial.available()>0){....

rodripelto:
Lo que hay que hacer es vaciar la variable estado.

Precisamente eso es lo que ocurre si no hay datos disponibles en el puerto serie. En tal caso Serial.read() retorna -1, indicando que no hay datos. En el caso de haber retornará un valor entre 0 y 255 (un valor válido para ser almacenado en un byte). Por eso el tipo que retorna Serial.read() es int, porque si fuera de tipo byte no podría retornar un valor que nos indicara que no es un dato válido.

Además, no se debe asignar una cadena (por muy vacía que esté) una variable de tipo int.

Y para "vaciar" la variable estado tampoco es aconsejable usar el valor 0, ya que este es un valor válido para un byte, y pudiera ser que se desee emplear dicho valor. Por eso lo mejor es "vaciarla" con un -1 aprovechando que está declararla de tipo int.

Otra solución es meter los otros tres if dentro del primero y quitar el delay(1000) para que"responda" inmediatamente. Ya de paso, declaramos la variable estado dentro del primer if, puesto que no la vamos a usar fuera de él. Como ahora nos estamos asegurando que sólo se usa si hay un byte disponible, podemos declararla de tipo byte en vez de int y ahorrarnos un byte de memoria (ojo, que si usamos byte es porque con available() ya nos estamos asegurando de que tenemos un valor válido). El código quedaría asi:

const int ledPin =  13;

void setup() {
    pinMode(13, OUTPUT);
    Serial.begin(9600);
    delay(1000);
}

void loop(){
    if(Serial.available() > 0) {
        byte estado = Serial.read();
        if (estado == 'a') {
            digitalWrite(13, HIGH);
            delay(100);
            digitalWrite(13, LOW);
        }
        if(estado== 'b' ){
            digitalWrite(13, HIGH);
        }
        if(estado== 'c' ){
            digitalWrite(13, LOW);
        }
    }
}

En la respuesta Puerto serie - #3 by IgnoranteAbsoluto - Software - Arduino Forum explico un poco mi teoría del uso de available().

Efectivamente IgnoranteAbsoluto tienes razón, estado="" está mal asignado ya que estado es int.
Me despistó que el la compara con letras.
Un saludo.

IgnoranteAbsoluto siento haberme inmiscuido en tu respuesta totalmente correcta dando yo además una recomendación incorrecta.

Yo comparto la solucion que mete las acciones dentro del if(Serial.available()>0)

Siempre resuelvo las cosas de ese modo.