Sommario:

Telecomando hackerabile per ZenWheels Microcar: 7 passaggi
Telecomando hackerabile per ZenWheels Microcar: 7 passaggi

Video: Telecomando hackerabile per ZenWheels Microcar: 7 passaggi

Video: Telecomando hackerabile per ZenWheels Microcar: 7 passaggi
Video: обзор/мнение Atomic Racers в масштабе 1:64 Micro RC 2024, Dicembre
Anonim
Image
Image
Assemblea
Assemblea

In questo tutorial costruiremo un telecomando personalizzato per la microcar ZenWheels. La microcar ZenWheels è una macchinina da 5 cm controllabile tramite un'applicazione Android o Iphone. Ti mostrerò come decodificare l'applicazione Android per scoprire il protocollo di comunicazione e come puoi costruire un telecomando usando arduino e un giroscopio.

Passaggio 1: componenti e strumenti

Parti:

1. La microcar ZenWheels

2. Arduino pro mini 328p

3. Tagliere

4. Giroscopio MPU6050

5. fonte di alimentazione <=5 v (qualche batteria che possiamo collegare alla breadboard)

6. Cavi jumper a forma di U (opzionali). Ho usato questi cavi jumper perché hanno un aspetto migliore sulla breadboard. In alternativa è possibile utilizzare cavi jumper normali

7. Modulo bluetooth HC-05 (con un pulsante per accedere alla modalità AT)

Utensili:

1. Adattatore FTDI da USB a seriale FT232RL per programmare Arduino pro mini

2. Arduino IDE

3. Telefono Android

4. Studio Android [Opzionale]

Passaggio 2: decodificare l'applicazione Android ZenWheels [opzionale]

Per comprendere questa parte è necessaria una certa conoscenza di Java e Android.

L'obiettivo del progetto è controllare la microcar utilizzando un giroscopio. Per questo abbiamo bisogno di saperne di più sulla comunicazione bluetooth tra questo giocattolo e l'app Android.

In questo passaggio spiegherò come decodificare il protocollo di comunicazione tra la microcar e l'app Android. Se vuoi solo costruire il telecomando, questo passaggio non è necessario. Un modo per scoprire il protocollo è guardare il codice sorgente. Hmm ma questo non è semplice, le applicazioni Android sono compilate e si può installare l'apk tramite Google Play.

Quindi ho creato una guida di base per farlo:

1. Scarica l'APK. Un Android Package Kit (APK in breve) è il formato di file del pacchetto utilizzato dal sistema operativo Android per la distribuzione e l'installazione di app mobili

Prima cerca l'applicazione su google play store, nel nostro caso cerca "zenwheels" e otterrai il link dell'applicazione

Quindi cerca su google "downloader apk online" e usane uno per scaricare l'apk. Di solito ci chiederanno il link dell'applicazione (quello che abbiamo ottenuto in precedenza), quindi premeremo un pulsante di download e lo salveremo nel nostro computer.

2. Decompilare l'APK. Un decompilatore nella nostra situazione è uno strumento che prende l'APK e produce il codice sorgente Java.

La soluzione più semplice è utilizzare un decompilatore online per eseguire il lavoro. Ho cercato su Google "decompiler online" e ho scelto https://www.javadecompilers.com/. Devi solo caricare l'APK che hai ottenuto in precedenza e

premere la decompilazione. Quindi devi solo scaricare i sorgenti.

3. Prova a decodificare il codice guardando il codice

Per aprire il progetto è necessario un editor di testo o meglio un IDE (ambiente di sviluppo integrato). L'IDE predefinito per i progetti Android è Android Studio (https://developer.android.com/studio). Dopo aver installato Android Studio, apri la cartella del progetto.

Poiché la nostra macchina è controllata da bluetooth ho iniziato la mia ricerca nel codice decompilato con la parola chiave "bluetooth", dalle occorrenze che ho trovato "BluetoothSerialService" era in grado di gestire la comunicazione. Se questa classe gestisce la comunicazione, deve avere un metodo di comando di invio. Si scopre che esiste un metodo di scrittura che invia i dati attraverso il canale bluetooth:

