Inhoudsopgave:

Digitaal horloge op Arduino met behulp van een eindige-toestandsmachine - Ajarnpa
Digitaal horloge op Arduino met behulp van een eindige-toestandsmachine - Ajarnpa

Video: Digitaal horloge op Arduino met behulp van een eindige-toestandsmachine - Ajarnpa

Video: Digitaal horloge op Arduino met behulp van een eindige-toestandsmachine - Ajarnpa
Video: Webinar ESP32 and the IoT 2024, November
Anonim
Digitaal horloge op Arduino met behulp van een eindige-toestandsmachine
Digitaal horloge op Arduino met behulp van een eindige-toestandsmachine

Hallo, ik ga je laten zien hoe een digitaal horloge kan worden gemaakt met YAKINDU Statechart Tools en kan worden uitgevoerd op een Arduino, die een LCD-toetsenbordschild gebruikt.

Het originele model van het digitale horloge is afkomstig van David Harel. Hij heeft een artikel gepubliceerd over de

"[…] brede uitbreiding van het conventionele formalisme van toestandsmachines en toestandsdiagrammen."

In dit artikel gebruikte hij het voorbeeld van het digitale horloge voor zijn onderzoek. Ik heb het als inspiratie gebruikt en het horloge opnieuw opgebouwd met YAKINDU Statechart Tools (een hulpmiddel om grafische modellen van staatsmachines te maken en daarmee C/C++-code te genereren) en het weer tot leven gebracht op een Arduino.

Benodigdheden

Hardware:

  • Arduino Uno of Mega
  • Scherm LCD-toetsenbord

Software:

  • YAKINDU Statechart-tools
  • Eclipse C++ IDE voor Arduino

Stap 1: Hoe het digitale horloge werkt

Image
Image

Laten we beginnen met te definiëren hoe het digitale horloge zou moeten werken. Herinner je je deze… laten we zeggen… "ultra coole" digitale horloges die iedereen in de jaren '90 had? Een geïntegreerde stopwatch, verschillende alarmen en zijn irritante piep om het hele uur. Zo niet, kijk dan eens: digitaal horloge uit de jaren 90.

Dus eigenlijk is het een configureerbaar horloge met verschillende modi. Hoofdzakelijk wordt de huidige tijd weergegeven, maar er zijn enkele andere functies. Als invoer heb je een aan/uit, een modus en een instelknop. Daarnaast kun je het licht aan- en uitzetten. Met de modusknop kunt u onderscheid maken tussen de modi en de klokfuncties activeren/deactiveren:

  • Geef de tijd weer (klok)
  • Geef de datum weer (Datum)
  • Stel het alarm in (Alarm 1, Alarm 2)
  • Belsignaal in-/uitschakelen (Chime instellen)
  • Gebruik de stopwatch (Stop Watch)

Binnen de menu's kunt u de aan/uit-knop gebruiken om de modus te configureren. Met de set-knop kunt u de tijd instellen - b.v. voor de klok of de alarmen. De stopwatch kan worden bediend - gestart en gestopt - door gebruik te maken van de licht aan en licht uit knop. U kunt ook een geïntegreerde rondeteller gebruiken

Verder is er een gong, die elk heel uur afgaat, en een regelbare achtergrondverlichting geïntegreerd. Bij de eerste stap heb ik ze niet op de Arduino aangesloten.

Stap 2: De staatsmachine

Scherm LCD-toetsenbord
Scherm LCD-toetsenbord

Ik wil niet te veel in detail treden voor de uitleg van dit voorbeeld. Het is niet omdat het te complex is, het is gewoon een beetje te groot. Ik zal proberen het basisidee van hoe het werkt uit te leggen. De uitvoering moet zelfverklarend zijn, door het model te bekijken of te downloaden en te simuleren. Sommige delen van de staatsmachine zijn samengevat in subregio's, zoals de ingestelde tijdregio. Hiermee moet de leesbaarheid van de toestandsmachine worden gewaarborgd.

Het model is opgesplitst in twee delen - een grafisch en een tekstueel. In het tekstgedeelte worden de gebeurtenissen, variabelen, etc. gedefinieerd. In het grafische gedeelte - het toestandsdiagram - wordt de logische uitvoering van het model gespecificeerd. Om een toestandsmachine te maken die aan het gespecificeerde gedrag voldoet, zijn enkele invoergebeurtenissen vereist, die in het model kunnen worden gebruikt: onoff, set, mode, light en light_r. Binnen de definitiesectie wordt een interne gebeurtenis gebruikt, die de tijdwaarde elke 100 ms verhoogt:

elke 100 ms / tijd += 1

Op basis van de stappen van 100 ms wordt de huidige tijd berekend in het HH:MM:SS-formaat:

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

display.second = (tijd / 600) % 60; display.derde = (tijd / 10) % 60;

De waarden zullen worden aangesloten op het LCD-scherm met behulp van de bewerking updateLCD elke keer dat de statusmachine wordt aangeroepen:

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

De basisuitvoering van de toestandsmachine is al gedefinieerd in de sectie Hoe het digitale horloge werkt. Binnen de tool heb ik enkele "speciale" modelleringselementen gebruikt zoals CompositeState, History, Sub-Diagrams, ExitNodes, enz. Een gedetailleerde beschrijving is te vinden in de gebruikershandleiding.

Stap 3: LCD-toetsenbordscherm

