
![]() | #1 (permalink) Top |
User Data registr.: 19-07-2008 Residenza: catania
Messaggi: 978
| 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. |
![]() | ![]() |
![]() | #2 (permalink) Top |
User Data registr.: 30-10-2011 Residenza: roma
Messaggi: 1.130
|
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 ![]()
__________________ blade mcpx brushless mini quadricottero con multiwii hk 250 gt flybarless |
![]() | ![]() |
![]() | #3 (permalink) Top |
User |
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. ![]() I componenti che formano il PB sono: R5, R8, R9 e C8, C9. ![]()
__________________ Peace & Love Fate le cose nel modo più semplice possibile, ma senza semplificare. (A. Einstein) ![]() |
![]() | ![]() |
![]() | #4 (permalink) Top | |
User Data registr.: 19-07-2008 Residenza: catania
Messaggi: 978
| 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:
| |
![]() | ![]() |
![]() | #5 (permalink) Top |
User Data registr.: 19-07-2008 Residenza: catania
Messaggi: 978
| 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; } |
![]() | ![]() |
![]() | #6 (permalink) Top |
User Data registr.: 19-07-2008 Residenza: catania
Messaggi: 978
| 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"); } } } |
![]() | ![]() |
![]() | #7 (permalink) Top |
User Data registr.: 19-07-2008 Residenza: catania
Messaggi: 978
| 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.
Ultima modifica di faustog_2 : 30 ottobre 12 alle ore 18:24 |
![]() | ![]() |
![]() | #8 (permalink) Top |
User Data registr.: 19-07-2008 Residenza: catania
Messaggi: 978
|
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 Ultima modifica di faustog_2 : 30 ottobre 12 alle ore 19:27 |
![]() | ![]() |
![]() | #9 (permalink) Top |
Adv Moderator Data registr.: 15-08-2007 Residenza: sto a Massa ma sono molto Positivo
Messaggi: 12.071
|
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.
__________________ Vivere in qeusto mondo e molto belo belo e vale la pena starci ma a volte in questa UNICA vita che ci apartiene posono succedere cose brute brute alora mi chiedo perche siete incazziati domani pole esere anche lultimo Grazie "TRANQUILLO" FAI 15766 |
![]() | ![]() |
![]() | #10 (permalink) Top | |
User Data registr.: 19-07-2008 Residenza: catania
Messaggi: 978
| 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:
| |
![]() | ![]() |
![]() |
Bookmarks |
| |
![]() | ||||
Discussione | Autore discussione | Forum | Commenti | Ultimo Commento |
Qualcuno sperimenta con Arduino? | Tom_1971 | Circuiti Elettronici | 192 | 21 dicembre 13 11:07 |
Nunchuk e wireless | geppino | Circuiti Elettronici | 4 | 19 settembre 12 10:53 |
A-Day - una giornata con Arduino | DiScienza | Incontri Modellistici | 0 | 19 marzo 12 20:39 |
quadricottero con arduino 2009 | sailormann26 | Aeromodellismo Progettazione e Costruzione | 0 | 27 dicembre 10 23:12 |