no tengo experiencia con temas de micro controladores admega328p y arduino , tengo un conflicto al utilizar una biblioteca o librera stepper al usar una interrupción externa por un sensor de impacto sencillo de placa metálicas y un contrapeso, su función detener un conteo de 40 segundos durante ese tiempo la compuerta se mantiene abierta ,si es impactada por movimiento ,golpe etc la interrupción externa debe detener el conteo de 40 segundos y regresar la compuerta de cierre de emergencia a su punto de cierre y activar indicador luminoso y sonoro
el conflicto se presenta al activar la interrupción externa el motor no se mueve que da consumiendo corriente y el código se bloquea y no responde
la funciones de abrir y cerrar funcionan bien
código dela compuerta
int abrir = 6; //pin 6 del puerto D como entrada
int cerrar = 7; //pin 7 del puerto D como entrada
int apertura ; //variable del tipo entero para apertura
int cierre ; //variable del tipo entero para cierre
int impacto = 2; // pin 2 del puerto D como entrada
#include <Stepper.h> //Importamos la librería para controlar motores paso a paso
// Ponemos nombre al motor, el número de pasos y los pins de control
Stepper M1(200, 8, 9, 10, 11);
////funcion apagar todas las bobinas
void apagado() // Apaga bobinados del motor
{
digitalWrite (8, LOW);
digitalWrite (9, LOW);
digitalWrite (10, LOW);
digitalWrite (11, LOW);
}
void setup()
{
Serial.begin(9600);
pinMode(abrir, INPUT); //pin 7 declarado como entrada
pinMode(cerrar, INPUT);//pin 6 declarado como entrada
pinMode(impacto, INPUT);//pin 2 pueto D como entrada sensor de impacto censillo
attachInterrupt(digitalPinToInterrupt(impacto), c_emergencia, FALLING); //interrupcion externa por impacto o movimiento para cierre
// Velocidad del motor en RPM
M1.setSpeed(120);
M1.step(120);
delay(500);
apagado();//funcion apagar todas las bobinas
}
void loop()
{
apertura = digitalRead (abrir);
if (apertura == LOW)//pregunta si el pin6 por D tiene un pulso bajo 0V
{
M1.step(-120); //movimiento del motor para abrir la compuerta
apagado();//funcion apagar todas las bobinas
delay(40000);//tiempo que debe permanecer abierta la compuerta
M1.step(120); //cierra la compuerta
apagado();
}
cierre = digitalRead(cerrar);
if (cierre == LOW)//pregunta si el pin7 por D tiene un pulso bajo 0V
{
M1.step(120);//movimiento del motor para cerrar la compuerta
apagado();//funcion apagar todas las bobinas
}
}
void c_emergencia()//interrupion externa pin 2 por D para cerrado de mergencia de la compuerta
{
M1.step(120);//ocaciona el conflicto al resibir la interrupcion externa del pin2 por D
apagado();//funcion apagar todas las bobinas
}
encontré lo que podría ser posiblemente una solución en el código, respondió ala interrupción sin bloquearse,
me quedo un un tiempo de unos 37 segundos variando a cual no responde el código después de cerrar la compuerta por impacto o movimiento ,acción echa por el sensor de impacto no e podido encontrar el porque se demora esos 37 segundos aproximadamente varia
esto fue la modificación que le ice al entrar ala interrupción.
quiero aclarar algo que se me olvido en el momento de la publicación.
al dársele la orden ala compuerta para que habrá se inicia un delay de 40 segundos en el momento de la interrupción por impacto o movimiento interrumpe el conteo cierra la compuerta , regresa al código y continua contando la variación de pende del instante de la interrupción que lleve contando delos 40 segundos
void c_emergencia1()//interrupion externa pin 2 por D para cerrado de mergencia de la compuerta
{
sei(); // activa las interrupciones
M1.step(120);//cierra la compuerta interrupción externa del pin2 por D
apagado();//función apagar todas las bobinas
cli(); // desactiva las interrupciones globales
}
El problema de fondo es que utilizas delay() para controlar el tiempo que la compuerta debe estar abierta (40 segundos). Recuerda que delay() bloquea la ejecución de todo lo demás. Es una función muy útil, pero no es para esto.
En tu programa le estás dando la vuelta a ese bloqueo haciendo el trabajo de mover la compuerta dentro de la rutina de interrupción, y este no es el uso adecuado de las interrupciones.
Una rutina de interrupción debe tener una ejecución sumamente breve, y usualmente se usa para cambiar los valores de unas cuantas variables.
Por ejemplo, la interrupción puede modificar una bandera que indique que la compuerta debe cerrarse de emergencia. Esto se detecta en el loop(), que se ejecuta con gran rapidez cuando no usamos delay().
Lo que te conviene hacer aquí es usar millis() para controlar el tiempo de apertura, y estar monitoreando la bandera para activar de inmediato el cierre de la compuerta.
Para empezar, ayúdanos a sacar adelante tu proyecto publicando un diagrama de las conexiones que tienes, para no estar haciendo suposiciones que luego no eran correctas. Puedes hacer un dibujo a mano y publicar una foto.
Y échale un vistazo al ejemplo de "BlinkWithoutDelay" para familiarizarte con el uso de millis() como temporizador de eventos.
dado al pedido de mancera1979 de que le subiera una imagen de las conexiones, monte todo en proteus anexo la simulación, el código actual el hex para la simulación.
el simulador no hace girar el motor bien, en el circuito físico el motor gira bien Compuerta.zip (308,0 KB)
la imagen no se como colocarla en el foro, le pido a un moderador en caso que la imagen quede mal si me puede ayudar a corregirla
A ver si este código funciona. He eliminado todos los llamados a delay() salvo el del setup que no afecta.
int abrir = 6; // pin 6 del puerto D como entrada
int cerrar = 7; // pin 7 del puerto D como entrada
int impacto = 2; // pin 2 del puerto D como entrada
#include <Stepper.h> // Importamos la librería para controlar motores paso a paso
// Ponemos nombre al motor, el número de pasos y los pins de control
Stepper M1(200, 8, 9, 10, 11);
volatile bool emergencia = false; // Variable de bandera para la interrupción
// Función apagar todas las bobinas
void apagado() {
digitalWrite(8, LOW);
digitalWrite(9, LOW);
digitalWrite(10, LOW);
digitalWrite(11, LOW);
}
void setup() {
Serial.begin(9600);
pinMode(abrir, INPUT); // Pin 7 declarado como entrada
pinMode(cerrar, INPUT); // Pin 6 declarado como entrada
pinMode(impacto, INPUT); // Pin 2 puerto D como entrada sensor de impacto sencillo
attachInterrupt(digitalPinToInterrupt(impacto), c_emergencia, FALLING); // Interrupción externa por impacto o movimiento para cierre
// Velocidad del motor en RPM
M1.setSpeed(120);
M1.step(120);
delay(500);
apagado(); // Función apagar todas las bobinas
}
void loop() {
static unsigned long startMillis = 0;
static bool contando = false;
if (emergencia) {
M1.step(120); // Mover motor para cerrar la compuerta
apagado(); // apagar todas las bobinas
emergencia = false; // Resetear la bandera de emergencia
}
int apertura = digitalRead(abrir);
if (apertura == LOW && !contando) { // Pregunta si el pin6 por D tiene un pulso bajo 0V
M1.step(-120); // Movimiento del motor para abrir la compuerta
apagado(); // Función apagar todas las bobinas
startMillis = millis(); // Guardar el tiempo de inicio
contando = true; // Empezar el conteo
}
if (contando && (millis() - startMillis >= 40000)) { // Si han pasado 40 segundos
M1.step(120); // Cierra la compuerta
apagado(); // Función apagar todas las bobinas
contando = false; // Resetear el conteo
}
int cierre = digitalRead(cerrar);
if (cierre == LOW) { // Pregunta si el pin7 por D tiene un pulso bajo 0V
M1.step(120); // Movimiento del motor para cerrar la compuerta
apagado(); // Función apagar todas las bobinas
}
}
void c_emergencia() { // Interrupción externa pin 2 por D para cierre de emergencia de la compuerta
emergencia = true; // Establecer la bandera de emergencia
}
Observa que la rutina de interrupción ahora solo maneja un flag y ese flag corre y activa o no lo que deba en el loop(). La rutina de interrupción entonces trabaja como debe ser, rápida y veloz.
Si hay emergencia o sea si se pone en HIGH (activada la interrupción)
se ejecuta en el loop esto
if (emergencia) {
M1.step(120); // Mover motor para cerrar la compuerta
apagado(); // apagar todas las bobinas
emergencia = false; // Resetear la bandera de emergencia
}
cerramos compuerta, apagamos motor y ponemos en false el flag de nuevo. Listo.
Si hay apertura, entonces activamos contando, disparamos millis() a través de startMillis (la diferencia es la cuenta en segundos transcurridos) y al final lo mismo..cerramos puerta y apagamos motor.
Gracias por tomarse el tiempo y con la colaboración.
copie el código que subió lo cargue al arduino , a ensayarlo al accionar cierre de emergencia sigue corriendo el tiempo restante delos 40 segundos antes de dejar hacer otra función.
se podrá detener el conteo de los 40 segundos al accionar cierre de emergencia para que el código siga avanzando después del cierre de emergencia.
otra de talle del código una ves que se accione el cierre de emergencia se tiene que acciona un modulo de doble rele se acciona con 0V (LOW) ,utilizo los pines 12 y 13 para accionar los reles uno para buzzer y el otro para foco o bombillo (con fin de indicador luminoso y audible)
podría hacerme el favor de colaborarme con esas modificaciones
Gracias con la modificación que colocaste ,al recibir el impacto o movimiento cierra la compuerta, borra el conteo y el código sigue respondiendo sin de mora alguna
Dado a que no me explique bien al colocarlo en el primer if por lo novato que soy no me percate en el momento, el conteo de la compuerta de 40 segundos se suspendió, asiendo prueba y error termine colocándolo en el ultimo if.
void c_emergencia() // Interrupción externa pin 2 por D para cierre de emergencia de la compuerta
{
emergencia = true; // Establecer la bandera de emergencia
contando = false; // Resetear el conteo
Serial.println("cierre de emergencia");
}
funciona todo gracias
ahora sigo con el modulo doble de rele
Moderador:
Por favor, lee las Normas del foro y edita tu código/error usando etiquetas de código.
Ve a edición, luego selecciona todo el código que has publicado, lo cortas y click en (<CODE/>)
lo busque el código que mencionas, ese código le había como 3 veces al botón code .
lo que note es que escribí if para hacer referencia, será ese mensaje que esta dando dificultades, lo edite borre todo lo que había colocado el botón code lo seleccione todo y le di al botón code de nuevo y le dio formato a todo lo que escribí , toca hacer con todo lo mismo creía que solo tenia que seleccionar el código y darle al botón de code
Hoy se concluyo el proyecto de la compuerta quería subir un video del funcionamiento, el servidor no lo permitió por el tamaño de 17mb solo permitía 8mb.
Les agradezco a todos los que me colaboraron que comparten sus conocimientos ,con los que apenas estamos profundizando con el micro controlador Admega328p y la tarjeta de desarrollo Arduino .
Gracias a todos