Arduino filoguidato con joystick analogico

Problema,
voglio controllare 2 motori tramite un driver con l298 ed un joystick analogico di quelli a 2 potenziometri e vorrei realizzare un controllo di direzione/velocità basato sulla risposta del joystick, quindi da fermo (posizioni centrali dei joy) i motori non si devono muovere, se muovo il joy in avanti i due motori devono azionarsi nella stessa direzione e con velocità proporzionale alla lettura di un potenziometro, stessa cosa per la retromarcia, se giro a destra i due motori devono girare con velocità complementari derivate dalla lettura dell'altro potenziometro del joystick.
Ho iniziato a scrivere un pò di codice ma subito sono stato assalito da una marea nera di dubbi.. tipo la lettura che mi viene dai potenziometri, ha come valore centrale 512, che per il lato pwm equivale a zero... come scrivo la funzione che realizza la "rimappatura" dei valori?
In palla totale, help
P.S.
il driver ha un pin per direzione per ogni motore

se non ho capito male il settaggio dell'analogico puoi farlo

if(val<512)
 retro
if(val>512)
  avanti
if(val==512)
  fermo

si, ma quello sarebbe più o meno semplice se fosse solo on/off , il problema è che con quei valori ci devo "PWMmare" i pin di direzione dei motori [smiley=cheesy.gif]
la parte avanti indietro:

//+++joydrive by brainbooster************

int pwm_a = 10; //PWM controllo per motore 1 avanti
int pwm_b = 11; //PWM controllo per motore 2 avanti
int dir_a = 12; //PWM direzione invertita motore 1
int dir_b = 13; //PWM direzione invertita motore 2

int joyPin1 = 0; // slider variable del pot1 connesso al pin 0
int joyPin2 = 1; // slider variable del pot2 connesso al pin 1
int value1 = 0; // variable per leggere dal pin 0
int value2 = 0; // variable per leggere dal pin 1

void setup() {

Serial.begin(9600);
pinMode(pwm_a, OUTPUT); //Setto un pò di uscite
pinMode(pwm_b, OUTPUT);
pinMode(dir_a, OUTPUT);
pinMode(dir_b, OUTPUT);
analogWrite(pwm_a, 0);
analogWrite(pwm_b, 0);
analogWrite(dir_a, 0);
analogWrite(dir_b, 0);
}

int treatValue(int data) {
return (data ) ;
}

void loop() {
// leggo i valori dei potenziometri del joy
value1 = analogRead(joyPin1);
//routine di avanti
if (joyPin1 >=520) {
analogWrite(pwm_a, 512 - value1/2); //A vai avanti come il pot dice
analogWrite(dir_a, 0); //A indietro a LOW
analogWrite(pwm_b, 512 - value1/2); //B vai avanti come il pot dice
analogWrite(dir_b, 0); //B indietro a LOW
}
if (joyPin1 <=500) {
analogWrite(dir_a, 512 - value1/2); //A vai indietro come il pot dice
analogWrite(pwm_a, 0); //A avanti a LOW
analogWrite(dir_b, 512 - value1/2); //B vai indietro come il pot dice
analogWrite(pwm_b, 0); //B avanti a LOW
}
//Fermo con zona morta
if (joyPin1 >=500 && joyPin1 <=520) {
analogWrite(pwm_a, 0); //A avanti a LOW
analogWrite(dir_a, 0); //A indietro a LOW
analogWrite(pwm_b, 0); //B avanti a LOW
analogWrite(dir_b, 0); //B indietro a LOW

}

//piccola pausa per evitare di leggere valori doppi
delay(100);
// leggo l'altro pot
value2 = analogRead(joyPin2);

//Scrivo fuori l'output della lettura dei pot AvantiIndietro e DestraSinistra
Serial.print("AI=");
Serial.print((value1 / 2),DEC);
Serial.println();
Serial.print("DS=");
Serial.print((value2 /2 ),DEC);
Serial.println();

}

ciao brainbooster

come hai giustamente modificato nel progeamma non definerei il valore 512 come valore intermedio di stop ma una zona lí intorno.
Percui:

if(val<480)
retro
if(val>540)
avanti
if(val >= 480 && val <= 540)
fermo

I valori opportuni devi definirli tu.
Questo perché la lettura analogica ha piccole flutuazioni dato da disturbi sulle linee e piccole incertezze sulla conversazione.

Ciao Uwe

l'avevo prevista, la zona morta, ed ho dato da 500 a 520.
ma dici che così funzionerebbe?

ciao brainbooster
Sí avevo visto.
Volevo riprendere il discorso perché nel Tuo primo post aveni scritto diveso ed é molto visibile. nel listino del programma non é facile da trovare.
Cambio il mio Post.

Sono cose difficili da sapere prima. Se la zona morta é abbastanza o é troopo grande perché la noti muovendo il joystik Ti puo dare certezza solo delle prove. Tanto variare il valore é una cosa da 3 secondi.

Ciao Uwe

