Premetto che questo è il primo programma che scrivo per un microcontrollore, la mia unica esperienza di programmazione risale a più 30 anni fa con il commodore 64.
Fatta la premessa, volevo imparare ad usare il modulo DDS AD9850, ma per particolari motivi non volevo realizzare il solito generatore di funzioni con l'encoder che setta la frequenza per incrementi, ma bensì generare un set di frequenze predefinito.
Leggendo molto per cercare di capire e scopiazzando qualche riga qua e là, il programma l'ho scritto... e gira anche. Lo posto sotto, perchè mi interesserebbe ricevere consigli a livello didattico su come potrebbe essere stato scritto, in maniera più "elegante", in particolare so che per evitare la catena dei comandi per scrivere sull'LCD, si possono usare altre funzioni e quindi gradirei consigli sulla struttura.
L'ho commentato anche eccessivamente, ma mi è servito più che altro per cercare di capire quello che stavo facendo.
Il programma è questo:
/* Questo programma invia a un modulo DSS un set predefinito di frequenze
che vengono cambiate ciclicamente con la rotazione di un encoder, alla
pressione del pulsante dell'encoder viene avviato il modulo per un tempo
predefinito.
*/
#include <LiquidCrystal.h>
#include <DDS.h> /* descrizione: http://m0xpd.blogspot.com/2014/03/dds-and-duedds-libraries.html
download: https://github.com/m0xpd/DDS */
const int rs = 7, e = 8, d4 = 9, d5 = 10, d6 = A3, d7 = 12; // costanti pin per display LCD
const int W_CLK = 13, FQ_UD = A2, DATA = 11, RESET = A0; // costanti pin per modulo DDS
LiquidCrystal lcd(rs, e, d4, d5, d6, d7); // assegno i pin al display LCD
DDS dds(W_CLK, FQ_UD, DATA, RESET); // assegno i pin al modulo DDS
int ciclo = 0; // setta a 0 la variabile del ciclo
int Freq = 174; // variabile di settaggio frequenza
int encoder = 1; // posizione di start dell'encoder
int sendFreq = 174; /* la prima frequenza di default da inviare al DDS
che corrisponde alla posizione 1 dell'encoder */
bool letturaPrec = HIGH; // Variabile lettura encoder
unsigned long StartTime = 0; // definisce l'inizio del nuovo ciclo
unsigned long WorkTime = 10000; // preimposta il tempo di lavoro del ciclo
unsigned long contTempo; // variabile conteggio tempo
void setup() {
pinMode (4, INPUT_PULLUP); // pin CLK encoder
pinMode (5, INPUT_PULLUP); // pin DT encoder
pinMode (6, INPUT_PULLUP); // pin pulsante encoder
lcd.begin(16, 2); // inizializza LCD
dds.init(); // inizializza modulo DDS
dds.trim(125000000); /* opzionale per la taratura fine della frequenza dell'oscillatore
rispetto alla reale frequenza del quarzo. Esempio: (125000017) */
}
void loop() {
if (ciclo == 0 && (digitalRead(6) == HIGH)) {
byte n = digitalRead(4); // assegna alla variabile "n" il livello letto dal pin CLK dell'encoder
if ((letturaPrec == HIGH) && (n == LOW)) // rileva rotazione dell'encoder (fronte discesa CLK)
{
if (digitalRead(5) == HIGH) { // se il pin DT è alto direzione decremento
encoder--; // decrementa il valore di encoder
if (encoder == 0) encoder = 10; // decrementa circolarmente da 10 a 1
} else {
encoder = (encoder % 10) + 1; // incrementa circolarmente da 1 a 10
}
}
letturaPrec = n;
unsigned int freqs[] = { 174, 220, 315, 483, 532, // set di frequenze predefinito
596, 651, 798, 842, 974
};
Freq = freqs[encoder - 1]; /* assegna il valore di frequenza predefinito
a seconda della posizione dell'encoder */
lcd.setCursor(0, 0); // posiziona il cursore a 0 sulla prima riga
lcd.print("FREQ SET");
lcd.print(" ");
lcd.print (Freq); // visualizza la frequenza di set
lcd.print(" Hz");
lcd.setCursor (0, 1); // posiziona il cursore a 0 sulla seconda riga
lcd.print(" IN ATTESA ");
}
if (ciclo == 0 && (digitalRead(6) == LOW)) { // se il pulsante encoder viene premuto
sendFreq = Freq; // assegna il valore di Freq a sendFreq
dds.setFrequency(sendFreq); // invia la frequenza selezionata al modulo DDS e lo avvia
lcd.setCursor (0, 1); // posiziona il cursore a 0 sulla seconda riga
lcd.print("FREQ USO");
lcd.print(" ");
lcd.print(sendFreq); // visualizza la frequenza inviata al DDS
lcd.print(" Hz");
StartTime = millis(); // scrive il tempo passato fino questo momento nella variabile StartTime
ciclo = 1; // mette a 1 la variabile ciclo per eseguire le istruzioni successive
while (digitalRead(6) == LOW); // finchè il pulsante è premuto non fa altro
}
if (ciclo == 1 && digitalRead(6) == HIGH) { // se il pulsante è rilasciato ed ha eseguito il ciclo precedente
do {
contTempo = millis() - StartTime; /* sottrae il tempo di inattività dal tempo globale
e lo assegna alla variabile di conteggio tempo*/
}
while (WorkTime > contTempo && digitalRead(4) == HIGH && digitalRead(5) == HIGH); /* esce dal ciclo se viene raggionto il tempo di
lavoro preimpostato o se l'encoder viene ruotato */
}
ciclo = 2;
if (ciclo == 2) {
digitalWrite(RESET, HIGH); // invia impulso di reset al DDS di un millisecondo
delay(1);
digitalWrite(RESET, LOW);
ciclo = 0; // torna all'inizio
}
}
Ho parecchi problemi con la sintassi e devo andarmela spesso a rivedere anche per comandi che ho già usato.
Quando sono riuscito a farlo compilare, o il display flickerava, oppure ne vedevo solo la metà, o il programma
smetteva di girare.
L'ho scritto e riscritto, ma non ne vengo a capo, e non riesco a immaginare quale sia l'impostazione corretta e
avrei bisogno di qualche aiuto.
Grazie