PDA

Ver la versión completa : C Quiero dejar de usar delay en Arduino



Kabanya
21/11/2021, 12:23
Tengo que hacer un código para que se escuche un morse por el buzzer en Arduino, y que al pulsar un botón cambie a otro morse distinto, prácticamente todo lo que veo sobre morse usa la función delay, claro con eso cuando pulso el botón pasa de mí mientras está el delay activo, he visto que la alternativa (y la forma de hacerlo en condiciones) es usar la función millis, pero me lío muchísimo.

Si alguien se maneja bien a ver si puede echarme una mano, paso un ejemplo del código.
const int buzzerPin = 12; //pin de salida del tono de audio
const int dotlength = 150; //longitud de un punto en milisegundos
const int dashlength = dotlength*3; //longitud de una raya en milisegundos
const int inter = dotlength; //longitud de espaciado entre carácteres
const int pulsadorpin = 2;
int pulsador = 1;
int opcion = 0;
int freq;

void setup()
{
pinMode(12, OUTPUT);
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
Serial.begin(9600);
}

void loop()
{
estado_pulsador();
if (opcion%2==0) prueba();
if (opcion%2!=0) prueba2();
}


void dot(int freq)
{
tone(buzzerPin, freq);
delay(dotlength);
noTone(buzzerPin);
delay(inter);
}

void dash(int freq)
{
tone(buzzerPin, freq);
delay(dotlength*3);
noTone(buzzerPin);
delay(inter);
}

void prueba()
{
I(150);L(150);E(150);Z(150);L(150);final();
}

void prueba2()
{
I(90);L(90);E(90);Z(90);L(90);final();
}

void estado_pulsador()
{
pulsador = digitalRead(2);
if (pulsador==0) opcion = opcion+1;
}

void I(int freq)
{
dot(freq);
dot(freq);
}

void L(int freq)
{
dot(freq);dash(freq);dot(freq);dot(freq);
}

void E(int freq)
{
dot(freq);
}

void Z(int freq)
{
dash(freq);dash(freq);dot(freq);dot(freq);
}

void final()
{
delay(dashlength*3);
}

Mis dotes de programación son menos que mínimos y de hace veinte años, no me echéis las manos al cuello xD

swapd0
21/11/2021, 14:20
Pero solo lees el estado del pulsador en la función estado_pulsador, aunque cambies la función delay hasta que no salga de prueba o prueba2 y pase otra vez por esa función no vas a leer nada.

Kabanya
21/11/2021, 20:50
La leo en Loop, aunque lea el estado en otros sitios, nunca leerá nada mientras esté en modo delay, que es bastante tiempo.

swapd0
21/11/2021, 22:07
ok, lo suyo es que cambies la función Delay por algo así


void wait(uint32_t time)
{
// leo el tiempo actual
uint32_t now = mills();
// mientras no haya pasado mas de time y no hayas pulsado nada sigo esperando
// estado_pulsador deberá devolver 0 si no se ha pulsado nada y cualquier otra cosa cuando se pulse el boton
// de esta forma se cancelara la espera pero se seguirá por los siguientes sonidos, si los quieres cancelar
// esta función puede devolver 0 si se termina la espera y 1 si se cancela.
while ( mills() - now < time && !estado_pulsador())
;
}

Kabanya
19/12/2021, 13:48
Entre una y otra cosa no te di las gracias, usé tu función, substituyendo el delay por una llamada a la función y especificando el tiempo en milisegundos, el programa fue perfecto.
Muchas gracias :)