| |
| | #1 (permalink) Top |
| User Data registr.: 10-12-2012 Residenza: roma
Messaggi: 430
|
Sempre in rete ho trovato questo, ma...non riesco a capirlo ![]() Codice: //this programm will put out a PPM signal
//////////////////////CONFIGURATION///////////////////////////////
#define chanel_number 1 //set the number of chanels
#define default_servo_value 1500 //set the default servo value
#define PPM_FrLen 22500 //set the PPM frame length in microseconds (1ms = 1000µs)
#define PPM_PulseLen 300 //set the pulse length
#define onState 1 //set polarity of the pulses: 1 is positive, 0 is negative
#define sigPin 10 //set PPM signal output pin on the arduino
//////////////////////////////////////////////////////////////////
/*this array holds the servo values for the ppm signal
change theese values in your code (usually servo values move between 1000 and 2000)*/
int ppm[chanel_number];
void setup(){
//initiallize default ppm values
for(int i=0; i<chanel_number; i++){
ppm[i]= default_servo_value;
}
pinMode(sigPin, OUTPUT);
digitalWrite(sigPin, !onState); //set the PPM signal pin to the default state (off)
cli();
TCCR1A = 0; // set entire TCCR1 register to 0
TCCR1B = 0;
OCR1A = 100; // compare match register, change this
TCCR1B |= (1 << WGM12); // turn on CTC mode
TCCR1B |= (1 << CS11); // 8 prescaler: 0,5 microseconds at 16mhz
TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
sei();
}
void loop(){
//put main code here
static int val = 1;
ppm[0] = ppm[0] + val;
if(ppm[0] >= 2000){ val = -1; }
if(ppm[0] <= 1000){ val = 1; }
delay(10);
}
ISR(TIMER1_COMPA_vect){ //leave this alone
static boolean state = true;
TCNT1 = 0;
if(state) { //start pulse
digitalWrite(sigPin, onState);
OCR1A = PPM_PulseLen * 2;
state = false;
}
else{ //end pulse and calculate when to start the next pulse
static byte cur_chan_numb;
static unsigned int calc_rest;
digitalWrite(sigPin, !onState);
state = true;
if(cur_chan_numb >= chanel_number){
cur_chan_numb = 0;
calc_rest = calc_rest + PPM_PulseLen;//
OCR1A = (PPM_FrLen - calc_rest) * 2;
calc_rest = 0;
}
else{
OCR1A = (ppm[cur_chan_numb] - PPM_PulseLen) * 2;
calc_rest = calc_rest + ppm[cur_chan_numb];
cur_chan_numb++;
}
}
} |
| | |
| | #3 (permalink) Top | |
| User Data registr.: 10-12-2012 Residenza: roma
Messaggi: 430
| Citazione:
L'uscita l'ho messa sul pin 5, ed ho aggiunto pinMode(auxPin,OUTPUT);, ma niente da fare...la gui di multiwii non legge niente... | |
| | |
| | #4 (permalink) Top |
| Adv Moderator Data registr.: 15-08-2007 Residenza: sto a Massa ma sono molto Positivo
Messaggi: 12.071
|
Il tuo codice lo vedo molto critico dal punto di vista del segnale generato, cerco di spiegarti il perché: Codice: void setup(){
pinMode(throttleInput,INPUT);
auxServo.attach(auxOutput);
auxServo.write(0); //inizializzo il valore del canale aux su BASSO
} Codice: pinMode(auxOutput,OUTPUT); Codice: void setup(){
pinMode(throttleInput,INPUT);
pinMode(auxOutput,OUTPUT);
auxServo.attach(auxOutput);
auxServo.write(0); //inizializzo il valore del canale aux su BASSO
} continuando.... il seguente codice: Codice: //Acquisisco il valore del throttle throttleVal = pulseIn(throttleInput,HIGH,25000); ovvero il segnale di uscita non verrà generato fino a che, o l'impulso viene rilevato, o avviene un timeout. Andiamo avanti con l'analisi degli orrori Codice: //controllo il valore del throttle
if(throttleVal <= 0){ //se il valore del throttle è andato a zero attivo il "failsafe" comunque questo non inficia il funzionamento ma è solo un questione di pulizia del codice. Tuttavia non confronterei mai con 0, stai aspettando un segnale che deve avere un ampiezza compresa fra 1000 e 2000us.... perché rischiare di prendere delle spurie da pochi uSec come segnale valido ? Codice: auxServo.write(179); //"invio" un segnale ALTO
delay(15);
} Codice: auxServo.write(179); //"invio" un segnale ALTO
} else {
auxServo.write(0); //"invio" un segnale BASSO
} pulseIn aspetta 25ms... ritorna 0.. auxServo.write() genera un impulso di 2ms delay aspetta 15ms in totale il tuo impulso viene generato ogni 42 ms...secondo me sono un po' troppi. forse allora togliendo il delay almeno lo avresti generato ogni 27ms e le cose andrebbero meglio. Nel caso l'impulso sia presente con il tuo codice (tolto il delay e inserito l'else) invece avverrebbe la cosa seguente: chiamiamo Ton il tempo in cui l'impulso di ingresso va alto: Tduty la larghezza dell'impulso in ingresso Ttot il periodo del ppm in ingresso (tipicamente 18ms) servoin aspetta l'impulso T0=Ton al tempo Ton+Tduty (variabile e dipendente dall'impulso in ingresso) auxServo.write() genera un impulso di larghezza 1000uSec e ritorna al ciclo successivo di pulseIn A questo punto pulseIn aspetterà Ttot-1000usec-Tduty che si ripresenti l'impulso successivo. essendo Tduty variabile è evidente che l'impulso generato da auxServo.write() avrà un jitter dipendente dalle variazioni dell'ingresso... E' vero che all'elettronica che legge l'impulso probabilmente non gliene frega nulla, ma è concettualmente sbagliato. La generazione del PPM deve essere fatta in un interrupt che setta l'uscita, regola il timer per la chiamata successiva dopo i ms di ampiezza dell'impulso, la chiamata successiva resetta l'uscita e imposta il timeout dell'interrupt successivo a 22.5-(larghezza impulso) ms (quello che correttamente viene fatto nella ISR(TIMER1_COMPA_vect) del codice da te postato. nel tuo caso andrebbe fatto per un solo canale e non per tutti quelli dello stream PPM: Spero di essere stato sufficientemente chiaro, cordiali saluti
__________________ 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 Ultima modifica di romoloman : 01 dicembre 13 alle ore 16:35 |
| | |
| | #5 (permalink) Top | |
| User Data registr.: 19-07-2008 Residenza: catania
Messaggi: 978
| Non è una cosa complicata!
tutto sommato non è complicato.... abbiamo il Timer1 che cresce a ritmo di mezzo microsecondo.. (prescaler 8) ovvero 500 nS (nano secondi) quando raggiunge il valore del periodo, si verifica un interrupt.... che viene catturato dalla funzione ISR( ecc...) ..dentro questa funzione viene azzerato il timer... viene eseguito il fronte di salita sul pin in causa... Adesso il compare dovrà osservare non più il periodo ma un altro registro l'OCR1A appena il Timer1 raggiunge questo valore avviene dinuovo un interrupt ma stavolta esegue il fronte di discesa STOP! fine della storia.. ovviamente i registri Citazione:
| |
| | |
![]() |
| Bookmarks |
| |
Discussioni simili | ||||
| Discussione | Autore discussione | Forum | Commenti | Ultimo Commento |
| aiuto con arduino e ppm | alex-military | Circuiti Elettronici | 0 | 22 febbraio 13 14:52 |
| Ricevitore di segnale PPM | CarloRoma63 | Radiocomandi | 2 | 06 marzo 12 18:24 |
| Installazione Frsky V8HT interno - Trovare il segnale ppm +e - sulla radio | searchworlds | Radiocomandi | 4 | 22 maggio 11 23:18 |
| GRAUPNER MX-16S 35 Mhz. PROBLEMI DI SEGNALE IN PPM | rentwc | Radiocomandi | 2 | 30 marzo 10 00:41 |
| trovare segnale ppm | silviocross | Radiocomandi | 8 | 11 marzo 10 22:21 |