Buenas, tengo un problema con la programación de Arduino y no se como solucionarlo. El caso es que tengo que hacer una persiana que sea automática según las variables de la luz y la temperatura interior de la casa. El caso es que he conseguido que funcione como un ciclo, pero el problema esta en que no se como parar el ciclo en un momento y hacerlo continuar si una variable cambia. El código es este:
#include <OneWire.h>
#include <DallasTemperature.h>
#define DIR 2
#define STEP 3
#define MS1 4
#define MS2 5
int sensorLDR;
int temp_sensor = 9;
int dir;
int steps = 400; //numero de vueltas, teniendo en cuenta que 200 es una vuelta
float temperature = 0;
int limit = 26;
OneWire oneWirePin(temp_sensor);
DallasTemperature sensors(&oneWirePin);
void setup () {
Serial.begin(9600);
delay(1000);
Serial.begin(9600);
sensors.begin();
pinMode (DIR, OUTPUT);
pinMode (STEP, OUTPUT);
pinMode (MS1, OUTPUT);
pinMode (MS2, OUTPUT);
digitalWrite (MS1, LOW);
digitalWrite (MS2, LOW);
digitalWrite (DIR, HIGH);
}
void loop ()
{
start:
sensorLDR = analogRead(0);
Serial.print("Valor del sensor LDR: ");
Serial.println(sensorLDR);
if (sensorLDR < 25)
{
{
for (int i=0; i<400; i++)
{
digitalWrite (DIR, HIGH);
digitalWrite (STEP, HIGH);
delay (5);
digitalWrite (STEP, LOW);
delay (5);
steps--; //El motor se encenderia para bajar la persiana
}
if (sensorLDR >= 25)
{
goto start;
}
}
}
else if (sensorLDR >= 25)
{
sensors.requestTemperatures(); //Prepara el sensor para la lectura
temperature = sensors.getTempCByIndex(0);
Serial.print(temperature); //Se lee e imprime la temperatura en grados Celsius
Serial.println(" Grados Centigrados");
if(temperature <= limit)
{
for (int i=0; i<400; i++)
{
digitalWrite (DIR, LOW);
digitalWrite (STEP, HIGH);
delay (5);
digitalWrite (STEP, LOW);
delay (5);
steps--;
}
if ((temperature > limit) or (sensorLDR < 25))
{
goto start;
}
}
else if(temperature > limit)
{
for (int i=0; i<400; i++)
{
digitalWrite (DIR, HIGH);
digitalWrite (STEP, HIGH);
delay (5);
digitalWrite (STEP, LOW);
delay (5);
steps--;
}
if ((temperature <= limit) or (sensorLDR < 25))
{
goto start;
}
}
delay (1000);
}
}
El código se supone que analiza la el resultado de un ldr y cuando este es menor a 25 la persiana debe bajar (porque es de noche) y cuando es superior a 25 entra la variable de la temperatura interior de la casa, en la que si es menor a 26ºC la persiana sube y cuando supera los 26ºC la persiana baja. El caso es que el motor segun las variables si que funciona hacia la direccion correcta, pero no se como lograr que solo haga una secuencia, se espere y solo se active si alguna de las variables cambia, sin repetir todo el ciclo de nuevo.
Si alguien puede respondermelo me haría un gran favor.
Gracias de antemano.
Buenas noches amigo, lo mejor era editar el primer post y colocar el código tal cual lo colocaste en el segundo post y borra el segundo.
Tengo varias dudas:
1.- Porque repites Serial.begin(9600)?
void setup () {
Serial.begin(9600); //Porque declaras 2 veces el Serial.begin(9600) ?????
delay(1000);
Serial.begin(9600); //acá también lo haces...
sensors.begin();
2.- Que funcion tiene steps--; ?
if (sensorLDR < 25)
{
{ // ------------------------> Esta llave esta de mas...
for (int i=0; i<400; i++)
{
digitalWrite (DIR, HIGH);
digitalWrite (STEP, HIGH);
delay (5); //Que buscas con este delay de 5 milisegundos? ??????
digitalWrite (STEP, LOW);
delay (5);
steps--; //no entiendo que hace steps aca....??? Que decrementa? donde usas esta variable?
}
if (sensorLDR >= 25)
{
goto start;
}
}
}
Por lo que veo, el código puede estar mejor estructurado, tu error debe estar en la manera como lo organizaste haciendo de éste un ciclo infinito.
Una pregunta, como opera el motor de la persiana? que alimentas con los pines DIR, STEP, MS1 y MS2 ?
Fijate este otro problema:
steps--; //El motor se encenderia para bajar la persiana
}
if (sensorLDR >= 25) //------------------> SI EL VALOR ES >=25 REGRESAS A START...
{
goto start;
}
}
}
else if (sensorLDR >= 25) //---------------> ACA TAMBIEN VUELVES A COMPARAR... ES UN CHOQUE..
{
sensors.requestTemperatures(); //Prepara el sensor para la lectura
temperature = sensors.getTempCByIndex(0);
Serial.print(temperature); //Se lee e imprime la temperatura en grados Celsius
Serial.println(" Grados Centigrados");
Revisa por favor lo antes mencionado y cualquier duda por aca te apoyaremos.. Saludos
Buenas, antes que nada me gustaría decir que soy nuevo y no he sabido editar mi post. Siento haber causado molestias con ello. A lo de Serial.begin(9600); ha sido un error mio, lo he quitado y funciona exactamente igual. A lo segundo de step--; también los he sacado todos y funciona igual. A lo tercero que has dicho no es un choque, o como mínimo mi intención no era que lo fuera. Lo que quería conseguir con eso es que en el primer if (sensroLDR >= 25) es para que cambie si la variable cambia. Lo que quiero decir es que el motor cuando el sensor capta 25 bajaría la persiana pero si capta más de 25 tiene que volver al principio para ejecutar otra orden, ya que la persiana tiene que subir. El segundo if (sensroLDR >= 25) es para que cuando se inicie el programa de nuevo, si esa variable se cumple, vaya directamente a los resultados de los sensores de temperatura. El motor que uso es bipolar. Con el pin DIR selecciono la direccion, con el STEP los pasos. El MS1 y MS2 los puse por si un caso los necesitaba. El motor esta controlado por un easydriver.
Me gustaría que fuera un ciclo infinito, pero que el del motor fuera finito. Que el motor solo hiciera un número de pasos y esperara a que la variable cambiase. Si la variable no llegara a cambiar el motor no se movería, pero si cambia cualquiera de ellas tendría que regresar al start para poder evaluarla y ejecutar la orden correspondiente a ella.
Gracias por responder tan rápido y ofrecerme el apoyo, me miraré como editar el post. Saludos.
Muy bien, acá te dejo el código modificado, por favor pruebalo y me comentas
#include <OneWire.h>
#include <DallasTemperature.h>
#define DIR 2
#define STEP 3
#define MS1 4 //NO SE PARA QUE LO USAS... NO LE VEO UTILIDAD
#define MS2 5 //A ESTE TAMPOCO
int sensorLDR;
int temp_sensor = 9;
int dir;
int steps = 400; //numero de vueltas, teniendo en cuenta que 200 es una vuelta
float temperature = 0;
int limit = 26;
boolean esta_abajo = true; //este valor lo uso como referencia para indicarle al programa si la persiana esta abajo o esta arriba...!
OneWire oneWirePin(temp_sensor);
DallasTemperature sensors(&oneWirePin);
void setup() {
Serial.begin(9600);
delay(1000);
sensors.begin();
pinMode (DIR, OUTPUT);
pinMode (STEP, OUTPUT);
pinMode (MS1, OUTPUT); //NO SE PARA QUE LO USAS... NO LE VEO UTILIDAD
pinMode (MS2, OUTPUT); //A ESTA TAMPOCO...
digitalWrite (MS1, LOW); //NO SE PARA QUE LO USAS... NO LE VEO UTILIDAD
digitalWrite (MS2, LOW); //A ESTA TAMPOCO LE VEO UTILIDAD
digitalWrite (DIR, HIGH);
}
void loop() {
sensorLDR = analogRead(0);
Serial.print("Valor del sensor LDR: ");
Serial.println(sensorLDR);
if (sensorLDR < 25){ //Si la medicion del sensor es menor a 25 entonces es de noche y bajo persiana llamando a una funcion
bajar();
}else if(sensorLDR >=25){ //si es >=25 entonces es de noche y debo controlar por temperatura con referencia a 26°
if (temperature <= limit){ //si la temperatura es menor a 26° entonces subo la persiana
subir();
}else if(temperature > limit){ //si la temperatura es mayor a 26° entonces bajo la persiana
bajar ();
}
}
}
void bajar(){
if (esta_abajo == false){ //aca pregunto si esta_abajo == false, es decir, que esta arriba, procedo a bajarla con le ciclo for...!
for (int i=0; i<400; i++)
{
digitalWrite (DIR, HIGH);
digitalWrite (STEP, HIGH);
delay (5);
digitalWrite (STEP, LOW);
delay (5);
}
}
}
void subir(){
if (esta_abajo == true){ //si la persiana efectivamente esta abajo
for (int i=0; i<400; i++)
{
digitalWrite (DIR, LOW);
digitalWrite (STEP, HIGH);
delay (5);
digitalWrite (STEP, LOW);
delay (5);
}
}
}
Como resultado al programa que me has mandado lo que sucede es que el motor no deja de dar vueltas hacia una dirección. Por lo que parece no tiene en cuenta la temperatura, porque al calentar el sensor no deja de girar ni cambia la dirección. Cuando tapo la LDR el motor deja de girar, pero no gira hacia el otro lado. La utilidad de las MS1 y MS2 son que cuando las tengo puestas de este modo el motor gira a una velocidad mucho más elevada.
¿Sabrías decirme como puedo hacer una pausa dentro del programa para que analice las variables de nuevo y si han cambiado vuelva a start? ¿Y como paro el ciclo for?
Cierto, discúlpame esa, revisando el código se me olvido manipular el estatus de la persiana, acá te lo dejo arreglado. Debería funcionar:
#include <OneWire.h>
#include <DallasTemperature.h>
#define DIR 2
#define STEP 3
#define MS1 4
#define MS2 5
int sensorLDR;
int temp_sensor = 9;
int dir;
int steps = 400; //numero de vueltas, teniendo en cuenta que 200 es una vuelta
float temperature = 0;
int limit = 26;
boolean esta_abajo = true; //este valor lo uso como referencia para indicarle al programa si la persiana esta abajo o esta arriba...!
OneWire oneWirePin(temp_sensor);
DallasTemperature sensors(&oneWirePin);
void setup() {
Serial.begin(9600);
delay(1000);
sensors.begin();
pinMode (DIR, OUTPUT);
pinMode (STEP, OUTPUT);
pinMode (MS1, OUTPUT); //NO SE PARA QUE LO USAS... NO LE VEO UTILIDAD
pinMode (MS2, OUTPUT); //A ESTA TAMPOCO...
digitalWrite (MS1, LOW); //NO SE PARA QUE LO USAS... NO LE VEO UTILIDAD
digitalWrite (MS2, LOW); //A ESTA TAMPOCO LE VEO UTILIDAD
digitalWrite (DIR, HIGH);
}
void loop() {
sensorLDR = analogRead(0);
Serial.print("Valor del sensor LDR: ");
Serial.println(sensorLDR);
if (sensorLDR < 25){ //Si la medicion del sensor es menor a 25 entonces es de noche y bajo persiana llamando a una funcion
bajar();
}
if(sensorLDR >=25){ //si es >=25 entonces es de noche y debo controlar por temperatura con referencia a 26°
if (temperature <= limit){ //si la temperatura es menor a 26° entonces subo la persiana
subir();
}
if(temperature > limit){ //si la temperatura es mayor a 26° entonces bajo la persiana
bajar ();
}
}
}
void bajar(){
if (esta_abajo == false){ //aca pregunto si esta_abajo == false, es decir, que esta arriba, procedo a bajarla con le ciclo for...!
for (int i=0; i<400; i++)
{
digitalWrite (DIR, HIGH);
digitalWrite (STEP, HIGH);
delay (5);
digitalWrite (STEP, LOW);
delay (5);
}
esta_abajo = true;
}
}
void subir(){
if (esta_abajo == true){ //si la persiana efectivamente esta abajo
for (int i=0; i<400; i++)
{
digitalWrite (DIR, LOW);
digitalWrite (STEP, HIGH);
delay (5);
digitalWrite (STEP, LOW);
delay (5);
}
esta_abajo = false;
}
}
Esta perfecto! Muchísimas gracias! Esta justo como quería que estuviera. Por cierto, me puedes dar alguna recomendación para aprender más sobre la programación de arduino? Este es mi primer proyecto e iba un poco (por no decir muy) perdido. Llevaba semanas con este proyecto, empece des de cero, pero tu me lo has solucionado muy rápido. Te agradeceria mucho que me dijeras donde puedo aprender más sobre ello.
La plataforma arduino es muy versatil y facil de programar. Te recomiendo aca mismo en el foro este link donde podras encontrar varios tutoriales, igualmente en youtube podras encontrar videotutoriales y el mismo programa de arduino trae muchos ejemplos para que puedas estudiar.
Acá el link:
Tutoriales de Arduino
Muchísimas gracias por todo. Cierro el tema.