Vai al contenuto
PLC Forum


Curiosità Su Arduino


roberto8303

Messaggi consigliati

Ciao a tutti,

ho compilato un programma per arduino uno

unsigned int contatore=0;
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.println(contatore);
contatore=contatore+1;
delay(1);
}
Se il delay 1 equivale a 1millisecondo, prima che si azzeri il contatore cioe precisamente a 65536 quanti secondi sono passati? 65536/1000?
Link al commento
Condividi su altri siti


  • Risposte 57
  • Created
  • Ultima risposta

Top Posters In This Topic

  • walterword

    16

  • Livio Orsini

    15

  • roberto8303

    12

  • Ctec

    7

Si, esatto, ma il problema te lo potrebbe dare la stampa su seriale, che aggiunge ritardo.

A 9600baud, per inviare un byte ci si impiega 1,0416ms. Se il messaggio è di 10 bytes, ad esempio, la sola trasmissione impiegherà circa 10ms, e non potrà partirne una finchè la precedente non è finita (o il buffer pieno, non so come funziona), per cui il tempo di ogni ciclo aumenta parecchio...

Link al commento
Condividi su altri siti

grazie Ctec non conoscevo il tempo per inviare un byte, allora è per questo che sul monitor leggevo 1000 sul contatore ogni 30 secondi!!! e se aumento la velocità a 115000 baud?

invece se avessi un display liquid cristal non dovrei avere questo problema giusto?

Modificato: da roberto8303
Link al commento
Condividi su altri siti

Per fare il conto, considera che i baud sono bit al secondo. Considerando un byte di 8 bit, se si trasmette 8N1 (nessuna parità, un bit di stop) con lo start fanno 10 bit.

Se fai quindi il conto, dividendo 1/9600 e poi per il numero di bit, vedi che un byte impiega come detto poco più di 1ms per essere inviato. Ma un messaggio generalmente impiega ben più di un byte...

Se vai a 115200baud, otterrai allora circa 86.8us per byte, se ne hai 10 circa 868us, non molto meno di 1ms (1000us)

