05 maggio 20, 00:42 | #101 (permalink) Top |
Guest Data registr.: 17-07-2013
Messaggi: 3.734
|
ma se il problema non fosse nello sketch ma dovuto alla mancanza di un filtro passa basso? oppure un toroide intorno ai fili dei segnali in entrata? per ipotesi una resitenza in serie al segnale e un condensatore tra segnale e ground? però non so determinare quali valori per questi componenti. sparo bischerate? |
05 maggio 20, 09:19 | #102 (permalink) Top |
User Data registr.: 02-10-2019 Residenza: Orvieto
Messaggi: 307
|
Buon giorno, ieri sera avevo un po' di tempo e ho fatto qualche prova... La macchina a stati non l'ho analizzata perché non credo porti beneficio in questa applicazione (ovviamente è solo un mio parere) ma con uno sketch nuovo, quindi privo dei calcoli, ho riscontrato un particolare: Facendo leggere all'arduino un canale solo, I valori sono corretti e senza disturbi, mentre, facendo leggere due canali, i valori letti sono molto sballati e si rivelano precisi su un canale solo scollegando fisicamente il pin dell'altro canale mentre arduino esegue le letture. Stessa cosa sul secondo canale scollegando il pin del primo. Se la lettura non è affidabile non può esserlo nemmeno il risultato quindi sarebbe meglio utilizzare un codice che lavori direttamente sul micro, quindi senza l'ausilio delle librerie che sicuramente hanno i propri limiti. Inviato dal mio PRA-LX1 utilizzando Tapatalk |
05 maggio 20, 10:09 | #103 (permalink) Top | |
User | Citazione:
__________________ Peace & Love Fate le cose nel modo più semplice possibile, ma senza semplificare. (A. Einstein) | |
05 maggio 20, 10:16 | #104 (permalink) Top | |
User | Citazione:
Per l'applicazione in oggetto vedrei molto meglio un PIC od un ARM, la differenza di costo dei componenti è risibile ed anche per questi micro gli ambienti di sviluppo sono gratuiti ed esiste moltissima documentazione in rete ed anche alcune librerie (spesso sviluppate dalle case costruttrici) decenti. Ho sempre sostenuto che Arduino è stata una grande idea ma ha generato un effetto collaterale: quello di far credere a molti di svegliarsi una mattina e saper sviluppare firmware e nel caso del modellismo senza neanche avere le basi del HW.
__________________ Peace & Love Fate le cose nel modo più semplice possibile, ma senza semplificare. (A. Einstein) | |
05 maggio 20, 10:55 | #105 (permalink) Top |
User Data registr.: 02-10-2019 Residenza: Orvieto
Messaggi: 307
|
Forse è un'idea malsana ma una strada percorribile potrebbe essere quella di far leggere solo il canale dello sterzo e dare al servo delle ruote posteriori un andamento esponenziale... Del resto in massima velocità difficilmente si porta lo stick dello sterzo a fine corsa...credo Con la lettura di un solo canale, dalle prove che ho fatto, mi è sembrato che i valori acquisiti siano abbastanza precisi. Inviato dal mio PRA-LX1 utilizzando Tapatalk |
05 maggio 20, 13:01 | #106 (permalink) Top | |
User Data registr.: 03-05-2020 Residenza: milano
Messaggi: 47
| Citazione:
Ma ElNonino mi hai hato un idea. invece di guardare il Software guardiamo dal lato HW (hardware) il problema. Bene facciamo gli elettronici seri (sono sempre un pochino arruggito ma ci provo) Quindi ho fatto un paio di prove Inserito il serial.print nel sofware ho verificato senza toccare la radio quali valori venissero letti da pulsein. Erano un po' ballerini ma neanche eccessivamente meno del 1% di errori. Quindi per capire se il problema fosse la radio che si fa? si piglia un vecchio ma serio oscilloscopio digitale Tektronix 100MHz e si misurano gli impulsi. Risultato? valori inchiodati quindi non e' la ricevente che genera errori. Bene e le tensioni? il segnale della radio verso il servo e' un onda quadra circa 3.5Volt compatibile con ingresso di Arduino. quindi non e' li' il problema. Proviamo a mettere i pullup? magari con un diodo? non cambia nulla quindi eliminato. Quindi dato che arduino usa per pulsein il Timer1 interno al processore, che viene usato anche per altro la soluzione sarebbe quella di usare un pulsein che adoperasse il timer2 ad esempio. Oppure… Fermiamo interrupt (blocca le interruzioni ai timer tra le altre cose) Leggiamo il valore Riabilitiamo Interrupt e... Miracolo senza mettere un processore quantistico abbiamo un valore che balla +/-1 lultima cifra.. Un milionesimo di secondo badate bene… Sto programmando un plc per lavoro (Ebbene si' lo confesso faccio questo lavoro) ma più tardi posto il codice modificato… La linea da da inserire e' la seguente: noInterrupts(); e dopo i pulsein interrupts(); per riabilitarli Provate per credere oppure aspettate un paio d'ore che produco.. Smsteves Ultima modifica di Smsteves : 05 maggio 20 alle ore 13:04 | |
05 maggio 20, 13:01 | #107 (permalink) Top |
Guest Data registr.: 17-07-2013
Messaggi: 3.734
|
con un solo canale funziona perfettamente l'altro sketch, quello nel quale decidi solo la corsa e il verso. certo che a tutto gas ti trovi a dare tutto sterzo.. il senso di questa applicazione è solo quella di limitarlo proporzionalmente quando superi un certo valore del gas, altrimenti va benissimo l'altra dove il gas non è collegato. mi riferisco a questa che funziona benissimo https://pastebin.com/s27QJ37c comunque la soluzione è questa Codice: #include <Servo.h> Servo myservo; #define N_STORIASTERZO 7 // numero valori passati utilizzati per il calcolo della media valori sterzo. Da cambiare sperimentalmente #define N_STORIAGAS 7 // numero valori passati utilizzati per il calcolo della media valori gas. Da cambiare sperimentalmente unsigned int storiaSterzo[ N_STORIASTERZO ]; // array di N_STORIASTERZO elementi che memorizza gli ultimi valori di sterzo letti dal radiocomando per calcolarne la media unsigned int storiaGas[ N_STORIAGAS ]; // array di N_STORIAGAS elementi che memorizza gli ultimi valori di gas letti dal radiocomando per calcolarne la media long totaleStoriaSterzo = 0; // conterrà sempre la somma degli ultimi N_STORIA valori di sterzo letti dal radiocomando, per poi fare la media // (inizializzato a zero perché tutti i valori inizialmente sono zero) // lo dichiaro long perché se N_STORIA è grande la somma di int potrebbe andare in overflow long totaleStoriaGas = 0; // conterrà sempre la somma degli ultimi N_STORIA valori di gas letti dal radiocomando, per poi fare la media // (inizializzato a zero perché tutti i valori inizialmente sono zero) // lo dichiaro long perché se N_STORIA è grande la somma di int potrebbe andare in overflow int indiceSterzo = 0; // posizione del prossimo elemento che entra nella storia, da spostare passo dopo passo. Partiamo da zero // (in realtà, dato che al primo passo si incrementa subito, potremmo inizializzarlo a -1, ma non cambia nulla // perché fa tutto il giro int indiceGas = 0; // posizione del prossimo elemento che entra nella storia, da spostare passo dopo passo. Partiamo da zero // (in realtà, dato che al primo passo si incrementa subito, potremmo inizializzarlo a -1, ma non cambia nulla // perché fa tutto il giro unsigned int Rxpulse; unsigned int Gaspulse ; unsigned int Gain; unsigned int NewPos, OldPos; void setup() { for ( int i=0; i<N_STORIASTERZO; i++ ) storiaSterzo[ i ] = 0; for ( int i=0; i<N_STORIAGAS; i++ ) storiaGas[ i ] = 0; myservo.attach(10); //-- rear servo signal out pin pinMode(8, INPUT); //-- front servo signal in pin pinMode(7, INPUT); //-- throttle signal in pin } void loop(){ Rxpulse = pulseIn(8, HIGH); Gaspulse = pulseIn(7, HIGH); Rxpulse = mediaStoriaSterzo( Rxpulse ); Gaspulse = mediaStoriaGas( Gaspulse ); if (Gaspulse > Slowlimit) { Gain = map(Gaspulse, Slowlimit, Maxspeed, 0, Max_gain ); NewPos = map(Rxpulse, Antsx, Antdx, (Postsx + Gain), (Postdx - Gain)); } else { NewPos = map(Rxpulse, Antsx, Antdx, Postsx, Postdx); } if (abs(NewPos - OldPos)> Tolerance) { OldPos = NewPos; myservo.write(NewPos + Center); } } unsigned int mediaStoriaSterzo( unsigned int valore ) { /* * questa funzuine ritorna il valor medio degli ultimi N_STORIA valori elaborati, * incluso l'ultimo, cancellando il più vecchio dei valori attualmente memorizzati * I valori sono memorizzati nell'array 'storia' * Per cancellare e sostituire il valore più vecchio, invece di spostarli tutti all'indietro e far posto al nuovo, * andiamo noi a scegliere il valore da sostituire spostando un indice. * Si parte da 0 e si va avanti sino in fondo, poi si torna a zero. * Il primo giro in assoluto sostituiamo i valor iniziali tutti a zero, poi effettivamente cominceremo a sostituire il più veccio di tutti */ // determino la posizione su cui operare: incremento l'indice per andare sul prossimo, se arriva in fondo torna a zero if ( ++indiceSterzo >= N_STORIASTERZO ) indiceSterzo = 0; // aggiorno il totale, sottraendo il valore vecchio e sommando il nuovo totaleStoriaSterzo = totaleStoriaSterzo - storiaSterzo[ indiceSterzo ] + valore; // memorizzo il nuovo valore al posto di quello vecchio storiaSterzo[ indiceSterzo ] = valore; // ritorno la media: totale diviso numero elementi return( totaleStoriaSterzo / N_STORIASTERZO ); } unsigned int mediaStoriaGas( unsigned int valore ) { /* * come la precedente, ma per il valore di Gas */ // determino la posizione su cui operare: incremento l'indice per andare sul prossimo, se arriva in fondo torna a zero if ( ++indiceGas >= N_STORIAGAS ) indiceGas = 0; // aggiorno il totale, sottraendo il valore vecchio e sommando il nuovo totaleStoriaGas = totaleStoriaGas - storiaGas[ indiceGas ] + valore; // memorizzo il nuovo valore al posto di quello vecchio storiaGas[ indiceGas ] = valore; // ritorno la media: totale diviso numero elementi return( totaleStoriaGas / N_STORIAGAS ); } |
05 maggio 20, 14:15 | #108 (permalink) Top |
User |
Ma in Arduino per iniziallizzare un array a 0 occore fare così: for ( int i=0; i<N_STORIASTERZO; i++ ) storiaSterzo[ i ] = 0; for ( int i=0; i<N_STORIAGAS; i++ ) storiaGas[ i ] = 0; Per il resto la soluzione adottata è una semplice media mobile (credo si potrebbe fare meglio anche in Wire) sul segnale d'ingresso che è evidentemente "ballerino", sarebbe da verificare il tempo di risposta all'impulso di tali filtri, considerando che il mezzo è lento non dovrebbe dare problemi. Se i campionamenti sono multipli di 2 (ed è bene che lo siano) anzichè usare la divisione spesso conviene usare lo spostamento a dx di n bit, mentre la divisone richiede diversi cicli del microprocessore lo shifright ne usa uno solo.
__________________ Peace & Love Fate le cose nel modo più semplice possibile, ma senza semplificare. (A. Einstein) |
05 maggio 20, 14:44 | #109 (permalink) Top |
Guest Data registr.: 17-07-2013
Messaggi: 3.734
|
in pratica questo è un filtro. La funzione mediaStoria ( entrambe, sono uguali) funzionano un po' come se mettessi un condensatore in parallelo al filo che porta i valori: invece di darti il valore diretto lo media con i precedenti. se i valori oscillano intorno al valore 10, come 7, 9, 11, 12, 10 la loro media è 9. Se il prossimo valore fosse 13, si butta via il 7, la media diventa 11. Se il prossimo fosse 8 la media sarà 10. Quindi le oscillazioni vengono ammortizzate. Più grande è il numero di elementi che vengono conservati e meno pesa un valore difforme dagli altri, quindi tutto si stabilizza. Ma accelerando devono uscire diversi valori bassi prima che i nuovi valori alti prevalgano e alzino la media, quindi si ottiene una maggiore lentezza della risposta. Il tutto si svolge in microsecondi ad ogni giro. il ritmo effettivo lo determina pulseIn che sta fermo a misurare la linea in attesa dei fronti del segnale. questo è lo sketch ripulito dai commenti, rivisto e corretto. perfettamente stabile e funzionante. Codice: //----------- signal setup ------------------------------------- #define Neutral 1500 // -- minimum throttle forward signal #define Maxspeed 2000 // -- maximum throttle forward signal #define Antsx 1000 // -- in front servo signal sx #define Antdx 2000 // -- in front servo signal dx #define Postsx 1000 // out rear servo sx end point (if inverted with postdx it reverse) #define Postdx 2000 //-- out rear servo dx endpoint (if inverted with postsx it reverse) #define Center 0 //-- add or subtract your value to center steering (+- 50 or more) //--------- user driving setup ------------------------------ #define Max_gain 600 //-- gain steering reduction width at max throttle (if reverse add (-) before value) #define Slowlimit 1700 //-- slow forward percentage without endpoint correction #define Tolerance 0 //-- if poor quality servo vibrates try 5 //---------------------------- #include <Servo.h> Servo myservo; #define N_STST 7 #define N_STGAS 7 unsigned int stSt[ N_STST ]; unsigned int stGas[ N_STGAS ]; long toStSt = 0; long toStGas = 0; int inSt = 0; int inGas = 0; unsigned int Rxpulse; unsigned int Gaspulse ; unsigned int Gain; unsigned int NewPos, OldPos; void setup() { for ( int i=0; i<N_STST; i++ ) stSt[ i ] = 0; for ( int i=0; i<N_STGAS; i++ ) stGas[ i ] = 0; myservo.attach(10); //-- rear servo signal out pin pinMode(8, INPUT); //-- front servo signal in pin pinMode(7, INPUT); //-- throttle signal in pin } void loop(){ Rxpulse = pulseIn(8, HIGH); Gaspulse = pulseIn(7, HIGH); Rxpulse = meStSt( Rxpulse ); Gaspulse = meStGas( Gaspulse ); if (Gaspulse > Slowlimit) { Gain = map(Gaspulse, Slowlimit, Maxspeed, 0, Max_gain ); NewPos = map(Rxpulse, Antsx, Antdx, (Postsx + Gain), (Postdx - Gain)); } else { NewPos = map(Rxpulse, Antsx, Antdx, Postsx, Postdx); } if (abs(NewPos - OldPos)> Tolerance) { OldPos = NewPos; myservo.write(NewPos + Center); } } unsigned int meStSt( unsigned int val ) { if ( ++inSt >= N_STST ) inSt = 0; toStSt = toStSt - stSt[ inSt ] + val; stSt[ inSt ] = val; return( toStSt / N_STST ); } unsigned int meStGas( unsigned int val ) { if ( ++inGas >= N_STGAS ) inGas = 0; toStGas = toStGas - stGas[ inGas ] + val; stGas[ inGas ] = val; return ( toStGas / N_STGAS ); } Ultima modifica di wrighizilla : 05 maggio 20 alle ore 14:48 |
05 maggio 20, 15:06 | #110 (permalink) Top |
User Data registr.: 03-05-2020 Residenza: milano
Messaggi: 47
|
Eccomi di ritorno. Un po' di dati Frequenza segnale in uscita dalla radio 50 Hz (alcune anche 60Hz) numero di impulsi in un secondo quindi 50. se per fare il calcolo ne aspettiamo 2 di impulsi abbiamo un ritardo di 1sec/50cicli=20msx2=40 mS. Attendendo i 7 necessari a fare la media diventano 20*7=140 ms. Abbiamo un ritardo di 1.4 decimi di secondo.. Non va bene per la reattività giusto? avete letto il post 106 ? |
Bookmarks |
| |
Discussioni simili | ||||
Discussione | Autore discussione | Forum | Commenti | Ultimo Commento |
buggy da completare | BoBoPoP | Automodellismo Mot. Scoppio Off-Road | 41 | 18 maggio 16 17:56 |
monster da completare...! | bronto_19 | Automodellismo Mot. Elettrico Off-Road | 2 | 22 giugno 10 17:35 |
Sto costruendo uno schiumino (o tzagi), mi aiutate??? | crido96 | Aeromodellismo Principianti | 72 | 07 febbraio 10 02:26 |
Come completare una associated B4? | ryan-j | Automodellismo Mot. Elettrico On-Road | 9 | 04 maggio 08 11:55 |