Proyecto control de persianas automatizadas

Buenas tardes,

estoy haciendo un proyecto de final de carrera de un sistema de control de persianas y luces. Me encuentro con que las persianas y las luces funcionan en algunos caso pero en otros no:

NO FUNCIONA: si el LDR NO DETECTA LUZ (LED ROJO ENCENDIDO) Y ESTAS PULSADO EL PULSADOR DE LA LUZ (pulsador amarillo), no enciende y apaga el led rojo.

en caso contrario, estando el LDR detectando LUZ(LED rojo APAGADO), puedes pulsar el pulsador y el LED se encienda y apaga.

los led amarillo y verde son motor subiendo y motor bajando respectivamente.

la Protoboard pequeña es para otra parte del proyecto y simplemente tengo en comun GND.

Estoy un poco perdido ahora mismo porque no encuentro mi error o errores, ayuda por favor.

Puedes explicarte mejor!!

Yo no comprendo la relación entre subir/bajar y el LDR ademas de tu botón que cambia el estado.

Recuerda que nosotros no estamos ahi pero lo que mas me sorprende es que es tu tesis de modo que deberías poder explicarte con mayor claridad. Si nosotros no entendemos, espero que tu profesor si.

A ver si mejoras las comunicación. Yo tengo tu código corregido pero haciendo lo mismo porque luego no pude entender tus objetivos.

Persianas,suben o bajan. Ok Luz dia/noche => Luz dia ABRIR. Luz de noche BAJAR

Bien, que mas? quieres que el boton pase por encima de esta orden y suba/baje las persianas independientemente de la luz exterior?

Sigue haciendo lo mismo que antes, funciona segun el LDR pero detecta la pulsación y cambia la variable state pero no cambia el estado del LED.

Hola.
Presumiblemente lo que te ocurre es que estás actuando constantemente sobre la luz, por ejemplo, encendiendo o apagando siempre que el LDR esté por encima o debajo de un valor, en lugar de sólo cuando se produzca el salto de condición. Por ello, aunque la actives manualmente, en el siguiente loop se establece de nuevo según el valor del LDR.

Esto es una máquina de estados. El meollo de la misma es el switch que se evalúa en cada loop. Dependiendo del estado de la máquina, se verifican unas condiciones, y se realizan determinadas acciones, entre las que está el cambiar dicho estado. En esos cambios, precisamente, actuamos sobre los distintos led, una sola vez.
Fuera de la máquina de estados, sencillamente trabajamos el interruptor de forma independiente, con lo que permanecerá en dicho estado hasta que vuelva a haber un cambio de estado en la máquina.

/* Use File->Load Prog to
   load a different Program
*/

//boton pulsador
const int LED =8; //pin del LED
const int LEDSUBE =4; //pin del LED motor subiendo
const int LEDBAJA =5; //pin del LED motor bajando

const int PULSADOR = 7; // pin pulsador

const int FINCARRERAUP = 2; // pin FC subida
const int FINCARRERADOWN = 3; // pin FC bajada

const int LDR = A0; // pin sensor LDR

int ultimoEstadoPulsador=LOW;

enum {	SUBIENDO, ARRIBA, BAJANDO, ABAJO, DESCONOCIDO} estadoPersiana = DESCONOCIDO;
void setup(){
	pinMode(LED,OUTPUT); // establecer que el pin digital es una señal de salida
	digitalWrite(LED, LOW);
	pinMode(LEDSUBE,OUTPUT); // establecer que el pin digital es una señal de salida
	digitalWrite(LEDSUBE, LOW);
	pinMode(LEDBAJA,OUTPUT); // establecer que el pin digital es una señal de salida
	digitalWrite(LEDBAJA, LOW);
	
	pinMode(PULSADOR,INPUT); // y BOTON como señal de entrada
	
	pinMode(FINCARRERAUP,INPUT); // y FC subida como señal de entrada
	pinMode(FINCARRERADOWN,INPUT); // y FC bajada como señal de entrada
	
	Serial.begin(9600);	
}

