Tabla de contenido:

Reloj digital en Arduino usando una máquina de estado finito: 6 pasos
Reloj digital en Arduino usando una máquina de estado finito: 6 pasos

Video: Reloj digital en Arduino usando una máquina de estado finito: 6 pasos

Video: Reloj digital en Arduino usando una máquina de estado finito: 6 pasos
Video: Ejercicio sencillo de una secuencia usando Modelo Moore y Mealy 2024, Noviembre
Anonim
Reloj digital en Arduino usando una máquina de estado finito
Reloj digital en Arduino usando una máquina de estado finito

Hola, voy a mostrarles cómo se puede crear un reloj digital con YAKINDU Statechart Tools y ejecutarlo en un Arduino, que usa un protector de teclado LCD.

El modelo original del reloj digital fue tomado de David Harel. Ha publicado un artículo sobre la

"[…] Amplia extensión del formalismo convencional de máquinas de estados y diagramas de estados".

En este artículo, utilizó el ejemplo del reloj digital para su investigación. Lo usé como inspiración y reconstruí el reloj con YAKINDU Statechart Tools (una herramienta para crear modelos gráficos de máquinas de estado y generar código C / C ++ con él) y lo devolví a la vida en un Arduino.

Suministros

Hardware:

  • Arduino Uno o Mega
  • Escudo del teclado LCD

Software:

  • Herramientas de gráficos de estado de YAKINDU
  • Eclipse C ++ IDE para Arduino

Paso 1: Cómo funciona el reloj digital

Image
Image

Comencemos por definir cómo debería funcionar el reloj digital. ¿Recuerdas estos … digamos … relojes digitales "ultra geniales" que todos tenían en los años 90? Un cronómetro integrado, diferentes alarmas y su molesto pitido cada hora. Si no es así, eche un vistazo: reloj digital de los 90.

Entonces, básicamente, es un reloj configurable con diferentes modos. Principalmente, se mostrará la hora actual, pero hay algunas otras características. Como entrada, tiene un botón de encendido / apagado, un modo y un botón de configuración. Además, puede encender y apagar la luz. Con el botón de modo puede distinguir entre los modos y activar / desactivar las funciones del reloj:

  • Mostrar la hora (reloj)
  • Mostrar la fecha (fecha)
  • Configurar la alarma (Alarma 1, Alarma 2)
  • Activar / desactivar timbre (Establecer timbre)
  • Utilice el cronómetro (cronómetro)

Dentro de los menús, puede utilizar el botón de encendido / apagado para configurar el modo. El botón de configuración le permite configurar la hora, p. Ej. para el reloj o las alarmas. El cronómetro se puede controlar, iniciar y detener, utilizando el botón de encendido y apagado de la luz. También puede utilizar un contador de vueltas integrado

Además, hay un timbre, que suena cada hora completa, y una luz de fondo controlable integrada. En el primer paso, no los conecté al Arduino.

Paso 2: la máquina de estado

Escudo del teclado LCD
Escudo del teclado LCD

No quiero profundizar mucho en la explicación de este ejemplo. No es porque sea demasiado complejo, es un poco demasiado grande. Intentaré explicar la idea básica de cómo funciona. La ejecución debe ser autoexplicativa, echando un vistazo al modelo o descargándolo y simulándolo. Algunas partes de la máquina de estado se resumen en subregiones, como la región de tiempo establecida. Con esto, debe garantizarse la legibilidad de la máquina de estados.

El modelo se divide en dos partes: una gráfica y otra textual. En la parte textual se definirán los eventos, variables, etc. En la parte gráfica, el diagrama de estados, se especifica la ejecución lógica del modelo. Para crear una máquina de estados, que cumpla con el comportamiento especificado, se requieren algunos eventos de entrada, que se pueden usar en el modelo: onoff, set, mode, light y light_r. Dentro de la sección de definición se utiliza un evento interno, que incrementa el valor de tiempo cada 100 ms:

cada 100 ms / vez + = 1

Sobre la base de los pasos de 100 ms, la hora actual se calculará en el formato HH: MM: SS:

display.first = (tiempo / 36000)% 24;

display.second = (tiempo / 600)% 60; display.third = (tiempo / 10)% 60;

Los valores se conectarán a la pantalla LCD utilizando la operación updateLCD cada vez que se llame a la máquina de estado:

display.updateLCD (display.first, display.second, display.third, display.text)

La ejecución básica de la máquina de estado ya está definida en la sección Cómo funciona el reloj digital. Dentro de la herramienta he utilizado algunos elementos de modelado "especiales" como CompositeState, History, Sub-Diagrams, ExitNodes, etc. Se puede encontrar una descripción detallada en la Guía del usuario.

Paso 3: Escudo del teclado LCD

El LCD Keypad Shield es bastante bueno para proyectos simples, que requieren una pantalla para visualización y algunos botones como entrada, una HMI (interfaz hombre-máquina) típica y simple. El protector del teclado LCD contiene cinco botones de usuario y otro para reiniciar. Los cinco botones en conjunto están conectados al pin A0 del Arduino. Cada uno de ellos está conectado a un divisor de voltaje, lo que permite distinguir entre los botones.

