Purtroppo il progetto con il sensore ad ultrasuoni è fallito, nella teoria funziona ma in pratica non c'è abbastanza potenza per mandare avanti la macchina (circa 1kg).
Non mi sono arreso e facendo varie ricerche ho scoperto che il modulo "L293D" funge anche da amplificatore come un transistor e avendo 4 ingressi è risultato perfetto per 4 motori.
Ecco i materiali necessari:

Qui è come ho gestito il cablaggio:

Il motore 1 è stato collegato al pin 4, il motore 2 al pin 5, il motore 3 al pin 12 e il motore 4 al pin 8.
Per ogni motore il pin dell'Arduino viene collegato all'ingresso del modulo (secondo e penultimo dentino) mentre l'uscita (terzo e terzultimo dentino) va collegata al motore: al + se volete che il motore giri in senso orario mentre al - se volete che il motore giri in senso antiorario, l'altro filo va sempre collegato al GND dell'Arduino (-).
Il sensore a infrarossi è collegato al 2 pin all'uscita, il GND al GND dell'Arduino e l'alimentazione (VCC) ai 3.3V.
Nel codice all'inizio viene richiamata la libreria per il sensore IR: IRremote.h.
int RECV_PIN = 2; viene definita la variabile per il sensore e assegnato il pin 2, vengono anche definiti i pin per ogni motore.
Nella funzione setup(): Serial.begin(9600) inizializza la comunicazione a una velocità di 9600 baud per inviare dati alla console per il debug.
IrReceiver.begin(RECV_PIN, ENABLE_LED_FEEDBACK); inizializza il ricevitore IR con il pin RECV_PIN definito all'inizio e abilita il LED del ricevitore infrarosso.
pinMode(motor1, OUTPUT); ecc... configura i pin dei motori come pin di output per controllare l'alimentazione.
Nella funzione loop() (cuore del programma): if (IrReceiver.decode()) controlla se è stato ricevuto un segnale IR valido.
unsigned long irCode = IrReceiver.decodedIRData.decodedRawData; estrae il valore IR ricevuto e lo memorizza nella variabile irCode.
Il programma quindi verifica il valore di irCode e in base a questo valore esegue determinate azioni:
In questo caso, se è uguale a 0xF30CBF00 rileva che è stato premuto il tasto 0 quindi la macchina andrà avanti in trazione posteriore.
Se irCode è uguale a 0xEF10BF00 rileva che è stato premuto il tasto 1 quindi la macchina andrà in retromarcia in trazione anteriore.
Se irCode è uguale a 0xEE11BF00 rivela che è stato premuto il tasto 2 e la macchina viene configurata per "sterzare a sinistra". Entra in gioco il Motore2 (verso antiorario) e Motore3 (verso orario) che generano un meccanismo simile ad una coppia di forze che fa cambiare direzione alla macchina. Comportamento simile per il tasto 3 con irCode 0xED12BF00 altro che si usano i motori 1 e 4.
Dopo l'esecuzione di una delle condizioni, il programma riprende la ricezione dei segnali IR con IrReceiver.resume(), in modo che possa ripetersi il ciclo per rispondere in continuazione ai comandi IR successivi.
Come detto in precedenza i codici esadecimali cambiano in base ai materiali che avete, vi consiglio di provare prima con quelli indicati nella spiegazione, se non vanno potete aggiungere queste righe di codice:
Serial.print("Codice IR ricevuto: 0x");
Serial.println(irCode, HEX);
Che vi restituiscono sulla console i risultati IR dopo aver premuto un tasto.
Ecco il codice completo:
#include <IRremote.h>
int RECV_PIN = 2;
int motor1 = 4;
int motor2 = 5;
int motor3 = 12;
int motor4 = 8;
void setup() {
Serial.begin(9600);
IrReceiver.begin(RECV_PIN, ENABLE_LED_FEEDBACK);
pinMode(motor1, OUTPUT);
pinMode(motor2, OUTPUT);
pinMode(motor3, OUTPUT);
pinMode(motor4, OUTPUT);
}
void loop() {
if (IrReceiver.decode()) {
unsigned long irCode = IrReceiver.decodedIRData.decodedRawData;
Serial.print("Codice IR ricevuto: 0x");
Serial.println(irCode, HEX); // IR esadecimale
if (irCode == 0xF30CBF00) { // "0"
// trazione posteriore
digitalWrite(motor1, HIGH);
digitalWrite(motor2, LOW);
digitalWrite(motor3, HIGH);
digitalWrite(motor4, LOW);
} else if (irCode == 0xEF10BF00) { // "1"
// trazione anteriore
digitalWrite(motor1, LOW);
digitalWrite(motor2, HIGH);
digitalWrite(motor3, LOW);
digitalWrite(motor4, HIGH);
} else if (irCode == 0xEE11BF00) { // "2"
// Sterza sx
digitalWrite(motor1, LOW);
digitalWrite(motor2, HIGH);
digitalWrite(motor3, HIGH);
digitalWrite(motor4, LOW);
} else if (irCode == 0xED12BF00) { // "3"
// Sterza dx
digitalWrite(motor1, HIGH);
digitalWrite(motor2, LOW);
digitalWrite(motor3, LOW);
digitalWrite(motor4, HIGH);
}
IrReceiver.resume(); // IR
}
}
Schema elettrico:

LINK TINKERCAD AL PROGETTO QUI