si però hai 12 dalla parte "retro" e 8 dalla "avanti" in pratica non l'hai messo al centro potresti metterlo al centro e aumentare il range come dice @uwefed cosi nel caso di disturbi non avanza o arretra... ;D

(non ho saputo resiste a rispondere.. ma con te non dovrei avere problemi ::slight_smile: )

Dovresti anche rapportare il valore del controllo in PWM in modo proporzionale alla differenza tra il massimo o il minimo e il limite che hai scelto per la posizione di fermo.
Ovvero:

if(val<480){
// retro
pwm = 256-(folat)((256/480)(float)(val));
}
if(val>540){
// avanti
pwm = (folat)((256/484)
(float)(val));
}
if(val >= 480 && val <= 540){
// fermo
pwm = 0;
}

E spero di non aver commesso errori :wink:

Dubbio: ho scritto 256 supponendo che sia il valore massimo del PWM, ora poi controllo ed eventualmente correggo.

ciao milionario

Il L298 é un integrato fatto per pilotare motori passo-passo.
Non ho capito se vuoi pilotare 2 motori Dc con questo.
Comunque il segnale DIR é un segnale digitale Low o High, Se ci metti un segnale PWM non funziona.

Ciao Uwe

tnx
faccio un pò di modifiche e poi vi faccio sapere, oggi sono cotto... sto anche giocando (per lavoro) con un framework bellissimo ma anche molto complesso :o e che entrerà sicurissimamente a far parte della mia toolbox . ma mi sà che per stasera il mio neurone appenderà il cartello "torno subito" :slight_smile:
O.T.(per i curiosi, è metasploit)

l'l298 è un doppio ponte H , da 2A per canale, ci si fanno un sacco di cose, ma principalmente ci si pilotano motori (brushed, stepper ecc..)

quello che decodifica per gli stepper è l'l297, forse vi siete confusi con quello, per gli stepper, di solito si usano insieme l297 l298 ma a differenza dei motori dc, si può pilotare un solo motore (hanno più avvolgimenti da controllare, min 4 fili) e chiaramente l'uso è differente.
nel mio caso ci controllo due motoriduttori a 300rpm e 6kg di torque a 12V.
edit: adesso il codice è così... Grazie kokiua, per varie cose... :slight_smile:

//+++joydrive by brainbooster************

int pwm_a = 10; //PWM controllo per motore 1 avanti
int pwm_b = 11; //PWM controllo per motore 2 avanti
int dir_a = 12; //PWM direzione invertita motore 1
int dir_b = 13; //PWM direzione invertita motore 2

int joyPin1 = 0; // slider variable del pot1 connesso al pin 0
int joyPin2 = 1; // slider variable del pot2 connesso al pin 1
int value1 = 0; // variable per leggere dal pin 0
int value2 = 0; // variable per leggere dal pin 1

void setup() {

Serial.begin(9600);
pinMode(pwm_a, OUTPUT); //Setto un pò di uscite
pinMode(pwm_b, OUTPUT);
pinMode(dir_a, OUTPUT);
pinMode(dir_b, OUTPUT);
analogWrite(pwm_a, 0);
analogWrite(pwm_b, 0);
analogWrite(dir_a, 0);
analogWrite(dir_b, 0);
}

int treatValue(int data) {
return (data ) ;
}

void loop() {
// leggo i valori dei potenziometri del joy
value1 = analogRead(joyPin1);
//routine di avanti
if (joyPin1 >=134) {
analogWrite(pwm_a, 7 - value1/4); //A vai avanti come il pot dice
analogWrite(dir_a, 0); //A indietro a LOW
analogWrite(pwm_b, 7 - value1/4); //B vai avanti come il pot dice
analogWrite(dir_b, 0); //B indietro a LOW
}
//routine di indietro
if (joyPin1 <=120) {
analogWrite(dir_a, 262 - value1/4); //A vai indietro come il pot dice
analogWrite(pwm_a, 0); //A avanti a LOW
analogWrite(dir_b, 262 - value1/4); //B vai indietro come il pot dice
analogWrite(pwm_b, 0); //B avanti a LOW
}
//Fermo con zona morta
if (joyPin1 >=120 && joyPin1 <=134) {
analogWrite(pwm_a, 0); //A avanti a LOW
analogWrite(dir_a, 0); //A indietro a LOW
analogWrite(pwm_b, 0); //B avanti a LOW
analogWrite(dir_b, 0); //B indietro a LOW

}

//piccola pausa per evitare di leggere valori doppi
delay(100);
// leggo l'altro pot
value2 = analogRead(joyPin2);

//qui andranno le routine per il Destra-Sinistra

//Scrivo fuori l'output della lettura dei pot AvantiIndietro e DestraSinistra
Serial.print("AI=");
Serial.print((value1 / 4),DEC);
Serial.println();
Serial.print("DS=");
Serial.print((value2 / 4 ),DEC);
Serial.println();

}

