Muy bien, he aprendido todos los fundamentos del AVR y ahora estoy pensando en construir un reloj como proyecto. Usaré el ATMega328P junto con el RTC DS1307. La hora se mostrará en una pantalla LCD u OLED. Lo que quiero saber es cómo será la estructura general del programa. Sé que habrá dos modos; uno para ajustar la hora y otro en el que el reloj funciona normalmente. Necesito algo de ayuda en cuanto a cómo voy a implementar estos modos y dos cambiar entre ellos usando botones externos. Sería estupendo si alguien pudiera arrojar luz sobre esto. Gracias.
Respuestas
¿Demasiados anuncios?Cuando trabajes con modos y estados, te aconsejo encarecidamente que utilices bucles while.
Así que un comienzo sería algo así:
#define up_button 0
#define down_button 1
#define set_button 2
#define leave_set_button 3
main_loop(){
read_RTC_clock();
//Through spi or i2c or what have you
write_RTC_clock_to_display();
//To the LCD or OLED display
read_button_states();
//Update the input_port variable
if(input_port&set_time_button){
while(!input_port&leave_set_button){//"and" out the leave button
//If you are in this loop, then you will stay in here
//until the user chooses to leave.
//so we better make it possible for the user to leave by
//reading the inputs and updating the button status
read_button_states();
//Update the input_port variable
switch(input_port){
case up_button|down_button:
//up_button|down_button means that
// I press both simultaneously
increment_step = 60/increment_step;
//if increment_step is 60, then it's now 1 second
//if increment_step is 1, then it's now 60 seconds
break;
case up_button: time+=increment_step; break;
case down_button: time-=increment_step; break;
}
//and why not show the LED or OLED what we're doing
write_settings_to_display();
}
write_time_to_RTC_clock();//update the RTC with the time we set
}
}
No voy a escribir más... pero... así es como yo empezaría el proyecto. También desbarataría los botones en el software. También me preguntaría cuántos botones quiero realmente, cuantos más botones más fácil es su uso. Podria funcionar con solo 2 botones, pero entonces tendrias que usar un poco de tiempo para que si mantienes un boton presionado por 1 segundo signifique algo diferente que si solo lo tocas por 10 milisegundos.
¿Orientación? Claro... no lo lleves a la escuela.
En serio, si usted está usando el RTC esto es bastante simple, ya que usted no tiene que preocuparse de mantener el tiempo. La visualización de la hora podría ser sólo un bucle de conveniencia que consulta el RTC y luego actualiza la pantalla. Parece que tu pantalla también está orientada a los comandos en lugar de algo que necesitarías multiplexar explícitamente como un LED de 4 dígitos y 7 segmentos.
En cuanto al ajuste del reloj, un enfoque sería considerar el concepto de Máquina de Estado Finito .
Sin embargo, en el nivel más simple, podría tener una lógica que compruebe si se pulsa un solo botón de "ajuste". Si es así, el tiempo se adelanta en alguna unidad de tiempo más rápida que la real y se muestra, se espera un retraso de algún trozo de segundo y luego se repite el ciclo.
Ese retardo tendrá la ventaja tanto de marcar el ritmo para el usuario, como de resolver el contact bounce
problema simplemente ignorando el botón durante un rato después de cada vez que concluya que está (todavía) pulsado.
Un diseño más refinado podría ofrecer un botón rápido y otro lento. O se podría construir un botón de aceleración en el que el retardo comience siendo largo y se reduzca al mínimo cuanto más tiempo se mantenga pulsado el botón.
En un extremo, podría proporcionar botones individuales para subir y bajar las horas y los minutos, o incluso para cada dígito de cada uno.
O puedes construir un esquema más orientado al estado, donde tienes un botón de selección de dígitos que cambia los dígitos que parpadean, y un botón de incremento que aumenta el dígito seleccionado.
Un proyecto más avanzado sería hacer todo esto con el MCU y sus temporizadores en chip, sin el chip RTC. Potencialmente, incluso se podría hacer desde el oscilador de baja velocidad que funciona con un cristal de reloj.