public void write(byte out)

Questo è un buon inizio, ho cercato il metodo.write(in uso e c'è una classe "ZenWheelsMicrocar" che estende il nostro "BluetoothSerialService". Questa classe contiene la maggior parte della logica della nostra comunicazione tramite Bluetooth. L'altra parte di la logica è nei controller: BaseController e StandardController.

Nel BaseController abbiamo l'inizializzazione del servizio, e anche le definizioni dei canali sterzo e acceleratore, i canali sono infatti prefissi di comando per specificare che seguirà qualche tipo di comando:

microcar ZenWheelsMicrocar protetto = new ZenWheelsMicrocar(this, this.btHandler);

uscite ChannelOutput protette = {new TrimChannelOutput(ZenWheelsMicrocar. STEERING_CHANNEL), nuovo TrimChannelOutput(ZenWheelsMicrocar. THROTTLE_CHANNEL)};

Nello StandardController lo sterzo è gestito in:

public void handleSteering(TouchEvent touchEvent) {

… this.microcar.setChannel(steeringOutput.channel, sterzoOutput.resolveValue()); }

Analizzando il metodo, lo sterzoOutput.channel ha il valore 129 (canale utilizzato per lo sterzo) e lo sterzoOutput.resolveValue() può avere un valore compreso tra -90 e 90. Il valore del canale (129) viene inviato direttamente e il valore dello sterzo viene modificato applicando operazioni bit per bit:

private final int value_convert_out(int value) {

booleano negativo = falso; if (valore < 0) { negativo = f6D; } int valore2 = valore & 63; if (negativo) { valore restituito2 | 64; } restituisce valore2; }

C'è un metodo simile nello StandardController chiamato

public void handleThrottle(TouchEvent touchEvent)

Passaggio 3: componenti

Parti:

1. Arduino pro mini 328p 2 $

2. Tagliere

3. Giroscopio MPU6050 1.2$

4. Modulo 6 pin master-slave HC-05 3$

5. 4 batterie AA con 4 batterie

6. Cavi jumper a forma di U (opzionali). Ho usato questi cavi jumper perché hanno un aspetto migliore sulla breadboard e i led sono più visibili in questo modo. Se non hai questi cavi puoi sostituirli con cavi Dupont.

I prezzi sopra indicati sono presi da eBay.

Utensili:

1. Adattatore FTDI da USB a seriale FT232RL per programmare arduino pro mini

2. Arduino IDE

3. Android Studio (opzionale se si desidera eseguire il reverse engineering da soli)

Passaggio 4: assemblaggio

Assemblea
Assemblea

L'assemblaggio è molto semplice perché lo stiamo facendo su una breadboard:)

- per prima cosa posizioniamo i nostri componenti sulla breadboard: il microcontrollore, il modulo bluetooth e il giroscopio

- collegare i pin RX e TX bluetooth HC-05 ai pin arduino 10 e 11. Il giroscopio SDA e SCL deve essere collegato ai pin arduino A4 e A5

- collega i pin di alimentazione al bluetooth, al giroscopio e all'arduino. i pin devono essere collegati a + e - sul lato della breadboard

- per ultimo collegare un alimentatore (tra 3,3 V e 5 V) alla breadboard, ho usato una piccola batteria LiPo a una cella ma qualsiasi cosa andrà bene finché è nell'intervallo di potenza

Si prega di controllare le immagini sopra per maggiori dettagli

Passaggio 5: associare il Bluetooth HC-05 alla Microcar

Associa l'HC-05 Bluetooth alla Microcar
Associa l'HC-05 Bluetooth alla Microcar
Associa l'HC-05 Bluetooth alla Microcar
Associa l'HC-05 Bluetooth alla Microcar
Associa l'HC-05 Bluetooth alla Microcar
Associa l'HC-05 Bluetooth alla Microcar

Per questo avrai bisogno di un telefono Android, del modulo bluetooth HC-05 e dell'adattatore seriale FTDI con fili. Inoltre utilizzeremo l'IDE Arduino per comunicare con il modulo bluetooth.

Per prima cosa dobbiamo scoprire l'indirizzo bluetooth della microcar:

- abilita il bluetooth sul tuo telefono

- accendi l'auto e vai alla sezione bluetooth delle tue impostazioni in Android

- cercare nuovi dispositivi e dovrebbe apparire un dispositivo chiamato "Microcar"

- accoppiare con questo dispositivo

- quindi per estrarre il MAC bluetooth, ho usato questa app da Google Play Serial Bluetooth Terminal

Dopo aver installato questa app, vai al menu -> dispositivi e lì avrai un elenco con tutti i dispositivi Bluetooth accoppiati. Ci interessa solo il codice sotto la miniera "Microcar" è 00:06:66:49:A0:4B

Quindi collegare l'adattatore FTDI al modulo bluetooth. Prima i pin VCC e GROUND e poi FTDI RX su bluetooth TX e FTDI TX su bluetooth RX. Inoltre dovrebbe esserci un pin sul modulo bluetooth che dovrebbe essere collegato al VCC. Così facendo il modulo bluetooth entra in "modalità programmabile". Il mio modulo ha un pulsante che collega il VCC a quel pin speciale. Quando si collega l'FTDI all'USB, dovrebbe essere con il pin collegato / premuto il pulsante per entrare in questa modalità programmabile speciale. Il bluetooth conferma l'ingresso in questa modalità di funzionamento lampeggiando lentamente ogni 2 secondi.

Nell'IDE di Arduino selezionare la porta seriale, quindi aprire il monitor seriale (sia NL che CR con velocità di trasmissione di 9600). Digitare AT e il modulo dovrebbe confermare con "OK".

Digitare "AT+ROLE=1" per mettere il modulo in modalità master. Per accoppiare il tuo modulo bluetooh scrivi: "AT+BIND=0006, 66, 49A04B", nota come il nostro "00:06:66:49:A0:4B" viene trasformato in "0006, 66, 49A04B". Bene, dovresti fare la stessa trasformazione per il tuo MAC bluetooh.

Ora accendi l'auto Zenwheels, quindi scollega l'FTDI e ricollegalo senza premere il pulsante / pin speciale collegato. Dopo un po' dovrebbe connettersi all'auto e noterai che l'auto emette un suono di connessione specifico.

Risoluzione dei problemi:

- Ho scoperto che di tutti i moduli Bluetooth che avevo, solo quello con un pulsante funzionava da master!

- assicurarsi che l'auto sia completamente carica

- assicurarsi che l'auto non sia collegata al telefono

- se il Bluetooth entra in modalità AT (lampeggia lentamente) ma non risponde al comando assicurati di avere ENTRAMBI NL e CR e sperimenta anche altre velocità BAUD

- ricontrolla che RX sia connesso a TX e viceversa

- prova questo tutorial

Passaggio 6: codice e utilizzo

Per prima cosa devi scaricare e installare due librerie:

1. Libreria MPU6050 per il giroscopio

2. Sorgente della libreria I2CDev

Quindi scarica e installa la mia libreria da qui o copiala da sotto:

/** * Librerie: * https://github.com/jrowberg/i2cdevlib * https://github.com/jrowberg/i2cdevlib */ #include "I2Cdev.h" #include "MPU6050_6Axis_MotionApps20.h" #include "Wire.h" #include "SoftwareSerial.h"

const int MAX_ANGLE = 45;

const byte comandoStering = 129; const byte commandSpeed = 130;

inizializzazione bool = false; // imposta true se l'inizializzazione DMP ha avuto successo

uint8_t mpuIntStatus; // mantiene il byte di stato dell'interrupt effettivo dalla MPU uint8_t devStatus; // restituisce lo stato dopo ogni operazione del dispositivo (0 = successo, !0 = errore) uint16_t packetSize; // dimensione prevista del pacchetto DMP (il valore predefinito è 42 byte) uint16_t fifoCount; // conteggio di tutti i byte attualmente in FIFO uint8_t fifoBuffer[64]; // Buffer di memorizzazione FIFO Quaternion q; // [w, x, y, z] contenitore di quaternioni VectorFloat gravità; // [x, y, z] vettore gravità float ypr[3]; // [imbardata, beccheggio, rollio] contenitore imbardata/beccheggio/rollio e vettore di gravità volatile bool mpuInterrupt = false; // indica se il pin di interruzione MPU è andato alto

unsigned long lastPrintTime, lastMoveTime = 0;

SoftwareSerial BTserial(10, 11);

MPU6050 MPU;

configurazione nulla()

{ Serial.begin(9600); BTserial.begin(38400); Serial.println("Programma avviato"); inizializzazione = initializeGyroscope(); }

ciclo vuoto() {

if (!inizializzazione) { return; } mpuInterrupt = falso; mpuIntStatus = mpu.getIntStatus(); fifoCount = mpu.getFIFOCount(); if (hasFifoOverflown(mpuIntStatus, fifoCount)) { mpu.resetFIFO(); Restituzione; } if (mpuIntStatus & 0x02) { while (fifoCount < packetSize) { fifoCount = mpu.getFIFOCount(); } mpu.getFIFOBytes(fifoBuffer, packetSize); fifoCount -= dimensione pacchetto; mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); steer(ypr[0] * 180/M_PI, ypr[1] * 180/M_PI, ypr[2] * 180/M_PI); } }