Puede usar analogRead (0) para encontrar los valores específicos, que, por supuesto, pueden diferir según el fabricante. Este sencillo proyecto muestra el valor actual en la pantalla LCD:

#include "Arduino.h"

#incluya "LiquidCrystal.h" LiquidCrystal lcd (8, 9, 4, 5, 6, 7); configuración vacía () {lcd.begin (16, 2); lcd.setCursor (0, 0); lcd.write ("Valor medido"); } bucle vacío () {lcd.setCursor (0, 1); lcd.print (""); lcd.setCursor (0, 1); lcd.print (analogRead (0)); retraso (200); }

Estos son mis resultados medidos:

  • Ninguno: 1023
  • Seleccionar: 640
  • Izquierda: 411
  • Abajo: 257
  • Arriba: 100
  • Derecha: 0

Con estos umbrales es posible leer los botones:

#define NONE 0 # define SELECT 1 #define LEFT 2 #define DOWN 3 #define UP 4 #define RIGHT 5 static int readButton () {int result = 0; resultado = analogRead (0); if (resultado <50) {return DERECHA; } si (resultado <150) {volver ARRIBA; } si (resultado <300) {volver ABAJO; } if (resultado <550) {return IZQUIERDA; } if (resultado <850) {return SELECT; } return NONE; }

Paso 4: Interfaz de la máquina de estados

Interfaz de la máquina de estados
Interfaz de la máquina de estados

El código C ++ generado de la máquina de estado proporciona interfaces, que deben implementarse para controlar la máquina de estado. El primer paso es conectar los eventos in con las teclas del Keypad Shield. Ya he mostrado cómo leer los botones, pero para conectarlos a la máquina de estado, es necesario eliminar los rebotes de los botones; de lo contrario, los eventos se generarían varias veces, lo que da como resultado un comportamiento impredecible. El concepto de eliminación de rebotes de software no es nuevo. Puedes echar un vistazo a la documentación de Arduino.

En mi implementación, detecto un borde descendente (soltando el botón). Leo el valor del botón, espero 80 ms (obtuve mejores resultados con 80 en lugar de 50), guardo el resultado y leo el nuevo valor. Si el resultado anterior no fue NINGUNO (sin presionar) y el nuevo resultado es NINGUNO, sé que el botón se presionó antes y ahora se soltó. Luego, levanto el evento de entrada correspondiente de la máquina de estado.

int oldState = NONE; static void raiseEvents () {int buttonPressed = readButton (); retraso (80); oldState = buttonPressed; if (oldState! = NONE && readButton () == NONE) {switch (oldState) {CASO SELECCIONAR: {stateMachine-> getSCI_Button () -> raise_mode (); rotura; } caso IZQUIERDO: {stateMachine-> getSCI_Button () -> raise_set (); rotura; } caso ABAJO: {stateMachine-> getSCI_Button () -> raise_light (); rotura; } caso ARRIBA: {stateMachine-> getSCI_Button () -> raise_light_r (); rotura; } caso DERECHA: {stateMachine-> getSCI_Button () -> raise_onoff (); rotura; } predeterminado: {descanso; }}}}

Paso 5: Conectando las cosas juntas

El programa principal utiliza tres partes:

  • La máquina de estado
  • Un temporizador
  • Un controlador de pantalla (impresión lcd típica (…))

Reloj Digital * stateMachine = nuevo Reloj Digital (); CPPTimerInterface * timer_sct = nuevo CPPTimerInterface (); DisplayHandler * displayHandler = new DisplayHandler ();

La máquina de estado usa un controlador de pantalla y tiene un temporizador, que se actualizará para controlar los eventos cronometrados. Posteriormente, la máquina de estado se inicializa y se ingresa.

configuración vacía () {stateMachine-> setSCI_Display_OCB (displayHandler); stateMachine-> setTimer (timer_sct); stateMachine-> init (); stateMachine-> enter (); }El bucle hace tres cosas:

  • Generar eventos de entrada
  • Calcule el tiempo transcurrido y actualice el temporizador
  • Llame a la máquina estatal

long current_time = 0; long last_cycle_time = 0; bucle vacío () {subirEventos (); last_cycle_time = tiempo_actual; tiempo_actual = millis (); timer_sct-> updateActiveTimer (stateMachine, current_time - last_cycle_time); stateMachine-> runCycle (); }

Paso 6: Obtenga el ejemplo

Eso es todo. Probablemente, no he mencionado todos los detalles de la implementación, pero puedes echar un vistazo al ejemplo o dejar un comentario.

Agregue el ejemplo a un IDE en ejecución con: Archivo -> Nuevo -> Ejemplo -> Ejemplos de gráficos de estado de YAKINDU -> Siguiente -> Arduino - Reloj digital (C ++)

> Puedes descargar el IDE aquí <<

Puede comenzar con una prueba de 30 días. Luego, debe obtener una licencia, que es gratuita para uso no comercial.

Recomendado: