Bionic Spider Controller - Teil 2 - AZ-Delivery

Nell'ultimo post del blog, il ragno bionico è stato controllato con un controller autocostruito tramite il protocollo ESPNOW.

Ciò consente una semplice connessione da dispositivo a dispositivo senza dover essere collegati a una rete.

In questo blog, utilizziamo il protocollo Internet UDP per scambiare pacchetti di dati tra i microcontrollori. A tale scopo, il telecomando e lo spider devono trovarsi nella stessa rete.

Tuttavia, questa piccola limitazione ha anche il vantaggio che la portata dei ripetitori e dei punti di accesso della rete domestica è di solito più ampia e completa e la connessione può essere stabilita anche su una distanza maggiore rispetto alla linea di vista.

 

Hardware

Se il controllore è già stato installato nella cartella Blog del controllore ragno si può saltare la parte seguente e proseguire con il software.

 

Sono disponibili due versioni del joystick: da un lato, il joystick KY-023 è possibile utilizzare un modulo di tipo "a". Tuttavia, dato che anche in questo caso sarebbe necessario un cablaggio molto lungo, si consiglia di usare il modulo Schermo per joystick PS2che può anche essere collegato direttamente ad un microcontrollore con Uno Il layout può essere collegato.

Poiché il microcontrollore deve comunicare con il robot, è necessario un microcontrollore con funzionalità WiFi. Inoltre, sono necessari due ADC per ciascuno degli assi X e Y, motivo per cui è necessario utilizzare un ESP32.

