Macchina comandata da 2 Arduini

Salve a tutti,
sono entrato nel mondo di Arduino da circa due anni.
Ultimamente mi sto cimentando nel modificare una macchina radiocomandata per funzionare con Arudino.
Allego uno schema per farvi capire quello che voglio fare.
La parte hardware non ho problemi, per il software invece si.
I potenziometri dei joystick sono da 1 Kohm, li trovate qui: Servizio di incisione e taglio laser - FuturaShop
Dovrei pilotare 2 servomotori per lo sterzo con l'asse X di un joystick, un altro servomotore con l'asse Y di questo joystick
e infine due servomotori rispettivamente con gli assi X e Y dell'altro joystick, il tutto via seriale. Sono un novellino nella comunicazione seriale, non l'ho mai usata. Se qualcosa non è chiaro chiedete.

Grazie, Gibi2000

Non ho capito bene quale sia la domanda, comunque faccio una piccola carrellata su quello che secondo me dovresti fare, poi vedi tu se è quello che serviva.

Con un'entrata analogica leggi il valore ritornato dal potenziometro e hai i due dati di velocità e sterzo suppongo.
Puoi direttamente elaborarli lato radiocomando e quindi usare la funzione map per fare la proporzione tra i tuoi valori massimi in ingresso (0-1023) e quelli in uscita (che se non erro dipende dal pwm 0-255 per la velocità, e dal pwm più massimo angolo di rotazione dello sterzo-quindi a me verrebbe di usare due volte la funzione map, ma volendo c'è una libreria servo che fa tutto da solo-) Questa parte puoi farla anche lato 'centralina'.
Per l'invio seriale basta che inizializzi le seriali alla stessa velocità, usa Serial.write e il dato che ti serve mentre nella ricevente qualcosa del tipo while (Serial.available()) {a=Serial.read()...} Considera che la comunicazione avviene in byte quindi tu leggi un solo byte in arrivo per ogni volta che usi read. Controllerei quindi di lasciare una breve pausa alla fine di una comunicazione (oppure userei un flag tipo quello che c'è al termine delle stringe NMEA) per evitare che arrivino due dati alla centralina prima che lei sia stata in grado di attuare sui servi l'informazione, altrimenti rischi che vada in loop infinito il while e non il void loop!

Questo da uno che in realtà non ha mai costruito una macchina come vuoi fare tu, quindi attendi info più certe dai più esperti. Io ho messo la le prime cose che mi sono venute in mente e le prime problematiche.

Per quanto riguarda la gestione dei motori a spazzole alimenta la scheda esternamente perchè io facendo due prove ci ho bruciato una seriale usb una volta

ciao,
grazie per la tua risposta immediata e per i consigli, ma non ho capito molto bene la comunicazione seriale.
avrei delle domande:
ad esempio ho il potenziometro 1 che attraverso la funzione map mi da l'output in una variabile come pot1.
stessa cosa per il potenziometro n°2, la cui variabile è pot2.
Come posso inviare i due dati separatamente e sull'altro Arduino leggerli separatamente con la funzione specifica della libreria servo?
se non ti do fastidio mi potresti fare un esempio anche semplificato?

Per l'invio seriale basta che inizializzi le seriali alla stessa velocità, usa Serial.write e il dato che ti serve mentre nella ricevente qualcosa del tipo while (Serial.available()) {a=Serial.read()...}

Perchè devo scrivere questo?
Scusa se sono ignorante ma come detto prima sono nuovo per la comunicazione seriale.
Grazie, Gibi2000

Figurati, il forum è fatto apposta :wink:

Non so bene cosa intendi per inviare i due dati separatamente, comunque in genere per suddividere le cose in programmazione si usano delle flag, cioè dei simboli particolari (nell'NMEA che citavo è *) o comunque qualcosa che sai che invii solo tu quando hai finito di trasmettere. Una sorta di 'passo e chiudo'.
In questo caso, dovendo tu trasmettere un numero, verosimilmente un int a 16 bit (2 byte) puoi suddividerlo in due variabile byte con high e low byte e quindi trasmetti. Tu hai due variabili composte da due pezzi, sai che i primi due byte trasmessi sono della prima, gli ultimi due della seconda variabile.

int pot1 = map(.....);
int pot2 = map(....);

byte low1=lowByte(pot1);
byte high1=lowByte(pot2);
Serial.print(low1);
Serial.print(high1);//qui stai attento a usare print e non println perchè credo che println invii un byte anche per dare il new line.

Il ciclo while serve per leggere tutti i valori presenti nella seriale, nel caso fatto sopra in teoria hai solo 4 byte quindi puoi anche fare un for che produce quattro iterazioni. In generale si usa il while perchè non conosci quanti byte hai passato.

La libreria servo l'ho usata una volta in passato e non ricordo molto bene, comunque credo che faccia da se alcune cose che ti ho detto passo passo prima. Dai un occhio nella reference.

Tutto quello che ti ho detto l'ho scritto 'a memoria' quindi è possibile ci sia qualche imprecisione, i passaggi però dovrebbero essere corretti.
Come prima, fai delle prove e magari attendi qualche risposta più quotata della mia :slight_smile:

Non so bene cosa intendi per inviare i due dati separatamente

Grazie, comunque per inviarli separatamente intendo inviarli sulla seriale e "decodificarli".
Poco tempo fa avevo pensato ad una decodificazione del tipo che la variabile pot1 venisse inviata in questo modo:
Serial.write(1pot1);
solo che è un'idea, una sorta di codifica ad esempio se il valore di pot1 è 115, sulla seriale venga scritto 1155, a significare che il valore compreso tra 999 e 1999 è assegnato a pot1. Invece a pot2 sarà assegnato il numero 2, quindi se il valore di pot2 è 120, sulla seriale venga scritto 2120.
Spero di non aver scritto cose senza senso.

Grazie in anticipo
Gibi2000

Scrivere 1pot1 non ha senso in quanto la variabile è pot1 e se aggiungi un uno in testa ottieni solo un errore in quanto il micro non trova nulla con quel nome!
Avrebbe senso se fossi in grado di sapere quante cifre ha e ci aggiungi un uno, oppure se trasformi tutto in stringa e aggiungi un uno in testa, ma secondo me appesantisci il programma per nulla.
Le due alternative secondo me sono

A - conosco da quanti 'pezzi' è composto ogni dato: non ho bisogno di flag per dire che uno è finito e semplicemente dico che i primi x pezzi sono dell'uno, gli altri del due.

B - non conosco quanto lunga sia:
.print(pot1);
.print("");
.print(pot2);
.print("
");

e nella parte di lettura sai che ogni volta che trovi un * stai saltando da un dato all'altro.

Molto più semplice e credo che alla fine occupi anche meno memoria

Grazie ancora. :slight_smile:
Però bisogna dire all'Arduino in lettura che il simbolo "*" significa che si passa all'altro dato..
pensavo che si potesse usare qualcosa tipo

int datarec= 0;
if (datarec == *) {...}

spero che possa funzionare.
Ciao Gibi2000

Penso sia meno macchinoso con un ciclo while, avendo solo due dati e sapendo sempre qual'è il primo puoi dire: finchè il valore è diverso da * lo inserisci in uno (appena trova * esce da questo), quindi: finchè il valore è diverso da * lo inserisci in due. Appena trova un * esce dal while, procede col loop e poi ricomincia da capo...per via del buffer, se non hai una comunicazione tale da riempirlo interamente prima di leggerlo ottieni sempre di leggere il più vecchio entrato...Se hai velocità esagerato puoi optare per due flag diversi...

Ciao,
ho sviluppato due programmi, uno per il "telecomando" e uno per la ricevente.
Quello del "telecomando":

int pot;      
int potser;

void setup() {
Serial.begin(9600);      //inizializza la seriale alla velocità di 9600 bps
}

void loop() {
  pot = analogRead(A0);      //assegna il valore della lettura di A0 alla variabile pot
  
potser = map(pot,0,1023,0,180); //converte la variabile pot(0,1023) alla variabile potser(0,180)
  
Serial.println(potser);      //scrive sulla seriale la variabile potser.
  
 delay(10);      //pausa 
}

per il momento invia sulla seriale solo il valore dell'asse y del joystick.
Fin qui non ci sono problemi...

la ricevente:

#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); // RX, TX

int datarec;

void setup() {
  Serial.begin(9600); //avvio la seriale per monitorare il tutto dal monitor seriale
  mySerial.begin(9600); // avvio la seriale che riceve i dati dal telecomando
  }

void loop() {
  datarec = mySerial.read();            
  delay(10);
  Serial.println(datarec); //scrivo sulla seriale (di modo che dal pc veda tutto) il valore ricevuto dal telecomando
  
}

qui non funziona: sul monitor seriale mi arriva "53" come valore. Quando sposto il joystick da una parte diventa "48. quando lo sposto dall'altra diventa "49". Non ho la più pallida idea di cosa c'è che non va... :~

grazie, Gibi2000

ciao gibi2000

seriale mi arriva "53" come valore. Quando sposto il joystick da una parte diventa "48. quando lo sposto dall'altra diventa "49". Non ho la più pallida idea di cosa c'è che non va... smiley-confuse

come ti ha gia detto mastraa

mastraa:
...
Considera che la comunicazione avviene in byte quindi tu leggi un solo byte in arrivo per ogni volta che usi read

tu dalla seriale leggi un byte per volta e quei numeri corrispondono al codice ASCII di quel carattere.
ti consigli di leggere questo articolo di leo72 che sicuramente fa al caso tuo.
ciao
pippo72