Tieni sempre presente che questo tempo (sempre dipendendo dal buffer di comunicazione) tende a sommarsi al ritardo delay (andrebbe considerato anche il tempo di esecuzione dell'incremento del contatore, ad esser corretti...)

Mica è detto. Anche il display ha necessità di tempo per scrivere (metti l'indirizzo, scrivi la cifra, poi la successiva, ecc...) e bisogna fare il tutto considerando le tempistiche del controller del display.

Poi i migliori cristalli liquidi per monitor (non i display a caratteri, che sono lenti...) hanno tempi di persistenza di 6-8ms, quindi l'incremento del ms non lo vedrai mai.

Se poi ci mettiamo anche che l'occhio umano non percepisce variazioni troppo veloci, fossi in te mi accontenterei di un aggiornamento ogni 50ms...

Link al commento
Condividi su altri siti

Se vuoi un conteggio preciso, indipendentemente dal tempo di aggiornamento, non devi usare i ritardi bloccanti ma un temporizzatore ad interrupt.

Se hai problemi ti metto le due righe di codice.

Link al commento
Condividi su altri siti

Generalmente (non so su arduino) si può fare così.

Generi un interrupt a tempo minore di quanto tu debba aspettare come minimo (che so, ogni 100us) e incrementi una variabile, chiamato spesso tick

Per far partire il timer, te metti a 0 la variabile (l'ideale è anche ricaricare il timer, ma lasciamo fare).

Poi nel tuo programma verifichi se il tick ha superato il valore impostato (nel tuo caso 10 per avere 1ms), altrimenti prosegui a fare le altre cose ( continui il loop, insomma).

L'errore è generalmente minimo e accettabile purchè tu non voglia farci un orologio.

Non so se la cosa sia implementabile su Arduino, ma su tutti i microcontroller in C o assembler si

Link al commento
Condividi su altri siti

Non so se la cosa sia implementabile su Arduino, ma su tutti i microcontroller in C o assembler si

Arduino non è altro che la scheda di sviluppo del micro Atmel. Questo come praticamente tutti i microcontroller (PIC, etc.) ha 3 timer programmabili, alla cui scadenza si può generare un interrupt.

Basta scrivere poche righe di codice e si ha una interruzione a tempi precisi, ripetibili ed indipendenti dall'evovlvere del programma. Anche la funzione delay è basata su uno di questi contatori.

int cnt1 = 10;
void setup() {
  noInterrupts();           // disable all interrupts
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 64911;   // preload timer
  TCCR1B |= (1 << CS12);    // 256 prescaler
  TIMSK1 |= (1 << TOIE1);   // enable timer overflow interrupt
  interrupts();             // enable all interrupts
//...........................................................................................
  Serial.begin(9600);
}

ISR(TIMER1_OVF_vect)        // interrupt service routine
{
   TCNT1 = 64911;   // preload timer per interrupts ogni 10 ms
   digitalWrite(13, digitalRead(13) ^ 1); // uscita temporizzata
   if (cnt1 > 0) {
    cnt1--; // totalizzatore per 0.1"
  }
  else {
    cnt1 = 10; //trascorso 1", ricarico il contaore
    pulsAnalogValue = analogRead(pulsAnalog);
  }
}

Il codice di esempio soprariportato genera un'oda quadra con periodo di 20 ms sul'uscita 13 e usa cnt1 per generare un tempo di 100 ms

C'è un bell'articolo su questo sito che spiega bene, in italiano, l'uso dei timers di arduino; devi avere solo la pazienza di cercarlo, se ricordo correttamente è parte di un articolo sullìuso della schda "Centaur" interfaccia per pilotare motori in PWM.

E' possibile ottimizzare ulteriormente il codice di esempio, però ho cercato di renderlo più facilmente comprensibile.

Modificato: da Livio Orsini
Link al commento
Condividi su altri siti

Siccome io sapevo che erano implementate delle librerie (funzioni particolari) proprie di Arduino, pensavo che, a mo' di RTOS, utilizzasse alcuni timer e altre funzioni per uso proprio, e che non si avesse accesso totale al micro, pena togliergli il firmware di base.

Se così non è, continuo a preferire le schede basate sui cortex (STM e NXP)...

Link al commento
Condividi su altri siti

Arduino:1.5.8 (Windows 7), Scheda:"Arduino Uno"
a(main.cpp.o): In function `main':
C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/main.cpp:43: undefined reference to `loop'
collect2: error: ld returned 1 exit status
Errore durante la compilazione
ci sto provando ma da errore...
il codice è cosi ho dichiarato le due variabile analog read come intero e una su A0
int cnt1 = 10;
int pulsAnalog=A0;
int pulsAnalogValue=0;
void setup() {
noInterrupts(); // disable all interrupts
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 64911; // preload timer
TCCR1B |= (1 << CS12); // 256 prescaler
TIMSK1 |= (1 << TOIE1); // enable timer overflow interrupt
interrupts(); // enable all interrupts
//...........................................................................................
Serial.begin(9600);
}
ISR(TIMER1_OVF_vect) { // interrupt service routine
TCNT1 = 64911; // preload timer per interrupts ogni 10 ms
digitalWrite(13, digitalRead(13) ^ 1); // uscita temporizzata
if (cnt1 > 0) {
cnt1--; // totalizzatore per 0.1"
}
else {
cnt1 = 10; //trascorso 1", ricarico il contaore
pulsAnalogValue = analogRead(pulsAnalog);
}
}
Link al commento
Condividi su altri siti

Hai dimenticato la funzione loop, l'ho aggiunto alla fine :

int cnt1 = 10;
int pulsAnalog=A0;
int pulsAnalogValue=0;

void setup() {
  
  noInterrupts();           // disable all interrupts
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 64911;   // preload timer
  TCCR1B |= (1 << CS12);    // 256 prescaler
  TIMSK1 |= (1 << TOIE1);   // enable timer overflow interrupt
  interrupts();             // enable all interrupts
//...........................................................................................
  Serial.begin(9600);
}
 
ISR(TIMER1_OVF_vect)      {  // interrupt service routine
 
   TCNT1 = 64911;   // preload timer per interrupts ogni 10 ms
   digitalWrite(13, digitalRead(13) ^ 1); // uscita temporizzata
   if (cnt1 > 0) {
    cnt1--; // totalizzatore per 0.1"
  }
  else {
    cnt1 = 10; //trascorso 1", ricarico il contaore
    pulsAnalogValue = analogRead(pulsAnalog);
  }
}

void loop()
{
  // Scrivi qui il codice del main
}
Link al commento
Condividi su altri siti

Setta l'opzione che inserisce i numeri di riga, poi leggi la segnalazione di errore, ti dirà riga, carattere e tipo di errore rilevato.

la funzione di "loop" che è il main del programma, non l'ho riportata perchè la davo per scontata. :(

Se così non è, continuo a preferire le schede basate sui cortex (STM e NXP)...

Io preferisco la cortex di TI; costa niente e c'è una piattaforma chiamata "Energia", assolutamente gratuita che la rende identica ad arduino. Anche i tool software (ambiente e compilatore "C") la TI li fornisce in modo assolutamente gratuito.

L'unico timer usato dall'ambiente di arduino è TM0, con il quale si impostano i cicli di ritardo; inoltre se si usano le uscite PWM anche gli altri 2 timer possono essere impegnati dalle funzioni di libreria.

Però se vuoi implemetarti uno scheduler non è che ci voglia molto. Personalmente per le applicazioni risolvibili con arduino non trovo necessario implementare un vero e propio schedulatore o, addirittura, un kernel di RTOS.

Link al commento
Condividi su altri siti

Io uso CooCox come ambiente sviluppo, completamente gratuito. Gestirebbe anche i TI, non ho mai avuto occasione di provarli.

Sono piuttosto soddisfatto degli STM, ultimamente mi sono concentrato su quelli. Comunque indagherò...

Link al commento
Condividi su altri siti

si me ne sono accorto dopo, comunque per capire bene il funzionamento, se volessi generare un onda quadra sempre sull uscita 13 con intervallo di mezzo secondo quale valore devo variare nel programma?

Link al commento
Condividi su altri siti

con intervallo di mezzo secondo quale valore devo variare nel programma?

Attualmente hai il tic minimo, ovvero il tempo tra due interruzioni, pari a 10 ms. Lasciando invariato questo tempo devi ntervenire sul contatore "cnt1" e portarlo a 50. Poi devi trasferire il pilotaggio dell'uscita 13 nell'"else" di ricarica del contatore.

int cnt1 = 10;
void setup() {
   noInterrupts(); // disable all interrupts
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 64911; // preload timer
  TCCR1B |= (1 << CS12); // 256 prescaler
  TIMSK1 |= (1 << TOIE1); // enable timer overflow interrupt
  interrupts(); // enable all interrupts
//...........................................................................................
  Serial.begin(9600);
}

 ISR(TIMER1_OVF_vect) // interrupt service routine
   {
      TCNT1 = 64911; // preload timer per interrupts ogni 10 ms
      if (cnt1 > 0) {
     cnt1--; // totalizzatore per 0.5"
   }
  else {
              digitalWrite(13, digitalRead(13) ^ 1); // uscita temporizzata
              cnt1 = 50; //trascorso 1", ricarico il contaore
       }
}

Walter non conosco queste schede, probabilmente troverai le informazion i sul sito STM dove quasi certamente c'è anche il link al forum di discussione.

Modificato: da Livio Orsini
Link al commento
Condividi su altri siti

per Walterword

Il tool di programmazione gratuito completo e ti posso assicurare ben funzionante (e non lavora solo con STM...) è il già da me citato CooCox. Compilatore con IDE e debugger. Se prendi le schede STM con a bordo anche il programmatore, ti serve solo un cavetto miniUSB...

Sul sito tutte le informazioni.

Gli STM32 son dei gran processori molto ben supportati e diffusi, per cui si trovano esempi di tutto per tutto.

Link al commento
Condividi su altri siti

grazie Ctec

Una domanda , le schede sono quelle che normalmente hanno il pcb bianco ?

Vedevo delle schede ST bianche con pin header tipo arduino a prezzi veramente stracciati ....:(

Link al commento
Condividi su altri siti

Si, quella serie consente di montare alcuni shield Arduino, ma come potenza siamo ben oltre (per esempio quella con lo STM32F103).

Ma anche le varie schede Discovery fatte direttamente da ST sono molto interessanti. Tutte hanno praticamente tutti i pin del micro accessibili su pin header

PS: non è pubblicità, non lavoro per ST o alti costruttori di chip (purtroppo...). Faccio solo presente una esperienza diretta.

Modificato: da Ctec
Link al commento
Condividi su altri siti

PS: non è pubblicità, non lavoro per ST o alti costruttori di chip (purtroppo...). Faccio solo presente una esperienza diretta.

E' evidente. E' come se, nella sezione PLC, si disquisse sulle prestazioni di Siemens, Omron, Mitsubishi; non può essere considerata pubblicità stante la diffusione dei marchi. Così come parlare di prodotti STM, TI, Microchip, etc.

P.S: Se non ricoedo male sulla piattaforma Arduino c'è anche una versione con micro Intel

Modificato: da Livio Orsini
Link al commento
Condividi su altri siti

Nel mentre,

beccate 'sti link alle "schede bianche" della ST (Nucleo)

http://it.farnell.com/stmicroelectronics/nucleo-f302r8/scheda-svil-nucleo-stm32f302r8t6/dp/2424209

http://it.farnell.com/stmicroelectronics/nucleo-f072rb/scheda-di-sviluppo-nucleo/dp/2431224

eccetera, eccetera...

Ah, per Cocox ide

http://www.coocox.org/

P.S: Se non ricoedo male sulla piattaforma Arduino c'è anche una versione con micro Intel

Si, Livio, esiste questa board:

http://arduino.cc/en/ArduinoCertified/IntelGalileo

Ricordo, fra l'altro, che è possibile caricare sulle schede STM32F4 Discovery il MicroFramework 4.2 - 4.3 della Microsoft per programmare la board in C# tramite Visual Studio.

P.S.: Complimenti per il tuo meritatissimo 30!

Link al commento
Condividi su altri siti

Crea un account o accedi per commentare

Devi essere un utente per poter lasciare un commento

Crea un account

Registrati per un nuovo account nella nostra comunità. è facile!

Registra un nuovo account

Accedi

Hai già un account? Accedi qui.

Accedi ora

×
×
  • Crea nuovo/a...