Tutorial Arduino - Programmazione

Questa sezione contiene tutorial e guide orientate alla programmazione di Arduino e ai linguaggi come C, C++ e Processing.
Qui puoi svariate informazioni utili per i primi passi con la programmazione.
Grazie alla passione di voi utenti è presente un vasto database di strumenti intellettuali. Fai la tua parte ; )

Inserisci un articolo!
Programmazione


Brainbooster
Le librerie software ed Arduino
Tutorials -
Sabato 24 Luglio 2010 07:13
Scritto da Brainbooster

Che cos'è una libreria?

Le librerie software sono una specie di raccolta di procedure con compiti specifici che noi possiamo utilizzare, semplicemente richiamandole all'interno del nostro programma ! Se, per esempio, si vuole controllare un servomotore, è possibile usare la libreria servo.h : una serie di comandi già scritti per te, che puoi usare senza dover fare il lavoro sporco di imparare le sfumature di motori e di come si comandano, quindi invece di doversi studiare il sistema di posizionamento di un servo e scrivere un programma apposito per farlo funzionare possiamo dire alla libreria direttamente di portare il servo all'angolo desiderato ES. myservo.write(90).
Praticamente invece una libreria è una cartella con alcuni file in essa contenuti, i file avranno estensioni  .cpp  (file di codice) e . h (file di intestazione) , a volte anche file con estensione .o (oggetti compilati) ed il file opzionale keywords.txt.
I files con estensione .cpp e .h sono semplici files di testo che possiamo (avendo conoscenza del linguaggio C++) anche modificare per migliorare in qualche modo le librerie che usiamo nel nostro progetto e farle eseguire ad Arduino (ricordate di cancellare, se esistono, i file .o, dopo la ricompilazione l'IDE ne scriverà uno nuovo).

Come si usa una libreria?

Una delle cose migliori dell'ambiente di programmazione di Arduino è la capacità di poter utilizzarre librerie già scritte da altri per aggiungere supporto per un nuovo hardware, o effettuare calcoli complessi ed altro ancora. Ci sono tonnellate di librerie in giro su internet alcune sonoo già disponibili dall'IDE di Arduino, e si può scegliere a seconda delle esigenze del nostro progetto quale installare di volta in volta. Le librerie vengono caricate solo quando lo sketch sta lavorando e ne ha bisogno, e possono essere "interrogate" ogni volta che serve.

Come dicevamo prima, se si vuole utilizzare una libreria basta includerla nel nostro progetto con il comando include

#Include 

Attenzione, se non avete incluso la libreria o questa non è installata e tenterete di usarla riceverete un errore!

E se volessi usare una libreria non inclusa nell'IDE? come si installano?

La struttura della cartella della libreria √® molto importante! i¬† files . cpp e . h file devono essere nella cartella della libreria al "livello pi√Ļ basso. Ad esempio, non puoi avere Arduino \ libraries \ MiaLib \ MiaLib \ file.cpp o Arduino \ libraries \ Mielibrerie \ MiaLib \ file.cpp - deve essere Arduino \ libraries \ MiaLib\ file.cpp

Le librerie degli utenti sono memorizzate nella cartella di Arduino cartella \libraries. Quindi se volessimo installare la libreria Mialib, dovremmo creare nella cartella \libraries una cartella che si chiamerà MiaLib e che conterrà i nostri files mialib.cpp e mialib.h, riavviare l'IDE di Arduino ed il gioco è fatto :)

Ciao

Brainbooster

 
Edoardo Vignali
Arduino e Ubuntu
Tutorials -
Lunedì 19 Luglio 2010 14:07
Scritto da Edoardo Vignali

Questo articolo è per gli amanti del pinguino, come me.

Far funzionare arduino con ubuntu è molto semplice, basta installare il pacchetto librtx-java che sarebbe la JRE della sun e il compilatore gcc con le libc per programmare il nostro microcontrollore.

Prima di tutto fate un sudo apt-get update per essere sicuri di installare le ultime versioni di tutti i seguenti programmi. Successivamente nel terminale scrivete

$ sudo apt-get install sun-java6-jre avr-libc gcc-avr

Il mio pc è a 32 bit quindi per installare librxtx ho semplicemente digitato nel terminale:

$ sudo apt-get install librxtx-java

se invece siete su una macchina a 64 bit installate il seguente pacchetto .deb.

Adesso avrete predisposto il vostro pc alla programmazione dei micro avr e al funzionamento dell IDE di arduino.

L' ide arduino scaricatelo da qui http://arduino.cc/en/Main/Software.

Scaricatelo in home poi nel terminale scrivete

$ tar zxvf arduino-xxxx.tgz

adesso sarete pi√Ļ o meno in questa situazione entrando nella cartella dell' ide

Arduino

Cliccando sull ide vi comparirà questa finestra:

Arduino mostra ecc ecc

Eseguitelo e se tutto è andato bene vi comparirà l IDE.

Ide

Collegate la vostra scheda e dopo aver selezionato la scheda giusta sotto Tools->board e la porta com giusta sotto Tools->Serial Port provate a caricare lo sketch Blink.

Se tutto sarà andato a buon fine allora potrete usare il vostro ide tranquillamente.

Aprire tutte le volte l'Ide entrando nella cartella HOME e premendo sempre esegui è di una noia mortale, allora come crearsi un lanciatore? Semplicissimo.

Per creare un lanciatore arduino su un pannello dovrete cliccare col sinistro sul pannello, poi premete aggiungi al pannello e vi si aprirà questa schermata.

Creazione Lanciatore
Premete Lanciatore applicazione personalizzato, poi vi si aprirà questa finestrina. Cliccate su esplora e si aprirà la HOME. In home entrate nella cartella in cui è contenuto l IDE e selezionate il File Arduino.

Come Nome mettete Arduino-xxxx dove xxxx sta per la versione, il commento è facoltativo. Per avere l un immagine bellina del lanciatore potrete utilizzarte questa.

Arduino Icon

Cliccateci sopra e si aprirà in un'altra pagina, poi la salvate con nome nella cartella di arduino in home e la potrete utilizzare come icona del vostro lanciatore.

Lo stesso processo lo potrete utilizzare per AWN, ecco la mia dock bar

DockBar Ubuntu
Ho usato lo stesso metodo anche per installare Processing come potete vedere.

CC

 
Brainbooster
Che cos'è il PWM
Tutorials -
Lunedì 05 Luglio 2010 22:44
Scritto da Brainbooster

Ovvero prendiamo confidenza con il PWM di Arduino Duemilanove

La modulazione di larghezza di impulso (Pulse Width Modulation) pu√≤ essere usata da Arduino in diversi modi. In questo tutorial cercher√≤ di spiegare l'uso di PWM "semplici" , cos√¨ come come utilizzare il PWM  ed i registri che lo regolano per un maggiore controllo sul ciclo di lavoro e di frequenza.

Un segnale PWM √® un'onda quadra (meglio rettangolare) che varia da 0V a VCC (tensione di uscita massima che per arduino √® 5V) , dove la frequenza √® costante , e cambia la frazione di tempo in cui il segnale √® attivo  a VCC ( detto ciclo di lavoro utile o dutycycle) pu√≤ essere variata tra 0 e 100 %.

Your browser may not support display of this image.

Il PWM ha diversi utilizzi :

  • Variare la luminosit√† di un led LED (tramite un filtro rc), fornendo una tensione analogica tra lo 0% e il 100%.
  • Generare di frequenze udibili e quindi audio
  • Controllare la velocit√† dei motori
  • Controllare servomotori da modellismo
  • Puo essere usato come generatore di segnale modulante
  • Ed altro ancora

Semplice PWM con l'uso del comando analogWrite

Il linguaggio di programmazione Arduino, rende il PWM facile da usare , è sufficiente chiamare analogWrite(Pin , dutyCycle ), Dove dutyCycle è un valore da 0 a 255, e Pin è uno dei pin PWM (3, 5 , 6, 9 , 10, o 11). Il comando analogWrite fornisce una semplice interfaccia per il PWM hardware, ma non fornisce alcun controllo sulla frequenza.

Ma andiamo un p√≤ pi√Ļ in profondit√†... ci sono altre opzioni che forniscono pi√Ļ flessibilit√† :)