void loop() {
	switch(estadoPersiana) {
		case SUBIENDO:
			if (digitalRead(FINCARRERAUP)) {	// si la persiana abre del todo
				digitalWrite(LEDSUBE, LOW); // detenemos subida
				digitalWrite(LED, LOW); // apagamos la luz cuando ha terminado de subir				
				estadoPersiana = ARRIBA;
			}
			break;
		case BAJANDO:
			if (digitalRead(FINCARRERADOWN)) {	// si la persiana cierra del todo
				digitalWrite(LEDBAJA, LOW); // detenemos bajada
				estadoPersiana = ABAJO;
			}
			break;
		case ARRIBA:
			if (analogRead(LDR) < 200) {	// si baja la luz
				baja();
			}
			break;
		case ABAJO:
			if (analogRead(LDR) > 300) {	// podemos dejar un tramo de histéresis entre subida y bajada
				sube();
			}			
			break;
		default: // por descarte, DESCONOCIDO
			if (analogRead(LDR) > 300) 
				sube();
			else
				baja();
	}	
	
	// independientemente de lo que hagamos en el switch actuamos sobre el interruptor
	if (ultimoEstadoPulsador!= digitalRead(PULSADOR)) {
		ultimoEstadoPulsador = !ultimoEstadoPulsador;
		if (ultimoEstadoPulsador) {
			digitalWrite(LED, !digitalRead(LED));
		}
	}
}


void baja() 
{
	digitalWrite(LEDBAJA, HIGH); // iniciamos bajada de persiana
	digitalWrite(LED, HIGH); // encendemos la luz antes de bajar del todo
	estadoPersiana = BAJANDO;
}

void sube()
{
	digitalWrite(LEDSUBE, HIGH); // iniciamos subida de persiana
	estadoPersiana = SUBIENDO;
}

No está totalmente probado, aunque creo que se aproxima a lo que buscas. Lo importante es que seas capaz de comprender el funcionamiento.
Saludos.

Ok. No había entendido entonces tu problema.

Prueba a ver con este otro código como base. He intentado comentarlo profusamente a ver si resulta comprensible el funcionamiento buscado y tal vez falte algún fleco, pero creo que se aproxima.

const int LED = 4; //pin del LED
const int LEDSUBE = 5; //pin del LED motor subiendo
const int LEDBAJA = 6; //pin del LED motor bajando

const int PULSADORLUZ = 7; // pin pulsadorLUZ
const int PULSADORUP = 8; // pin pulsador subida
const int PULSADORDOWN = 9; // pin pulsador bajada

const int FINCARRERAUP = 2; // pin FC subida
const int FINCARRERADOWN = 3; // pin FC bajada

const int LDR = A0; // pin sensor LDR

int ultimoEstadoPulsadorLuz=LOW, ultimoEstadoPulsadorDown=LOW, ultimoEstadoPulsadorUp=LOW;
int nuevoEstadoPulsadorLuz=LOW, nuevoEstadoPulsadorDown=LOW, nuevoEstadoPulsadorUp=LOW;
int estadoFinCarreraUp, estadoFinCarreraDown;
enum {	DIA, NOCHE, DESCONOCIDO} estadoLDR = DESCONOCIDO;

void setup(){
	// Salidas de luz y motores de persiana
	pinMode(LED,OUTPUT); 
	digitalWrite(LED, LOW);
	pinMode(LEDSUBE,OUTPUT);
	pinMode(LEDBAJA,OUTPUT);
	digitalWrite(LEDSUBE, LOW); 
	digitalWrite(LEDBAJA, LOW); 
	
	// Entradas botones manuales de luz y persiana
	pinMode(PULSADORLUZ,INPUT); 
	pinMode(PULSADORUP,INPUT); 
	pinMode(PULSADORDOWN,INPUT);
	
	// Entradas finales de carrera
	pinMode(FINCARRERAUP,INPUT); // y FC subida como señal de entrada
	pinMode(FINCARRERADOWN,INPUT); // y FC bajada como señal de entrada
	Serial.begin(9600);
	
}