(L'ESP8266 ha solo un ingresso ADC).

 

Per la realizzazione del progetto sono necessari:

ESP32 NodeMCU D1 R32

Schermo per joystick PS2

(opzionale) Batteria di blocco da 9V + Clip per batteria

e naturalmente uno assemblato Kit robot Bionic Spider

 

Poiché gli ingressi analogici dei due assi del joystick sono collegati ai GPIO 2 e 4, che sono collegati all'ADC2, questi non possono essere utilizzati contemporaneamente al modulo WLAN. Tuttavia, le connessioni IO 34 e IO35 (ADC1) si trovano direttamente accanto a queste, il che significa che la funzionalità può essere facilmente stabilita tramite un ponticello.

Figura 1: Ponte di fili tra le connessioni

 

Collegare i collegamenti come indicato sopra.


Poiché il LED di bordo è collegato al GPIO 2, il pin deve essere rimosso in questo punto, poiché altrimenti il collegamento influirebbe sul valore della tensione dell'asse X.

Lo stesso vale per il pin D12, che interferisce con il processo di avvio e quindi non è possibile avviare il sistema con lo shield inserito. Il pulsante centrale del joystick è collegato a questa connessione, il che significa che non può più essere utilizzato. Se si desidera comunque implementarlo, è necessario ricollegarlo a una connessione libera.

 

Figura 2: Scudo con modifiche

 

Lo schermo può essere semplicemente collegato al D1 R32. Assicuratevi che il piccolo interruttore nell'angolo sinistro sia impostato su 3v3 Altrimenti l'ESP32 potrebbe essere danneggiato dalla tensione eccessiva di 5 V.

 

Software

Se si sta programmando un ESP32/ESP8266 nell'IDE Arduino per la prima volta, copiare i seguenti URL nell'IDE Arduino in: File->Preferences->Additional boards manager URLs :  https://dl.espressif.com/dl/package_esp32_index.json

http://arduino.esp8266.com/stable/package_esp8266com_index.json

 

e installare il pacchetto ESP32 e ESP8266 nell'amministrazione della scheda.

 

Per la comunicazione, i pacchetti di dati vengono scambiati utilizzando UDP. Con questo protocollo di comunicazione, i pacchetti vengono semplicemente inviati senza controllare se il pacchetto è stato ricevuto.

Questo rende lo scambio di dati molto veloce, ma anche insicuro, poiché non è possibile determinare se il destinatario riceve effettivamente i dati.

 

La libreria per la comunicazione UDP è già inclusa nei pacchetti di schede complete per ESP8266 e ESP32.

 

Nel blog ESPnow, per la comunicazione era richiesto l'indirizzo MAC del microcontrollore.
Quando si comunica via UDP, è necessario solo l'indirizzo IP del ricevitore. Questo viene assegnato automaticamente tramite il server DHCP del router al momento della connessione alla rete domestica (WLAN).
L'indirizzo IP può essere determinato tramite l'interfaccia utente del router, ma viene anche visualizzato sul monitor seriale all'inizio del programma del ricevitore.

 

Codice Ragno bionico

Caricare il seguente codice sull'ESP8266 del kit Bionic Spider selezionando la porta e la scheda corretta nell'IDE Arduino.

 

#include <ESP8266WiFi.h>
#
include <WiFiUdp.h>
#
include "commands.h"

const char* ssid = "Name";
const char* password = "PSWD";
String cmd; //recieved Command

WiFiUDP udp;

void setup() {
  
Serial.begin(115200);
  
Serial.println();

  
WiFi.begin(ssid, password);
  
while (WiFi.status() != WL_CONNECTED) {
    
delay(500);
    
Serial.print(".");
    
if(millis() > 30000) ESP.restart();
  }

  udp.
begin(4210);

  
Serial.println("ESP8266 ready (Reciever)");
  
Serial.print("IP:");
  
Serial.println(WiFi.localIP());


  servo_14.
attach(14, SERVOMIN, SERVOMAX);// Connect the servo to pin 14
  servo_12.
attach(12, SERVOMIN, SERVOMAX);// Connect the servo to pin 12
  servo_13.
attach(13, SERVOMIN, SERVOMAX);// Connect the servo to pin 13
  servo_15.
attach(15, SERVOMIN, SERVOMAX);// Connect the servo to pin 15
  servo_16.
attach(16, SERVOMIN, SERVOMAX);// Connect the servo to pin 16
  servo_5.
attach(5, SERVOMIN, SERVOMAX);// Connect the servo to pin 5
  servo_4.
attach(4, SERVOMIN, SERVOMAX);// Connect the servo to pin 4
  servo_2.
attach(2, SERVOMIN, SERVOMAX);// Connect the servo to pin 2

  Servo_PROGRAM_Zero();
// Reset the servo program to zero
}

void loop() {
  
//Serial.print("IP:");
  
//Serial.println(WiFi.localIP());
  
int pSize = udp.parsePacket();
  
if (pSize) {
    
char buf[20];
    
int len = udp.read(buf, 20);
    buf[len] = 
0;

    cmd = 
String(buf);
    
Serial.println(cmd);
  }

  
if(cmd.length() > 0) {
    
if(cmd.indexOf("CMD_FWD") >= 0) {
      
Serial.println("FWD");
      forward();
    }
    
else if(cmd.indexOf("CMD_BWD") >= 0) {
      
Serial.println("BWD");
      back();
    }
    
else if(cmd.indexOf("CMD_RGT") >= 0) {
      
Serial.println("RGT");
      rightmove();
    }
    
else if(cmd.indexOf("CMD_LFT") >= 0) {
      
Serial.println("LFT");
      leftmove();
    }
    
else if(cmd.indexOf("BTN_A") >= 0) {
      
Serial.println("A");
      dance1();
    }
    
else if(cmd.indexOf("BTN_B") >= 0) {
      
Serial.println("B");
      dance2();
    }
    
else if(cmd.indexOf("BTN_C") >= 0) {
      
Serial.println("C");
      hello();
    }
    
else if(cmd.indexOf("BTN_D") >= 0) {
      
Serial.println("D");
      pushup();
    }
    
else if(cmd.indexOf("BTN_E") >= 0) {
      
Serial.println("D");
      turnright();
    }
    
else if(cmd.indexOf("BTN_F") >= 0) {
      
Serial.println("D");
      turnleft();
    }

    cmd = 
"";
    
// send ready to controller to recieve new commands
    udp.
beginPacket(udp.remoteIP(), udp.remotePort());
    udp.
print("RDY");
    udp.
endPacket();
    
Serial.println("ACK gesendet");
  }
 
}

Spiegazione:

Le librerie necessarie sono integrate all'inizio. Il file comandi.h con le sequenze di movimento si trova, insieme al codice, nel download alla fine di questa sezione.

Vengono quindi definiti i dati di accesso alla WLAN e viene dichiarata una variabile per il comando ricevuto. Viene inoltre creato l'oggetto per la libreria UDP.

In setup(), il microcontrollore viene collegato alla WLAN e i singoli servomotori vengono inizializzati.

Nel ciclo(), i pacchetti di dati in arrivo vengono trasferiti dal mittente al sistema cmd viene salvata. Questa viene poi analizzata dalle query if e il comando corrispondente viene eseguito. Una volta eseguito il comando, viene inviata una conferma al controllore.

 

È possibile scaricare il codice completo qui scaricare.
Inserire i dati di accesso alla WLAN nel programma al posto dei segnaposto.

 

Dopo il caricamento sul microcontrollore, aprire il monitor seriale e annotare l'indirizzo IP visualizzato.
Se questo non viene visualizzato all'inizio, si possono usare le due righe all'inizio nel loop() per l'output.

 

Codice Controllore

 

#include <WiFi.h>
#
include <esp_wifi.h>
#
include <WiFiUdp.h>

#
define X 34
#
define Y 35

#
define A 26
#
define B 25
#
define C 17
#
define D 16
#
define E 27
#
define F 14

const char* ssid = "name";
const char* password = "pswd";
const char* rcvIP = "192.168.178.xxx";


int calibY, calibX;
bool status = true;
long sentTime;
String msg;

WiFiUDP udp;

void setup() {
  
Serial.begin(115200);
  
delay(2000);

  
WiFi.begin(ssid, password);
  
while (WiFi.status() != WL_CONNECTED) {
    
delay(500);
    
Serial.print(".");
    
if(millis() > 7000) ESP.restart();
  }

  
Serial.println("ESP32 ready (Controller)");

  calibX = 
analogRead(X); //calibrating current Position to zero
  calibY = 
analogRead(Y);

  
pinMode(A, INPUT_PULLUP);
  
pinMode(B, INPUT_PULLUP);
  
pinMode(C, INPUT_PULLUP);
  
pinMode(D, INPUT_PULLUP);
  
pinMode(E, INPUT_PULLUP);
  
pinMode(F, INPUT_PULLUP);
}

void loop() {
  
int valX = analogRead(X) - calibX;
  
int valY = analogRead(Y) - calibY;
  
//Serial.println(valX);
  
//Serial.println(valY);

//no acknowledgement recieved after 10 sec. -> set marker to true; reenable sending
  
if((millis() - sentTime) > 10000) {
    status = true;
  }
  
if(status) {
    
//threshold values
    
if(valX < -50 || valY < -50 || valX > 50 || valY > 50) {
      
Serial.println("trig");
      
//choose dominant coordinate
      
if(abs(valX) > abs(valY)) {
        
if(valX < 0) {
          
Serial.println("LEFT");
          msg = 
"CMD_LFT";
        }
        
else {
          
Serial.println("Right");
          msg = 
"CMD_RGT";
        }
      }
      
else {
        
if(valY < 0) {
          
Serial.println("BWD");
          msg = 
"CMD_BWD";
        }
        
else {
          
Serial.println("FWD");
          msg = 
"CMD_FWD";
        }
      }
      status = false; 
//marking sent
      sentTime = 
millis(); //store time for limitation
    }
    
//check buttons
    
else {
      
if(!digitalRead(A)) {
        
Serial.println("A");
        msg = 
"BTN_A";
        status = false; 
//marking sent
        sentTime = 
millis(); //store time for limitation
      }
      
else if(!digitalRead(B)) {
        
Serial.println("B");
        msg = 
"BTN_B";
        status = false; 
//marking sent
        sentTime = 
millis(); //store time for limitation
      }
      
else if(!digitalRead(C)) {
        
Serial.println("C");
        msg = 
"BTN_C";
        status = false; 
//marking sent
        sentTime = 
millis(); //store time for limitation
      }
      
else if(!digitalRead(D)) {
        
Serial.println("D");
        msg = 
"BTN_D";
        status = false; 
//marking sent
        sentTime = 
millis(); //store time for limitation
      }
      
else if(!digitalRead(E)) {
        
Serial.println("E");
        msg = 
"BTN_E";
        status = false; 
//marking sent
        sentTime = 
millis(); //store time for limitation
      }
      
else if(!digitalRead(F)) {
        
Serial.println("F");
        msg = 
"BTN_F";
        status = false; 
//marking sent
        sentTime = 
millis(); //store time for limitation
      }
     
    }
    udp.
beginPacket(rcvIP, 4210);
    udp.
print(msg);
    udp.
endPacket();
    msg = 
"";
  }
 
  
int pSize = udp.parsePacket();
  
if (pSize) {
    
char buf[20];
    
int len = udp.read(buf, 20);
    buf[len] = 
0//termination

    
if (String(buf) == "RDY") {
      status = true;
      
Serial.println("ACK");
     
    }
  }
  
delay(100);
}

Spiegazione:

In primo luogo, si integrano le librerie necessarie, si creano le macro per i pin dei vari pulsanti e si dichiarano i dati di accesso alla WLAN e l'indirizzo IP del ricevitore. Vengono poi dichiarate le variabili globali per la calibrazione degli assi del joystick, per il comando da inviare e per l'implementazione del messaggio di conferma.

In setup(), il microcontrollore viene collegato alla WLAN, gli assi del joystick vengono calibrati e gli ingressi digitali vengono definiti.

Nel loop(), la posizione del joystick viene prima letta come valore analogico e memorizzata nelle variabili corrispondenti.

Segue un controllo, che ripristina lo stato di trasmissione dopo un timeout di 10 secondi.

L'algoritmo di valutazione della direzione del movimento controlla se i valori degli assi superano un valore limite di 50. Ciò è necessario perché sia i potenziometri, utilizzati per leggere la posizione degli assi, sia i convertitori analogico-digitali (ADC) si muovono minimamente intorno al valore zero anche in posizione zero (la cosiddetta deriva).

Se un asse supera il valore di soglia, i valori della magnitudo dei due assi vengono confrontati tra loro. In questo modo è possibile determinare l'asse che si è spostato di più e che quindi è direzionale.

Inoltre, gli ingressi digitali vengono letti e il comando corrispondente (designazione del pulsante) viene salvato nella variabile msg quando viene premuto un pulsante.

Infine, il comando viene inviato al robot come pacchetto UDP.

Quando il ricevitore ha eseguito il comando, invia una conferma al mittente. Se questa viene ricevuta, la variabile stato di nuovo in piedi vero che rende possibile un nuovo invio.

 

È possibile scaricare l'intero programma qui scaricare.

Caricare questo con i dati di accesso WLAN e l'indirizzo IP corretti sull'ESP32 D1 R32 selezionando la porta corretta.

 

Conclusione

In questo post avete imparato a controllare il robot bionico Spider utilizzando il protocollo di comunicazione UDP.

Naturalmente, questo progetto pone solo le basi per le vostre estensioni e modifiche. Ad esempio, è possibile utilizzare un microcontrollore in modalità AP per evitare di dover ricorrere a un router esterno.

Così, oltre al protocollo di comunicazione ESPnow con UDP, avete imparato a conoscere un protocollo molto diffuso, utilizzato in molte applicazioni time-critical.

 

Divertitevi a ricostruire :)

Esp32Esp8266Projekte für anfänger

Lascia un commento

Tutti i commenti vengono moderati prima della pubblicazione