Il PWM manuale su tutti i pin

√ą possibile  creare "manualmente" un PWM su ogni pin semplicemente "spegnendo" e "accendendo" un pin in uscita. ad esempio:

void setup ()

{

pinMode (13, OUTPUT) ;

}

void loop ()

{

digitalWrite (13 , HIGH) ;   / / Lascio il pin "acceso" (per 100ms)

delayMicroseconds (100); / / Circa il 10 %  di duty cycle (sarebbe 1KHz)

digitalWrite (13, LOW);     / / Spengo il pin ed aspetto il prossimo ciclo

delayMicroseconds (900) ;/ / Attesa prima del prossimo ciclo (per 900ms)

}

 

Facendo così, si ha il vantaggio di poter utilizzare qualsiasi pin di uscita digitale . Inoltre, avete il pieno controllo del duty cycle e della frequenza. Uno dei principali svantaggi è che ogni interrupt inciderà negativamente sui tempi , a meno che non si disattivino gli interrupt. Un altro svantaggio è che non si può lasciare girare il processo mentre il processore fa qualcos'altro. Infine , è difficile determinare le costanti appropriate per un ciclo di funzionamento particolare e la frequenza richiesta, a meno che non si calcoli attentamente dai cicli di clock.

Uso del PWM parlando con i registri dell'atmega di Arduino

Il chip ATmega168P/328P ha tre timer PWM , che controllano le 6 uscite PWM. Manipolando il timer del chip direttamente tramite i registri , è possibile ottenere un maggiore controllo rispetto al analogWrite per "piegarlo" alle nostre necessità.

Il datasheet dell'ATmega328P  fornisce una descrizione dettagliata dei timer PWM, ma ati pu√≤ essere difficile da capire, a causa delle molteplici modalit√† di uso dei timer.

Proviamo a capirci qualcosa. (datasheet alla mano ;) )

Il ATmega328P ha tre timer conosciuti come Timer 0, Timer 1 e Timer 2 . Ogni timer ha due output con dei registri a comparazione che controllano la larghezza PWM per il timer di due uscite : quando il timer raggiunge il valore di comparazione impostato nel registro , l'uscita corrispondente è attivata . Le due uscite per ogni timer normalmente hanno la stessa frequenza , ma possono avere cicli di lavoro differenti (a seconda dei rispettivi valori dei registri a comparazione).