Het LCD Keypad Shield is best cool voor eenvoudige projecten, die een scherm voor visualisatie en enkele knoppen als invoer vereisen - een typische, eenvoudige HMI (Human Machine Interface). Het LCD-toetsenbordscherm bevat vijf gebruikersknoppen en nog een voor reset. De vijf knoppen zijn allemaal samen verbonden met de A0-pin van de Arduino. Elk van hen is verbonden met een spanningsdeler, waardoor onderscheid kan worden gemaakt tussen de knoppen.

U kunt analogRead(0) gebruiken om de specifieke waarden te vinden, die natuurlijk per fabrikant kunnen verschillen. Dit eenvoudige project geeft de huidige waarde weer op het LCD-scherm:

#include "Arduino.h"

#include "LiquidCrystal.h" LiquidCrystal lcd (8, 9, 4, 5, 6, 7); void setup() { lcd.begin (16, 2); lcd.setCursor(0, 0); lcd.write("Gemeten waarde"); } void loop() { lcd.setCursor(0, 1); lcd.print(" "); lcd.setCursor(0, 1); lcd.print(analogRead(0)); vertraging (200); }

Dit zijn mijn meetresultaten:

  • Geen: 1023
  • Selecteer: 640
  • Links: 411
  • Beneden: 257
  • Omhoog: 100
  • Rechts: 0

Met deze drempels is het mogelijk om de knoppen te lezen:

#define NONE 0#define SELECT 1 #define LEFT 2 #define DOWN 3 #define UP 4 #define RIGHT 5 static int readButton() { int result = 0; resultaat = analoog lezen (0); if (resultaat < 50) { retourneer RECHTS; } if (resultaat < 150) { retourneer OMHOOG; } if (resultaat < 300) { retourneer OMLAAG; } if (resultaat < 550) { return LEFT; } if (resultaat < 850) { return SELECT; } retourneer GEEN; }

Stap 4: Interfacing met de staatsmachine

Interfacing met de staatsmachine
Interfacing met de staatsmachine

De gegenereerde C++-code van de toestandsmachine biedt interfaces die moeten worden geïmplementeerd om de toestandsmachine te besturen. De eerste stap is het verbinden van de in events met de toetsen van het Keypad Shield. Ik heb al laten zien hoe de knoppen moeten worden gelezen, maar om ze te koppelen aan de statusmachine, is het debouncen van de knoppen vereist - anders zouden de gebeurtenissen meerdere keren worden verhoogd, wat resulteert in onvoorspelbaar gedrag. Het concept van software debouncen is niet nieuw. U kunt de Arduino-documentatie bekijken.

In mijn implementatie detecteer ik een dalende rand (knop loslaten). Ik lees de waarde van de knop, wacht 80 ms (kreeg betere resultaten met 80 in plaats van 50), sla het resultaat op en lees de nieuwe waarde. Als het oude resultaat niet GEEN (niet ingedrukt) was en het nieuwe resultaat GEEN is, weet ik dat de knop eerder is ingedrukt en nu is losgelaten. Vervolgens verhoog ik de overeenkomstige invoergebeurtenis van de toestandsmachine.

int oldState = GEEN;static void raiseEvents() {int buttonPressed = readButton(); vertraging (80); oldState = knop ingedrukt; if (oldState != GEEN && readButton() == GEEN) { switch (oldState) { case SELECT: { stateMachine->getSCI_Button()->raise_mode(); pauze; } geval LINKS: { stateMachine->getSCI_Button()->raise_set(); pauze; } case DOWN: { stateMachine->getSCI_Button()->raise_light(); pauze; } case UP: { stateMachine->getSCI_Button()->raise_light_r(); pauze; } case RECHTS: { stateMachine->getSCI_Button()->raise_onoff(); pauze; } standaard: { pauze; } } } }

Stap 5: Dingen samen bedraden

Het hoofdprogramma maakt gebruik van drie delen:

  • De staatsmachine
  • een timer
  • Een display-handler (typisch lcd.print(…))

DigitalWatch* stateMachine = nieuwe DigitalWatch();CPPTimerInterface* timer_sct = nieuwe CPPTimerInterface(); DisplayHandler* displayHandler = nieuwe DisplayHandler();

De toestandsmachine gebruikt een display-handler en heeft een timer, die zal worden bijgewerkt om de getimede gebeurtenissen te regelen. Daarna wordt de toestandsmachine geïnitialiseerd en ingevoerd.

void setup () { stateMachine-> setSCI_Display_OCB (displayHandler); stateMachine->setTimer(timer_sct); stateMachine->init(); stateMachine->invoeren(); }De lus doet drie dingen:

  • Invoergebeurtenissen verhogen
  • Bereken de verstreken tijd en update de timer
  • Bel de staatsmachine

lange huidige_tijd = 0; lange laatste_cyclus_tijd = 0; void loop() { raiseEvents(); last_cycle_time = huidige_tijd; huidige_tijd = millis(); timer_sct->updateActiveTimer(stateMachine, current_time - last_cycle_time); stateMachine->runCycle(); }

Stap 6: Krijg het voorbeeld

Dat is het. Waarschijnlijk heb ik niet elk detail van de implementatie genoemd, maar je kunt het voorbeeld bekijken of een opmerking achterlaten.

Voeg het voorbeeld toe aan een draaiende IDE met: Bestand -> Nieuw -> Voorbeeld -> YAKINDU Statechart-voorbeelden -> Volgende -> Arduino - Digital Watch (C++)

> U kunt de IDE hier downloaden <<

U kunt beginnen met een proefperiode van 30 dagen. Daarna moet u een licentie krijgen, die gratis is voor niet-commercieel gebruik!

Aanbevolen: