Comandare 2 o 4 servi con JoyStick

Salve,
ho un problema con il seguente codice:

#include <Servo.h>
#define Analogico1 A0
#define Analogico2 A1

Servo myservo;
Servo myservo1;

int ValoreAnalogico;
int ValoreAnalogico2;

void setup()
{
Serial.begin(9600);
}

void loop()
{
ValoreAnalogico = analogRead(Analogico1);
ValoreAnalogico2 = analogRead(Analogico2);
ValoreAnalogico = map(ValoreAnalogico, 0, 1023, 0, 255);
ValoreAnalogico2 = map(ValoreAnalogico2, 0, 1023, 0, 255);

Serial.println(ValoreAnalogico);

Serial.println(ValoreAnalogico2);

if (ValoreAnalogico2 > 200)
{

myservo.attach(9);
myservo.writeMicroseconds(2000);
delay(100);
}
else
{
myservo.writeMicroseconds(1500);
delay(1);
}
if (ValoreAnalogico2 > 200)
{

myservo1.attach(10);
myservo1.writeMicroseconds(1000);
delay(100);
}
else
{
myservo1.writeMicroseconds(1500);
delay(1);
}

}

Siccome con due servi vorrei creare un MiniSumo in questo codice vado solamente in avanti, ma se mettessi gli stessi codici in retromarcia uno dei servi funziona a Scatti.
Ho guardato diverse guide, provato diversi modi… ma niente l’unica soluzione ( per le mi competenze ) è l IF ed ELSE.
Come potrei risolvere ?
Spero di essere stato chiaro.

Nessun idea ?

prova ad inserire la dichiarazioni:

myservo.attach(9)
myservo.attach(10)

nel setup invece che nel loop...

vedi se funzia.. :slight_smile:

Trovo strana la mappatura

ValoreAnalogico = map(ValoreAnalogico, 0, 1023, 0, 255);
ValoreAnalogico2 = map(ValoreAnalogico2, 0, 1023, 0, 255);

a cosa si riferisce ?? Cosa hai attaccato alle porte A0 e A1 ?

Immagino tu stia pilotando i servi a rotazione continua...allora perche' quei strani parametri sulle condizioni ?

if (ValoreAnalogico2 > 200)

Non sono a rotazione continua li ho modificati io... limando all'interno quella plastica.
Il joystick ha due potenziometri uno in Verticale e l'altro in Orizzontale.
A0 è l'Input verticale ed A1 è quello orizzontale.

Il valore l'ho dovuto "Mappare" visto che la lettura è di 10 bit e l'uscita da 8.... quindi (0, 1023, 0 , 255 ) che sarebbe 1024/4 = 256, siccome l'informatica parte da 0 a contare è 1023 o 255.

Ho messo che se il ValoreAnalogico2 è maggiore di 200 si avviano i Servi. Invece se cala sotto gli 80 i servi girano al contrario. La stessa cosa per girare a sinistra e destra.

Poi sto postando qua per imparare ad utilizzare questa stupenda piattaforma. Ho molti progetti in mente ed alcuni li ho realizzati.
Peccato che il lavoro mi occupa molto tempo che non posso dedicare ad arduino.

Ops....non avevo notato prima.

NOTI NIENTE DI STRANO ??

Servo Destro

if (ValoreAnalogico2 > 200)
myservo.writeMicroseconds(2000);
else
myservo.writeMicroseconds(1500);
delay(1);

Servo Sinistro

if (ValoreAnalogico2 > 200)
myservo1.writeMicroseconds(1000);
else
myservo1.writeMicroseconds(1500);

Con questa routine se il valore di ValoreAnalogico2 e' >200...avrai un servo che va in avanti e uno indietro...

In pratica a me sembra che tu abbia scritto:
SERVO DESTRO
Se il valore di Analogico2 e' maggiore di 200, poni myservo a 2000, cioe' vai avanti, altrimenti poni a 1500 cioe' stop (centro)

SERVO SINISTRO
Se il valore di Analogico2 e' maggiore di 200, poni myservo1 a 1000 cioe' vai indietro, altrimenti poni myservo1 a 1500 cioe' stop.

I millisecondi 1500 corrispondono al centro servo, 1000 ad una rotazione oraria e 2000 ad una rotazione antioraria ( o viceversa...ma 100 sempre al centro ).
Questo in un servo standard ,.... In uno a rotazione continua dipende da quanto preciso e' il servo e da quanto precisa e' la rete di resistenze di centraggio che e' stata messa al posto del potenziometro originale. Se la rete e' precisa...a 1500 i servi sono fermi a 1501 girano in un verso...mentre a 1499 girano nell'altro.
( Alcuni servocomandi escono dai parametri standard e possono coprire un range che va da 700 a 2300 ).
:slight_smile:

#include <Servo.h>
#define Analogico1 A0
#define Analogico2 A1

Servo myservo;
Servo myservo1;

int ValoreAnalogico;
int ValoreAnalogico2;

void setup()
{
Serial.begin(9600);
myservo.attach(9);
myservo1.attach(10);
}

void loop()
{
ValoreAnalogico = analogRead(Analogico1);
ValoreAnalogico2 = analogRead(Analogico2);
ValoreAnalogico = map(ValoreAnalogico, 0, 1023, 0, 255);
ValoreAnalogico2 = map(ValoreAnalogico2, 0, 1023, 0, 255);

Serial.println(ValoreAnalogico);

Serial.println(ValoreAnalogico2);

if (ValoreAnalogico2 > 200)
{
myservo.writeMicroseconds(2000);
delay(100);
}
else
{
myservo.writeMicroseconds(1500);
delay(1);
}

if (ValoreAnalogico2 > 200)
{
myservo1.writeMicroseconds(1000);
delay(100);
}
else
{
myservo1.writeMicroseconds(1500);
delay(1);
}

if (ValoreAnalogico2 < 80)
{
myservo.writeMicroseconds(2000);
delay(100);
}
else
{
myservo.writeMicroseconds(1500);
delay(1);
}

if (ValoreAnalogico2 < 80)
{
myservo1.writeMicroseconds(1000);
delay(100);
}
else
{
myservo1.writeMicroseconds(1500);
delay(1);
}

}

Con questo codice succede:

" I motori girano avanti " = Tutto bene

Premendo il JoyStick analogico all’indietro girano sempre avanti e l’altro mi va a scatti…
Invece dovrebbero girare indietro senza problemi.
Forse perchè non sono Servi a 360° ? Ma fanno solamente un angolo di 90° ?? Oppure è errato il mio codice ?
Grazie mille! per i vostri chiarimenti.

@X Ray

Devo farli girare uno a 1000 e l altro a 2000 perchè altrimenti... la macchina non andrebbe avanti no ? Uno deve girare l'opposto dell'altro.

Ho provato e questi hanno un Range da 700 a 2300 però mandarli lentamente nel mio "progetto" ( MiniSumo ) non mi sembra il caso.

Scusami ma già stavo scrivendo il post precedente e non ho visto il tuo.

Credo tu possa anche semplificare questa routine:

ValoreAnalogico = analogRead(Analogico1);
ValoreAnalogico2 = analogRead(Analogico2);
ValoreAnalogico = map(ValoreAnalogico, 0, 1023, 0, 255);
ValoreAnalogico2 = map(ValoreAnalogico2, 0, 1023, 0, 255);

ValoreAnalogico = map(analogRead(Analogico1), 0, 1023, 0, 255);
ValoreAnalogico2 = map(analogRead(Analogico2), 0, 1023, 0, 255);

FERMO...FERMO...FERMO !!!

Hai scritto:

Non sono a rotazione continua li ho modificati io... limando all'interno quella plastica.

Se dici che NON SONO a rotazione continua...perche' hai limato quella plastica ???

E se hai limato quella plastica....hai modificato anche il potenziometro che e' solidale all'asse del servo ?

Se l'hai fatto come andava fatto...HAI UN SERVO a ROTAZIONE CONTINUA.....
Se non l'hai fatto....HAI LETTO MALE LE ISTRUZIONI !!!! :slight_smile:

Se hai tagliato la linguetta o il fermo del servo...senza modificare il potenziometro....Ora il servo non sa piu' la sua posizione e naturalmente funziona a casaccio...

Oltre ad aver tagliato la linguetta...hai smontato il potenziometro ed inserito le due resistenze ( o il trimmer meglio se multigiri) che dovrebbero ripristinare il centraggiop del servo ??

Se non l'hai fatto ..hai fatto un lavoro a meta'.. ::slight_smile:

Dai un occhiata qui:
http://www.robot-italy.com/article_info.php?cArticlePath=1&articles_id=1

qui:
http://www.robot-italy.com/article_info.php?cArticlePath=1&articles_id=2

e qui:
http://www.robot-italy.com/article_info.php?cArticlePath=1&articles_id=3

:wink:

Grandissimo!!! questo passaggio non l ho proprio fatto.
Cosa mi consigli per una rotazione continua ?
Mettere le due resistenze oppure il trimmer ?

Quindi il funzionamento errato "Avanti" e "Indietro" è dovuto a questo fattore ?

Ho aperto un servo e le resistenze ce l'avevo messe :stuck_out_tongue: ( mi ero dimenticato ) sono 2-3 anni che ce l'ho!

Vedi se ti puo’ andar bene questo…
Il codice dovrebbe essere giusto…sempre che i tuoi servi siano stati modificati giusti per la rotazione continua

Tieni pero’ presente che i servi , o vanno al massimo o stanno fermi…non e’ possibile regolarne la velocita’ con la funzione “Servo.”…a meno di non creare una routine con un ciclo di for…alternando una istruzione di Avanti ad una istruzione di " delay(ritardo) " naturalmente creando una variabile “ritardo” ad hoc …
Credo !!! …Ma forse qualcuno piu’ esperto di me potrebbe darti una soluzione diversa…magari piu’ valida.
Intanto prova lo sketch che ti ho dato…in attesa degli esperti :wink:

#include <Servo.h>
#define Analogico1 A0
#define Analogico2 A1

Servo servoDX; //servo destro
Servo servoSX; //servo sinistro

int ValoreIngresso1; // Variabile che contiene valore potenziometro avanti-indietro
int ValoreIngresso2; //Variabile che contiene valore potenziometro DX-SX

int Avanti = 2000; // Variabile per comando servo Avanti
int Indietro = 1000; // Variabile per comando servo Indietro
int Stop = 1500; // Variabile per comando servo Stop

/* I valori delle variabili Avanti-Indietro-Stop vanno settate sul tipo di servo
possono contenere anche 700 - 1500 - 2300.
I servi possono anche essere comandati direttamente con gli angoli.
In questo caso sostituisci tutte le istruzioni tutte le istruzioni “writeMicrosecond”
con “servoDX.write” e sostituisci i valori delle variabili con 180 per Avanti, 0 per
Indietro e 90 per Stop*/

void setup()
{
Serial.begin(9600);
servoDX.attach(9);
servoSX.attach(10);
}

void loop()
{
/* Lettura e mappatura porte analogiche A0 e A1 (potenziometri) e assegnazione
dei valori alle variabili ValoreIngresso1 e ValoreIngresso2 */

ValoreIngresso1 = map(analogRead(Analogico1), 0, 1023, 0, 255);
ValoreIngresso2 = map(analogRead(Analogico2), 0, 1023, 0, 255);

Serial.print(ValoreIngresso1); //ogni riga visualizza i valori di entrambi gli ingressi
Serial.print(","); // separati da una virgola
Serial.print(ValoreIngresso2);
Serial.println(""); // a capo

if (ValoreIngresso1 >=200) // Se valoreIngresso1 >=200 entrambi i 2 servi avanti
{
servoDX.writeMicroseconds(Avanti);
servoSX.writeMicroseconds(Avanti);
}

else if(ValoreIngresso1 <=80) // Se valoreIngresso1 <=80 entrambi i 2 servi indietro
{
servoDX.writeMicroseconds(Indietro);
servoSX.writeMicroseconds(Indietro);
}
else
{
servoDX.writeMicroseconds(Stop); // Se valoreIngresso1 <200 e >80 entrambi i 2 servi stop
servoSX.writeMicroseconds(Stop);
}
while (ValoreIngresso2 >=200) // Finche’ valoreIngresso2 >=200 rotazione a sinistra
{
servoDX.writeMicroseconds(Avanti); // Servo destro avanti
servoSX.writeMicroseconds(Indietro); // Servo sinistro indietro
}
while (ValoreIngresso2 <=80) // Finche’ valoreIngresso2 <=80 rotazione destra
{
servoDX.writeMicroseconds(Indietro); // Servo destro indietro
servoSX.writeMicroseconds(Avanti); // Servo sinistro avanti
}}

con un trimmer saresti piu' sicuro....ma se i servi stanno fermi senza "ronzare" ...va bene lo stesso.

In pratica un servo standard lo comandi con l'istruzione:

servo.writeMicroseconds(1500);

oppure con l'istruzione:

servo.write(90);

Nel primo caso dai l'istruzione al servo di muoversi secondo l'ampiezza dell' impulso ( 1500 sta per il centro ) che puo' andare da 1000 a 2000 ...in alcuni casi da 700 a 2300

Nel secondo caso..cioe' servo.write(90) dai istruzioni al servo di muoversi di un determinato angolo (90 sta per il centro) che puo' andare da 0 a 180.

Tieni pero' presente che entrambi i comandi funzionano con i servi standard NON MODIFICATI....perche' togliendo il potenziometro dall'asse del servo...il tuo servo non riconoscera' piu' la sua posizione, quindi cerchera' di trovare sempre e solo la posizione di centro..cioe' ruotera' in continuo a destra o a sinistra.
Per poterne variare la velocita' bisognerebbe piloatre il servo in modo diverso...

Azz…scusa…ci ho pensato ORA che i servi sono contrapposti…ergo e’ da corregere la routine:

Scusami…spero non ci siano altre sviste:
Ecco la routine corretta:

#include <Servo.h>
#define Analogico1 A0
#define Analogico2 A1

Servo servoDX; //servo destro
Servo servoSX; //servo sinistro

int ValoreIngresso1; // Variabile che contiene valore potenziometro avanti-indietro
int ValoreIngresso2; //Variabile che contiene valore potenziometro DX-SX

int Avanti = 2000; // Variabile per comando servo Avanti
int Indietro = 1000; // Variabile per comando servo Indietro
int Stop = 1500; // Variabile per comando servo Stop

/* I valori delle variabili Avanti-Indietro-Stop vanno settate sul tipo di servo
possono contenere anche 700 - 1500 - 2300.
I servi possono anche essere comandati direttamente con gli angoli.
In questo caso sostituisci tutte le istruzioni tutte le istruzioni “writeMicrosecond”
con “servoDX.write” e sostituisci i valori delle variabili con 180 per Avanti, 0 per
Indietro e 90 per Stop*/

void setup()
{
Serial.begin(9600);
servoDX.attach(9);
servoSX.attach(10);
}

void loop()
{
/* Lettura e mappatura porte analogiche A0 e A1 (potenziometri) e assegnazione
dei valori alle variabili ValoreIngresso1 e ValoreIngresso2 */

ValoreIngresso1 = map(analogRead(Analogico1), 0, 1023, 0, 255);
ValoreIngresso2 = map(analogRead(Analogico2), 0, 1023, 0, 255);

Serial.print(ValoreIngresso1); //ogni riga visualizza i valori di entrambi gli ingressi
Serial.print(","); // separati da una virgola
Serial.print(ValoreIngresso2);
Serial.println(""); // a capo

if (ValoreIngresso1 >=200) // Se valoreIngresso1 >=200 marcia avanti
{
servoDX.writeMicroseconds(Avanti);
servoSX.writeMicroseconds(Indietro);
}

else if(ValoreIngresso1 <=80) // Se valoreIngresso1 <=80 marcia indietro
{
servoDX.writeMicroseconds(Indietro);
servoSX.writeMicroseconds(Avanti);
}
else
{
servoDX.writeMicroseconds(Stop); // Se valoreIngresso1 <200 e >80 entrambi i 2 servi stop
servoSX.writeMicroseconds(Stop);
}
while (ValoreIngresso2 >=200) // Finche’ valoreIngresso2 >=200 rotazione a sinistra
{
servoDX.writeMicroseconds(Avanti); // Servo destro avanti
servoSX.writeMicroseconds(Avanti); // Servo sinistro avanti
}
while (ValoreIngresso2 <=80) // Finche’ valoreIngresso2 <=80 rotazione destra
{
servoDX.writeMicroseconds(Indietro); // Servo destro indietro
servoSX.writeMicroseconds(Indietro); // Servo sinistro indietro
}}

FERMO !!
Ho capito il funzionamento a scatti…

Se con un potenziometro dai marcia avanti…i servi ricevono l’istruzione:
Servo DX avanti
Servo SX indietro

se contemporaneamente dai comando con l’altro potenziometro di girare a destra , darai un istruzione:
Servo Dx indietro
Servo SX indietro

ADESSO IMMAGINA IL TUTTO NEL LOOP…se mantinei entrambi i comandi…cioe’ se il joystick da’ contemporaneamente il comando avanti e destra…
AVRAI questa sequenza:

Servo DX avanti
Servo SX indietro
Servo Dx indietro
Servo SX indietro

Servo DX avanti
Servo SX indietro
Servo Dx indietro
Servo SX indietro

Servo DX avanti
Servo SX indietro
Servo Dx indietro
Servo SX indietro

Questi sono SOLO 3 cicli…da’ un occhiata a cosa avviene al servo SX…fara’ i 3 cicli macchina sempre indietro…ehehe

Adesso guarda cosa avviene al servo destro…ehehe ;D
In pratica gli fai fare AVANTI e INDIETRO di continuo…alla velocita’ del Loop…Ecco perche’ il servo vibra ehehehe ;D

Bisognerebbe modificare la routine in modo di stoppare uno dei servi
quando si da’ comando di rotazione…

Puoi fare cosi…inserisci tutto il loop in un ciclo di for …al primo giro ad uno dei servi fai fare uno stop, al secondo un passo avanti…cosi il servo esterno alla curva fara’ due step…mentre quello interno ne fara’ 1 ( oopure 3 e 1 a seconda dell’agolo di svolta desiderata ).

Mi viene sempre in mente qualcosa…man mano che ci penso…
Beh meglio tardi che mai…
Se non riesci a modificare…domani magari te la riscrivo…fammi sapere… :wink:

Se ti aiuta…

Nei comandi Avanti e Indietro Destra e Sinistra …PURI…cioe’ non combinati con altri comandi…cioe’ con un solo potenziometro azionato,non avrai problemi.

MENTRE
Avanti+Rotazione Destra:
Vibrera’ il servo destro

Avanti con rotazione Sinistra:
Vibrera’ il servo sinistro

Indietro +Rotazione Destra:
Vibrera’ il servo sinistro

Indietro +Rotazione Sinistra:
Vibrera’ il servo destro

Quindi salvo errori dovuti all’ora TARDA (sono le 3 e 17)

#include <Servo.h>
#define Analogico1 A0
#define Analogico2 A1

Servo servoDX; //servo destro
Servo servoSX; //servo sinistro

int ValoreIngresso1; // Variabile che contiene valore potenziometro avanti-indietro
int ValoreIngresso2; //Variabile che contiene valore potenziometro DX-SX

int Avanti = 2000; // Variabile per comando servo Avanti
int Indietro = 1000; // Variabile per comando servo Indietro
int Stop = 1500; // Variabile per comando servo Stop

/* I valori delle variabili Avanti-Indietro-Stop vanno settate sul tipo di servo
possono contenere anche 700 - 1500 - 2300.
I servi possono anche essere comandati direttamente con gli angoli.
In questo caso sostituisci tutte le istruzioni tutte le istruzioni “writeMicrosecond”
con “servoDX.write” e sostituisci i valori delle variabili con 180 per Avanti, 0 per
Indietro e 90 per Stop*/

void setup()
{
Serial.begin(9600);
servoDX.attach(9);
servoSX.attach(10);
}

void loop()
{
/* Lettura e mappatura porte analogiche A0 e A1 (potenziometri) e assegnazione
dei valori alle variabili ValoreIngresso1 e ValoreIngresso2 */

ValoreIngresso1 = map(analogRead(Analogico1), 0, 1023, 0, 255);
ValoreIngresso2 = map(analogRead(Analogico2), 0, 1023, 0, 255);

Serial.print(ValoreIngresso1); //ogni riga visualizza i valori di entrambi gli ingressi
Serial.print(","); // separati da una virgola
Serial.print(ValoreIngresso2);
Serial.println(""); // a capo

if (ValoreIngresso1 >=200) // Se valoreIngresso1 >=200 marcia avanti
{
servoDX.writeMicroseconds(Avanti);
servoSX.writeMicroseconds(Indietro);
}

else if(ValoreIngresso1 <=80) // Se valoreIngresso1 <=80 marcia indietro
{
servoDX.writeMicroseconds(Indietro);
servoSX.writeMicroseconds(Avanti);
}

else if(ValoreIngresso2 >=200) // Se valoreIngresso2 >=200 rotazione destra
{
servoDX.writeMicroseconds(Indietro);
servoSX.writeMicroseconds(Indietro);
}

else if(ValoreIngresso2 <=80) // Se valoreIngresso1 <=80 rotazione sinistra
{
servoDX.writeMicroseconds(Avanti);
servoSX.writeMicroseconds(Avanti);
}
else
{
servoDX.writeMicroseconds(Stop); // Se valoreIngresso1 e 2 <200 e >80 entrambi i 2 servi stop
servoSX.writeMicroseconds(Stop);
}
while (ValoreIngresso2 <=80 && ValoreIngresso1 >=200) //rotazione avanti sinistra
{
servoDX.writeMicroseconds(Avanti); // Servo destro avanti
servoSX.writeMicroseconds(Stop); // Servo sinistro Stop
}
while (ValoreIngresso2 >=200 && ValoreIngresso1 >=200) //rotazione avanti destra
{
servoDX.writeMicroseconds(Stop); // Servo destro Stop
servoSX.writeMicroseconds(Avanti); // Servo sinistro avanti
}
while (ValoreIngresso2 <=80 && ValoreIngresso1 <=80) // rotazione indietro sinistra
{
servoDX.writeMicroseconds(Stop); // Servo destro Stop
servoSX.writeMicroseconds(Indietro); // Servo sinistro indietro
}
while (ValoreIngresso2 >=200 && ValoreIngresso1 <=80) // rotazione indietro destra
{
servoDX.writeMicroseconds(Avanti); // Servo destro Avanti
servoSX.writeMicroseconds(Stop); // Servo sinistro Stop
}
}

ma perchè mappate i servo a 255 invece che 0 -180?
come mai non c'è una deadband nella zona centrale?
la storia dovrebbe essere:
da 0 a 89 -->avanti
da 89 a 91-->stop (deadband=3, ma sarebbe meglio allargarla)
da 91 a 180-->indietro
questo per i servi..
il valore dei potenziometri del joystick devi considerarlo mappato sullo stop
quindi se analog read ti restituisce un valore di 512 (joy fermo) , siamo nella deadband dei servi e il bot sta fermo
se analog read di dà un valore superiore a 512 (joy in basso) siamo nella zona 91-180 e il servo và indietro
se analog read dice che sei a meno di 512 (joy in alto) il servo dovrebbe avanzare.
chiaramente la deadband che scegli per i servi devi anche traslarla sui valori di analog read.

@X Ray

Ho provato il tuo codice ed è perfetto, grazie mille! ora ho capito dove sbagliavo.

Vorrei sapere un'altra informazione, quando per caso premo il Joystick in obliquo un servo gira ininterrottamente senza fermarsi, anche dandogli un'altra direzione.
Da cosa può essere dovuto ?

Non saprei...quale servo ? il dx o il sx o entrambi....
E la cosa succede sia in obliquo avanti o anche in obliquo indietro ??

A me a dir la verita' non convinceva da SUBITO la tua mappatura...
Mi rendo conto che haii pensato che essendo i servi ad 8 bit potevi leggere da a 255.

Secondo me trasformerei la mappatura

ValoreIngresso1 = map(analogRead(Analogico1), 0, 1023, 0, 255);
ValoreIngresso2 = map(analogRead(Analogico2), 0, 1023, 0, 255);

in
ValoreIngresso1 = map(analogRead(Analogico1), 0, 1023, 0, 180);
ValoreIngresso2 = map(analogRead(Analogico2), 0, 1023, 0, 180);

e chiaramente dovranno essere reimpostati i parametri delle condizioni..
Do un occhiata a come sia possibile la cosa...

Ho rimappato e cambiato tutti i valori ma il problema persiste.

Il problema succede in tutti i 4 punti obliqui.

A sto punto invece che usare il Joystick faccio prima a mettere 4 pulsanti.....almeno non ci stanno tutti questi problemi.