Ciascuno dei timer ha un prescaler che genera il suo clock dividendo il clock di sistema per un fattore di Prescale come 1, 8, 64 , 256 o 1024. Arduino duemilanove ha un clock di sistema di 16MHz e la frequenza di clock del timer sarà la frequenza di clock di sistema diviso per il fattore Prescale . Attenzione il Timer 2 ha un diverso insieme di valori Prescale rispetto agli altri timer .

I timers sono complicati da diverse modalit√† di uso e controllo. Le modalit√† PWM principali sono " PWM Fast "e" PWM a correzzione di fase ". Il timer pu√≤ essere pilotato con valori 0-255 (8 bit) , o da un valore fisso, se serve. (Il  Timer 1  √® dotato di modalit√† supplementari per supportare valori fino a 16 bit. ) Ogni uscita pu√≤ anche essere invertita.

Il timer può anche generare interrupt con overflow , ma questo và oltre le mie possibilità esplicative (per adesso).

Timers e Registri

Per controllare ogni timer vengono utilizzati vari registri. I Timer / Counter dei Registri di controllo  TCCRnA e TCCRnB contengono il bit di controllo principale per i timers.Questi registri possono contenere diversi gruppi di bit :

  • bit di Generazione di forme d'onda ( WGM ): questa e la modalit√† di controllo globale del timer. (Questi bit sono divisi tra TCCRnA e TCCRnB .)
  • bit Clock Select ( CS ): questo serve a controllare il prescaler sul clock
  • bit di comparazione uscita A ( COMnA ): questo serve ad attivare / disattivare / l'output invertito per  l'uscita A
  • bit di comparazione uscita B ( COMnB ): questo serve ad attivare / disattivare / l'output invertito l'uscita B

Le uscite di comparazione dei Registri OCRnA e OCRnB servono ad impostare i livelli a cui le uscite A e B saranno "azionate". Quando il valore del timer corrisponde al valore di registro , l'uscita corrispondente viene modificata come specificato dalla modalità.

I bit sono leggermente diversi per ogni timer , (vedi datasheet per i dettagli).Come dicevamo prima, il Timer 1 è un timer a 16 bit e dispone di modalità aggiuntive e Timer 2 ha valori diversi di prescaler .

Fast PWM

Nel "semplice" PWM , il timer conta ripetutamente 0-255 . L'uscita si accende quando il timer √® a 0, e si spegne quando il timer corrisponde a quanto impostato nell'apposito registro. Pi√Ļ alto √® il valore nel registro di uscita , maggiore √® il dutycycle. Questa modalit√† √® nota come Fast PWM Mode.

L'esempio seguente illustra come usare le uscite per due valori particolari di OCRnA e OCRnB . Da notare che entrambe le uscite hanno la stessa frequenza, ed usano la frequenza di un ciclo completo di clock .

Fast PWM Mode

L'esempio di codice seguente imposta il PWM sui pin 3 e 11, (Timer 2). Per riassumere le impostazioni di registro , Il bit di generazzione di forma d'onda WGM lo impostiamo a 011 (selezione fast PWM mode). Impostiamo i bit COM2A e COM2B a 10 (PWM non invertito per le uscite A e B). l'impostazione del bit CS la mettiamo a 100 (quindi dividiamo il clock di sistema per 64). (Poiché i bit sono diversi per i diversi timer , consultare il datasheet .)

Le uscite dei registri di comparazione sono impostate arbitrariamente a 180 e 50 per il controllo del dutycycle del PWM per le uscite A e B. (Naturalmente, si può anche modificare i registri direttamente invece di utilizzare pinMode, ma è necessario impostare il pin di uscita. )

 

Su Arduino Duemilanove , abbiamo questi valori :

* Frequenza dell'uscita A: 16 MHz / 64 / 256 = 976.5625Hz

* Uscita A dutycycle: (180 +1) / 256 = 70,7%

* Frequenza dell'uscita B: 16 MHz / 64 / 256 = 976.5625Hz

* Uscita B dutycycle: (50 +1) / 256 = 19,9%

La frequenza di 16MHz (frequenza del clock di sistema), diviso per il valore prescaler (64) , diviso per i 256 cicli necessari per un ciclo del timer.

PWM a correzione di fase

La seconda modalit√† di PWM  √® chiamata phase-correct PWM. In questa modalit√† , il timer conta da 0 a 255 e poi di nuovo gi√Ļ a 0. L'uscita si spegne, appena il timer raggiunge il valore del registro di comparazione di uscita durante la salita , e si gira nuovamente appena il timer raggiunge il valore del registro di comparazione di uscita durante la discesa . Il risultato √® un uscita pi√Ļ simmetrica . La frequenza di uscita sar√† pari a circa la met√† del valore per la modalit√† fast PWM, perch√© avverr√† allo scadere del tempo , sia in su che in gi√Ļ (un p√≤ dome le memorie DDR dei pc).

L'esempio seguente imposta il PWM a correzione di fase sui pin 3 e 11, (Timer 2). I bit di forma d'onda WGM sono impostati su a 001 (fase -correct PWM).

Gli altri bit sono uguali allèesempio del fast PWM .

pinMode (3, OUTPUT) ;

pinMode (11, OUTPUT) ;

TCCR2A = _BV ( COM2A1 ) | _BV ( COM2B1 ) | _BV ( WGM21 ) | _BV ( WGM20 );

TCCR2B = _BV ( CS22 );

OCR2A = 180 ;

OCR2B = 50;