void loop() {
	switch(estadoLDR) {
		case DIA:
			if (analogRead(LDR) < 200) {	// si baja la luz
				baja();
				
				estadoLDR = NOCHE;
			}
			break;
		case NOCHE:
			if (analogRead(LDR) > 300) {	// podemos dejar un tramo de histéresis entre subida y bajada
				sube();
				estadoLDR = DIA;
			}			
			break;
		default: // por descarte, DESCONOCIDO
			if (analogRead(LDR) > 300) {
				sube();
				estadoLDR = DIA;
			}
			else {
				baja();
				estadoLDR = NOCHE;
			}
	}	
	
	// LECTURA DE INTERRUPTORES Y FINALES DE CARRERA
	estadoFinCarreraDown=digitalRead(FINCARRERADOWN);
	estadoFinCarreraUp=digitalRead(FINCARRERAUP);
	nuevoEstadoPulsadorLuz = digitalRead(PULSADORLUZ);
	nuevoEstadoPulsadorUp = digitalRead(PULSADORUP);
	nuevoEstadoPulsadorDown = digitalRead(PULSADORDOWN);
	
	
	// Si se detecta final de carrera paramos.
	if (estadoFinCarreraUp) {
		digitalWrite(LEDSUBE, LOW); 
		digitalWrite(LED, LOW); // apagamos la luz al terminar de subir
	}
	if (estadoFinCarreraDown) {
		digitalWrite(LEDBAJA, LOW); 
	}
	
	// independientemente de lo que hagamos en el switch actuamos sobre el cambio en estado interruptor
	if (ultimoEstadoPulsadorLuz != nuevoEstadoPulsadorLuz) {
		ultimoEstadoPulsadorLuz = nuevoEstadoPulsadorLuz;
		// Si el interruptor pasa de OFF a ON, hacemos el switch de la luz
		if (nuevoEstadoPulsadorLuz) {
			digitalWrite(LED, !digitalRead(LED));
		}
	}
	
	// independientemente de la máquina de estados trabajamos los cambios de estado en pulsadores de persiana.
	if (ultimoEstadoPulsadorUp != nuevoEstadoPulsadorUp) {
		ultimoEstadoPulsadorUp = nuevoEstadoPulsadorUp;
		// Si iniciamos pulsación y no es final de carrera, subimos
		if (nuevoEstadoPulsadorUp && !estadoFinCarreraUp) {
			sube();
		} 
		// Al soltar pulsador, para en cualquier punto
		else { 
			digitalWrite(LEDSUBE, LOW); 
		}
	}
	// con el else, evitamos responder a los dos pulsadores (tendría preferencia el up)
	else if (ultimoEstadoPulsadorDown != nuevoEstadoPulsadorDown) {
		ultimoEstadoPulsadorDown = nuevoEstadoPulsadorDown;
		// Si iniciamos pulsación y no es final de carrera, subimos
		if (nuevoEstadoPulsadorDown && !estadoFinCarreraDown) {
			baja();
		} 
		// Al soltar pulsador, para en cualquier punto
		else { 
			digitalWrite(LEDBAJA, LOW); 
		}
	}
}


void baja()
{	
	digitalWrite(LEDSUBE, LOW); // Aseguramos no encender los dos motores simultáneamente
	digitalWrite(LEDBAJA, HIGH); // iniciamos bajada de persiana
	digitalWrite(LED, HIGH); // encendemos la luz antes de bajar del todo
}

void sube()
{
	digitalWrite(LEDBAJA, LOW); // Aseguramos no encender los dos motores simultáneamente
	digitalWrite(LEDSUBE, HIGH); // iniciamos subida de persiana
}

He estado convirtiendo tu codigo a mis conexiones y detecto varias cosas que no funcionan:

1º Al switch LDR entra una vez si hay luz y otra si provocas un cambio, pero no lee constante el valor del LDR por tanto solo se queda con el valor del momento del cambio.

2º El juego de los LEds de persianas lo hace OK si hay luz sube y si no baja pero, los finales de carrera no funcionan, cuando detecta el final de carrera no pasa nada.

3º El manejo de los LED de la persiana de forma manual, me gustaria hacerla solo con un unico pulsador.

¿¿Me podriais ayudar, con el ultimo codigo que puso RodriPelto que era con el que empece a trabajar y el me ayudo a continuar, a meter el pulsador???

ivitito: He estado convirtiendo tu codigo a mis conexiones y detecto varias cosas que no funcionan:

1º Al switch LDR entra una vez si hay luz y otra si provocas un cambio, pero no lee constante el valor del LDR por tanto solo se queda con el valor del momento del cambio.

2º El juego de los LEds de persianas lo hace OK si hay luz sube y si no baja pero, los finales de carrera no funcionan, cuando detecta el final de carrera no pasa nada.

3º El manejo de los LED de la persiana de forma manual, me gustaria hacerla solo con un unico pulsador.

¿¿Me podriais ayudar, con el ultimo codigo que puso RodriPelto que era con el que empece a trabajar y el me ayudo a continuar, a meter el pulsador???

Pues no lo probé profundamente, pero en la simulación que hice, creo que funcionaba bastante bien, aunque quedaba algún pequeño fleco por arreglar. La diferencia con el otro código en el que estáis trabajando, es básicamente que no hay ningún momento de "desatención" en el programa. Es decir, que en mitad de una subida o bajada de persiana los pulsadores manuales pueden interrumpir dicho movimiento, sin esperar a que se complete la subida o bajada en curso.

No obstante, si el código de RodriPelto lo lleváis más maduro, es lógico que continuéis por esa vía, teniendo en cuenta lo que él te ha dicho sobre el planteamiento de un proyecto, porque coincido en que es mejor el planteamiento global que el ir parcheando sobre un planteamiento puntual.