/*

* Riceve angolo da 0 a 180 dove 0 è max sinistra e 180 è max destra * Riceve velocità da -90 a 90 dove -90 è max indietro e 90 è max avanti */ void moveZwheelsCar(byte angle, int speed) { if (millis() - lastMoveTime = 90) { resultAngle = map(angle, 91, 180, 1, 60); } else if (angolo 0) { resultSpeed = map(speed, 0, 90, 0, 60); } else if (velocità < 0) { resultSpeed = map(velocità, 0, -90, 120, 60); } Serial.print("actualAngle=");Serial.print(angolo);Serial.print("; "); Serial.print("actualSpeed=");Serial.print(resultSpeed);Serial.println("; "); BTserial.write(commandStering); BTserial.write(resultAngle); BTserial.write(commandSpeed); BTserial.write((byte) resultSpeed); lastMoveTime = millis(); }

void steer(int x, int y, int z)

{ x = constrain(x, -1 * MAX_ANGLE, MAX_ANGLE); y = constrain(y, -1 * MAX_ANGLE, MAX_ANGLE); z = constrain(z, -MAX_ANGLE, MAX_ANGLE); int angolo = map(y, -MAX_ANGLE, MAX_ANGLE, 0, 180); int velocità = map(z, -MAX_ANGLE, MAX_ANGLE, 90, -90); printDebug(x, y, z, angolo, velocità); moveZwheelsCar (angolo, velocità); }