Su Arduino Duemilanove , abbiamo questi valori:

  • Frequenza uscita A : 16 MHz / 64 / 255 / 2 = 490.196Hz
  • Dutycycle uscita A: 180/255 = 70,6%
  • Frequenza uscita B : 16 MHz / 64 / 255 / 2 = 490.196Hz
  • Dutycycle uscita B : 50 / 255 = 19,6%

Come vedete dai valori, il PWM phase correct , divide la frequenza in due rispetto al fast PWM, perché il timer scatta sia a monte che a valle . Sorpresa delle sorprese, la frequenza è divisa per 255 invece di 256, e ai calcoli del Ciclo non aggiunge uno come per il fastPWM.

Oltre il limite : fast PWM

Entrambi le modalit√† di PWM dispongono di un modo aggiuntivo che permette di controllare la frequenza di uscita . In questa modalit√† , il timer conta da 0 a OCRA, invece  che da 0 a 255. Questo d√† un controllo sulla frequenza di uscita pi√Ļ preciso rispetto alle modalit√† precedenti. (Per un controllo di frequenza ancora pi√Ļ preciso, usa il timer 1 a 16 bit ).

Si noti però,che in questa modalità, solo uscita B può essere utilizzata per il PWM ; OCRA non può essere utilizzato in due modi contemporaneamente. Tuttavia, vi è una modalità speciale per caso "Toggle Ocna on Match "che cambia lo stato di uscita A alla fine di ogni ciclo , generando un duty cycle fisso del 50% e la frequenza di un mezzo in questo caso.

Nel diagramma seguente, il timer viene azzerato quando cicla OCRnA , producendo una frequenza di uscita pi√Ļ veloce per OCnB che negli esempi precedenti. Nota come Ocna cambia una volta per ogni reset del timer.

Fast PWM con cimatura di OCRA.

Il codice seguente imposta PWM fast sui pin 3 e 11, (Timer 2), utilizzando OCR2A come valore di limite superiore del timer. Il bit di forma d'onda e generazione WGM sono impostati su 111 per PWM fast ma ora OCRA  ha il controllo sul limite superiore. Il limite superiore di OCR2A lo fissiamo arbitrariamente a 180 , e  OCR2B lo fissiamo arbitrariamente a 50. OCR2A adesso e in modalit√† " Attiva quando corrisponde", imposiamo il bit COM2A a 01 .

pinMode (3, OUTPUT) ;

pinMode (11, OUTPUT) ;

TCCR2A = _BV ( COM2A0 ) | _BV ( COM2B1 ) | _BV ( WGM21 ) | _BV ( WGM20 );

TCCR2B = _BV ( WGM22 ) | _BV ( CS22 );

OCR2A = 180 ;

OCR2B = 50;

Sul Arduino Duemilanove , abbiamo questi valori :

  • Frequenza di uscita A: 16 MHz / 64 / (180 +1) / 2 = 690.6Hz
  • Dutycycle uscita A : 50%
  • Frequenza di uscita B : 16 MHz / 64 / (180 +1) = 1381.2Hz
  • Dutycycle uscita B: (50 +1) / (180 +1) = 28,2%

Si noti che in questo esempio, il timer va da 0 a 180, che però prende 181 cicli di clock , per cui la frequenza di uscita è divisa per 181. L'uscita A ha la metà della frequenza dell'uscita B perché la modalità di confronto cambia l'uscita A una volta per ogni ciclo completo del timer .

Oltre ogni limite : ma per il phase-correct PWM

Allo stesso modo , il timer può essere configurato per il phase -correct PWM e ciclare quando raggiunge OCRnA .

L'esempio seguente imposta PWM phase correct sui pin 3 e 11, (con il Timer 2), utilizzando OCR2A come valore superiore per il timer. I bit del WGM sono impostati su a 101 per PWM phase correct con il controllo del limite superiore. Il limite superiore  OCR2A √® fissato arbitrariamente a 180 , e la OCR2B (registro di confronto) √® fissato arbitrariamente a 50. OCR2A modalit√† √® impostato su " Attiva su corrispondenza al confronto", impostando i bit COM2A a 01 .

pinMode (3, OUTPUT) ;

pinMode (11, OUTPUT) ;

TCCR2A = _BV ( COM2A0 ) | _BV ( COM2B1 ) | _BV ( WGM20 );

TCCR2B = _BV ( WGM22 ) | _BV ( CS22 );

OCR2A = 180 ;

OCR2B = 50;

Sul Arduino Duemilanove , abbiamo questi valori :

  • Frequenza dell'uscita A: 16 MHz / 64 / 180 / 2 / 2 = 347.2Hz
  • Dutycycle uscita A : 50%
  • Frequenza dell'uscita B: 16 MHz / 64 / 180 / 2 = 694.4Hz
  • Dutycycle uscita B: 50 / 180 = 27,8%

Si noti che in questo esempio, il timer va da 0 a 180 e di nuovo a 0 , il che prende 360 cicli di clock. Così, tutto è diviso per 180 o 360, a differenza del caso PWM fast, che invece ha diviso tutto con per 181 ( vedi sotto per i dettagli).

L'errore "Off- by-one".

Avrete notato che PWM fast e PWM phase correct sembrano essere off- by-one l'uno  rispetto all'altro , dividendo per 256 invece che per 255 e aggiungendo uno in vari luoghi.

