Ciao a tutti.
Ho un progetto realizzato con Arduino UNO nel quale sto leggendo 4 sensori hall tramite 4 interrupt pin change che fanno capo a 4 funzioni ISR distinte. Questi interrupt ovviamente vanno a occupare molti cicli della cpu, il segnale di ingresso ha una frequenza di 50Hz e un duty-cycle del 50%. Tutto funziona bene, se non quando cerco di leggere dei dati provenienti dalla seriale. I valori provenienti dai sensore di hall variano. Questo presumo perchè a sua volta la porta seriale è collegata ad un ISR che impiega un certo tempo per essere gestito. Esiste secondo voi un modo, "semplice" per far si che non vengano alterate le misure quando ricevo dati dalla porta seriale?
Grazie per l'aiuto ![]()
... cambiare board e passare ad una con clock decisamente superiore.
Purtroppo stai parlando di tutte cose che utilizzano interrupts e la MCU è una sola, quindi se è impegnata con l'interrupt che gestisce la seriale, ovviamente NON asserve (anzi, sulla UNO sono proprio disabilitati) gli altri interrupt. ![]()
Guglielmo
No, non con la UNO (non so neanche come tu abbia fatto ad usare 4 interrupt, se solo i pin 2 e 3 si possono usare).
Per risponderti genericamente comunque bisognerebbe vedere cosa fai nelle ISR (aka: mostraci il codice e vediamo)
... te lo ha spiegato, ha usato il pin change interrupt che puoi usare su tutti i pin digitali ![]()
Guglielmo
@docdoc Lo faccio attraverso gli interrupt PinChange presenti su tutti i pin.
@gpb01 Per esempio quale MCU potrei utilizzare per i miei scopi? Posso volendo trovare una stratagemma come ad esempio un multiplexer che va a leggere sequenzialmente ognuno dei 4 sensori da un unico pin collegato ad un interrupt unico?
Non puoi adottare qualche trucco? Per esempio, se leggi una velocità, potresti interrompere la lettura mentre usi la seriale. Non sapendo che cosa vuoi fare, però, è impossibile dire di più...
@Datman
Devo leggere questi 4 sensori in un intervallo di tempo definito, tra 1 o 3 secondi è accettabile. Devo poter far commutare un led se la misura è troppo bassa o differente rispetto a quella prestabilita. In separata sede devo poter far si che attraverso un software che comunica via seriale impostare delle variabili all'interno di Arduino.
E questo lo devi proprio fare mentre continua la misura? Non puoi interrompere la fase di misura, leggere i dati in arrivo dalla seriale, impostare le tue variabili e poi riprendere la lettura dei sensori?
Guglielmo
Ma ,,, già una UNO R4 MINIMA monta una MCU che lavora a 48 MHz, altrimenti ... c'è sempre la Teensy 4.1 ...
... un mostriciattolo che viaggia a 600 MHz e si programma sempre con l'IDE di Arduino ![]()
Guglielmo
Ma, a parte tutto, questo codice è così segreto da non poter essere pubblicato? C'è di mezzo la CIA, il Mossad, etc?? Se poi devi ucciderci tutti lascia perdere, altrimenti forse se vediamo il codice qualcosina si può anche fare... ![]()
Ciao, Ale.
@ilguargua
no no quali segreti.
Ho provato a mantenere solo una lettura di un sensore ma il problema rimane. Pensavo se magari secondo voi potrei leggere il sensore per un secondo ogni 3 secondi e nei 2 secondi di tempo a disposizione potrei leggere i dati provenienti dalla seriale. E' fattibile?
Qui sotto il codice base per leggere un solo sensore. Mi rimane difficile però pensare a come poter implementare millis() affinche legge il sensore come descritto sopra, cioè per un secondo ogni 3 secondi....
volatile int counter = 0;
unsigned long prev_time[2] = {0,0};
unsigned long intervals[2] = {1000, 3000};
unsigned int rpm = 0;
void setup()
{
Serial.begin(9600);
pinMode(3, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(3), reading, FALLING);
}
void loop(){
if(millis()-prev_time[0] >= intervals[0]){
prev_time[0] = millis();
detachInterrupt(3);
rpm = 60*counter;
counter = 0;
Serial.print("RPM value: ");
Serial.println(rpm);
attachInterrupt(digitalPinToInterrupt(3), reading, FALLING);
}
}
void reading(){
counter++;
}
Ecco, per dire, se quel 9600 lo fai diventare 115200 (e credo potresti anche rinunciare a scrivere ogni volta "RPM value:") il tempo impiegato per la comunicazione seriale si ridurrà sensibilmente, magari non basterà solo questo, ma intanto parti da li...
Ciao, Ale.
come dice giustamente @ilguargua alza la velocità della seriale, riduci i tempi di trasmissione
comunque io non vedo grosse difficoltà
anche a 9600 una uno R3 ci riesce benissimo
invece di impegolarsi con interrupt e contatori e similia, basta usare le funzioni native
in particolare la pulsein()
io ho provato, e gestisco sia tre led a finestra (frequenza bassa, giusta ed alta)
Forse la prima volta che uso una elseif
che la trasmissione continua della frequenza che la ricezione di comandi, a 9600bps
era questo che cercavi, giusto?
giusta regola un canale solo, visto che non ho abbastanza materiale per fare 4 canali, ma tu puoi sempre provare a bps maggiori, dovresti starci facile
Buonasera @Salvorhardin
PulseIn() è una funzione bloccante e come tale, se viene aggiunto del codice che fa riferimento alla funzione millis(),quindi al Timer0 nel mio caso, crea problemi. L'ho provato sia su Mega che su Uno e ti posso dire che quella funzione , per la lettura degli RPM ad esempio, non è utilizzabile soprattutto quando i sensori da leggere sono molti. Questa affermazione è fatta sulla base della mia esperienza, che è opinabile.
Allora finito qui
Buona notte
Non ho seguito il topic, ho solo visto che si parlava di pulsIn non bloccante e quindi se il codice che ho postato può essere di utilità prendi quello che serve e scarta il resto.
PS: è stato scritto 8 mesi fa e non ricordo nulla.
Ciao.
Secondo me puoi andare anche oltre, tipo 250000bps o 500000bps.
Se i collegamenti non sono troppo lunghi e il protocollo è robusto, azzarderei anche 1Mbps.
Molti firmware usano questi valori di default senza problemi, come ad esempio quelli per stampanti 3D giusto per citarne qualcuno.
Si, sono d'accordo, anche io ho usato più volte velocità del genere senza problemi.
Quali collegamenti? In questo caso (cioè se parla di comunicazione tra PC e scheda via USB) l'unico collegamento rilevante ai fini della velocità è quello tra l'MCU e il convertitore seriale/USB, che essendo sulla stessa scheda è senz'altro breve. Poi l'USB comunica sempre al massimo della velocità ammissibile dal protocollo, che è ampliamente superiore a quelle citate. Infatti se si usa una MCU con USB nativa specificare la velocità è irrilevante, come specificato anche nelle note del reference.
Ciao, Ale.
Ma il programma originale, non quello con un solo pin, dov'è ?
Sarebbe interessante, secondo me
Non so, sicuramente mi sfugge qualcosa... Ma se nel tuo codice (che ancora non abbiamo visto..) hai una ISR come quella che hai mostrato come esempio, dove si limita ad incrementare un contatore e non fa altro, non vedo quali problemi tu possa avere, e, anche se entro la ISR è possibile perdere dati dalla seriale, dato che la seriale ha il suo buffer teoricamente non dovresti neanche perdere dati in ingresso.
Quindi dato che nell'esempio hai impostato l'ISR su FALLING, tu avrai circa 50 chiamate al secondo per ogni sensore, quindi globalmente circa 200 interrupt al secondo. Dando per scontato che ognuno di questi ISR si limitino ad incrementare un contatore, non mi sembra che sia un carico eccessivo per la CPU. Se hai problemi con i contatori quando c'è la comunicazione seriale a me viene il sospetto che tu abbia o messo delle ISR che "fanno cose" (ma non "vedono gente"
) o "pasticciato" in qualche modo con gli interrupt andando ad interferire con quello che gestisce la seriale.
Morale della favola: o ci fai vedere il codice "reale" oppure non possiamo dirti nulla più di questo.