![]() |
Head track con Arduino e Nunchuk Salve, dopo un po di tempo libero a disposizione, mi sono messo all'opera per costruirmi un head Track artigianale, ho fatto delle prove .. dai test sembra funzionare! Cos'è un Head track ? in volo FPV con occhiali LCD avere la possibilità di pilotare la telecamera solo con il movimento della testa! in questo modo si offre al pilota una sensazione di maggiore realtà nel volo, voi girate la testa verso destra e la telecamera esegue lo stesso movimento. In casa mi trovavo un Nunchuk, non originale dal costo di circa 10 euro, dopo non poca fatica sono riuscito a captare il segnale protocollo I2C, dei sensori accellerometri, ricordo che l'affare invia anche i dati del Joystick di bordo e dei due bottoni. Insomma captando solo i due accellerometri che mi servono attraverso la funzione analogWrite(pin, valore_x) comunico in PWM la posizione dello stick della radio. Ovviamente occorre aprire la radio, tagliare i cavetti dei poteziometri ch6 e ch7, creare delle spinette in modo che se domani volete ripristinare la radio sarà sufficiente collegare le spinette, ritornando alla funzione originale della vostra radio. Quindi dovete mettere per ognuno dei due potenziometri il GND con quello di Arduino, poi il PWM sullo stesso pin dell'uscita del poteziometro, ovvero il pin del potenziomentro che offre la variazione di voltaggio... per smorzare l'effetto PWM facendo tremare il servo mettete due condensatori da 220 uF 35 V ...in questo modo il servo tornerà ad essere fermo. L'effetto alle estremità è ridotto perchè il duty cycle al 100% implica un segnale praticamene costante ..così come duty cycle 0% ...mentre nelle fasi intermedie ..il servo "balla", quindi usando i condensatori il servo ritornerà fermo ai vostri ordini. In una fase successiva smonto il Nunchuk per estrarre gli accellerometri e disporli in un contenitore apposito. |
ciao. non ho capito una cosa. io sapevo che i potenziomentri degli stick agivano da partitore di tensione determinando la posizione dello stick, il pwm di arduino fa la stessa cosa?? io ho una dx6i, 6 canali bastano per far volare un quadricottero e usare un head tracking?? se non è un problema potresti mettere qualche foto e lo sketch che hai usato???? grazie:) |
Fausto direi che questa volta non ci siamo proprio, ti leggo sempre con attenzione ed apprezzo il tuo desiderio di comunicare i tuoi risultati ad altri però....... Poichè in questo forum cercano suggerimenti e risposte molti niubbi ritengo doveroso correggere alcune imprecisioni. Con un accelerometro a 3 assi come quello contenuto nel Nunchuck (originale) non è possibile rilevare la rotazione della testa per un head tracker, bensì solo le inclinazioni del capo fronte/retro e destra/sinistra come già ti scrissi in un altro post. Se tu sei riuscito a leggere la rotazione sull'asse Z con un accelerometro ti sarei grato se postassi l'algoritmo utilizzato. Anche il sistema di filtraggio del PWM con elettrolitici da 220uF è decisamente sbagliato, per convertire un PWM in tensione va utilizzato un apposito filtro passa-basso opportunamente dimensionato in base alla frequenza e durata impulso (min/Max) del PWM, filtro che deve tener conto anche della tempo di risposta all'impulso. (ad es. rotazione repentina della testa da dx a sx). Questa tecnica è quella comunemente usata nei convertitori DAC, lo schema qui sotto mostra come sono solito convertire in alcune applicazioni un PWM in cc. http://win.wallytech.it/public/PWM_Filter.jpg I componenti che formano il PB sono: R5, R8, R9 e C8, C9. :yeah: |
il primo ciao ElNonino... io devo sempre ringraziarti, perchè mi hai sempre illustrato tutto con chiarezzza, guarda ho fatto le prove io roteo il nunchuk e così rotea anche il servo! meglio di così ? io di elettronica son una frana , come programmatore.. diciamo che ancora me la cavo. dunque per il momento posto i sorgenti in tutto sono tre: il primo #ifndef _NUNCHUK_H_ #define _NUNCHUK_H_ #define NUNCHUK_BUFFER_SIZE 6 class Nunchuk { public: void initialize(); bool update(); //__________________________________________________ _____ int joystick_x() const { return _buffer[0]; } //__________________________________________________ _____ int joystick_y() const { return _buffer[1]; } //__________________________________________________ _____ int x_acceleration() const { return ((int) (_buffer[2]) << 2) | ((_buffer[5] >> 2) & 0x03); } //__________________________________________________ _____ int y_acceleration() const { return ((int) (_buffer[3]) << 2) | ((_buffer[5] >> 4) & 0x03); } //__________________________________________________ _____ int z_acceleration() const { return ((int) (_buffer[4]) << 2) | ((_buffer[5] >> 6) & 0x03); } bool z_button() const { return !(_buffer[5] & 0x01); } bool c_button() const { return !(_buffer[5] & 0x02); } private: void request_data(); char decode_byte(const char); unsigned char _buffer[NUNCHUK_BUFFER_SIZE]; }; #endif Citazione:
|
il secondo il primo era nunchuck.h il secondo nunchuck.cpp il terzo NunchuckDemo.ino questo è il secondo: #include <WProgram.h> #include <Wire.h> #include "nunchuk.h" #define NUNCHUK_DEVICE_ID 0x52 void Nunchuk::initialize() { Wire.begin(); Wire.beginTransmission(NUNCHUK_DEVICE_ID); Wire.write(0x40); Wire.write(0x00); Wire.endTransmission(); update(); } bool Nunchuk::update() { //delay(1); Wire.requestFrom(NUNCHUK_DEVICE_ID, NUNCHUK_BUFFER_SIZE); int byte_counter = 0; while(Wire.available() && byte_counter < NUNCHUK_BUFFER_SIZE) { _buffer[byte_counter++] = decode_byte(Wire.read()); } request_data(); return byte_counter == NUNCHUK_BUFFER_SIZE; } void Nunchuk::request_data() { Wire.beginTransmission(NUNCHUK_DEVICE_ID); Wire.write(0x00); Wire.endTransmission(); } char Nunchuk::decode_byte(const char b) { return (b ^ 0x17) + 0x17; } |
il terzo: ecco il terzo NunchuckDEmo.ino include <Wire.h> #include "nunchuk.h" const unsigned int BAUD_RATE = 9600; const unsigned int MIN = 304; const unsigned int MAX = 712; const unsigned int MIN_OUT = 0; const unsigned int MAX_OUT = 255; Nunchuk nunchuk; int buffer_x = 0; int buffer_y = 0; int buffer_z = 0; int out_x_value = 0; void setup() { Serial.begin(BAUD_RATE); nunchuk.initialize(); } void loop() { analogWrite(3,out_x_value); if(nunchuk.update()) { buffer_x = map(nunchuk.x_acceleration(), MIN,MAX,MIN_OUT,MAX_OUT); buffer_y = map(nunchuk.y_acceleration(), MIN,MAX,MIN_OUT,MAX_OUT); buffer_z = map(nunchuk.z_acceleration(), MIN,MAX,MIN_OUT,MAX_OUT); } if(nunchuk.update()) { if( buffer_x != map(nunchuk.x_acceleration(), MIN,MAX,MIN_OUT,MAX_OUT) || buffer_y != map(nunchuk.y_acceleration(), MIN,MAX,MIN_OUT,MAX_OUT) || buffer_z != map(nunchuk.z_acceleration(), MIN,MAX,MIN_OUT,MAX_OUT)) { out_x_value = map(nunchuk.x_acceleration(), MIN,MAX,MIN_OUT,MAX_OUT); Serial.print(out_x_value); Serial.print(","); Serial.print(map(nunchuk.y_acceleration(), MIN,MAX,MIN_OUT,MAX_OUT)); Serial.print(","); Serial.print(map(nunchuk.z_acceleration(), MIN,MAX,MIN_OUT,MAX_OUT)); Serial.print("\n\r"); } } } |
ok ovviamente si tratta di una demo... appena ho tempo mi ci rimetto per migliorare e metterlo a posto, allo stato attuale converte solo uno dei due assi... infatti invoca solo una volta analogWrite, visto che sono in una fase sperimentale. Per il discorso del DAC avevo pensato di usarlo ho in casa il DAC0808 quindi approvo perfettamente il tuo discorso.... ..però mi son detto prima provo ad usare direttamente il PWM !! facendo le prove mi son imbattuto con il problema della vibrazione del servo, ho capito che si trattava dell'effetto frequenza. Ho provato pure a usare una fotoresistenza al posto del potenziometro, la foto resistenza inserita a calza con un termo restingente , dove dentro ho messo un led pilotato appunto dal PWM di Arduino. Anche in questo caso il risultato ottimo! Comunque la cosa piu semplice è appunto usare il PWM prodotto da Arduino con analogWrite(pin, value) due condensatori da 220 uF 35 V il servo non vibra più e adesso segue perfettamente la roteazione del Nunchuck. |
4 Allegato/i ciao ancora Elnonino.. anch'io tempo fa avevo fatto una discussione sul fatto che il Nunchuk avesse due assi piuttosto che tre come spesso viene spacciato, ricordo anche che alcuni colleghi mi dissero che erano tre assi e che dovevo indagare meglio. Eccola http://www.baronerosso.it/forum/circ...-tre-assi.html Bene in realtà sono solo due come la mia affermazione fatta tempo fa il terzo coincide con il secondo esegue un conteggio sfasato di 90 gradi di inclinazione ma confermo che è sono due assi. Per rendere chiaro tutto metto le foto per far capire quali roteazioni sente il nunchuk, la prima foto e l'ultima mostrano la roteazione x, mentre la seconda e la terza foto mostrano la roteazione y. L'asse z per Nunchuk invece è un invenzione dei marziani! a dopo fausto |
Fausto scusa ma non ci siamo... non ti riesco a seguire. Il nunchuck contiene tre accelerometri, il problema è che tu lo stai utilizzando per leggere una rotazione... Dato il sistema di riferimento XYZ con Z parallelo a G (forza di gravità) mentre effettivamente puoi capire una rotazione sugli assi x e y mediante una composizione in seno e coseno di G non potrai mai capire una rotazione attorno a Z poiché le componenti di G su X e Y non cambiano e la componente Z rimane costante. Non è il nunchuck che non va, è la base che ci sta dietro, per capire una rotazione attorno a Z serve o una bussola magnetica o un giroscopio. |
nota il software .ino che ho scritto ha una particolarità se andiamo a variare const unsigned int MIN_OUT = 0; const unsigned int MAX_OUT = 50; quindi riduciamo il range operativo, lo rendiamo meno sensibile! in questo modo sarà piu facile osservare che esso invierà i dati solo se cambiano.. per esempio supponendo che io voglia creare un sistema di livellamento, non posso occupare costantemtne la seriale, ma solo se ci sono variazioni.. per cui ho creato un firmware che si presta anche per altri esperimenti. a dopo fausto Citazione:
|
Fausto, a volte è difficile capire se leggi le risposte o continui per la tua strada imperterrito..... Bello il tuo lavoro di divulgazione ma almeno provare a capire quello che io e El Nonino ti stiamo dicendo renderebbe i tuoi post un po' meno da blog personale e un po' più da forum... |
scusate la domanda stupida. ma quindi il duty cicle può essere visto come una tensione variabile?? come è possibile che il pwm sul segnale in uscita del potenziometro possa dare una tensione variabile?? sono un po confuso. scusate per l'intromissione tra voi smanettoni |
si si per me è si, aspetto informazioni di Elnonino.. lui in elettronica è piu preparato... Comunque io son partito proprio con quell'idea di simulare il potenziometro con il PWM, poi però sono stato costretto a mettere un paio di condensatori perchè la frequenza del PWM genera vibrazioni.. ho fatto la prova funziona bene! aspetto dei consigli da parte di Elnonino. a dopo Citazione:
|
ok ho capito scusa romoloman.... ...è vero ho sto difetto... sei stato bravo ad attirarmi nell'attenzione... ...comunque adesso che sono stato attento ...ho capito! quindi non potrò mai misurare la posizione angolare secondo l'asse z tenendo conto he questo asse sia parallelo alla forza di gravità ovvero verso il basso, per questo nn è possibile rilevare la roteazione destra/sinistra della testa, ma solo sopra/sotto, diciamo se dovessi usare un disco musicale ( di quelli in vinile di una volta) il nunchick non potrebbe mai informarci della posizione , invece su una ruota di bicicletta potrebbe informarci istante per istante la sua posizione angolare! In altre parole, Il nunchuk potrebbe essere utilizzato come stabilizzatore d'assetto, rollio e beccheggio di aereo, ma non di direzione... per questo dovrebbe intervenire un sensore magnetico... Comuque adesso lascio l'esperimento in corso Head Track ma continuo a studiare per ottenere maggiori competenze con questo Nunchuck , poi passerò ai gyroscopi. a dopo fausto Quindi i definitiva l'asse z dovrebbe rispondere alle accellùerazioni verso il basso, ovviamente se porto su oppure giù con rapidità o diciamo appunto con un accelerazione. Citazione:
|
Citazione:
Buona continuazione di esperimenti..... |
Citazione:
Poiché i potenziometri nelle radio vengono usati come partitori di tensione il trucco di Fausto funziona.... |
Citazione:
Inoltre il tempo di risposta potrebbe essere decisamente elevato per la funzione richiesta nel FPV, un filtro PB ben calcolato funzionerebbe meglio ed Arduino ringrazierebbe. :wink: :D :yeah: |
ok ho capito. io ho una dx6i, se volessi usare un head tracking, su quali canali dovrei trasmettere?? lo switch gyro e gear, supportano una tensione variabile o funzionano solo da switch?? ciao:) |
grazie signori per prima cosa volevo ringraziarvi per la pazienza dimostrata nei miei confronti, sono il primo ad ammettere il fatto di essere incompetente, ma ciò non mi frena!!! sono testardo ! ..Grazie anche Romoloman che meglio di me ha espresso il concetto... ovvero: Il duty cycle cambia il valore efficace della tensione in uscita, per cui l'effetto finale è quello desiderato.. in piu il potenziometri delle radio sono usati come partitori di tensione e.. quindi chi volesse provarci avrà una certezza che l'esperimento funziona.... ...diciamo che non sono solo chiacchiere! Facendo le prove ho raccolto immediatamente il risultato, per il condensatore... ho fatto delle prove, il miglior risultato l'ho ottenuto con un condensatore da 470 uF 25 Vcon questo il servo non vibra piu.. sta fermo e segue perfettamente i comandi.... Spero che i codici sorgenti siano stati recepiti... e provati da voi... Sempre per chiarire chi legge questa discussione, il Nunchuk purtroppo non può essere usato per leggere roteazioni orizzontali , per capirci sopra un disco musicale di vinile tipo 33 giri !! ma solo su un asse in roteazione posto verticalmente, sempre per capirci nell'asse di roteazione di una ruota di bicicletta ... Per questo il Nunchuk potrebbe essere utile per realizzare uno stabilizzatore d'assetto per aerei, e facendo le prove direi anche che è molto affidabile, inclinando l'affare si accorge anche della minima inclinazione... Nel codice .ino ho inserito un semplice controllo che legge solo le variazioni di inclinazione.. in modo da non intasare il calcolo.. supponendo che lo stesso processore debba occuparsi di altro. Da questa discussione ho capito piu a fondo l'uso degli accelerometri e del protocollo I2C, anche se però la libreria di Arduino nasconde tante cammurrie !! |
Citazione:
ElNonino, che come avrai capito è uno che se ne intende davvero, e Romoloman che non è da meno ti hanno spiegato più volte che per convertire in tensione una frequenza con duty cycle veriabile (PWM) serve un filtro RC, non solo C!! ElNonino ti ha mandato lo schema e ti ha messo in guardia dal collegare 220uF in uscita dal micro perchè sono troppi e tu cosa fai... ne metti 470. A condensatore scarico, hai idea della corrente che passa ? Non so a che frequenza vai, ma probabilmente 1uF con 1-2.2K è già fin troppo; comunque se ci dici a che frequenza generi il PWM, ti dico che valori usare e vedrai che funzionerà bene ugualmente! Michele |
ok nessun problema, anzi grazie per l'avviso! ... nn me la prendo, lo so benissimo che i due signori hanno i capelli bianchi a via di resistenze e transistor, e che i loro consigli sono preziosissimi... ..da quelllo che leggo anche te nn scherzi.. riguardo le capacità dei condensatori vanno accoppiate con una resistenza entrambe opportune in base alla frequenza... assieme compongono un filtro RC appunto resistenza Capacità, bene adesso non quale frequenza usa Arduino di default, mi informo quando ho tempo e scrivo immediatamente qui.. nel frattempo .. sto sistemando il mio cane.. ha appena leccato una bustina di veleno per topi... il vicino di casa le usa nel suo garage! a dopo Citazione:
|
Citazione:
per regolare la frequenza devi agire sui timer. ciao:) |
Citazione:
Dalla documentazione di Arduino: * * The resulting frequency is equal to the base frequency divided by * the given divisor: * - Base frequencies: * o The base frequency for pins 3, 9, 10, and 11 is 31250 Hz. * o The base frequency for pins 5 and 6 is 62500 Hz. * - Divisors: * o The divisors available on pins 5, 6, 9 and 10 are: 1, 8, 64, * 256, and 1024. * o The divisors available on pins 3 and 11 are: 1, 8, 32, 64, * 128, 256, and 1024. * * PWM frequencies are tied together in pairs of pins. If one in a * pair is changed, the other is also changed to match: * - Pins 5 and 6 are paired on timer0 * - Pins 9 and 10 are paired on timer1 * - Pins 3 and 11 are paired on timer2 * * Note that this function will have side effects on anything else * that uses timers: * - Changes on pins 3, 5, 6, or 11 may cause the delay() and * millis() functions to stop working. Other timing-related * functions may also be affected. * - Changes on pins 9 or 10 will cause the Servo library to function * incorrectly. |
la frequenza è 977 Hz rimanendo sull'uso delle funzioni standard delle librerie, usando il pin 3 che utilizza il Timer2 da 8-bit... poichè il prescaler di default è 64 significa che ogni incremento costa 4 uS.... dunque avremo 4 uS ogni incremento, per riempire un registro di 8 bit abbiamo alla fine 4 * 256 = 1024 uS quindi 1.000.000 / 1024 = 976. 56 arrotondabile a 977 Hz qui c son spiegate un po di cose: Advanced Arduino: direct use of ATmega counter/timers Dunque per Romoloman la frequenza è 977 Hz, per il discorso RC, capisco che se mettiamo la resistenza diminuisce la quantità di corrente, per cui possiamo diminuire anche il condensatore ...ed avere quantità di cariche meno pericolose... ovviamente la coppia RC vanno dimensionate.. aspetto tue info, nel frattempo faccio altro. a dopo fausto |
5 Allegato/i Per quella frequenza un buon compromesso è resistenza da 22K e condensatore da 1uF. Aumentando resistenza e/o condensatore migliori il ripple sull'uscita, ma aumenti il tempo necessario per stabilizzare l'uscita sul valore finale, diminuendo R e/o C aumenti il disturbo presente sull'uscita, ma diminuisci il tempo di set-up. Nelle immagini allegate vedi l'uscita al 10%, 20%, 50% e 90% e la risposta ad un treno di 50 impulsi al 90% dove si vede il tempo che impiega ad arrivare al valore corrispondente al 90% da 0; ovviamente questo è il tempo maggiore preso agli estremi della corsa, in tutti gli altri casi sarà minore. Michele |
Giusto per aggiungere un po' di sana teoria alla descrizione di Michele la frequenza di taglio di un filtro passa basso è data da: 1/(2*pi*R*C) e con i valori dati da Michele è 7,2 Hz. Riguardo ai valori proposti da Michele non sapendo l'impedenza dell'ingresso personalmente abbasserei la resistenza e aumenterei il condensatore portando la resistenza a 4.7k e il condensatore intorno ai 5/10uF. Probabilmente non serve vista l'alta impedenza dell'ingresso del micro ma in ogni caso non dovrebbe fare danni... |
grazie ok grazie del supporto... proverò sia la soluzione di MSchiepp, che quella di romoloman, ci proverò dopodomani... oggi e domani sono in riposo psicologico! grazie ancora fausto Citazione:
|
|
funziona! ok funziona, ho provato con una resistenza da 4,7 e un cond da 10 uF, poi ho provato con resistenza 22 kohm e cond da 1 uF funziona con entrambe le combinazioni FORTE! vedere che con il Nunchuk si muove un servo sull'aereo... i miracoli di Arduino... peccato che non rileva il movimento di roteazione testa destra sinistra.. comunque ..il prossimo step sarà un gyroscopio, nel frattempo mi occuperò d'altro, diciamo che l'idea di iniettare un PWM al posto del potenziometro funziona, e non è poco visto e considerato che l'alternativa era catturare il segnale dalla presa allievo maestro, poi eliminare i segnali 6 e 7, poi aggiungere al loro posto i due provenienti dal movimento della testa ecc.. per il momento termino qui l'esperienza ringraziando gli intervenuti per i preziosi consigli, spero che le 4 righe di codice possano servire a chi si volesse cimentare in questo esperimento a presto fausto Citazione:
|
Citazione:
scusa se mi intrometto solo adesso, ma forse posso aggiungere il tassello che manca in questa conversazione. All'inizio tu hai scambiato il segnale PWM per un segnale continuo e nessuno ti ha corretto esplicitamente. Questo ha certamente generato in te quella confusione che ha allungato questo post... un segnale PWM, acronimo di Pulse Width Modulation cioè Modulazione dell'Ampiezza dell'Impulso, è un segnale ad onda quadra che oscilla, tipicamente, tra i valori 0 e +Vcc (tensione di batteria, nel nostro caso +5V). Il periodo di "0" è definito tempo OFF, quello a +Vcc è definito tempo ON. Trattandosi di un segnale "impulsivo", la tensione che misuri con un tester analogico (non digitale, per avere una misura accurata occorre l'inerzia dell'ago) è un valore medio che dipende dal rapporto tra il tempo ON (ovverosia +5V) ed il tempo OFF+ON (cioè del periodo del nostro impulso).Questo rapporto si chiama DutyCycle. Per avere il valore della tensione letta dal tester devi moltiplicare questo valore per la tensione di ON. Facciamo un esempio: se ho un PWM con un periodo di 100mS ed un tempo ON di 40mS (e quindi un tempo OFF di 60mS) avrò un DutyCycle del 40%. Se la tensione +Vcc è di 5V, allora il tester leggerà il 40% di 5, cioè 2V. Per convertire un segnale PWM in un segnale continuo occorre un circuito RC (come ti hanno già spiegato) che stabilizzi la tensione in ingresso. In pratica, nei periodi ON il condensatore si carica attraverso la R (che contemporaneamente fornisce anche la corrente al carico), nei periodi OFF è il condensatore a fornire la corrente al carico. I due componenti vanno dimensionati in funzione del carico da alimentare e dalla frequenza (inverso del periodo) del segnale PWM in ingresso. Un C troppo piccolo non sarà in grado di stabilizzare bene la tensione in uscita, uno troppo grande renderà l'uscita poco sensibile alle variazioni del DutyCycle del PWM in ingresso. Tu hai collegato un condensatore da 470micro direttamente all'uscita dell'arduino e dici che così funziona, credendo quindi che la R che ti hanno detto di inserire non sia realmente necessaria. Nulla di più falso! L'arduino ha, proprio per come è costruito, una R sulle sue uscite e tu stai sfruttando proprio quella. Il problema è che, così facendo, la stressi troppo (non è costruita per quello scopo) e rischi di fare danni. Ti consiglio caldamente di inserire nel circuito la R e di utilizzare i valori di R e C che ti sono già stati forniti. Sperando di avrti chiarito gli ultimi dubbi :) Carlo |
| Tutti gli orari sono GMT +2. Adesso sono le 12:39. |
Basato su: vBulletin versione 3.8.11
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
E' vietata la riproduzione, anche solo in parte, di contenuti e grafica. Copyright 1998/2019 - K-Bits P.I. 09395831002