Supponiamo che il timer sia impostato in modalit√† PWM fast √® impostata a contare fino a un valore di OCRnA di 3. Il timer assumer√† i valori 012301230123 ... Si noti che ci sono 4 cicli di clock per ogni ciclo del timer. Cos√¨, la frequenza sar√† divisa per 4 e non 3. Il dutycycle sar√† un multiplo di 25%, dato che il segnale sara "alto" a  0, 1, 2 , 3 o 4 . Allo stesso modo, se il timer conta fino a 255 , ci saranno 256 cicli di clock in ogni ciclo del timer , e il dutycycle sar√† multiplo di 1 / 256 . Quindi, PWM fast divide per N +1 , dove N √® il valore del timer massimo (sia OCRnA o 255).

Ora consideriamo la modalit√† PWM phase correct con il timer conta fino ad un valore di OCRnA 3. I valori di timer sar√† 012321012321 ... Ci sono 6 cicli di clock per ogni ciclo del timer ( 012.321 ). Cos√¨ la frequenza sar√† diviso per 6. Il ciclo di lavoro sar√† un multiplo di 33%, dato che il segnale sar√† "alto"  per 0, 2 , 4 o 6 dei 6 cicli . Allo stesso modo, se il timer conta fino a 255 e ritorno verso il basso , ci saranno 510 cicli di clock in ogni ciclo del timer , e il dutycycle sar√† un multiplo di 1 / 255 . Quindi, PWM phase correct divide per 2N , dove N √® il valore del timer massimo.

La seconda differenza importante √® che il PWM fast tiene l'output ad alto per un ciclo pi√Ļ lungo del valore del registro di comparazione. La motivazione di ci√≤ √® che PWM fast  conta fino a 255 , il dutycycle pu√≤ essere 0-256 cicli, ma il registro pu√≤ contenere solo un valore da 0 a 255. Cosa succede al valore mancante ? La modalit√† PWM fast mantiene l' alta l'uscita per cicli di N +1 quando il registro di comparazione √® impostato su N cos√¨ un registro con valore di 255 √® 100 % del dutycycle, ma un registro con valore 0 √® non dutycycle  0 %, ma 1 / 256 del dutycycle. Questo a differenza del PWM phase correct, in cui un valore di registro di 255 √® 100 % del dutycycle e un valore di 0 √® un dutycycle dello 0%.

Timer e Arduino

