⚡ Descuentos en cursos en video - Lleva tu aprendizaje técnico al siguiente nivel y aprovecha precios especiales antes de que termine la oferta. 🔥 Aprovechar oferta ahora 🔥
Arduino

Timer y mas con ARDUINO

medrub
medrub
2
hace 11 años
hace 11 años
hola, estoy haciendo un control con arduino, para controlar tres salidas con tres pulsadores, dos de los cuales controlan las salidad on/off, osea, cada vez q preciono el pulsador, cambia de estado la salida y la tercer salida es controlada por la accion de un pulsador, que activa un timer (timer 1), que despues de 6 segundo apaga la salida, el problema es q no hace muy bien lo que quiero, sobre todo el timer, ya q el primer pulso es de 1 segundo menos, los demas pulsos si son de 6 segundos, aki dejo el programa que hice #include <avr/io.h> #include <avr/interrupt.h> #include <EEPROM.h> volatile byte segundos; long time = 0; // long debounce = 500; //////////////////////////////RUTINA ON/OFF///////////////////////////////// void antirebote_on_off(int *lect_de_pinE, int *lec_de_pinS, int *pin_salida){ int previous = LOW; if (*lect_de_pinE == HIGH && previous == LOW && millis()+100 - time > debounce) { if (*lec_de_pinS == HIGH) { *lec_de_pinS = LOW; time = millis(); } else { *lec_de_pinS = HIGH; time = millis(); } } digitalWrite(*pin_salida, *lec_de_pinS); previous = *lect_de_pinE; } //////////////////////////////RUTINA TIMER///////////////////////////////// void antirebote_timer(int *lect_de_pinEnt){ int lddpE=*lect_de_pinEnt; if (lddpE == HIGH && millis()+100 - time > debounce) { cli(); TCCR1A=0; TCCR1B=0; TCCR1B |= (1<<WGM12);//resetea el contador a 0 cuando termina la comparacion TCCR1B |= (1<<CS10);//prescaler 1024 TCCR1B |= (1<<CS12);//prescaler 1024 OCR1A=15625; TIMSK1|=(1<<OCIE1A);//habilita la interrupcion por comapracion de igualdad digitalWrite(9, HIGH); sei(); time = millis(); } } //////////////////////////////RUTINA CONTROL DE TIEMPO///////////////////////////////// //////////////////////////////RUTINA DE CONTROL ON/OFF LLENAVASO/////////////////////// void control(int *pin){ int pE=*pin; if (pE == HIGH && millis()+100 - time > debounce) { digitalWrite(13, LOW); time = millis(); } } //////////////////////////////ATENSION DE INTERRUPCION///////////////////////////////// ISR(TIMER1_COMPA_vect){ segundos++; if(segundos==2){ digitalWrite(9, LOW); cli(); TCCR1A=0; TCCR1B=0; segundos=0; cli(); } } ////////////////////////////////////////////////////////////////////////////////////// void setup() { pinMode(11, OUTPUT);//SALIDA DE CONTROL PARA LA BACHA pinMode(5, INPUT); //ENTRADA DE CONTROL DE LA BACHA digitalWrite(11, LOW); pinMode(10, OUTPUT);//SALIDA DE CONTROL DE GIRO Y CONTRAGIRO pinMode(6, INPUT); //ENTRADA DE CONTROL DE GIRO Y CONTRAGIRO digitalWrite(10, LOW); pinMode(9, OUTPUT);//SALIDA DE CONTROL DE LLENAVASO pinMode(8, INPUT);//ENTRADA DE CONTROL DE LLENAVASO digitalWrite(9, LOW); } void loop() { int a=digitalRead(5); int b=digitalRead(11); int c=11; antirebote_on_off(&a, &b, &c);//CONTROL DE BACHA int d=digitalRead(6); int e=digitalRead(10); int f=10; antirebote_on_off(&d, &e, &f);//GIRO Y CONTRA GIRO int g=digitalRead(8); antirebote_timer(&g);//CONTROL DE LLENA VASO if(digitalRead(9)==HIGH){control(&g);} }
erepairman
erepairman
2.423
hace 11 años
hace 11 años
Vamos por partes. Primero que todo tuve que hacer esfuerzo para entender del enunciado la función del circuito. Al leer el código veo un par de errores y tengo varias sugerencias: 1) En "antirebote_on_off" la variable previous siempre se sobreescribe con LOW al empezar la función, así que nunca guarda el valor anterior. 2) No sé qué hace la función control, creo que "activa alguna salida" para mostrar el tiempo que dura encendida la salida 9. Si es así debería simplemente estar en la misma "antirebote_timer" después del digitalWrite(9, HIGH); 3) No sé si ud no se confunde con los nombres de las variables y las funciones, ej. a,b,c.., antirrebotes. Para mí esos nombres no dicen nada acerca de lo que son. Los nombres deben permitir entender el código sin mucho problema. 4) Yo Implementaría primero el "debouncing" por hardware con un capacitor para evitar toda esa complejidad agregada a una simple lectura de pin y cuando ya tuviera todo bien le agregaría el debouncing por software con una función aparte y probada que me permita simplemente escribir "pin8 = leerPin8()" sin tener que confundir el código de debouncing con la lógica del programa en general. Me faltó leer la parte del timer, tal vez más tarde.
erepairman
erepairman
2.423
hace 11 años
hace 11 años
Creo que las fallas se dan porque todas las funciones llamadas "antirrebote..." usan la misma variable time. Además en "antirrebote_timer" falta código para que alterne el estado de la salida 9 de la misma manera que lo hace "antirrebote_on_off" independientemente de que exista el timer. Aquí un pseudo-código de cómo debería funcionar la input 8: En el loop (o si se quiere mejorar después, en un pin que genere interrupción) hacer lo ste: if (switch8_presionado()) // Con una fn que haga el debouncing internamente { // Toggle(9) usando una variable global pin9 inicializada en 0 pin9 = !pin9; digitalWrite(9, pin9); if (pin9) // O sea si es HI { IniciarTimer(); } } La función IniciarTimer() { Con el mínimo código necesario probado que cuente bien } La función ISR() { Se debe limitar a sumar segundos, comparar con los deseados y apagar el pin9 usando la variable pin9 } En general, creo que el código actual tiene todo lo necesario pero está fallando por las variables compartidas como "time" y "previous", y se está complicando su arreglo por la falta de organización: aislar el debouncing para que leer un pin sea algo tan transparente como escribir pin8 = leer_pin(8); Otra cosa más: ¿para qué pasar como referencia las variables a las funciones?
medrub
medrub
2
hace 11 años
hace 11 años
muchisimas gracias, voy a cambiar esto y te aviso. Te comento que es mi primer trabajo en lo que es microcontrolador, yo lo estoy usado en base al poco conocimiento que poseo, ya que en la facu vi y programe el 8051 y en base a eso y lo q voy viendo en internet intente hacer funcionar el proyecto, T comento que lo que estoy programando es para controlar un sillon odontologico, el cual se le daño la placa madre y el rto es muy caro y demora en llega, por eso decidí hacer esto. Con la cual con tras pulsadores controlo un llena vaso, abrir y cerrar el agua de la bacha y cambiar el sentido de giro de un motor
medrub
medrub
2
hace 11 años
hace 11 años
como seria para hacer una rutina para un control on/off, con antirebotes?? yo afuera uso un cd40106 para elimir el rebote por haware.
erepairman
erepairman
2.423
hace 11 años
hace 11 años
Muy interesante el proyecto, me gusta cuando se puede aplicar lo que uno sabe en cosas reales. Por hardware yo he hecho el antirrebote con un simple capacitor. Y por software sí es más o menos como ud lo tiene, sino que hay que evitar el problema por las variables globales. Voy a consultar código y sugiero algo más.
erepairman
erepairman
2.423
hace 11 años
hace 11 años
Aquí el código para leer un botón con debouncing por software: No lo he probado, por favor hacerlo en un programa aparte para confirmar. Está adaptado del código de ejemplo en arduino.cc /* Asumiendo que el input pin del botón es HIGH cuando se presiona Pushbutton de el pin a VCC Resistor 10K de el pin a GND */ long lastDebounceTime = 0; int lastButtonState = LOW; // the previous reading from the input pin int presionadoBoton(int numPin) { int reading = digitalRead(numPin); if (reading != lastButtonState) { // reset the debouncing timer lastDebounceTime = millis(); lastButtonState = reading; } if ((millis() - lastDebounceTime) > 50) { if (reading == HIGH) return 1; } return 0; } La idea es usarlo como: if (presionadoBoton(8)) { Aquí lo que se necesite, como hacer toggle en alguna salida } Se debe tener en cuenta que para usar varios botones hay que tener diferentes variables globales lastDebounceTime y lastButtonState para cada botón. Por otro lado, revisando el código que he trabajado antes, no he hecho debouncing por software sino que he usado el botón en un pin con modo interrupción.
medrub
medrub
2
hace 11 años
hace 11 años
otra consulta, porque pude ser que se ativen solas las salidas? este es el circuito que hice
erepairman
erepairman
2.423
hace 11 años
hace 11 años
Amigo: sin valorar las respuestas uno sólo encuentra el post por casualidad y cree que no se ha avanzado nada más. Por otro lado, ¿cuál es el código actual? ¿está seguro que el debouncing le funciona? ¿los switches conectan a GND? ¿las salidas que dice que se activan solas son todas o sólo las que está usando?
medrub
medrub
2
hace 11 años
hace 11 años
ok, gracias, ahora q m desis de los Transistores, recuerdo, q use dos q tenia y esos funcionan bien, no se activan, el tercero es el q se activa y es el que corresponde al del giro y contra giro, el cual ya tenia el Tr en la placa y use ese, por ahi puede que venga el problema. En relación al soft antirebote sigo con dudas, pero simule el q m mandaste a modo de prueba y por ahi m genera algun rebote, pero ya te digo q solo lo simule en proteus, asi q si tenes algun soft antirebote, te agradeceria si me lo podes compartir y creo q eso seria todo. Dejo para empezar el año y de paso m va a servir para estudiar, el tema de Timer, ya q debo rendir toda la teoria del 8051 de philips, para la facultad. Saludos
erepairman
erepairman
2.423
hace 11 años
hace 11 años
No tengo otro código de "antirrebotes" porque como comenté anteriormente yo lo he hecho por hardware con un capacitor y una resistencia sin integrados, o he usado el pin para el switch en modo interrupción. El código que puse lo hice derivado de http://arduino.cc/en/Tutorial/Debounce, tal vez probando el ejemplo tal cual directamente en el Arduino se pueda encontrar qué falta, puesto que el algoritmo es muy sencillo, simplemente consiste en comparar durante una cantidad predeterminada de ms que el estado del pin se matenga. ¡Saludos! Ha sido un placer poder ayudar en un tema tan interesante
medrub
medrub
2
hace 11 años
hace 11 años
Hola, si los switch se conectan a GND, pero el cd 40106 lo invierte y las entradas del micro se activan por alto. Al codigo por ahora lo utilizo sin el Timer, solo son controles tipo on/off. solo y se activa algunas veces una de ella y por ahi deja de responder, lo apago y enciendo de nuevo al equipo y funciona de nuevo, te adjunto el codigo q uso ahora, hice las variables globales volatiles. Lo del pasaje por referencia lo hice por inercia de programacion, ya que uso mucho el lenguaje C++ y lo uso siempre al pasaje por referencia, vos m decis q no es recomendable en este caso?? [#include <avr/io.h> #include <avr/interrupt.h> volatile byte segundos; volatile long time = 0; // volatile long debounce = 500; //////////////////////////////RUTINA ON/OFF///////////////////////////////// void antirebote_on_off(int *lect_de_pinE, int *lec_de_pinS, int *pin_salida){ int previous = LOW; if (*lect_de_pinE == HIGH && previous == LOW && millis()+100 - time > debounce) { if (*lec_de_pinS == HIGH) { *lec_de_pinS = LOW; time = millis(); } else { *lec_de_pinS = HIGH; time = millis(); } } digitalWrite(*pin_salida, *lec_de_pinS); previous = *lect_de_pinE; } void setup() { pinMode(11, OUTPUT);//SALIDA DE CONTROL PARA LA BACHA pinMode(5, INPUT); //ENTRADA DE CONTROL DE LA BACHA digitalWrite(11, LOW); pinMode(10, OUTPUT);//SALIDA DE CONTROL DE GIRO Y CONTRAGIRO pinMode(6, INPUT); //ENTRADA DE CONTROL DE GIRO Y CONTRAGIRO digitalWrite(10, LOW); pinMode(9, OUTPUT);//SALIDA DE CONTROL DE LLENAVASO pinMode(8, INPUT);//ENTRADA DE CONTROL DE LLENAVASO digitalWrite(9, LOW); } void loop() { int a=digitalRead(5); int b=digitalRead(11); int c=11; antirebote_on_off(&a, &b, &c);//CONTROL DE BACHA int d=digitalRead(6); int e=digitalRead(10); int f=10; antirebote_on_off(&d, &e, &f);//GIRO Y CONTRA GIRO int g=digitalRead(8); int h=digitalRead(9); int i=9; antirebote_on_off(&g, &h, &i);//GIRO Y CONTRA GIRO } ][/code]
erepairman
erepairman
2.423
hace 11 años
hace 11 años
Leí rápidamente el código, no sé si me salté algo, pero no veo ningún error que pueda activar de vez en cuando las salidas, aunque no entendí cuál de las salidas se activa aleatoriamente. Lo de pasar por referencia no tiene problema, es sólo que conceptualmente hablando el uso del paso por referencia es para cuando se quiere cambiar el valor de la variable por fuera o por cuestión de velocidad de ejecución cuando los datos por valor son muy grandes, y en este caso no aplica ninguno de los dos casos. No me gustó ver todavía ese código aparatoso de debouncing y lo inútil de la var previous, aunque sé que está en desarrollo. Finalmente, creería que si se activan las salidas aleatoriamente, lo mejor es probar con leds antes que con los transistores, puede que alguno de los tr esté defectuoso.

¿Conoces una solución?

¡Aprende a reparar con estos cursos YoReparo!

4.73
(22)

Curso Reparación de Fuentes Conmutadas de PC y Equipos Electrónicos

Maximiliano Resch
$ 40 USD
$ 20 USD
4.6
(10)

Curso Localización de Fallas en Refrigeración en Heladeras/Neveras On/Off

Yamil Alarcón
$ 29 USD
$ 12 USD
4.64
(11)

Curso Electrónica para Reparación de Placas

Santiago Cediel
$ 29 USD
$ 11 USD
¿Tienes una mejor respuesta a este tema? ¿Quieres hacerle una pregunta a nuestra comunidad y sus expertos?
Regístrate gratis