void printDebug(int x, int y, int z, int angolo, int velocità)

{ if (millis() - lastPrintTime < 1000) { return; } Serial.print("z=");Serial.print(x);Serial.print("; "); Serial.print("y=");Serial.print(y);Serial.print("; "); Serial.print("z=");Serial.print(z);Serial.print("; "); Serial.print("angolo=");Serial.print(angolo);Serial.print("; "); Serial.print("speed=");Serial.print(speed);Serial.println("; "); lastPrintTime = millis(); }

bool initializeGyroscope()

{ Wire.begin(); mpu.initialize(); Serial.println(mpu.testConnection() ? F("Connessione MPU6050 riuscita"): F("Connessione MPU6050 non riuscita")); devStatus = mpu.dmpInitialize(); mpu.setXGyroOffset(220); mpu.setYGyroOffset(76); mpu.setZGyroOffset(-85); mpu.setZAccelOffset(1788); if (devStatus != 0) { Serial.print(F("Inizializzazione DMP fallita (codice "));Serial.println(devStatus); return false; } mpu.setDMPEnabled(true); Serial.println(F("Abilitazione rilevamento degli interrupt (Arduino external interrupt 0)…")); attachInterrupt(0, dmpDataReady, RISING); mpuIntStatus = mpu.getIntStatus(); Serial.println(F("DMP pronto! In attesa del primo interrupt…")); packetSize = mpu.dmpGetFIFOPacketSize(); return true; }