Il Arduino supporta PWM su alcuni dei pin di uscita. Può non essere immediatamente evidente che c'è in timer che ne controlla l'utilizzo , ma la tabella seguente chiarirà la situazione. Essa fornisce, per ogni uscita del temporizzatore, il pin di uscita sul Arduino (cioè l'etichetta serigrafata sulla scheda) , il pin sul chip ATmega , e il nome e poco di porta di uscita . Per esempio Timer 0 OC0A uscita è collegata all'uscita Arduino pin 6 , utilizza chip pin 12 che è anche conosciuto come PD6 .

Timer di uscita Uscita su Arduino Pin sul chip Nome pin

OC0A                          6                          12                 PD6

OC0B                          5                          11                 PD5

OC1A                          9                          15                 PB1

OC1B                         10                          16                 PB2

OC2A                         11                          17                 PB3

OC2B                           3                            5                 PD3

Arduino inizializza il prescaler su tutti e tre i timer per dividere il clock per 64. Timer 0 è inizializzato in PWM fast, mentre i Timer 1 e Timer 2 vengono impostati come PWM phase correct .

Il Arduino utilizza il Timer 0 interno per i comandi Millis () e delay () , quindi sappiate che modificando la frequenza di questo timer quei comandi danno segni di pazzia. Usare le uscite PWM, invece,  √® sicuro se non si cambiamo le frequenze.

Con il comando analogWrite (pin , duty_cycle ) si imposta il pin appropriato PWM e  l'output appropriato nel registro di comparazione (Con il caso particolare di dutycycle del Timer 0 su 0). Il comndo digitalWrite () disattiva l'uscita PWM se viene chiamato su un pin timer.

Se si utilizza analogWrite (5, 0) si ottiene un dutycycle dello 0% , anche se il pin 5 del timer ( Timer 0) utilizza PWM fast. Come è possibile , quando un valore di PWM fast di 0 produce un ciclo di 1 / 256 , come spiegato sopra? La risposta è che analogWrite " bara" , ha un codice per i "casi speciali" per spegnere il pin quando si usa il Timer 0 con un dutycycle pari a 0. Come conseguenza , il ciclo che doveva essere 1 / 256 non è disponibile quando si utilizza analogWrite su Timer0 , e vi è un salto nel ciclo di lavoro reale tra i valori di 0 e 1.

Spero che questo piccolo tutorial messo insieme studianodo varii documenti reperibili sulla rete ed il datasheet dell'atmega 328, sia utile a tutti voi così come è stato utile per mè.

trovate il documento originale su cui è basato questo tutorial all'indirizzo: http://www.arcfn.com/2009/07/secrets-of-arduino-pwm.html

Ciao

Brainbooster

 
gbm
Che cos'è l'algoritmo PID
Tutorials -
Lunedì 05 Luglio 2010 01:42
Scritto da gbm

Ciao a tutti. In queste ultimi mesi mi sono dedicato principalmente ad algoritmi per la correzione di un errore. Sono partito dall'algoritmo PID. Questo costrutto matematico è uno strumento molto utile nel line following (inseguitori di linea) e in quasi tutti gli altri campi dell'automazione. E' un'ottima base matematica da capire ed utilizzare per gestire la reazione ad un dato errore. Chiaramente non è la scelta piu' indicata per qualsiasi applicazione ma risulta davvero versatile. Trovo che sia fondamentale per un appassionato conoscere il funzionamento di questo tipo di correzione. Per questo ho scritto questa guida. Allo stesso modo noto che è un ambito abbastanza discusso, ma soprattuto ho trovato varie "interpretazioni" di questo algoritmo. Esiste una libreria: PID library arduino l'ho testa insieme al suo ottimo visualizzatore grafico che consiglio: Graphical frontend PID arduino ma sinceramente non mi sono trovato come avrei voluto. Poi caricare una libreria e perdersi il concetto di base secondo me è sbagliato. Quindi l'ho riscitto e ci ho lavorato parecchio. Alla fine sono 5 righe e non credo serva realmente una libreria per questo.

 

Proporzionale


P - proporzionale PID

P = valore errore * kP (variabile utilizzata per la regolazione)

L'azione proporzionale varia proporzionalmente all'errore. Questa parte è importante per le micro-correzioni o comunque in tutto il range di utilizzo dove la considerazione del tempo è trascurabile. E' possibile correggere un errore utilizzando unicamente questa parte, solo che il comportamento del sistema sarà oscillante e difficilmente convergerà verso lo 0, ma piu' probabilmente avrà un'andamento instabile che spesso ricade in risonanza.

Ponendo kP 0 e aumentandola uniformemente otterremo miglioramento nel tempo di crescita della correzione, aumento dell'esagerazione nella correzione, una grande diminuzione dell'errore in stato statico e a valori alti un effettivo degrado della stabilità.

 

Integrale


I - integrale PID

I  = [valore errore * őĒt (durata loop) ] * per kI (regolazione)

L'azione integrale è propriamente l'integrale dell'errore rispetto al tempo. In parole povere I è un valore in cui viene sommato l'errore, questo viene moltiplicato per l'intervallo di tempo tra questa acquisizione e quella precedente. Il risultato (supponendo si volesse correggere un errore negativo) è un valore che non si azzerera raggiunto lo 0 come fa P, ma necessita che l'errore diventi negativo per un tempo che varia in rapporto all'accumulazione dell'errore stesso. Questa parte è un'ottima base per la correzione dell'inerzia acquisita se l'errore si protrae nel tempo (o almeno io l'ho utilizzata in quest'ambito) e soprattutto se ben regolata aiuta l'algoritmo a raggiungere lo zero ammorbidendo la forma della curva di risposta.

Ponendo kI 0 e aumentandola uniformemente otterremo rallentamento nel tempo di crescita della correzione, aumento massiccio dell'esagerazione nella correzione, una diminuzione dell'errore in stato statico e a valori alti un effettivo degrado della stabilità.

 

Derivativa


D - derivativa PID

D = valore errore - valore errore loop precedente / őĒt (durata loop)

L'azione derivativa è studiata per compensare rapidamente le variazioni del segnale di errore. Questa correzione varia in rapporto alla velocità di cambiamento dell'errore. In poche parole è necessario ricordare l'errore della scorsa acquisizione e sottrarlo all'errore attuale. Ho notato che molti sul web snobbano questa parte, in tantissimi programmi viene regolata al minimo. Secondo me questa parte è poco capita dalla comunità. Io stesso ho faccio fatica a trovare una regolazione corretta e spesso ricado nel disabilitarla. Consiglio vivamente di sperimentare.

Ponendo kD 0 e aumentandola uniformemente otterremo una diminuzione leggera nel tempo di crescita della correzione, una diminuizione dell'esagerazione nella correzione e se kD ha un valore piuttosto basso puo' migliorare la stabilità.

 

La somma di questi tre termini è la correzione prodotta dall'algoritmo. Guardando le formule (fonte wiki) per molti sembrerà roba da nerd inconcepibile (e questo è anche un po' colpa dei matematici), ma studiata e applicata su qualcosa di fisico e ricontrabile è facile farla propria.

La cosa importante su cui io all'inizio sono caduto √® l'analisi del tempo. E' facile pensare che il loop gia scandisca di per se il tempo, ma la durata di ogni loop √® differente, in rapporto a come vengono svolte le routine e cosa sta succedendo, per questo serve salvarsi in due variabili (nel codice di esempio time e previousTime, i millis() di prima e dopo l'acquisizione per conoscere l'intervallo di tempo intercorso (őĒt). Chiaramente aggiungendo funzioni o routine, √® possibile che őĒt aumenti e modifichi il comportamento del PID in questo caso andr√† ricalibrato (molto probabilmente baster√† diminuire equamente I e D in rapporto a quanto √® aumentato őĒt ).

Qui credo di scrivere qualcosa di leggermente discordante da questo interessante ebook creato da Sergio Camici per www.roboitalia.com. Come potete leggere la ritmica di funzionamento che usa Sergio è a tempo costante. Io ho scirtto una cosa leggermente diversa. Invece che avere un tempo costante e scartare il tempo avanzato aspettando il prossimo turno, semplicemente cronometro il tempo necessario per ogni loop e lo moltiplico. In questo caso, se un'acquisizione è durata piu' di un'altra avrà piu' peso nella correzione. Il codice sottostante sono decine di ore di sperimentazione e test empirici. Ma devo dire funziona piuttosto bene, è ancora leggermente affetto da Parkinson, ma spero di risolvero affinando le regolazioni.

 

Ecco un video che dimostra il funzionamento:

 

 

