Hola y gracias por leerme.
Desde hace algunos días voy de cabeza con un problema:
Tengo una ESP32 que maneja un trenecito de lego, y como quiero que pare en la estación, uso un contacto eléctrico en esta (Se que hay otras opciones pero por un tema del proyecto estoy obligado a usar esta...)
El problema es que cuando el tren detecta esto, se reinicia la placa (por lo que entiendo que el problema esta en el hardware) y no se me ocurre lo mas mínimo del porque. Dejo por aquí el esquema del tren y toda la información, así como el código.
(El transistor es el 2N3904, no hacer caso al de este esquema)
#define vel 60 // Valor fijo de velocidad para pruebas
#define PWM_CH 0 // Canal PWM que vamos a controlar
#define PWM_Hz 1000 // Hz para el PWM
#define PWM_Res 8 // Resolucion en bits del canal, max 16, usamos 8 que es e 0 a 255
#define MotorDirA_pin 15 // Pin del input 1 para la direccion del motor
#define MotorDirB_pin 2 // Pin del input 1 para la direccion del motor
#define StationPin 13 // Pin de interrupcion para el paso por estacion
TaskHandle_t Task1;
volatile boolean stationVar=0;
void PWM_SET(uint8_t dir);
void setup() {
pinMode(MotorDirA_pin, OUTPUT); // Se declaran como salidas los pines que se usaran en el PWM
pinMode(MotorDirB_pin, OUTPUT);
// Configuraos las propiedades del PWM
ledcSetup(PWM_CH, PWM_Hz, PWM_Res);
ledcAttachPin(MotorDirA_pin, PWM_CH); // Asignamos el pin al canal
ledcAttachPin(MotorDirB_pin, PWM_CH); // Asignamos el pin al canal
Serial.begin(115200); // Inicializacion del serial
pinMode(StationPin, INPUT);
xTaskCreatePinnedToCore(
Task1code, /* Task function. */
"Task1", /* name of task. */
10000, /* Stack size of task */
NULL, /* parameter of the task */
1, /* priority of the task */
&Task1, /* Task handle to keep track of created task */
0); /* pin task to core 0 */
delay(500);
}
void Task1code( void * parameter) {
Serial.print("Task2 running on core ");
Serial.println(xPortGetCoreID()); // informa de en que nucleo corre el programa
for(;;) {
if(digitalRead(StationPin)==LOW && !stationVar) { // Lee continuamente el in (Las interupciones dan problemas)
stationVar=true; // Pone a true una variable booleana para pocesar mas tarde la informacion
Serial.println("Estacion activada"); // Informa via serial
}
delay(50);
}
}
void loop() {
static int dir=0;
PWM_SET(dir); // Pone en marcha el tren
if (stationVar) { // Si pasa por la estacion
PWM_SET(2); // Para el tren
delay(5000); // Espera 5 segundos
if (dir==1) dir=0; // Cambia la direccion a izquierda si estaba en derecha
else dir=1; // Cambia la direccion a derecha si estaba en izquierda
stationVar=false; // Se prepara para la siguiente ronda
}
}
void PWM_SET(uint8_t dir) {
if (dir==0) { // Derecha
ledcAttachPin(MotorDirA_pin, PWM_CH); // Asignamos el pin al canal
ledcDetachPin(MotorDirB_pin); // Desasignamos el pin al canal
digitalWrite(MotorDirB_pin, LOW);
ledcWrite(PWM_CH, map(vel*2.55,0,255,110,255));
}
else if (dir==1) { // Izquierda
ledcAttachPin(MotorDirB_pin, PWM_CH); // Asignamos el pin al canal
ledcDetachPin(MotorDirA_pin); // Desasignamos el pin al canal
digitalWrite(MotorDirA_pin, LOW);
ledcWrite(PWM_CH, map(vel*2.55,0,255,110,255));
}
// Cambiamos la velocidad, si la direccion es !=0 o !=1 solo variara la velocidad
Serial.println("Encendiendo PWM");
if (dir==2) { // Parar
ledcDetachPin(MotorDirA_pin); // Asignamos el pin al canal
ledcDetachPin(MotorDirB_pin); // Desasignamos el pin al canal
digitalWrite(MotorDirA_pin, LOW);
digitalWrite(MotorDirB_pin, LOW);
}
}
Hi,
Es posible que cuando energizas el motor este genera ruidos y este ruido causa el esp32 que se re-inialize. No dices que voltaje y corriente usa el motor. Si el motor tiene escobillas entonces instalale un condensador the .1 nf en paralelo a los terminales del motor. Tu estas usando bateria o estas usando otra fuente para suplir el voltaje .
El contacto electrico es un contacto seco? Es decir, no tiene vinculación con nada, un limite de carrera digamos?
Si es asi para que usas el BC337 o 2N3904 decidete cual es el que usas.
El contacto puede ir solo entre GPIO13 y GND. Solo!! insisto.
Ahh sin palabras!!!!!!!!
xTaskCreatePinnedToCore(
Task1code, /* Task function. */
"Task1", /* name of task. */
10000, /* Stack size of task */
NULL, /* parameter of the task */
1, /* priority of the task */
&Task1, /* Task handle to keep track of created task */
0); /* pin task to core 0 */
delay(500);
}
un delay en una tarea a realizar que seguramente tiene que ver con la interrupción que no se para qué usas.
Saca ese delay() por favor, se esta reiniciando por watch dog.
En condiciones normales te diría no uses delay() pero nunca delay() o serial.print o lcd.print en una interrupción.
Hola, gracias por tu respuesta, en cuanto al motor desafortunadamente no tengo mucha información ya que es el que viene de serie con el tren, va montado en las ruedas a si que solo he cogido los contactos eléctricos, como se indica en el esquema tiene un buck converter a 9V, aunque por lo general trabaja en el rango de 0-5V. En cuanto a la corriente, no consume mas de 500mA por lo que he podido comprobar. Si tiene escobillas o no, lo desconozco por completo.
No obstante, por lo que dices creo que se me ha entendido mal, el problema no sucede al encender el motor ni apagarlo, el motor puede estar dando vueltas indefinidamente, pero cuando hace contacto eléctrico el sistema de detección de la vía, entonces es cuando se reinicia, aunque esto si que causa que el motor se apague (Por que se reinicia la placa)
En cuanto a la alimentación, como se puede ver en el esquema uso una batería , esta es de 2300mAh a 11.1V, dejo aquí el enlace:
En cualquier caso, voy a tratar de poner un optoacoplador y reducir los ruidos al máximo a ver.
El código no lo has subido completo porque la libreria que maneja TaskHandle no esta indicada.
Tal vez estaba al comienzo y no la incluiste en tu copy & paste.
Hola, muchas gracias por tu respuesta, voy a tratar de responderte lo mejor que pueda.
Si, es un contacto seco, tal como puedes ver en las imágenes son los dos contactos de cobre con cables cuando pasa por encima de el cobre que esta puesto en las vías, similar a un final de carrera. Soy consciente de lo cutre que es esto, pero como he dicho, es así por obligación
El transistor es el 2N3904, disculpa, el programa que use para diseñar el esquema puso un nombre y no me di ni cuenta, he editado la pregunta para especificar esto.
No entiendo a que te refieres exactamente con ir solo entre el GPIO 13 y GND, si te refieres a usar un INPUT_PULLUP y que el contacto eléctrico vaya literalmente del GPIO 13 a GND, lo tenia asi antes de montar el transistor y daba mas problemas si cabe.
En el código que mencionas el delay(500); no esta dentro de la interrupción, esta justo al final del void setup(), sin embargo si tengo un delay(50); dentro de la subrutina, aun asi, aunque el task es una interrupción, este esta corriendo en el segundo núcleo (El main corre en el 1 y este en el 0)
No se esta reiniciando por watch dog, Esto es un bucle infinito por lo que si fuese una interrupción normal, hasta donde yo se, también seria un problema, y eso no lo es, ya que se reinicia al hacer el contacto, independientemente del tiempo que haya pasado desde que el motor comenzó a moverse.
Puedes verificar que un código con delay() y Serial.print en esas subrutinas funciona viendo este video: ESP32 Dual Core Programming | ESP 32 Multitasking - YouTube
Además cuando reinicia por watch dog puedes ver en el serial un aviso sobre esto, adjunto aquí una imagen de este inicio:
Aunque no se puede ver muy bien (Disculpa la mala calidad) se puede observar que justo antes de la fecha, el dato es un 9, un dato que imprime mi programa (por un contador que estaba antes), es decir, es de antes de reiniciarse.
De nuevo, gracias por tu interés en este tema
Que yo sepa no hay ninguna librería para usar esta función en el ESP32, me base en el codigo del video que te he dejado en la respuesta anterior, donde puedes observar que no hay ninguna librería, en cualquier caso, te dejo ese mismo código aquí:
Si es un contacto como el de un fin de carrera pues lo conectas directamente un terminal a GND y el otro al GPIO y listo.
Defines el GPIO como entrada INPUT_PULLUP y si tiene rebotes le agregas alguna rutina antirebotes. Algo que no contemplaste.
Sin delay() sin nada por el estilo.
Sin transitores y todo lo que has puesto que esta de mas.
Super error mio, disculpas. Pense que era el responsable en la tarea Task1.
Okay, vamos por otro lado.
Mira esto, sugiere borrar la flash del ESP32, a ver si tiene que ver con tu problema
Hi,
Tu mencionas que cuando actua el switcher es que ocure el problema si yo lo entiendo bien. Cuando te da ese mansaje quire decir que hubo un problema en la programacio y hace lo que llama "dump" que si sabes leerlo explica que paso en el en la programacion.. Yo tuve ese problema una vez pero no acuerdo como lo resolvi. Ahora tu tienes ese switch alambrado corectamente? Aparentemente parece como que tu esta llevando el voltaje del micro a ground. Por eso es posiblemente se esta reinicializando.
Ajunto link que explica que pudo causar ese dump:
Preguntonta:
¿La variable vel dónde está definida?
No la encuentro como local en PWM_SET() ni como global.
ledcWrite(PWM_CH, map(vel*2.55,0,255,110,255)); }
Agrego:
Declaré vel como local, le asigné un valor, conecté un pulsador entre pin 13 y masa para simular el contacto y el código corre.
No se si hace exactamente lo que debe pero corre sin bloquearse.
Hola Surbyte
Ahora entiendo un poco mejor lo que dices, pero como había mencionado, ya había probado a conectar el GND al switch y de ahí al GPIO 13 con el INPUT_PULLUP, de hecho, fue lo primero que hice, y esto me producía este mismo problema, fue al poner el transistor que dejo de dar dicho problema por algún tiempo, pero ha vuelto a aparecer. En cuanto a los rebotes, no son un problema, ya que cuando funcionaba, leía sin problemas.
En cuanto al enlace que has mandado, parece muy interesante, pero no podre probarlo hasta mañana, ya que por trabajo no estoy en la ubicación.
Hola tauro0221
Hasta donde yo se, el mensaje que se muestra es normal, pues este lo muestran todas las placas ESP32 que he usado, al encenderse o al pulsar el botón de reset, además, siguiendo el enlace que has mandado, el mensaje parece distinto del que mencionas.
Hola gatul y gracias por responder.
La variable vel, es una constante definida arriba del programa, indica una velocidad de 0-100 para poder hacer pruebas y demás, como esta arriba del todo, no la copie, disculpa. (Ya esta corregido)
EL PWM_SET() es una función que esta definida mas abajo, el IDE de Arduino te permite usarla aun sin definirla antes, por eso te dará el error, ya he corregido en el código eso, he probado en la simulación y efectivamente funciona sin problemas.
En cuanto a la simulación que mencionas, estoy de acuerdo con que todo esta bien, pero yo tengo la sospecha que el hecho de usar los contactos de forma tan pobre como la que tengo es lo que causa los problemas.
Hi,
Si esos coorecto pero una vez que este corriendo la programacion no es correcto. Algo pasa cuando esta corriendo la programacion que causa este "DUMB". Es mi opinion.
Si pero apenas serían 3mA de consumo, no creo que sea tan sensible (no se podría ni encender un LED si así fuera) pero si acaso fuese el caso los capacitores deberían amortiguar cualquier rizado, incluso los que pudieran provocar los servos.