::slight_smile: ho modificato il codice come vedete sopra (fungerà?) ma adesso mi viene un dubbio, ma per il destra sinistra il discorso cambia? si vero?
cioè, quando per esempio, giro a destra, se la ruota sinistra girerà con un pwm di 255 la destra riceverà 0, oppure se la sinistra riceve un pwm di 100 la destra avrà 155 giusto?
oppure durante le curve è sempre meglio bloccare la ruota "interna" alla curva e far girare in pwm solo l'altra?
quale delle due? pwm complementari oppure zero fisso su una ruota?

Se vuoi che il "mezzo" che controlli abbia una tenuta di strada "fenomenale" ::slight_smile: secondo me l'ideale sarebbe che tu riuscissi a rapportare correttamente la velocità della ruota interna rispetto all'esterna (rispetto al raggio di curvatura) così da dare ad entrambe la forza motrice corretta. Fermarne una ti fa sicuramente girare ma lo ottieni in modo non uniforme (di solito c'è apposta un differenziale per questo.. :wink: )

Grazie ancora kokiua, :slight_smile:
quindi, dovrei implementare un differenziale in software.
tieni conto che i motori fanno max. 300rpm quindi non sarà una "scheggia" :slight_smile:
comunque, da buon curiosone ho cercato un po... (wiki non mi ha aiutato)
ed ho trovato un bel documento, abbastanza esplicativo, ma con un botto di calcoli (allergia!), ma vale la pena di postare il link alla pagina, magari qualcuno lo capisce meglio di mè.

altra domanda:
vale la pena?, considerata la velocità (300rpm) dei motori e considerato che dovrei fare combattere il mio neurone per tradurre le formule per arduino?

Fossi in te non mi preoccuperei tanto di quei calcoli che sarebbero indispensabili se vuoi che il tuo dispositivo abbia una sorta di "consapevolezza" della posizione che ha dopo che ha percorso una determinata distanza in modo non rettilineo.
Tu hai un comando a filo quindi si suppone che ci sia qualcuno che guarda dove il tuo "coso" sta andando, così io mi limiterei semplicemente a far ruotare più o meno in modo proporzionale al valore del joystick la ruota a seconda della sua posizione rispetto al dispositivo. Mi spiego meglio:

direzione destra:
ruota a destra riduce la sua velocità in modo proporzionale al valore del joy
ruota a sinistra aumenta la sua velocità in modo inversamente proporzionale al valore del joy

per la direzione a sinistra il ragionamento è il medesimo ma con le due ruote che si scambiano di logica.

Chiaramente potrà esserci da fare qualche ritocchino al rapporto da applicare in funzione di quale vuoi che sia il raggio di curvatura minimo e massimo del tuo "coso". E queste sono correzioni che puoi fare navigando "a vista"...

P.S. non è che mi devi ringraziare ad ogni intervento... e poi per cosa?? :wink:

io ringrazio chiunque costringa il mio neurone a fare palestra ;D
ed ad ogni tuo intervento mi si accendono una decina di lampadine sulla testa che a loro volta illuminano altrettante stanze rimaste buie nel mio castello di ragionamenti.
Quindi Grazie! [smiley=dankk2.gif]
tornando a noi, diciamo che se una ruota riceve un pwm 100 l'altra avrà 155 giusto?
poi dovrò anche pensare a girare in retro.....

Edit:
quindi una cosa tipo questa?

//routine per avandi a destra
if (joyPin2  >=134) {
   analogWrite(pwm_a, 7 - value2 / 4); //A vai avanti come il pot dice
 analogWrite(dir_a, 0);  //A indietro a LOW
  analogWrite(pwm_b, (255 - (7 - value2 / 4))); //B vai avanti con pwm complementare
 analogWrite(dir_b, 0);  //B indietro a LOW
 }

Si, il codice mi sembra a posto. Ricorda però che se vuoi che il tuo "coso" ti faccia delle curve meno strette devi cambiare il rapporto per la ruota che deve andare più piano, es.:

  analogWrite(pwm_b, (255 - (char)((float)((7 - value2 / 4) * 0.75 )) ); //B vai avanti con pwm complementare e rapportato ad 1/4 della velocità

... hop, hop, hop neuroni :smiley: ;D

perchè 0,75?

0.75 per avere un rapporto ad 1/4 ..
se fosse di 0.66 di 1/3
se fosse di 0.50 sarebbe di 1/2, e via dicendo :wink:

(ora ti saluto che mi vedo la partenza in F1 :slight_smile: )

haaa, dalle mie parti si dice: "mo so capit tutt!" ;D
per la traduzione:

edit: un pò in ritardo ma alla fine ho capito :slight_smile:
oggi provo e magari uploado un pò di codice...
anche se un pò grezzo può sempre servire da spunto a qualcun'altro...
dopo vedrò di scrivere qualcosa di più elegante :slight_smile: magari utilizzando delle variabili, come si deve, per tenere i valori del pwm, map per il condizionamento dei range e case per i comandi che ne dite?