Come potete vedere la correzione è tutt'altro che perfetta. E' ancora oscillante e troppo determinata da P. Ma la cosa che davvero mi entusiasma è quanto la I sia in grado di correggere il momento inerziale acquisito da PICO in rapporto al tempo (e quindi quanto ha accelerato) in una direzione. Riesce effettivamente ad annullare il momento inerziale e spesso a riportare il robot quasi nella stessa posizione da cui è stato spinto via.

Ecco il codice:

//Giovanni Blu Mitolo - Gioblu Robotics - released under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License..
//use and enjoy free :-) - gioscarab[att]gmail.com
//Giovanni Blu Mitolo - Gioblu Robotics - materiale rilasciato sotto licenza Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
//usa pure e divertiti  :-) - gioscarab[att]gmail.com

#include  //Library used to interface servos - ibreria utilizzata per pilotare servi 
                    
Servo left; 
Servo right;

float time = 0;

#define servoLeftPin     9
#define servoRightPin   10
#define servoZero       81 //calibration 4 servos - calibrazione per servi
#define IRFront          2 
#define IRBack           3
#define ledPin          13 
#define leftIr           2 //proximity ir emitters - emettitori ir x sensori prossimità
#define rightIr          4


int frontSense = 0; //forward ir sensor - sensore ir anteriore
int backSense = 0;  //backward ir sensor - sensore ir posteriore
int orientation = 0;
int previousOrientation = 0;

float P = 0;
float I = 0;  //Il mesurement (empirism) - misurazione inerziale
float D = 0;
int fall = 0;       //value used to determine if the robot is fall
                    //variabile utilizzata per determinare se il robot è caduto
float kP = 12;      //used to tune
float kI = 430;
float kD = 20;

void setup() {
pinMode(ledPin, OUTPUT);
left.attach(servoLeftPin);
right.attach(servoRightPin);
left.write(servoZero);
right.write(servoZero);
Serial.begin(9600);
}


void getOrientation() {
  frontSense = 0;
  backSense = 0;
  orientation = 0;
 for (int i = 0; i < 10; i++) {
  frontSense = analogRead(IRFront) + frontSense;
  backSense = analogRead(IRBack) + backSense;
  if (i == 9) {
   frontSense = frontSense / 10;
   backSense = backSense / 10;
   orientation = frontSense - backSense;
  }
 }
}

/*Simplest thing ever
Stop wheels for 1/4 of a second
to get momentum to get up*/

/*La cosa piu' semplice del mondo
Stop alle ruote per 1/4 di secondo
per ottenere abbastanza momento per 
rialzarsi*/

void autoGetUp() {
if (fall == 25 || fall == - 25) {
 left.write(servoZero);
 right.write(servoZero);
 delay(250);
 fall = 0;
 I = 0;
}
}


void loop() {
autoGetUp();
getOrientation();
float previousTime = time;
time = millis();
float interval = time - previousTime;
      P = orientation / kP;
      I = I + (P * interval) / kI;
      D = (orientation - previousOrientation) / interval / kD;
      float PID = P + I + D;
if(P > 90) P = 90; //stop increase or decrease of the value
if(P < -90) P = -90; //costrizione del valore tra 90 e -90
if(orientation > 250) fall = fall + 1; 
if(orientation < -250) fall = fall - 1;
if(PID <= 1 && PID > 0) PID = 0; //cut off micro-corrections
if(PID >= -1 && PID < 0) PID = 0;
left.write(81 - PID);
right.write(81 + PID); 
previousOrientation = orientation;
Serial.print(P);
Serial.print("  ");
Serial.print(I);
Serial.print("  ");
Serial.print(D);
Serial.print("  ");
Serial.print(interval);
Serial.print("  ");
Serial.println(orientation);
}

Creative Commons License
PID self balancing by Giovanni Blu Mitolo is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
Based on a work at
www.gioblu.com.

 
Edoardo Vignali
Upload bootloader arduino senza programmer AVR (BitBangMode)
Tutorials -
Venerdì 18 Giugno 2010 17:15
Scritto da Edoardo Vignali

Non avreste sempre voluto sapere come scrivere il bootloader arduino su dei chip vergini senza dover per forza comprare un programmatore AVR? In questa guida sarà illustrato come fare, servendoci semplicemente di un arduino Diecimila, Duemilanove o NG.

Ho testato personalmente con successo questo metodo su Windows XP, prossimamente proverò su Windows 7 e Ubuntu Lucid Lynx.

Per scrivere il nostro bootloader andremo ad utilizzare l'FT232 in modalità BitBang, che ci permette di trasformare gli 8 IO di questo integrato, in un bus bidirezionale a 8 bit. Utilizzeremo anche "avrdude-serjtag" che è un software che permette ad uno degli Arduino sopracitati di scrivere il bootloader su un chip vergine. Nei punti che seguono utilizzerò come esempio un arduino diecimila.

Il principio di funzionamento della bitbang è molto semplice e molto brutale, infatti si scrive direttamente sul micro tramite il chip FT232. Una perfetta analogia è in questa immagine.

 

Analogia

1. Modificare Arduino

Sulla nostra Board ci sono 4 piazzole (pads) chiamate X3 e si trovano vicino all'integrato FT232, dovrete rimuovere lo stagno dai fori passanti o con una pompetta "ciucciastagno" o con una treccia per saldare (solder wink). Adesso inserite 4 Pin nei fori e saldateli. Sconsiglio alle persone poco pratiche di saldare direttamente i pin sulla board senza aver tolto lo stagno presente, anzi consiglio di aggiungere del flussante.

