Trasferisci un codice all'editor.
Per iniziare a imparare come portare il codice C++ nell'editor di blocchi personalizzato C++, dobbiamo iniziare con un codice semplice. Supponiamo di avere il codice Arduino che rappresenta il funzionamento di un pulsante in vari regimi. Per creare un blocco personalizzato in C++ con questo codice, dobbiamo dividerlo in parti (Declare, Setup, Loop, Function) ed eliminare le parti delle righe di codice che non ci servono. Vediamo come si può fare.
Iniziamo con la parte "Declare" del codice.
Le prime quattro #define
non sono necessarie, verranno implementate nel progetto come input e output nello schema principale, vanno eliminate.
#define BUTTON_PIN 0 //Button pin input.
#define PIN_ONE_CLICK 1 //Pin output one click.
#define PIN_DOUBLE_CLICK 3 //Pin output double click.
#define PIN_LONG_CLICK 4 //Pin output long click.
Altri tre #define
verranno implementati come parametri, manteniamo il nome e il valore predefinito come nome e valore predefinito del parametro e li eliminiamo dal codice.
#define TIME_ONE_CLICK 70 //One click time.
#define TIME_DOUBLE_CLICK 500 //Double click on time.
#define TIME_LONG_CLICK 1000 //Long click on time.
Queste variabili devono essere inserite nel codice del blocco nella sezione Declare, sono variabili globali per il funzionamento del codice nel ciclo di Loop.
bool StartPressButton; //Start - press button
bool StopPressButton; //Stop - press button
bool PressButton; //flag - press button
bool ReleaseButton; //flag - release button
bool ReleaseButtonDoublePress; //flag - release after double pressing
unsigned long TimePressButton; //Timer for the last button press
unsigned long TimePressButton; //Timer for the last button press
unsigned long TimeButtonDoublePress; //Button double click timer
//Variables for exit delay timers
//Variables for exit delay timers
unsigned long ExitDelayTimer1;
unsigned long ExitDelayTimer2;
Queste variabili vengono eliminate ma manteniamo il nome per creare l'input e l'output del blocco.
//Variable to store the input values.
bool ButtonState = false;
//Variable to store values for the outputs
bool OneClick = false;
bool DoubleClick = false;
bool LongClick = false;
Le variabili di gestione del rimbalzo del pulsante vanno eliminate. Nello schema principale, quando creiamo un ingresso per un pulsante con contatti fisici, abbiamo la possibilità di attivare la funzione Bounce (c'è anche un blocco nella libreria dei blocchi incorporati).
//Variable for managing button bounce
bool BounceState = false;
bool BounceCurrentState = false;
unsigned long BounceTime = 0UL;
Setup.
La definizione dei pin e l'inizializzazione delle variabili verranno eseguite durante la compilazione del progetto. A questo punto nella sezione Setup va cancellato tutto.
//Definition of pins.
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(PIN_ONE_CLICK, OUTPUT);
digitalWrite(PIN_ONE_CLICK, LOW);
pinMode(PIN_DOUBLE_CLICK, OUTPUT);
digitalWrite(PIN_DOUBLE_CLICK, LOW);
pinMode(PIN_LONG_CLICK, OUTPUT);
digitalWrite(PIN_LONG_CLICK, LOW);
BounceCurrentState = digitalRead(BUTTON_PIN);
Loop.
Tutta questa parte di codice che gestisce il rimbalzo del pulsante deve essere eliminata, come detto sopra, verrà gestita nello schema principale quando creeremo l'input per il pulsante.
//Button bounce management
bool BouncedReading = (digitalRead (BUTTON_PIN));
if (BounceState) {
if (millis() >= (BounceTime + 40)) {
BounceCurrentState = BouncedReading;
BounceState = 0;
}
}
else
{
if (BouncedReading != BounceCurrentState) {
BounceState = 1;
BounceTime = millis();
}
}
//We set the value of the ButtonState variable.
ButtonState = !(BounceCurrentState);
Nella sezione Loop va invece inserita questa parte di codice che gestirà la funzione di input e output del blocco.
if (OneClick && ExitDelayTimer1 < millis()) {
ExitDelayTimer1 = millis() + TIME_ONE_CLICK;
}
if (OneClick && ExitDelayTimer1 == millis()) {
OneClick = false;
}
if (DoubleClick && ExitDelayTimer2 < millis()) {
ExitDelayTimer2 = millis() + TIME_ONE_CLICK;
}
if (DoubleClick && ExitDelayTimer2 == millis()) {
DoubleClick = false;
}
//Button press control.
//Button press.
if (ButtonState) {
StartPressButton = true;
PressButton = true;
}
else
{
StartPressButton = false;
StopPressButton = true;
}
if (StartPressButton && StopPressButton) {
TimePressButton = millis() + TIME_LONG_CLICK;
StartPressButton = false;
StopPressButton = false;
}
if (PressButton) {
//If button was released before TimePressButton, consider released and update TimeButtonDoublePress.
if (!ButtonState && !ReleaseButton && millis() < TimePressButton) {
ReleaseButton = true;
TimeButtonDoublePress = millis() + TIME_DOUBLE_CLICK;
}
//If button is inactive after TimeButtonDoublePress but before TimePressButton, single click counts.
if (ReleaseButton && !ReleaseButtonDoublePress && millis() > TimeButtonDoublePress && millis() < TimePressButton) {
OneClick = true;
ReleaseButton = false;
PressButton = false;
}
//If released and pressed again before TimeButtonDoublePress, count pressed twice.
if (ReleaseButton && ButtonState && millis() < TimeButtonDoublePress) {
ReleaseButtonDoublePress = true;
}
//If there was a double click and released, count the double click.
if (ReleaseButtonDoublePress && !ButtonState) {
DoubleClick = true;
ReleaseButtonDoublePress = false;
ReleaseButton = false;
PressButton = false;
}
//If more than TimePressButton is held, run "during hold"
if (ButtonState && !ReleaseButtonDoublePress && millis() > TimePressButton) {
LongClick = true;
}
//If released after hold, stop "during hold".
if (!ButtonState && LongClick) {
LongClick = false;
PressButton = false;
}
}
Questa parte del codice che gestisce il risultato dell'output va eliminata. Il risultato verrà gestito nello schema principale quando colleghiamo l'output al blocco.
//Send a signal to the pin.
digitalWrite(PIN_ONE_CLICK, OneClick);
digitalWrite(PIN_DOUBLE_CLICK, DoubleClick);
digitalWrite(PIN_LONG_CLICK, LongClick);
Quindi abbiamo eliminato tutte le parti del codice che non ci servono. Le restanti parti del codice verranno inserite nelle rispettive sezioni del blocco. Come si vede dal codice abbiamo eliminato le parentesi graffe dalle funzioni Setup e Loop, che a loro volta verranno inserite automaticamente in fase di compilazione del progetto.
Vedremo come creare un blocco nell'articolo "Creazione di un blocco personalizzato in C++"