![]() |
Miscelare segnali PPM con arduino Ciao a tutti, volevo chiedere se qualcuno ha provato a miscelare dei segnali PPM di una ricevente realizzando tipo un mix di quelli che si usano su modelli di aerei e se la cosa è di facile realizzazione. Grazie. |
!!! non è facile facile, devi conoscere bene il datasheet del ATMEGA328 o insomma del Micro.. per esempio il pin 8 è dotato di un modulo capture che ti consente di catturare con estrema precisione il fronte di salita del segnale PPM della ricevente.. successivamente puoi variare il segnale come vuoi. Citazione:
|
Citazione:
|
Citazione:
Immagino che vuoi fare un mixer che non hai in radio. Io sto progettando un governor con controllo temperatura e carburazione per un elicottero a benzina. Ciao |
arduino Leonardo & Micro allora ho avuto il tempo di studiare.. e fare le prove in effetti la funzione pulseIn risolve molto bene il discorso, una precisione paragonabile a quella che si ottiene lavorando con i registri del Timer del capture e del modulo compare.. circa 8 microsecondi rileva da un estremo 873 uS dall'altro estremo 2073 uS così come usando direttamente i registri... . Di seguito giusto una demo per leggere il segnale di una ricevente e inviarla alla seriale. C'è da dire che conviene usare una scheda LEONARDO o arduino Micro perchè hanno piu porte digitali a disposizione e piu pin per interrupt esterni... da attenzionare però il Serial.println.... che in effetti risulta rallentare il PC... per ovviare questo problema mi sono accorto che mi è sufficiente usare una semplice applicaziione scritta in java.... insomma basta evitare il serial monitor.. adesso tutto OK , poi per creare il PPM per muovere i servo.. si può usare delayMicroseonds ......in questo modo non utilizzando il timer1 che invece viene usato dalla funzione puklseInt... i valori conviene prenderli con la specifica long volatile. const int inputpin = 2; long val; void setup() { pinMode(inputpin, INPUT); Serial.begin(9600); val = pulseIn(inputpin,HIGH,25000); } //_________________________________________ void loop() { Serial.println(val); val = pulseIn(inputpin,HIGH,25000); } Spero di essere stato utile ai lettori.. a presto fausto Citazione:
|
Citazione:
Farlo in un loop usando pulseIn di fatto dimezza la frequenza di pilotaggio considerato anche il fatto che poi deve anche essere generato il segnale miscelato. Pertanto l'unico modo è usare gli interrupt per leggere le variazioni dei due ingressi... O utilizzando gli external interrupt (pin 2 e 3) oppure usando i pin change interrupts. |
ok concordo su ciò che hai scritto... io sto adoperando Arduino Micro, che dispone di ben 5 pin x interrupt, ho appena finito di testare questa piccola funzione... OK tutto regolare... però adesso ho un problema, ovvero se volessi costruirmi un drone, che legge i PPM dalla ricevente e contemporaneamente legge i dati dei sensori ( gyro, accelerometri) dalla porta I2C ...c'è il problema che due dei pin coincidono ovvero il 3 e il 2... per cui ..dovrò optare di leggere i 4 PPM provenienti dalla radio in unico bus... in un unico pin... (volevo evitarlo) grazie alle tante porte interrupt messe a disposizione di Arduini Micro... e invece.. purtroppo devo fare il circuito aggiuntivo che mi convoglia i 4 PPM in un unico BUS.. pazienza! a meno che non vado ad utilizzare sensori analogici.. solo che tali vanno a rallentare di parecchio il software.. quindi non vale la pena! /* PER ARDUINO MICRO questo software cattura i segnali provenienti da una ricevente per aeromodelli ch1 ch2 ch3 ch4 | | | | | |GND | | ___|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|____ | pin 3,2 pin 0,1 | USB | | | ARDUINO MICRO | |_____________________________________| | | | | | | | | | | | | | | | | | la stampa sulla seriale avviene con un grosso ritardo dovuto alla bufferizzazione dei dati, occorre prelevare con i dati da un'applicazione diversa da serial monitor, perche essa blocca il PC. */ const int ch1 = 3; // interrupt 0 const int ch2 = 2; // interrupt 1 const int ch3 = 0; // interrupt 2 const int ch4 = 1; // interrupt 3 volatile unsigned long microseconds_1; volatile unsigned long microseconds_2; volatile unsigned long microseconds_3; volatile unsigned long microseconds_4; volatile byte index =0; volatile unsigned long ch1_val; volatile unsigned long ch2_val; volatile unsigned long ch3_val; volatile unsigned long ch4_val; // External Interrupts: ch1 - pin 3 (interrupt 0)// ch2 - pin 2 (interrupt 1)// ch3 - pin 0 (interrupt 2) // ch4 - pin 1 (interrupt 3) // and 7 (interrupt 4). void setup() { pinMode(ch1, INPUT); pinMode(ch2, INPUT); pinMode(ch3, INPUT); pinMode(ch4, INPUT); Serial.begin(9600); attachInterrupt(0, CH1_val, CHANGE); // questo sul pin3 attachInterrupt(1, CH2_val, CHANGE); // questo sul pin2 attachInterrupt(2, CH3_val, CHANGE); // questo sul pin0 attachInterrupt(3, CH4_val, CHANGE); // questo sul pin1 } //__________________________________________________ ______________ void loop() { Serial.println(ch1_val); Serial.println(ch2_val); Serial.println(ch3_val); Serial.println(ch4_val); Serial.println("......."); delay(1); } //__________________________________________________ _______ void CH1_val() { if(digitalRead(ch1) == HIGH) microseconds_1 = micros(); else ch1_val = micros() - microseconds_1; } //__________________________________________________ _______ void CH2_val() { if(digitalRead(ch2) == HIGH) microseconds_2 = micros(); else ch2_val = micros() - microseconds_2; } //__________________________________________________ _______ void CH3_val() { if(digitalRead(ch3) == HIGH) microseconds_3 = micros(); else ch3_val = micros() - microseconds_3; } //__________________________________________________ _______ void CH4_val() { if(digitalRead(ch4) == HIGH) microseconds_4 = micros(); else ch4_val = micros() - microseconds_4; } a dopo fasuto Citazione:
|
ok COMUQUE per le miscelazioni questo software va bene.. si può aggiungere anche un quinto canale.. attraverso il PIN6 della scheda Arduino Micro, oppure Arduino LEONARDO... credo sia preferibile la Micro viste le ridotte dimensioni. potrebbe essere inserita in uno spazio veramente angusto... e quindi stare ben nascosta. a dopo fausto Citazione:
|
ciao Romoloman dunque ho fatto dei nuovi test proprio per lasciare liberi i pin 2 e 3 di Arduino Micro... utilizzando pulseIn con dei pin diversi esattamente 4,5,6,7 ..ottengo prestazioni paragonabili a quelle che si ottengono utilizzando gli interrupt.. evidentemente le librerie sono fatte bene... fatto sta che adesso non mi ritrovo nemmeno il rallentamento dei dati della seriale.. forse perchè non usando i pin 0 e 1 che sono della seriale.. probabilmente non entrano in conflitto lo stesso vale per i due pin I2C pin 3,2... quindi credo che continuo su questa linea.. piuttosto che andare a smanettare su tutti i registri e i bit dei registri ... sfrutto le librerie.. tali risultano veloci ed snelle.. const int pin1 = 4; const int pin2 = 5; const int pin3 = 6; const int pin4 = 7; volatile byte index =0; volatile unsigned long results_1; volatile unsigned long results_2; volatile unsigned long results_3; volatile unsigned long results_4; void setup() { pinMode(pin1, INPUT); pinMode(pin2, INPUT); pinMode(pin3, INPUT); pinMode(pin4, INPUT); Serial.begin(9600); } void loop() { results_1 = pulseIn(pin1,HIGH,25000); results_2 = pulseIn(pin2,HIGH,25000); results_3 = pulseIn(pin3,HIGH,25000); results_4 = pulseIn(pin4,HIGH,25000); Serial.println(results_1); Serial.println(results_2); Serial.println(results_3); Serial.println(results_4); Serial.println("__________________________________ ______"); } a dopo Citazione:
|
Citazione:
supponi l'ordine in cui cambiano i pin sia 4 3 2 1 o che cambino tutti assieme (caso comune in molte nuove riceventi) il primo pulseIn aspetta fino a 25000us per pin1 ma quando arriva a leggere un segnale valido passa al secondo pulseIn che dovrà aspettare tutto il frame ppm lo stesso per il terzo e il 8 in totale si arriva a 4 frame = 88ms Per fare una prova: memorizza millis() prima del primo pulseIn e sottrailo dal valore dopo l'ultimo, stampa i risultati e poi prova a cambiare l'ordine degli ingressi... |
OK grazie romoloman ciao Romoloman.. sei un grande! ..scusa ma te lo devo dire... seguendo i tuoi preziosi consigli, ho voluto osare di più.. dunque ho fatto la tua prova, e inoltre ho fatto la prova del 9, ovvero ho messo i servo! quindi nel caso dell'uso della pulseIn i servo tremano, troppo diciamo inutilizzabili. invece nel caso in cui uso l'interrupt i servo tremano molto meno... sono piu stabili e sicuramente utilizzabili.... nel caso di voler realizzare un drone o un sistema di miscelazione... la soluzione è ARDUINO LEONARDO e l'uso degli interrupt . di seguito il codice che legge dalla ricevente e invia ai servo senza un'elaborazione, diciamo che è il software di base. una riflessione.. secondo me occorre comunque aggiungere un circuito che porta i 4 canali in un unico bus.. dopo aver letto i 4 canali, il software può approfittare della lunga pausa di 20 mS per compiere tutte le elaborazioni e poi applicare eventuali modifiche ai segnali entranti.. per poi inviarli ai servo- #include <Servo.h> Servo myservo1, myservo2, myservo3, myservo4; const int ch1 = 3; // interrupt 0 const int ch2 = 2; // interrupt 1 const int ch3 = 0; // interrupt 2 const int ch4 = 1; // interrupt 3 volatile unsigned long microseconds_1; volatile unsigned long microseconds_2; volatile unsigned long microseconds_3; volatile unsigned long microseconds_4; volatile byte index =0; volatile unsigned long ch1_val; volatile unsigned long ch2_val; volatile unsigned long ch3_val; volatile unsigned long ch4_val; void setup() { pinMode(ch1, INPUT); pinMode(ch2, INPUT); pinMode(ch3, INPUT); pinMode(ch4, INPUT); myservo1.attach(9); myservo2.attach(10); myservo3.attach(11); myservo4.attach(12); Serial.begin(9600); attachInterrupt(0, CH1_val, CHANGE); // questo sul pin3 attachInterrupt(1, CH2_val, CHANGE); // questo sul pin2 attachInterrupt(2, CH3_val, CHANGE); // questo sul pin0 attachInterrupt(3, CH4_val, CHANGE); // questo sul pin1 } //__________________________________________________ ______________ void loop() { myservo1.write(map(ch1_val, 1000 ,2000, 0, 180)); myservo2.write(map(ch2_val, 1000 ,2000, 0, 180)); myservo3.write(map(ch3_val, 1000 ,2000, 0, 180)); myservo4.write(map(ch4_val, 1000 ,2000, 0, 180)); delay(15); /* Serial.println(ch1_val); Serial.println(ch2_val); Serial.println(ch3_val); Serial.println(ch4_val); Serial.println("......."); delay(1); */ } //__________________________________________________ _______ void CH1_val() { if(digitalRead(ch1) == HIGH) microseconds_1 = micros(); else ch1_val = micros() - microseconds_1; } //__________________________________________________ _______ void CH2_val() { if(digitalRead(ch2) == HIGH) microseconds_2 = micros(); else ch2_val = micros() - microseconds_2; } //__________________________________________________ _______ void CH3_val() { if(digitalRead(ch3) == HIGH) microseconds_3 = micros(); else ch3_val = micros() - microseconds_3; } //__________________________________________________ _______ void CH4_val() { if(digitalRead(ch4) == HIGH) microseconds_4 = micros(); else ch4_val = micros() - microseconds_4; } Citazione:
|
Citazione:
Anche la generazione del PPM verso i servi andrebbe fatta in un interrupt con una temporizzazione fissa, altrimenti il periodo complessivo dell'impulso ppm dipende troppo da quanto valgono i canali... Con 4 canali ci sono 4ms che ballano. |
Ok ok romoloman... ..ci tengo a sottolineare che è sempre un piacere scambiare opinioni e suggerimenti con te. Attraverso la funzione map .... map( valore, range_min_in, range_max_in, 0, 180) ...posso smorzare l'effetto traballante.. agendo sui valori range_min_in e range_max_in loro realizzano una sorta di discretizzazione, ovvero se hai un valore che oscilla tra 1973uS 1970uS il sistema map lo discretizza comunque fermo a 1970 per questo ho dei servo piuttosto stabili, diciamo utilizzabili. Tuttavia come suggerisci tu posso fare a meno della libreria Servo utilizzando la funzione DelayMicrosenconds, la libreria Servo utilizza Timer1, cosa che potrebbe essere utile Per il momento voglio creare il sistema per convogliare i pin dei 4 canali della ricevente in un unico bus e farlo catturare ad Arduino in uno dei 5 pin predisposti con gli Interrupt come già visto negli esempi precedenti Citazione:
|
Citazione:
|
@faustog_2: se fai tutto a scopo didattico od arricchimento personale ok, anche se Arduino per certe cose non è il massimo, altrimenti diventi membro onorario del UCAS. :D Naturalmente con simpatia. :yeah: |
Ucas !!!! Ufficio Complicazioni Affari Semplici !! hahhahah me lo ricordo... .me lo diceva il mio professore di costruzioni al geometra! ..si confermo tutto a scopo didattico... so che ci sono alternative pronte a costi piu bassi.. ne abbiamo già parlato.. il piacere è lavorarci e metterci le mani... ..per quello che concerne le miscelazioni, io nn ho tanto l'esigenza.. quando il discorso d prendere i segnali dalla ricevente poterli manomettere facendo interaggire con un accelerometro ,ggyro eccc.. Citazione:
|
salve a tutti, è stato portato avanti con successo il discorso qui trattato oppure è rimasto a limite teorico??? Sono interessato ma ancora non ho iniziato a metterci le mani, potrei anche leggere un solo canale in quanto ho la possibilità di montare anche 2 arduino , andranno montati su un rover tra un apm arducopter e la scheda motori in quanto per l'autopilota devo tenere conto di eventuali ostacoli e quindi interagire con sensori ultrasuoni e altro..... |
Tutti gli orari sono GMT +2. Adesso sono le 07:52. |
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