La soluzione che ho adottato io è stata quella di mettere dei pin femmina sia nella porta ICSP, sia nella porta X3, in questo modo posso connettere le due porte molto facilmente con quattro cavetti.

 

Collegamenti Bit Bang

Altri metodi di cablaggio

Collegamenti bit bang mode

2. Software da scaricare

  • "avrdude-serjtag" FTDI BitBang AVR-Writer

serjtag-0.3.zip

serjtag-0.3.tar.gz

  • Scaricate il file di configurazione per avrdude-serjtag

avrdude.conf

  • "avrdude-GUI (yuki-lab.jp Version)" GUI wrapper for avrdude

avrdude-GUI-1.0.5.zip mirror site

avrdude-GUI-1.0.5.zip original site (http://yuki-lab.jp/hw/avrdude-GUI/index.html)

  • avrdude-GUI ha bisogno della Microsoft Netframework 2.0

La troverete qui (Microsoft .NET Framework 2.0 download page)

3. Installazioni

  • Avrdude-serjtag

Per installare Avrdude-serjtag dovrete semplicemente estrarre la cartella in "C:\Program Files"

 

C:

Cancellate la cartella src dentro la cartella avrdude-serjtag.

  • avrdude.conf

Copiate questo file nella cartella C:\Program Files\avrdude-serjtag\binary sovrascrivendolo con l originale.

Il file che sovrascrivete a avrdude.conf conterrà i settings per arduino diecimila

# Arduino Diecimila
programmer programmatore
id="diecimila"; id = "diecimila";
desc = "FT232R Synchronous BitBang"; desc = "FT232R sincroni BitBang";
type = ft245r; tipo = ft245r;
miso = 3;  # CTS X3(1) miso = 3; CTS # X3 (1)
sck = 5;  # DSR X3(2) SCK = 5; # DSR X3 (2)
mosi = 6;  # DCD X3(3) Mosi = 6; X3 # DCD (3)
reset = 7;  # RI X3(4) reset = 7; # RI X3 (4)
;
  • avrdude-GUI (yuki-lab.jp Version)

Si installa come avrdude-serjtag. Estraete l'archivio, poi spostate la cartella ""avrdude-GUI-1.0.5" dentro  "C:\Program Files" folder. Funzioner√† solo con [1].

3. Settings

Aprite il file"avrdude-GUI.exe" che si troverà in "C:\Program Files\avrdude-GUI-1.0.5".

Avrdude gui

Adesso selezionate le scelte come in figura.

gui-markggui

In (i) dovrete premere il bottone con ... e navigare tra le cartelle finchè non troverete avrdude.exe. Il percorso è indicato in figura.

in (ii) dovrete scegliere bitbang diecimila. in (iii) dovrete scegliere un controllore, nel caso del diecimila, il 168. In (iv) si definiscono le opzioni di scrittura, -P sarebbe la porta, -B il baudrate (slow clock).

4. Testing

Prima di scrivere qualsiasi cosa sul nostro micro vediamo se tutto va bene, premete read e se i Fuses saranno quelli in foto allora il nostro micro e il nostro controllore staranno comunicando correttamente.

fuses atmega168

Se i Fuses saranno diversi da questi prima ricontrollate le connessioni, poi riprovate a leggere. Questa operazione va fatta con un Atmega già programmato e serve solo per testare se tutto funziona.

5. Scrivere il bootloader.

Per prima cosa dovrete staccare l arduino dal pc. Rimuovere il micro programmato, e inserire quello vergine. Dopo aver inserito il micro vergine, ricollegate arduino diecimila al pc. I chip vergini lavorano solo in SLOW CLOCK (attenzione), quindi il -B 4800 è necessario.

Cancellate il chip premendo chip erase, poi leggete il valore del Lock Bit.

erase chip

Inserite il valore dei fuses che aveva il vostro atmega originale e premete write. Adesso potrete togliere il -B4800.

flash

Premete sul bottone con i tre puntini ... , cercate adesso il bootloader per arduino diecimila con atmega 168. Si trova nella cartella dell ide arduino, lì troverete anche tutti gli altri bootloader. Una volta selezionato il giusto bootloader premete Erase-Write-Verify.

Ora che il Bootloader è stato scritto staccate arduino dal pc, scollegate la X3 dalla icsp e ricollegatelo al pc. Selezionate la giusta porta e la giusta scheda nell ide e caricateci sopra lo sketch blink per testare se tutto funziona.

I fuses per gli altri micro sono indicati in questa tabella

Micro hfuse lfuse efuse unlock lock
Atmega8 CA DF nc 3F 0F
Atmega168 DD FF 05 3F 0F
Atmega368 DA FF 05 3F 0F
Atmega1280 42 99 FF 3F 0F

Questo articolo è un riadattamento in italiano di questo articolo.

L'immagine in alto è stata presa da Hack a Day

cc

 
«InizioPrec.1234567Succ.Fine»

Pagina 6 di 7

Gioblu Robotics ¬© 2010 - 2012 · Sitemap · privacy

gioscarab@gmail.com · Via Savona 123 20146 Milano MI · PI 06977550968 · Codice fiscale MTLGNN86S09F205F

Gioblu BOTServer è online dal 10 Aprile 2010 - 319.232 Visite - 1.027.175 Pagine visualizzate - 182.309 Visitatori unici - 536 utenti attivi