void dmpDataReady()

{ mpuInterrupt = vero; }

boolean hasFifoOverflown(int mpuIntStatus, int fifoCount)

{ return mpuIntStatus & 0x10 || fifoCount == 1024; }

Carica il codice utilizzando l'adattatore FTDI su arduino, quindi collega le batterie.

Utilizzo del telecomando:

Dopo aver acceso l'arduino, accendi anche l'auto. Il modulo HC-05 dovrebbe connettersi all'auto, quando ciò accade l'auto emetterà un suono. Se non funziona, controlla il passaggio precedente e la sezione relativa alla risoluzione dei problemi.

Se inclini la breadboard in avanti, l'auto dovrebbe muoversi in avanti, a destra e l'auto dovrebbe muoversi a destra. Esegue anche movimenti più graduali come inclinare un po' in avanti e un po' a sinistra in questo caso l'auto andrebbe lentamente a sinistra.

Se l'auto va in un modo diverso quando si inclina la breadboard, tenere prima la breadboard in direzioni diverse.

Come funziona:

Lo sketch riceve le coordinate del giroscopio ogni 100 ms, effettua i calcoli e poi trasmette via bluetooth i comandi dell'auto. Innanzitutto c'è un metodo "steer" che viene chiamato con gli angoli x, yez grezzi. Questo metodo trasforma lo sterzo tra 0 e 180 gradi e l'accelerazione tra -90 e 90. Questo metodo chiama

void moveZwheelsCar(byte angle, int speed) che converte lo sterzo e l'accelerazione alle specifiche ZenWheels e poi trasmette i comandi tramite bluetooth.

Il motivo per cui ho eseguito la trasformazione in due passaggi è la riutilizzabilità. se avessi bisogno di adattare questo sketch al controllo remoto di qualche altro dispositivo, partirei dal metodo base "steer" che già mappa la velocità e lo sterzo su alcuni valori utili.

Passaggio 7: alternative

Un'alternativa al "reverse engineering". Ho parlato di come decodificare il progetto partendo dall'applicazione Android. Ma c'è un'alternativa a questo, puoi configurare un FTDI seriale + slave bluetooth (normale HC-05 senza specificare le impostazioni del master). Quindi dall'app ZenWheels connettiti all'HC-05 invece che alla "microcar".

Per decodificare i comandi dovrai tenere il volante in una certa posizione, quindi utilizzando uno script Python analizzare la comunicazione seriale. Sto suggerendo uno script Python perché ci sono caratteri non stampabili e Arduino IDE non è adatto a questo. Noterai che se tieni il volante in una posizione l'app trasmetterà regolarmente gli stessi due byte. Se si varia la posizione della ruota il primo byte rimarrà lo stesso, il secondo cambierà. Dopo molte prove puoi trovare l'algoritmo di sterzo, quindi decodificare l'acceleratore, ecc.

Un'alternativa al telecomando basato su arduino sarebbe un telecomando RaspberryPi. Il raspberry pi ha un modulo bluetooth incorporato che è indolore da configurare in modalità "master" e la libreria bluetooth python funziona come un incantesimo. Sono possibili anche alcuni progetti più interessanti come controllare l'auto usando Alexa echo:)

Spero che il progetto vi sia piaciuto e lasciate un commento qui sotto!

Consigliato: