Go Down

Topic: Problema con la seriale (Read 2859 times) previous topic - next topic

leo72


apire bene i delay e i flussi.

Nel codice di Arduino esiste un flusso principale del programma, ripetuto ininterrottamente. Il loop(). Tutto quello che è lì dentro viene ripetuto continuamente. Questo per scelta dei progettisti, che hanno strutturato un sketch in 2 blocchi distinti, setup() e loop(). Setup() viene eseguito solo 1 volta, il loop() sempre.
Siccome non c'è attesa tra un'istruzione e l'altra, può capitare di avere la necessità di attendere un certo lasso di tempo tra l'esecuzione di un'azione e la successiva. E' stato perciò pensato al delay(), una funzione che attende x millisecondi.
Il tutto però sempre inserito nel loop().

Quote

Anzi se qualcuno sa darmi consigli per capire flusso, delay e problematiche legate a questo. Ad esempio se chiamo una funzione nel loop, è sincrona o asincrona?

Cosa intendi per sincrono/asincrono?
Se intendi eseguito nel flusso principale, tutto quello che è scritto in linguaggio Arduino è sincrono. Ma sarebbe più corretto dire "seriale". Una istruzione dietro l'altra, ecco come viene eseguito il codice Arduino.
Se hai un loop() così strutturato:
loop() {
  funzione1();
  funzione2();
}
funzione2 sarà eseguito sempre e soltanto dopo funzione1. Dopo funzione2 sarà sempre eseguita funziona1 perché loop() è ciclico.

Quote

Esiste qualcosa di asincrono a parte gli interrupt?

Ad esser sinceri a livello di SW non esiste nulla di asincrono, ossia eseguito alternativamente a qualcos'altro. Questo perché l'Atmega non è dotato di multitasking per cui anche per eseguire un interrupt viene bloccata l'esecuzione del codice principale. Il micro infatti salva lo stato dei registri, esegue la routine di interrupt, e poi torna ad eseguire il programma dell'utente dal punto in cui era stato interrotto.
A livello di HW esiste un modulo asincrono, il timer 2, che può funzionare con una sorgente di clock differente da quella del clock di sistema, lavorando quindi anche a frequenze differenti ed anche quando il micro è in sleep. Ma non penso c'entri molto con quello che volevi sapere.

Quote
Gli interrupt interrompono anche un delay? La seriale continua a bufferizzare tranquillamente anche se sono in un delay vero?

Gli interrupt bloccano anche un delay. La funzione delay altro non fa che controllare che il contatore interno dei millisecondi (agganciato al timer 0 e letto tramite la funzione millis()) sia avanzato del valore passato come parametro, ossia sia trascorso il tempo richiesto. Ma per far ciò è interrotta continuamente dall'interrupt che incrementa il contatore del timer 0, nonché da altri interrupt. Un altro interrupt è proprio quello che gestisce i dati in arrivo sulla seriale ed in partenza su di essa. Tutte operazioni eseguite in background, quindi ad un livello inferiore rispetto a quello del codice utente. Ma io non mi azzarderei a definire un interrupt un'operazione asincrona perché, come detto, in realtà interrompi l'esecuzione dello sketch e poi la riprendi in un secondo tempo.

Quote

Chi mi sa dare consigli di dove trovare documentazione ben fatta su questa problematica con esempi?
Grazie

Cerca su internet, leggi un sacco su timer, interrupt, guarda il datasheet e sperimenta.

ƎR

ottimo direi, grazie per i chiarimenti! ;)
Riccardo Ertolupi of the Vicenza Thunders Team: http://www.VicenzaThunders.com

contecavour

Oggi sono nel mondo win32 e DB quindi niente Arduino, ma lunedì faccio un po' di prove.

Che l'interrupt interrompe un delay lo avevo provato ieri. Quindi ne ho la certezza fisica.

Quote
Cosa intendi per sincrono/asincrono?

Detto che è chiaro che essendoci un processore (oggi diremmo single core) parallelismi reali sono impossibili.
Per asincrono intendevo qualcosa tipo multithread. O flusso principale e gestione di eventi che interrompono il flusso.
Tipo funzione1 fa qualcosa in attesa di ma funzione2 viene eseguita proprio perchè funzione1 non porta via CPU.
MA dalla tua risposta ho gia capito, non ci sono meccanismio che lo facciano, devi essere tu che fai funzione uno che se non è successo qualcosa...finisca e al limite venga riattivata al prossimo loop.

Leo, anche se faccio un interrupt, la seriale ha un buffer e continua a leggere dati o smette e perde glie eventuali dati?

Altra cosa, se sto eseguendo un SerialEvent, è so solleva un interrupt... viene caricata la routine di interrupt o serialevent ha la priorità?
Ci sono tabelle di priorità?
Col MEGA ho 4 interrupt, c'è una logica di importanza (tipo nei xx86 che avevano un codice di importanza da 0 a 8 e uno di livello inferiore non poteva interrompere uno superiore) o qualunque può interrompere qualunque?

E' solo per capire tutto meglio, per la mia applicazione ho già tutto quello che mi serve.
Ciao





leo72


Detto che è chiaro che essendoci un processore (oggi diremmo single core) parallelismi reali sono impossibili.
Per asincrono intendevo qualcosa tipo multithread. O flusso principale e gestione di eventi che interrompono il flusso.
Tipo funzione1 fa qualcosa in attesa di ma funzione2 viene eseguita proprio perchè funzione1 non porta via CPU.
MA dalla tua risposta ho gia capito, non ci sono meccanismio che lo facciano, devi essere tu che fai funzione uno che se non è successo qualcosa...finisca e al limite venga riattivata al prossimo loop.

Esatto. Devi gestire tutto via software. E' ciò che fanno gli RTOS, i SO in tempo reale: assegnano dei tick ad ogni task, terminato il tempo a disposizione congelano il task salvando lo stato di tutti i registri e poi caricano i registri salvati del task successivo. Ma anche qui c'è un interrupt agganciato ad un timer a gestire i vari tick.

Quote

Leo, anche se faccio un interrupt, la seriale ha un buffer e continua a leggere dati o smette e perde glie eventuali dati?

Nel micro ci sono diversi interrupt, ognuno con una certa priorità sugli altri. Inoltre per default tutte le ISR sono compilate atomicamente (vale a dire che viene creato un codice non interrompibile da un'altra ISR) per cui se il micro sta eseguendo una ISR ed arriva qualcosa sulla seriale, l'evento viene registrato ma il relativo interrupt non viene eseguito finché non è terminata l'altra ISR. Terminata questa, viene eseguita l'ISR per gestire l'arrivo dei dati sulla seriale, che vengono riversati nel buffer.

Quote

Altra cosa, se sto eseguendo un SerialEvent, è so solleva un interrupt... viene caricata la routine di interrupt o serialevent ha la priorità?
Ci sono tabelle di priorità?

Sì, come ti ho detto ci sono delle priorità. Vedi il datasheet del 328 alla pag. 67, cap. 12.4.

Quote

Col MEGA ho 4 interrupt, c'è una logica di importanza (tipo nei xx86 che avevano un codice di importanza da 0 a 8 e uno di livello inferiore non poteva interrompere uno superiore) o qualunque può interrompere qualunque?

Diciamo che hai 4 interrupt esterni, non è corretto dire che hai 4 interrupt e basta  ;)
Anche in questo caso ci sono delle priorità: INT0 verrà eseguito prima di INT1, INT1 prima di INT2 ecc...

contecavour

Parli di questo documento?
http://www.atmel.com/Images/doc8161.pdf

Qui direi che parte da pagina 67.

Oppure dimmi tu il link del pdf di cui parli.
Grazie
Nic

leo72


Parli di questo documento?
http://www.atmel.com/Images/doc8161.pdf

Qui direi che parte da pagina 67.

Oppure dimmi tu il link del pdf di cui parli.
Grazie
Nic

Pag. 65. Sì, ma il tuo datasheet è del 2009. Qui c'è l'ultima versione, presa or ora dal sito Atmel:
http://www.atmel.com/Images/doc8271.pdf

contecavour

Mi sembrava un po' ingiallito.
Grazie

leo72


contecavour

Ecco adesso vi chiedo aiuto con questo esempio.
Code: [Select]

#include <Adafruit_VC0706.h>
#include <SoftwareSerial.h>   
Adafruit_VC0706 cam = Adafruit_VC0706(&Serial1);

int32_t time = millis();

void setup() {
  Serial.begin(38400);
  delay(1000);
  time = millis();
  Serial.print(time); Serial.println(" start");
  Serial.println("UNO");
 
  if (cam.begin()) {
    Serial.println(F("OK CAM"));
  } else {
    Serial.println("NO CAM");
  }
  time = millis() - time;
  Serial.print(time); Serial.println(" ms elapsed");
  Serial.println("DUE");
}

void loop() {

if (Serial.available())
  Serial1.write(Serial.read());

if (Serial1.available())
  Serial.write(Serial1.read());
  }


E questo è l'output.
Quote

999 start
UNO
OK CAM
14 ms elapsed
DUE
VC0703 1.00
Ctrl infr exist
User-defined sensor
625
Init end


Non mi spiego perchè ho del testo scritto dopo il "DUE" che è l'ultima istruzione.
Grazie




leo72

Vedendo che ciò che è stato scritto (VC0703 1.00) è simile al nome della libreria che usi (Adafruit_VC0706.h) e che istanzi proprio sulla seriale 1 (Adafruit_VC0706 cam = Adafruit_VC0706(&Serial1);), mi viene da pensare che sia o un messaggio della lib o qualcosa che può spedire la cam una volta aperta la connessione.

contecavour

Anche io penso a questo, ma perchè mi arriva dopo?
Cosa posso fare per farlo arrivare prima di tutto?
N

leo72

Studia la libreria.
Se la libreria non scrive nulla, allora è la cam. Potresti intercettare la prima stringa spedita e ignorarla semplicemente.

Michele Menniti

Quell'Init end mi fa pensare ad una procedura di inizializzazione della Webcam, come dice Leo basta intercettare la trasmissione dei dati e non visualizzarli, anche se forse quel valore 625 ha un suo significato che potrebbe tornare utile
Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

contecavour

Scusate non mi sono spiegato.
Non mi da fastidio e già la uso senza problemi, volevo solo capire le tempistiche e cosa succede.
Sempre per il discorso del flusso.
Avevamo detto che tutto segue il flusso, vorrei capire qual'è a vostro avviso l'istruzione del mio programma che scatena quella risposta.

Io penserei <<cam.begin()>>, ma a questo punto mi chiedo perchè arriva cosi tanto dopo.

N


contecavour

Code: [Select]
const uint8_t hexZero = 0x00;
void setup(){
  Serial.begin(38400);
  Serial1.begin(38400);
  delay(1000);
  Serial1.write(0x56);
  Serial1.write(hexZero);
  Serial1.write(0x26);
  Serial1.write(hexZero);
}
void loop() {
if (Serial1.available())
  Serial.write(Serial1.read());
}


Ottengo
Quote

0x760x000x260x00VC0703 1.00
Ctrl infr exist
User-defined sensor
625
Init end


I primi 4 li ho messi io in esadecimali, erano caratteri non stampabili.
N



Go Up