• Non ci sono risultati.

UNIVERSITA POLITECNICA DELLE MARCHE FACOLTA DI INGEGNERIA. Corso di Laurea triennale in Ingegneria Informatica e dell Automazione

N/A
N/A
Protected

Academic year: 2022

Condividi "UNIVERSITA POLITECNICA DELLE MARCHE FACOLTA DI INGEGNERIA. Corso di Laurea triennale in Ingegneria Informatica e dell Automazione"

Copied!
77
0
0

Testo completo

(1)

UNIVERSITA’ POLITECNICA DELLE MARCHE FACOLTA’ DI INGEGNERIA

Corso di Laurea triennale in Ingegneria Informatica e dell’Automazione

Programmazione di microcontrollore per la comunicazione Wi-Fi di una bicicletta elettrica autonoma

Microcontroller programming for control and management of an autonomous e-bike

Relatore: Chiar.mo Tesi di Laurea di:

Prof. Andrea Bonci Arianna Nazzarelli Correlatore:

Dott. Giuseppe Antonio Scala

A.A. 2020/ 2021

(2)

Indice

1. Introduzione: problema e soluzione proposta;

2. Descrizione dei componenti Hardware e Software utilizzati per la comuni- cazione WiFi di una e-Bike;

2.1 Renesas YRDKRX63N 2.2 Motori ed Encoder

2.2.1 Motore DC 28PA51G 2.2.2 Encoder adapter DF Robot 2.2.3 Motore DCX35L GB KL 18V

2.2.4 Encoder ENC30 HEDL 5540 500IMP 2.3 Driver MD10C

2.4 Sensore di corrente 2.4.1 INA219 2.4.2 ACS712

2.5 Convertitore di livello 2.6 ESP-WROOM-32 2.7 IMU

2.8 Alimentatori di corrente 2.8.1 Convertitore Buck LM2596 2.8.2 Convertitore Buck ICQUANZX 2.9 e2studio

2.10 Matlab 2.11 Putty 2.12 Docklight

3. Software Docklight e Putty: prove di comunicazione seriale e implemen- tazione precedente;

4. Protocollo di comunicazione per e-Bike;

5. Comunicazione Putty - Matlab:

(3)

5.1 Modifica del software utilizzato per la comunicazione;

5.2 Implementazione del codice Matlab;

5.3 Modifiche nel codice di programmazione dell’ESP-WROOM-32;

6. Prove sperimentali;

6.1 Prove su principali periferiche hardware della e-Bike;

6.1.1 verifiche di compatibilit`a del codice;

6.1.2 Risoluzione problema di conflitto tra i2c e Uart.

6.2 Prove su e-Bike:

6.2.1 cambio dei pin dei PWM per conflitto con pin di Rx e Tx del Wi-fi;

6.2.2 Risoluzione del problema pin JN2 della Renesas non funzionanti correttamente;

6.2.3 Cambio dell’interfaccia seriale di comunicazione con la SCI6.

7. Schema a blocchi e funzionale del codice WiFi;

7.1 Configurazione finale Dispositivo WiFi;

8. Schema a blocchi e funzionale del codice Matlab;

8.1 Configurazione finale Matlab;

9. Schema elettrico di connessione del dispositivo WiFi e la Scheda Renesas;

9.1 Tabella interconnessione PIN WiFi e Renesas;

(4)

Appendice

11. Codice WiFi Renesas;

12. Codice Matlab.

(5)

Chapter 1

Introduzione: problema e soluzione proposta

Il seguente elaborato ha lo scopo di implementare il controllo della stabilit`a di un veicolo automatizzato, ovvero l’e-Bike, il cui moto avviene senza l’ausilio umano.

L’e-Bike `e composta dal telaio di una bici con dimensioni ridotte, sulla quale sono stati installati due motori e varie componenti hardware, come verr`a mostrato nei capitoli successivi, necessari a raggiungere lo scopo prefissatoci.

Inizialmente, si `e ripreso il lavoro svolto in precedenza, per poi andare ad effet- tuare varie modifiche per migliorare quanto sviluppato.

Per cercare di raggiungere l’obbiettivo, si `e dapprima implementata una comu- nicazione Wi-fi attraverso il software Matlab che permetter`a di salvare i dati necessari per il controllo dell’e-Bike e la successiva stabilizzazione.

Infine, si `e passato alla realizzazione del controllo stesso attraverso l’ausilio di

(6)

controllori PID digitali, che permetteranno al veicolo di raggiungere una desider- ata velocit`a costante e mantenere l’equilibrio.

In particolare, in questa tesi, verr`a affrontata l’implementazione della comuni- cazione tra l’e-Bike e un modulo Wi-Fi. Dapprima, si `e deciso di riprendere la comunicazione implementata precedentemente utilizzando il Software Putty, per poi andarla a modificare per adattarla al server TCP/IP fornito da Matlab.

Attraverso questo software sar`a infatti possibile salvare i dati acquisiti dall’e- Bike; ci`o verr`a sfruttato successivamente per lo sviluppo del controllo del veicolo automatizzato.

(7)

Chapter 2

Descrizione dei componenti Hardware e Software utilizzati per la comunicazione WiFi di una e-Bike

Per poter procedere con l’elaborato, `e necessario introdurre i componenti Hard- ware e Software utilizzati per per la comunicazione Wifi dell’e-Bike.

2.1 Renesas YRDKRX63N

La Renesas YRDKRX63N `e la scheda di sviluppo su cui `e montato il micro controller RX63N, core della famiglia RX631. Il micro controller RX63N include:

ˆ un 32-bit MCU, il quale `e capace di operare oltre i 100 MHz;

ˆ l’FPU (Floating-PointUnit) necessario per i calcoli aritmetici;

ˆ oltre 21 canali per l’ADC a 12-bit e oltre 2 canali per il DAC;

ˆ unit`a Timers MTU2 [Multi Timer Unit Function], con funzioni di:

– capture, output compare, counter clearing per la generazione di seg- nali PWM e controllo motori;

– watchdog timer Independente e funzione CRC per lo standard di per applicazioni domestiche (IEC 60730);

– molte funzioni di comunicazione: Ethernet, SCI, RSPI, CAN, and I2C

(8)

2.2 Motori ed Encoder

2.2.1 Motore DC 28PA51G

Il Motore DC 28PA51G `e il motore scelto per la trazione della e-Bike. Tale motore ha le seguenti specifiche:

ˆ Tensione di lavoro: 12V

ˆ RPM a vuoto (prima del cambio): 8000±10

ˆ Nessun carico 68dBA (distanza di misurazione 10 cm)

ˆ Rapporto di trasmissione: 56:1

ˆ RPM a vuoto (dopo il cambio): 143±10

ˆ Corrente a vuoto: a 12V: 0.39A

ˆ Corrente di stallo: 3.6A

ˆ Coppia nominale a 12 V: 5,5 kgf.cm

ˆ Dimensioni: 123x36x36 mm

ˆ Peso: 270 g

(9)

Encoder adapter DF Robot

Nel motore di trazione `e presente l’Encoder adapter della DF Robot ed `e dotato di 4 pin:

ˆ VCC: alimentazione a 3.3V, connessa alla 3.3V dell’e-Bike;

ˆ GND: Ground collegato al ground del circuito generale del veicolo;

ˆ A: connesso al pin 25 del connettore JN2;

ˆ B: collegato al pin 6 del connettore JN2;

2.2.2 Motore DCX35L GB KL 18V

Il Motore DCX35L GB KL 18V `e il motore scelto per lo sterzo dell’e-Bike.

Questo ha le seguenti specifiche:

ˆ Tensione di lavoro: 18V

ˆ RPM a vuoto: 7200 rpm

ˆ Rapporto di trasmissione: 66:1

ˆ Corrente a vuoto: a 18V: 177mA

ˆ Corrente nominale 5.2 A

(10)

ˆ Coppia nominale a 18 V: 120 mNm

Encoder ENC30 HEDL 5540 500IMP

L’Encoder ENC30 HEDL 5540 500IMP `e l’encoder presente nel motore di sterzo ed `e dotato anch’esso di quattro pin:

ˆ l’alimentazione a 3.3V, connessa alla 3.3V dell’e-Bike;

ˆ il Ground, collegato al Ground del circuito generale del veicolo;

ˆ A `e collegato al pin 23 del connettore J8;

ˆ B `e collegato alla porta P24, capo della R42 vicino all’U12 porta usb-user;

2.3 Driver MD10C

Per il pilotaggio dei motori attraverso un segnale PWM si utilizzano due driver MD10C, con le caratteristiche riportate nella seguente tabella.

(11)

Specifiche Driver MD10C

Tensione da 5V a 30VDC

Corrente Max (Continua) 13Amps Corrente di Picco 30Amps (10 secondi)

Canale di output Motore mono-spazzola Input logico da 3.3V a 5.0VDC Segnale di controllo PWM

Limite di corrente No

2.4 Sensori di corrente

Per effettuare misure sulla corrente generata da entrambi i motori presenti nell’e-Bike, vengono utilizzati due tipologie di sensori di corrente: l’INA219 e l’ACS712.

2.4.1 Sensore INA219

L’INA219 `e un sensore di corrente digitale, dotato di un’interfaccia I2C e SMBus.

Tale sensore permette la misura di corrente e tensione che vengono generate dal motore di trazione, il DC 28PA51G. L’INA219 pu`o essere alimentato da +3.0V a +5.5V e in particolar modo, nel circuito interessato, ovvero l’e-Bike, questo viene alimentato a 3.3V. Infine, tale dispositivo di controllo ha un’elevata precisione con risoluzione a 12 bit e pu`o essere rilevata una tensione del bus da 0 V a +26 V.

(12)

2.4.2 Sensore ACS712 da 5A

L’ACS712 `e un sensore di corrente analogico, che ci permette di misurare la tensione, e la corrispondente corrente (che pu`o essere al massimo 5A), generata dal motore di sterzo. Tale sensore ha le seguenti specifiche:

ˆ Alimentazione da 4.5Vcc a 5.5Vcc;

ˆ Sensibilit`a di uscita : 185mV/A;

ˆ Larghezza di banda: 80KHz;

ˆ Isteresi magnetica vicina allo zero.

Attraverso la sensibilit`a di uscita dell’ACS712 `e possibile ottenere la corrente del motore, con la seguente proporzione:

sensitivity : max current = k : voltage

2.5 Convertitore di livello

E’ stato necessario utilizzare un convertitore di livello per traslare il livello logico alto di tensione del PC nel livello logico alto della scheda Renesas YRDKRX63N.

Il canale a 5V del traslatore gestisce i segnali a 5V, i quali, passando al canale B, vengono attenuati a 3.3V.

(13)

2.6 ESP-WROOM-32

L’ESP-WROOM-32 `e un micro-controller dotato di Wi-Fi integrato e Bluetooth dual-mode, che fornisce un processore su scheda con interfacce per la connessione a varie periferiche. L’ESP-WROOM-32 ha le seguenti specifiche:

ˆ CPU: microprocessore LX6 a 32 bit dual-core (o single-core) Xtensa, fun- zionante a 160 o 240 MHz

ˆ Memoria: 320 KiB RAM, 448 KiB ROM

ˆ Wi-Fi: 802.11 b/g/n

ˆ Bluetooth: v4.2 BR/EDR e BLE

ˆ 34 Ö GPIO programmabili

ˆ ADC SAR a 12 bit fino a 18 canali

ˆ 2 Ö DAC a 8 bit

ˆ 10 Ö sensori tattili ( GPIO a rilevamento capacitivo )

ˆ 4 Ö SPI

ˆ 2 Ö interfacce I²S

ˆ 2 Ö interfacce I²C

ˆ 3 Ö UART

Inoltre, per la stesura del seguente elaborato, sar`a necessario conoscere anche le caratteristiche della connessione di rete, in quanto nella e-Bike, tale micro- controller `e utilizzato come modulo Wi-Fi per poter trasmettere comandi ed acquisire dati dal dispositivo.

SSID ESP 089d2d

Protocollo Wi-Fi 4 (802.11n) Tipo di Sicurezza Aperta

Banda della rete 2.4GHz

Canale di rete 1

Indirizzo IPv4 192.168.4.1 Versione Driver 2024.0.10.121 Indirizzo fisico (MAC) 80-91-33-1C-F7 97

(14)

2.7 IMU

L’unit`a di misura inerziale , detta IMU , `e un dispositivo digitale che misura e segnala l’accelerazione, l’orientamento, le velocit`a angolari . `E composto da 3 accelerometri, 3 giroscopi e 3 magnetometri, uno per asse per ciascuno dei tre assi del veicolo: rollio, beccheggio e imbardata.

2.8 Alimentatori di corrente

Per alimentare i vari dispositivi presenti sull’e-Bike sono necessari quattro con- vertitori Buck:

ˆ Tre Convertitore Buck LM2596;

ˆ Convertitore Buck ICQUANZX;

2.8.1 Convertitore Buck LM2596

I tre Convertitore Buck LM2596, presenti sull’e-Bike, sono essenziali per conver- tire la tensione di alimentazione a 16V, proveniente dalla batteria, in tensione in uscita a 3.3V, 5V e 12V. La tensione di uscita a 3.3V `e utilizzata per ali- mentare i dispositivi che necessitano tale tensione in ingresso, quali l’IMU, il sensore INA219 e gli encoder. Allo stesso modo, il sensore ACS712, la scheda Renesas YRDKRX63N e l’ESP-WROOM-32 hanno come alimentazione la ten- sione a 5V, mentre il motore di trazione necessita della tensione in ingresso a 12V.

(15)

2.8.2 Convertitore Buck ICQUANZX

Il Convertitore Buck ICQUANZX, invece, `e presente sull’e-Bike per alimentare il motore di sterzo a 12V.

2.9 Batteria Turnigy nano-tech A-Spec G2

Per l’alimentazione del circuito della e-Bike, costituito dagli elementi sopra de- scritti, si `e utilizzata una batteria a litio Turnigy nano-tech A-Spec G2. Tale batteria ha come massima tensione 14.8A, ripartita in 4 celle e ha una capacit`a di 2600mAh

(16)

2.10 e2studio

Il software e2studio `e un ambiente di sviluppo integrato basato su Eclipse per la creazione di firmware per i micro-controller YRDKRX63N della Renesas.

2.11 Matlab

Matlab `e una piattaforma di programmazione utilizzata per l’analisi di dati, lo sviluppo di algoritmi e la creazione di modelli. In questo elaborato, tale software

`e stato utilizzato per l’implementazione della rete di comunicazione con l’e-Bike attraverso l’interfaccia TCP/IP.

2.12 PuTTY

PuTTY `e un software open source per la gestione di dispositivi informatici da remoto ed `e un client SSH, Telnet e rlogin combinato con un emulatore di terminale.

2.13 Docklight

Docklight `e un software utilizzato per l’analisi della comunicazione seriale tra diversi dispositivi. Il tipo di comunicazione impostato per questo elaborato `e RS232 Terminal/ RS232 Monitor.

2.14 Arduino IDE

Arduino IDE `e un ambiente di sviluppo integrato per la programmazione dei micro-controller ed `e un software libero.

(17)

Chapter 3

Software Docklight e Putty: prove di comunicazione seriale e

implementazione precedente

In questo capitolo, si mostrer`a il funzionamento della comunicazione Wi-Fi sviluppata precedentemente e si andranno a descrivere le prove effettuate per testare quanto implementato.

L’ESP-WROOM-32 era stato programmato con un codice sviluppato sulla pi- attaforma Arduino IDE. Originariamente, all’inizializzazione del dispositivo hard- ware, la scheda Renesas inviava uno specifico set di comandi AT a quest’ultimo per configurare il modulo come server TCP per connessioni multiple. I comandi AT sono delle stringhe ASCII, formate da alcuni caratteri standard, quali AT, CR e LF. I comandi che erano stati utilizzati sono:

ˆ AT+CWMODE=3⟨CR⟩⟨LF ⟩ per settare il modulo in WiFi mode;

ˆ AT+CIPMUX=1⟨CR⟩⟨LF ⟩ per abilitare la connessione multipla;

ˆ AT+CIPSERVER=1⟨CR⟩⟨LF ⟩ per configurare l’ESP-WROOM-32 come TCP server.

Tali comandi erano stati salvati in variabili globali nel file ”wifi settings.h, rispet- tivamente come ”WIFI COMMAND1”, ”WIFI COMMAND2” e

”WIFI COMMAND3” ed erano inviati al modulo Wi-Fi nel momento

dell’inizializzazione della periferica UART, tramite la funzione send data(char*

data,int length). Ci`o avveniva all’interno di uart init() nel file ”bike uart.c”.

/* Sending the setting command string to the wifi module */

send_data(WIFI_COMMAND1,str_length(WIFI_COMMAND1));

while (timeout++<=500000){} /*Waiting for response before of sending the next command */

send_data(WIFI_COMMAND2,str_length(WIFI_COMMAND2));

(18)

timeout=0;

while (timeout++<=500000){}

send_data(WIFI_COMMAND3,str_length(WIFI_COMMAND3));

La funzione mostrata di seguito inserisce la stringa, passata come parametro, all’interno della coda di trasmissione e abilita il relativo interrupt per inviare il dato.

void send_data(char data[], unsigned int dim_string) {

unsigned int i=0; /* index for the cycle for inserting data into buffer */

if (dim_string<(DIM_BUFFER-tx_queue_pointer->counterElements)) /* if there are sufficients empty slots */

for (i=0;i<dim_string;i++) /* putting each char of data array into the tx buffer */

{

tx_queue_pointer->data[(tx_queue_pointer->head)+i]=data[i];

/* Putting elements from head index */

tx_queue_pointer->counterElements++;

tx_queue_pointer->tail++;

if (tx_queue_pointer->tail>=DIM_BUFFER) /* Managing the tx buffer in a circular way */

tx_queue_pointer->tail=0;

}

interrupt_tx_init();

}

Ad ogni comando il dispositivo inviava tre risposte, tra cui la stringa

”OK\r\n\0\0\0\0” nel caso in cui la configurazione del dispositivo fosse andata a buon fine. In caso contrario, si riceveva un messaggio di errore

“ERROR\r\n\0”. Tali stringhe erano state memorizzate all’interno della define OK SET T IN G ed ERROR SET T IN G del file wif i setting.h.

Per verificare il corretto funzionamento di quanto appena detto, si `e connessa la scheda Renesas al computer per utilizzare il software Docklight. Per fare ci`o, si `e utilizzato un traslatore di livello per convertire il livello logico alto a 5V del computer al livello logico alto della scheda a 3.3V, secondo il seguente schema:

In particolar modo, sono stati coinvolti i seguenti pin della scheda Renesas:

ˆ Connettore JN2:

(19)

– pin 22- canale Tx – pin 23- canale Rx

ˆ Connettore JN1:

– pin 1- alimentazione a 5V – pin 2- Ground

Di seguito, il circuito finale ottenuto:

A questo punto, si `e aperta la comunicazione con la porta COM coin- volta e sono stati inviati i comandi AT per configurare il l’ESP-WROOM-32.

Dopodich´e, alla connessione del dispositivo alla rete del server, il modulo Wi-Fi ha inviato due pacchetti per indicare ci`o e mostrare il MAC e l’IP address del client connesso. Tali pacchetti sono i seguenti:

ˆ +STA CONNECTED:”60:ab:67:d3:33:73” ⟨ CR ⟩ ⟨ LF ⟩

ˆ +DIST SPA IP:”60:ab:67:d3:33:73”, “192.168.4.2” ⟨CR⟩⟨LF ⟩”

Inoltre, l’ESP-WROOM-32 era dotato di un meccanismo di time-out, in modo che se il client connesso al server non trasmetteva dati per un certo periodo di tempo, il server lo scollega e invia il seguente pacchetto:

+STA DISCONNECTED:”60:ab:67:d3:33:73” ⟨CR⟩⟨LF ⟩

(20)

Successivamente, sono state effettuate ulteriori prove con il software Putty, cio`e il terminale scelto per i dati mandati dalla scheda Renesas.

Di seguito, i pin coinvolti per connettere il microcontroller con il modulo Wi-Fi:

ˆ Connettore JN2:

– pin 22 canale Tx della scheda Renensas da connettere al canale Rx del modulo Wi-Fi;

– pin 23 canale Rx del microcontroller da collegare al canale Tx dell’ESP- WROOM-32.

ˆ Connettore JN1:

– pin 1 alimentazione a 5V da connettere al pin Vcc del modulo Wi-Fi;

– pin 2 Ground da collegare al pin GND dell’ESP-WROOM-32.

Innanzitutto, era stata definita la seguente struttura per le istruzioni da inviare alla scheda attraverso tale terminale.

+IPD,i,n:xxx dove:

ˆ i era l’identificativo del dispositivo connesso in ordine di connessione;

ˆ n era il numero di byte corrispondente al comando inviato;

ˆ xxx era il l’istruzione da inoltrare.

Nonostante il modulo fosse configurato in modalit`a ”multiconnection”, per evitare sovrapposizioni tra i vari dispositivi, si era deciso di gestire solo i pacchetti in- viati dal dispositivo con identificativo i=0.

(21)

Perci`o, la struttura dei pacchetti inviati dal terminale era la seguente:

+IPD,0,3:xxx

Per verificare la correttezza delle istruzioni ricevute da parte di Putty, erano stati definiti all’interno dei file ”wifi setting.h” e ”bike command.h”, la seguente struttura e le successive variabili globali.

#define SPLITTER ’:’ /* String splitter between header and command*/

#define DIM_HEADER 8 /* Dimension of the correct command’s header */

#define DIM_COMMAND 3 /* Dimension of the correct command */

#define DIM_BUFFER 100 /* Dimension of the data buffer for the communication */

#define CORRECT_HEADER "+IPD,0,3" /* Sample of the correct header of a command */

#define OK_SETTING "OK\r\n\0\0\0\0" /* Ok response from wifi Module to correct command */

#define ERROR_SETTING "ERROR\r\n\0" /* Erroro response from WiFi module */

typedef struct {

char header[DIM_HEADER]; /* vector containing the header of the packet */

char command[DIM_BUFFER]; /* vector containing the command of the packet */

int n; /* dimension of the command, for a correct command n=DIM_COMMAND */

} packet; /* Struct for managing commands sent by wifi serial communication */

Le istruzioni inviate attraverso il modulo Wi-Fi alla scheda Renesas erano sud- divide in header e command, che avevano dimensione rispettivamente pari a DIM HEADER e DIM COMMAND ed erano delimitati dallo Splitter. Per header si intendevano i primi 8 caratteri, ovvero “+IPD,0,3”, che erano stati quindi definiti come CORRECT HEADER; invece, si consideravano i tre carat- teri successivi allo Splitter come command. I command riconosciuti come cor- retti erano i seguenti:

/* Received command for ballbot function START,STOP,FORWARD, BACKWARD,LEFT,RIGHT*/

#define START "bON"

#define STOP "bOF"

#define FORWARD "bAV"

#define BACKWARD "bIN"

(22)

#define LEFT "bSX"

#define RIGHT "bDX"

Perci`o, dopo aver inviato l’istruzione con Putty, si attivava l’interrupt di ricezione, attraverso il quale, i dati ricevuti venivano trasferiti nel buffer di ricezione. A tal punto, se la coda di ricezione era piena o l’ultimo elemento in coda era

”\n”, avveniva l’elaborazione dei dati tramite la funzione di split(char* data).

Attraverso tale funzione, veniva suddivisa l’istruzione in header e command, per poi andarne a verificare la correttezza tramite le funzioni parseHeader() e parseCommand(). Attraverso quest’ultima funzione, veniva stampata la stringa corrispondente al comando sull’LCD della scheda Renesas. Dopodich´e, avvenuta l’elaborazione, il comando veniva pulito mediante il metodo clearCommand().

#pragma interrupt SCI12_RXI12_int (vect = VECT_SCI12_RXI12, enable) static void SCI12_RXI12_int()

{

int timeout=0;

/* Frame and Parity Error handling */

while(SCI12.SSR.BIT.ORER && timeout++<=10000) {

SCI12.SSR.BIT.ORER=0;

}

if (SCI12.SSR.BIT.FER) SCI12.SSR.BIT.FER=0;

if (SCI12.SSR.BIT.PER) SCI12.SSR.BIT.PER=0;

uint8_t read_byte=SCI12.RDR; /* Read byte from RDR register */

/* Putting the data from RDR register into the reception buffer */

rx_queue_pointer->data[rx_queue_pointer->tail]= read_byte;

rx_queue_pointer->counterElements++; /* Incrementing the counter of received elements */

rx_queue_pointer->tail++; /* Incrementing the tail pointer to the next position (it will point to an empty element) */

/* if the rx queue is full or last element of the rx queue is the

’\n’ we can start processing the received packet */

if (queue_is_full(rx_queue_pointer) ||

rx_queue_pointer->data[rx_queue_pointer->tail-1]==’\n’) /* The wifi module sends the received command

to renesas with ’\n’ in the final position */

{

(23)

char command[DIM_COMMAND]=split(rx_queue_pointer);

/* splitting

the received data from wifi module */

clearCommand(); /* clear the command array for being ready for

the next communication */

/* it is not necessary to clear the header because it is overwritten every time that a packet (correct or incorrect)

is received */

interrupt_rx_disable(); /* Disabling the rx interrupt in order to clear the rx queue completely without the risk of getting other packets */

queue_clear(rx_queue_pointer);

}

/* Enabling again the rx interrupt for being ready for receiving the next packet */

interrupt_rx_init();

}

char* split(char* data) {

int i=0;

int j=0;

while(data[i] != SPLITTER && i<DIM_HEADER) /* The first DIM_HEADER bits are put in the header array as soon as the splitter char (’:’) is found */

{

/* The header put in the packet structure may not respect the protocol of the correct header */

myPacket_pointer->header[i]=data[i];

i++;

}

myPacket_pointer->n=data[i-1]; /* the dimension of the command is the last char of the header */

i++;

/* In this phase it is not knowed if the received packet is a command or not, it is knowed by checking the header */

if (parseHeader()) {

/* Put DIM_COMMAND bits into the command array, starting from the i bits of the received data */

while(j<DIM_COMMAND) /* j is the index of the command array in

(24)

the packet structure */

{

myPacket_pointer->command[j]=data[i];

i++; /* i is the index of the data array */

j++;

}

return parseCommand(); /* parse the command */

}else

return "noCommand";

}

int parseHeader() {

if (!strcmp(myPacket_pointer->header,ERROR_SETTING)) /*If the header is equal to ERROR_SETTING string it means that an error has occured while setting the wifi module */

errorFlag=1;

if (!errorFlag) /* if the error flag is on, lcd displays the error */

{if (!strcmp(myPacket_pointer->header,OK_SETTING)) lcd_display(LCD_LINE4,"WiFi SET");

}else {

lcd_display(LCD_LINE4,"WiFi ERROR");

}

/* if the header of the packet is not correct the function returns 0 (false) */

if (!strcmp(myPacket_pointer->header,CORRECT_HEADER)) /* strcmp returns

0 if the two strings are equal */

return 1;

else return 0;

}

char* parseCommand() {

if (!strcmp(myPacket_pointer->command,START)) lcd_display(LCD_LINE8,"START");

if (!strcmp(myPacket_pointer->command,STOP))

(25)

lcd_display(LCD_LINE8,"STOP");

if (!strcmp(myPacket_pointer->command,FORWARD)) lcd_display(LCD_LINE8,"Forward");

if (!strcmp(myPacket_pointer->command,BACKWARD)) lcd_display(LCD_LINE8,"Backward");

if (!strcmp(myPacket_pointer->command,LEFT)) lcd_display(LCD_LINE8,"Left");

if (!strcmp(myPacket_pointer->command,RIGHT)) lcd_display(LCD_LINE8,"Right");

return myPacket_pointer->command;

}

void clearCommand() {

/* if the command vector has been loaded, it means that the received packet contained a

* correct command, so its dimension is of DIM_COMMAND

*/

int i;

for (i=0;i<DIM_COMMAND;i++) /* clear each bit of the command vector of the packet */

{

myPacket_pointer->command[i]=0;

} }

Quindi, attraverso il software Putty, si `e provato a testare il funzionamento di tale implementazione. Tuttavia, si `e riscontrata l’impossibilit`a di connettersi alla rete Wi-Fi generata dall’ESP-WROOM-32. Non avendo per`o a disposizione il codice Arduino per risolvere la problematica, si `e deciso di riprogrammare tale modulo Wi-Fi con il seguente codice.

WiFiServer server(80);

void setup() {

pinMode(LED_BUILTIN, OUTPUT);

Serial.begin(115200);

Serial.println();

Serial.println("Configuring access point...");

//Configure UART2

(26)

Serial2.begin(115200,SERIAL_8N1, 16, 17);

Serial.print("SSID=");

Serial.print(ssid);

Serial.print("\n");

// with password parameter if you want the AP to be open.

/* WiFi.softAP(ssid, password);

Serial.print("PW=");

Serial.print(password);

Serial.print("\n");

*/

// with AP open.

WiFi.softAP(ssid);

IPAddress myIP = WiFi.softAPIP();

Serial.print("AP IP address: ");

Serial.println(myIP);

server.begin();

Serial.println("Server started");

}

void loop() {

WiFiClient client = server.available();

// listen for incoming clients

if (client) { // if you get a client,

Serial.println("New Client."); // print a message out // the serial port String currentLine = ""; // make a String to hold

//incoming data //from the client

while (client.connected()) { // loop while the client’s // connected

unsigned int dly;

if(Serial.available()){

client.print(Serial.read());

Serial.flush(); //erase any data

dly=1000;

}

if(Serial1.available()){

client.print(Serial1.read());

Serial1.flush(); //erase any data

(27)

dly=1000;

}

if(Serial2.available()){

client.print(Serial2.read());

Serial2.flush(); //erase any data

dly=1000;

}

if (client.available()) { // if there’s bytes to read from the client,

char c = client.read(); // read a byte, then

Serial.write(c); // print it out

Serial1.write(c); // print it out

Serial2.write(c); // print it out

dly=1000;

}

//led manage if(dly>0) {

dly--;

digitalWrite(LED_BUILTIN, HIGH); //turns the LED on }

else

digitalWrite(LED_BUILTIN, LOW); //LED off }

// close the connection:

client.stop();

Serial.println("Client Disconnected.");

} }

Inizialmente, si `e acceduto al software impostando il tipo di connessione di tipo

”Raw”, l’indirizzo IP dell’ESP-WROOM-32 e aver specificato la porta TCP/IP a cui connettersi.

(28)

Dopodich´e, si `e provato ad inviare al modulo Wi-Fi alcuni dei comandi definiti in precedenza, riscontrando l’effettivo funzionamento di quanto implementato.

Si `e cos`ı proceduti ad apportare modifiche al codice sviluppato in precedenza e ad implementarne di nuovo, in modo da ottenere tramite l’ESP-WROOM-32 i dati dei sensori presenti sull’e-Bike. Tali dati, infatti, serviranno in seguito per poter sviluppare il controllo dello sterzo dell’e-Bike, necessario per mantenere quest’ultima in equilibrio.

(29)

Chapter 4

Protocollo di comunicazione per e-Bike:

impostazione dei comandi di

comunicazione e successive prove con i software;

In questa sezione, si illustrer`a quanto svolto per ottenere la trasmissione di dati dalla scheda Renensas al modulo ESP-WROOM-32.

Innanzitutto, sono stati eliminati i comandi AT da inviare al modulo Wi-Fi per il settaggio delle impostazioni, in quanto averlo riprogrammato ha com- portato il vantaggio di eliminare tale procedura. Conseguentemente, `e stata modificata la funzione uart init(), con la quale questi comandi erano trasmessi.

Successivamente, sono stati modificati i command che erano stati definiti nel file ”bike command.h”, per poter controllare la trasmissione dati e per azionare il controllo del motore di trazione. Si `e scelto di mantenere invariato il numero di byte riservati a questi comandi per mantenere una continuit`a. In particolare, sono stati selezionati i seguenti command:

ˆ per il motore di trazione:

– ”bON”, necessario per azionare la trazione dell’e-Bike;

– ”bFO”, per lo stop di emergenza del veicolo;

– ”bOF”, per fermare l’e-Bike.

ˆ per l’acquisizione dei dati:

– ”bSE”, per avviare la trasmissione dati dalla scheda Renesas all’ESP- WROOM-32;

– ”bND”, per fermare la comunicazione dati.

(30)

Di conseguenza, la funzione parseCommand() nel file ”data parser.c” `e mutata.

Infatti, quest’ultima verifica la correttezza del comando e ne esegue le azioni corrispondenti, altrimenti, ne segnala l’errore. In particolare, si `e scelto di utilizzare il costrutto Switch, al posto degli If precedenti, ed andare a controllare il terzo byte del comando passatogli.

Successivamente, per poter trasmettere i dati richiesti in maniera continuativa, sono state definite delle flag (TX Flag CSTART, TX Flag BSTART,

TX Flag FORCED ), ovvero delle variabili che possono assumere solo due stati e che segnalano, con il loro valore, se un dato evento si `e verificato oppure no.

Dapprima, le flag sono state assegnate al valore zero, ma, nel momento in cui viene ricevuto un comando, il valore della variabile corrispondente varia.

A questo punto, abbiamo introdotto nei 100ms della CMT nel main, dei costrutti If-else per andare a verificare i valori delle flag. Pi`u precisamente:

ˆ se TX Flag CSTART = 1, vengono inviati, attraverso la funzione send data(), i dati al modulo Wi-Fi;

ˆ se TX Flag BSTART = 1, il valore specificato all’interno del costrutto viene impostato come velocit`a di riferimento per il PID di trazione.

Infine, sono state effettuate delle prove di verifica del funzionamento del codice attraverso il software PuTTY, riscontrando successo nell’esecuzione. Infatti, in- viando, ad esempio, l’istruzione ”+IPD,0,3:bSE, la scheda Renesas trasmetteva i dati richiesti, i quali venivano tradotti in codice ASCII dall’ESP-WROOM-32.

(31)

Chapter 5

Comunicazione Putty - Matlab

Una volta verificato il funzionamento della comunicazione Wi-Fi, `e sorta la necessit`a di salvare in un file di testo i dati acquisiti tramite il modulo ESP- WROOM-32, per poterli successivamente analizzare. Tuttavia, PuTTY non offre tale possibilit`a, perci`o si `e deciso di non gestire pi`u la comunicazione con questo software, bens`ı di utilizzare il protocollo TCP/IP di Matlab.

5.1 Modifica del software utilizzato per la co- municazione

Inizialmente, `e stata modificata la struttura delle istruzioni inviate attraverso il protocollo TCP/IP alla scheda Renensas, in quanto Matlab non ha i limiti imposti dal software usato precedentemente.

Infatti, sono stati eliminati l’Header e lo Splitter dal comando da inviare alla scheda Renesas, per semplificare l’operazione svolta dall’utente. Di conseguenza,

`e stato necessario implementare una funzione denominata split matlab(char*

data), similare alla funzione split(char* data) utilizzata precedentemente. Si `e difatti preferito non andare a modificare quest’ultima funzione, per lasciare la possibilit`a di eseguire prove con i software PuTTY e Docklight.

La differenza principale tra queste due funzioni `e la suddivisione dell’istruzione inviata alla scheda Renesas tra Header e Command, che viene effettuata esclu- sivamente dalla funzione split. Attraverso la split matlab, invece, viene soltanto salvato l’istruzione nel vettore command della struttura myPacket pointer di tipo Packet, che sar`a necessario poi per il parsing del comando.

char* split_matlab(char* data){

int i = 0;

int j = 0;

while(j<DIM_COMMAND) /* j is the index of the command array in the packet structure */

(32)

{

myPacket_pointer->command[j] = data[i];

i++; /* i is the index of the data array */

j++;

}

return parseCommand(); /* parse the command */

}

Infine, si `e modificato l’interrupt di ricezione, il quale non richiama pi`u la fun- zione split(char*data) per andare ad analizzare il comando inviato, bens`ı la funzione split matlab(char* data).

#pragma interrupt SCI12_RXI12_int (vect = VECT_SCI12_RXI12, enable) static void SCI12_RXI12_int()

{

int timeout=0;

/* Frame and Parity Error handling */

while(SCI12.SSR.BIT.ORER && timeout++<=10000) {

SCI12.SSR.BIT.ORER=0;

}

if (SCI12.SSR.BIT.FER) SCI12.SSR.BIT.FER=0;

if (SCI12.SSR.BIT.PER) SCI12.SSR.BIT.PER=0;

uint8_t read_byte=SCI12.RDR; /* Read byte from RDR register */

/* Putting the data from RDR register into the reception buffer */

rx_queue_pointer->data[rx_queue_pointer->tail]= read_byte;

rx_queue_pointer->counterElements++;

/* Incrementing the counter of received elements */

rx_queue_pointer->tail++; /* Incrementing the tail pointer to the next position (it will point to an empty element) */

/* if the rx queue is full or last element of the rx queue is the ’\n’ we can start processing the received packet */

if (queue_is_full(rx_queue_pointer) ||

rx_queue_pointer->data[rx_queue_pointer->tail-1]==’\n’) /* The wifi module sends the received command to renesas with

’\n’ in the final position */

(33)

{

//char command[DIM_COMMAND]=split(rx_queue_pointer);

/* splitting the received data from wifi module with putty*/

char command[DIM_COMMAND]=split_matlab(rx_queue_pointer);

clearCommand(); /* clear the command array for being ready for the next communication */

/* it is not necessary to clear the header because it is overwritten every time that a packet (correct or incorrect) is received */

interrupt_rx_disable(); /* Disabling the rx interrupt in order to clear the rx queue completely without the risk of getting other packets */

queue_clear(rx_queue_pointer);

}

5.2 Implementazione del codice Matlab

Per l’implementazione della nuova comunicazione Wi-fi si `e utilizzato il proto- collo TCP/IP di Matlab. Il protocollo TCP/IP unisce due protocolli di per la trasmissione di dati, ovvero il Transmission Control Protocol (TCP) e l’Internet Protocol(IP). Attraverso il TCP si stabilisce la connessione tra due host e si gestisce la consegna dei pacchetti tra questi, mentre l’IP fornisce le istruzioni per il trasferimento dei dati.

Perci`o,per prima cosa, si `e creata la connessione tra i dispositivi coinvolti at- traverso la funzione tcpclient(address,port) di Matlab. Quest’ultima, infatti, crea la connessione tra l’host remoto dall’indirizzo passatogli e la porta remota specificata. Dopo aver dichiarato la variabile command per salvare il comando da inviare, la si trasmette al TCP/IP client (t) attraverso la funzione write- line(t,data).

Poi, `e stata creata una funzione di Callback, con la quale leggere i dati inviati dall’e-Bike mediante la funzione di readline(t) e conseguentemente salvarli nel file di testo deciso dall’utente con la writematrix. Per settare tale funzione si

`e utilizzata la configureCallback, con la quale si `e impostata la chiamata della callback ogni qual volta si incontri il terminatore LF.

Dopo aver implementato la connessione, `e stata verificata la sua funzionalit`a, andando a connettere il personal computer alla rete Wi-Fi dell’ESP-WROOM- 32, Automa, non riscontrando tuttavia successo, in quanto i dati ricevuti non erano completi e non corrispondevano ai dati richiesti. Quindi, per risolvere tale problema, si `e deciso di mettere una pausa di un secondo per permettere alla callback di terminare la sua esecuzione.

Successivamente, si `e andato ad analizzare il motivo per il quale non si ricevessero i dati voluti. In un primo momento, si `e provato a sostituire la funzione read- line con una read(t), la quale legge singoli byte alla volta; tuttavia, con questa soluzione, si creavano problemi in fase di traduzione del codice ASCII, perci`o si `e tornati all’implementazione originaria. Cos`ı si `e pensato di andare a verifi-

(34)

care la compatibilit`a del codice Matlab con la configurazione del modulo Wi-Fi, trovando ci`o che non permetteva la corretta trasmissione dei dati. Si vedr`a nella sezione successiva quanto svolto per risolvere il problema.

Infine, si `e aggiunta una flush prima della chiamata alla callback per pulire il buffer del dispositivo della porta seriale, poich´e altrimenti vi era sovrapposizione di byte e una conseguente traduzione errata del codice ASCII.

Dopo aver effettuato questi cambiamenti, si `e quindi riusciti a salvare i dati rice- vuti dalla scheda Renesas attraverso la comunicazione implementata con Matlab e andarli ad analizzare.

5.3 Modifiche nel codice di programmazione dell’ESP-WROOM-32

Come anticipato precedentemente, si `e andati a verificare l’implementazione del software presente sull’ESP-WROOM-32. Inizialmente, si `e andati a con- trollare se la scheda Renesas trasmettesse correttamente i dati voluti in codice ASCII al modulo Wi-Fi, per escludere, infine, errori nel software implementato su e2studio. Perci`o, si `e passati ad analizzare ci`o che veniva ricevuto dalla connessione TCP/IP, prima che i dati venissero letti dalla readline all’interno della funzione di callback, riscontrando in questo passaggio l’errore. Infatti, si

`e notato che quest’ultimi erano la traduzione in codice ASCII dei singoli byte ricevuti dalla scheda Renesas, che a sua volta traduceva i dati da trasmettere in codice ASCII. Perci`o, avveniva una duplice traduzione e si era impossibili- tati a ricostruire i dati acquisiti. La causa di questa duplice traduzione era la funzione di print presente nel codice di Arduino IDE per la programmazione dell’ESP-WROOM-32, che stampa i dati sulla porta seriale come testo ASCII.

Per risolvere il problema, si `e deciso di sostituire tale funzione con la write, che permette di scrivere dati binari come byte o serie di byte sulla porta seriale.

(35)

Chapter 6

Prove sperimentali

6.1 Prove su principali periferiche hardware della e-Bike (IMU e sensore di corrente)

Una volta conclusa l’implementazione del codice per la comunicazione Wi-Fi, sono stati eseguiti dei test per verificarne il funzionamento con l’IMU, uno dei principali hardware presenti sull’e-Bike.

6.1.1 Verifiche di compatibilit` a del codice

Per prima cosa, si `e unito il codice del Wi-Fi a quello dell’e-Bike preceden- temente implementato, creando una cartella apposita nel source di e2studio dedicato progetto.

Dopo aver commentato i componenti hardware non utilizzati durante il test, sono stati connessi in serie la scheda Renensas con l’ESP-WROOM-32 e l’IMU, rispettivamente alimentati a 5V e 3.3V, per poi provare ad acquisire i dati for- niti da quest’ultimo. Infatti, dopo aver caricato il codice sul microcontroller, si `e connesso il personal computer alla rete generata dal modulo Wi-Fi e si `e inviato, tramite il codice Matlab il comando ”bSE” per far avviare la trasmis- sione dei dati. Prontamente, si `e riscontrato un malfunzionamento in ricezione, perci`o si `e andato a verificare tramite il metodo di ”debug” ci`o che stava avvenendo nel codice implementato su e2studio. Dopo aver riscontrato suc- cesso nell’inizializzazione dell’IMU e delle periferiche UART, I2C, al momento dell’avvio del comando da parte di Matlab non si aveva risposta dall’interrupt di ricezione. Cos`ı, per capire l’origine del problema, si `e deciso di commentare tutte le inizializzazioni presenti, ad eccezione della CMT, dell’LCD e di UART, per poi andarle a rimettere una alla volta per verificare il funzionamento della comunicazione Wi-Fi con ognuna di queste. Alla fine di tali prove, si `e concluso che le due periferiche I2C e UART andavano in conflitto.

(36)

6.1.2 Risoluzione problema di conflitto tra I2C e Uart

Per cercare una soluzione al problema di conflitto tra le due periferiche dell’ESP- WROOM-32 e dell’IMU si `e andato ad analizzare dapprima il codice implemen- tato per quest’ultimo hardware, non riscontrando per`o alcun errore. Si `e alla fine trovato che la soluzione a tale problematica fosse quella di invertire l’ordine di inizializzazione delle due periferiche, ovvero avere come ultime quelle dell’I2C e dell’IMU di conseguenza.

6.2 Prove su e-Bike

Dopo aver effettuato le prove appena descritte si `e optato per connettere il modulo Wi-Fi con la scheda Renesas presente sull’e-Bike.

6.2.1 Cambio dei pin dei PWM per conflitto con pin di Rx e Tx del Wi-fi

Fin da subito, `e sorto un problema riguardante i pin scelti sul microcontroller per la comunicazione Wi-Fi, ovvero i pin 22 e 23 del JN2, in quanto erano gi`a stati adoperati per connettere i PWM. Quest’ultimi, sono dei segnali ad onda quadra con duty cycle variabile in funzione dell’ampiezza del segnale modulante, necessari per alimentare i motori presenti nel circuito dell’e-Bike. Andando ad analizzare l’implementazione di quest’ultimi, si `e per`o notato che vi erano quat- tro canali disponibili nel quale inizializzare i due segnali; perci`o si `e proceduto a controllare nello Schematics della scheda Renesas che i canali restanti corrispon- dessero a delle porte fisiche dove poter connettere i PWM. I canali rimanenti erano l’1, al quale era associata la porta logica P17 e il 2, con porta logica PJ3; a tali canali corrispondevano rispettivamente il pin 1 del connettore JP17 e il pin 15 del connettore J8. Avendo, perci`o, avuto un riscontro positivo con entrambi i canali, si `e proceduto a connettere i PWM alle porte fisiche appena citate per poter collegare il modulo Wi-Fi e testarne il funzionamento. Dopodich`e, `e stato necessario andare a modificare i canali dove avveniva l’inizializzazione dei PWM nel codice di e2studio. In particolar modo, `e stato assegnato il canale 1 al motore di trazione e il 2 al motore di sterzo. Infine, si `e deciso di segnalare nella funzione PWM Init(unsigned char channel number) nel file PWM.c l’utilizzo delle porte associate ai canali 3 e 4 per la comunicazione Wi-Fi.

6.2.2 Risoluzione del problema pin JN2 della Renesas non funzionanti correttamente

Dopo aver risolto la corrispondenza tra i pin dedicati ai PWM e al modulo Wi-Fi, si `e proceduto con il collegamento di quest’ultimo alla scheda Renen- sas. Tuttavia, si `e riscontrato ancora una volta un mal funzionamento nella comunicazione Wi-Fi; infatti, mentre in ricezione al microcontroller giungeva il comando correttamente e veniva stampata a schermo la stringa corrispon- dente, in trasmissione i dati inviati all’ESP-WROOM-32 o non erano esatti o

(37)

non veniva ricevuto alcunch´e. Si `e cos`ı deciso di verificare se ci fosse un qualche conflitto tra la periferica UART e i componenti non ancora analizzati del circuito dell’e-Bike. Dopo aver esaminato quest’ultimi singolarmente, per`o, si `e concluso che non vi erano contrasti come si era ritenuto probabile. Cos`ı, dopo un’attenta riflessione, si `e optato per connettere singolarmente i pin di ricezione e trasmis- sione del JN2 della scheda Renesas ad un oscilloscopio, per analizzarne l’uscita.

Per fare ci`o `e stato necessario inizializzare nuovamente i PWM nei canali usati precedentemente, ovvero il 3 e 4, corrispondenti ai pin interessati del micro- controller Renesas. Da questa analisi, si `e riscontrato che dal pin 22, ovvero il canale di ricezione, si aveva in uscita un segnale ad onda quadra, ovvero il PWM, come richiesto, mentre dal canale di trasmissione non si riscontrava alcunch´e.

Si `e quindi concluso che tale pin non fosse funzionante, perci`o `e stato necessario trovare un’alternativa alla SCI12, ovvero la serial communication interface 12.

La soluzione a tale problema verr`a affrontata nella sezione successiva.

6.2.3 Cambio dell’interfaccia seriale di comunicazione con la SCI6: problema di corto-circuito dei pin risolto poi incidendo nella parte posteriore la scheda Rene- sas

Per trovare un’alternativa alla SCI12, inizialmente, si `e consultato il Man- uale Hardware della scheda Renesas e lo Schematics, per verificare se ci fosse un’ulteriore interfaccia seriale con delle porte fisiche utilizzabili. Si `e trovato che la SCI6 era la periferica pi`u adatta all’esigenze dell’e-Bike, alla quale erano associate le porte logiche P31 e P32. Queste, rispettivamente, corrispondevano alle porte fisiche 24 di ricezione e 21 di trasmissione del connettore J8. Perci`o, si `e deciso di procedere andando a modificare l’implementazione delle funzioni presenti nel file bike uart.c su e2studio, nelle quali veniva utilizzata la SCI12 per sostituirla con la SCI6. Dopodich´e, si sono connessi i pin di Tx e Rx dell’ESP- WROOM-32 secondo la seguente tabella ed sono state eseguite delle prove per verificare il funzionamento di questa seriale.

ESP-WROOM-32 Connettore J8 Scheda Renesas

Pin Rx2 Pin 21

Pin Tx2 Pin 24

(38)

Tuttavia, si `e riscontrato anche in questo caso un malfunzionamento. Cos`ı,

`e stato necessario connettere anche tali pin all’oscilloscopio per verificare che fossero effettivamente funzionanti. Da tale analisi si `e riscontrata la presenza di un corto-circuito tra le due porte fisiche utilizzate. Andando ad esaminare i connettori coinvolti con le porte fisiche RXD6 e TXD6, si `e scoperto che nel connettore JP16, nella parte posteriore della scheda Renesas, era presente un corto circuito. Per poterlo rimuovere `e stato necessario incidere la scheda dove indicato dallo Schematics come riportato di seguito.

Dopo aver rimosso il corto circuito, sono stati effettuati ulteriori test per verifi- care se il problema fosse stato risolto, cosa che effettivamente `e avvenuta.

Si `e deciso, inoltre, di lasciare nei commenti l’implementazione del codice su e2studio con la SCI12 perch`e, se in futuro sar`a necessario sostituire la scheda Renensas presente nel circuito dell’e-Bike, sar`a possibile ripristinare il codice con la seriale precedentemente utilizzata.

(39)

Chapter 7

Schema a blocchi e funzionale del codice WiFi

In questo capitolo verr`a mostrato lo schema a blocchi e il funzionale del codice Wi-Fi implementato su e2studio, dopo aver eseguito la funzione uart init().

SCI6 RXI6 int split matlab parseCommand

send data bSE

main

T x F LAG CST ART = 1

send data

SCI6 T XI6 int

T X F LAG CST ART = 0

bN D

Dopo aver ricevuto un comando attraverso la comunicazione Wi-Fi, interviene l’interrupt di ricezione, che colloca i dati ricevuti nel buffer di ricezione. Se quest’ultimo `e pieno o si riceve la stringa ”\n” avviene la chiamata alla fun- zione split matlab(), che salva il comando ricevuto nella variabile apposita della struttura Packet. Dopo aver effettuato tale chiamata, si ripulisce il comando ricevuto e la coda di ricezione per la prossima comunicazione, poi si disabilita l’interrupt. Infine, si inizializza nuovamente l’interrupt di ricezione per essere

(40)

pronti per la comunicazione successiva.

All’interno di split matlab(), viene chiamata la funzione parse command(), da cui si possono avere due possibili scenari. Se il comando ricevuto `e ”bSE”, ovvero si vuole iniziare la trasmissione dati, inizialmente viene inviata una stringa attraverso la funzione send data() per indicare quali dati si stanno in- oltrando, poi si pone la flag Tx FLAG CSTART a uno. Tale variabile viene richiamata all’interno della CMT nel main, ove nei 100ms, se posta a uno, avviene la trasmissione dei dati attraverso la medesima funzione utilizzata in precedenza. Nel momento in cui avviene la chiamata alla funzione send data, al suo interno viene inizializzato l’interrupt di trasmissione attraverso la inter- rupt tx init(), che viene subito dopo avviato. All’interno di tale interrupt, se la coda non `e vuota, i dati da trasmettere vengono messi nel buffer di trasmissione e sono inoltrati. Dopo aver inviato tutti i dati, si disabilita l’interrupt e viene pulita la coda di trasmissione. Se, invece, il comando ricevuto `e ”bND”, quindi si vuole interrompere la trasmissione dei dati, viene posta la flag Tx FLAG CSTART a zero, cosicch´e nei successivi 100ms della CMT, non venga pi`u trasmessi al- cunch´e.

7.1 Configurazione finale Dispositivo WiFi

Dopo alcune modifiche, si `e giunti alla configurazione finale dell’ESP-WROOM- 32, il dispositivo Wi-Fi utilizzato in questo progetto. Inizialmente, si `e definito il pin 2 del GPIO come test led e sono state settate le credenziali desiderate per accedere al modulo Wi-Fi, per poi andare a creare, attraverso la classe WiFiServer, un server sulla porta 80 che `e in attesa di connessioni. Succes- sivamente, all’interno del Setup, si `e settata la baude rate della UART0 per la trasmissione di dati seriali a 115200 e si `e stampato sulla porta seriale una stringa per segnalare la configurazione. Allo stesso modo, si `e configurata la UART2, si `e stampato l’ssid sulla porta seriale e si `e settato l’access point della rete Wi-Fi. Poi, si `e definito l’indirizzo IP relativo alla rete Wi-Fi attraverso la classe IPAddress e lo si `e stampato a schermo. Dopodich´e, all’interno della void loop() ci si `e messi in attesa dei client. Nel momento in cui si connette un client si crea una stringa currentLine per contenere i dati in arrivo da quest’ultimo finch´e `e connesso. In seguito, vengono scritti i dati letti dalla seriale nel client, i quali, successivamente, verranno eliminati. Dopodich`e, si mette la variabile dly, definita in precedenza, uguale a 1000 e si ripete ci`o per tutte le seriali pre- senti. Infine, ogni volta che si trasmettono dati al client, si accende il pin 2 per segnalare la comunicazione.

#include <dummy.h>

#include <WiFi.h>

#include <WiFiClient.h>

#include <WiFiAP.h>

#define LED_BUILTIN 2 // Set the GPIO pin where you connected

(41)

//your test LED or comment this line out if your dev board //has a built-in LED

// Set these to your desired credentials.

const char *ssid = "Automa";

const char *password = "12345678";

WiFiServer server(80);

void setup() {

pinMode(LED_BUILTIN, OUTPUT); // sets the digital LED_BUILTIN as output

Serial.begin(115200);

Serial.println();

Serial.println("Configuring access point...");

//Configure UART2

Serial2.begin(115200,SERIAL_8N1, 16, 17);

Serial.print("SSID=");

Serial.print(ssid);

Serial.print("\n");

// with password parameter if you want the //AP to be open.

/* WiFi.softAP(ssid, password);

Serial.print("PW=");

Serial.print(password);

Serial.print("\n");

*/

// with AP open.

WiFi.softAP(ssid);

IPAddress myIP = WiFi.softAPIP();

Serial.print("AP IP address: ");

Serial.println(myIP);

server.begin();

Serial.println("Server started");

}

void loop() {

WiFiClient client = server.available();

// listen for incoming clients

(42)

if (client) { // if you get a client, Serial.println("New Client.");// print a message

// out the serial port String currentLine = ""; // make a String to hold

//incoming data //from the client while (client.connected()) { // loop while the //client’s connected unsigned int dly;

if(Serial.available()){

client.write(Serial.read());

Serial.flush(); //erase any data dly=1000;

}

if(Serial1.available()){

client.write(Serial1.read());

Serial1.flush(); //erase any data

dly=1000;

}

if(Serial2.available()){

client.write(Serial2.read());

Serial2.flush(); //erase any data dly=1000;

}

if (client.available()) { // if there’s bytes to read //from the client,

char c = client.read(); // read a byte, then Serial.write(c); // print it out Serial1.write(c); // print it out Serial2.write(c); // print it out dly=1000;

}

//led manage if(dly>0) {

dly--;

digitalWrite(LED_BUILTIN, HIGH); //turns the LED on }

else

digitalWrite(LED_BUILTIN, LOW); //LED off }

(43)

// close the connection:

client.stop();

Serial.println("Client Disconnected.");

} }

(44)

Chapter 8

Schema a blocchi e funzionale del codice Matlab

In questo capitolo verr`a mostrato lo schema a blocchi e il funzionale del codice Wi-Fi implementato su Matlab.

8.1 Configurazione finale Matlab

Command W ritematrix F ileT xt Run

Per poter trasmettere un comando alla scheda Renesas, inizialmente, `e neces- sario connettere il personal computer alla rete Wi-Fi ”Automa”, creata dall’ESP- WROOM-32. Dopo aver cambiato la variabile command con il comando che si desidera inviare, `e necessario andare a modificare il nome del file ”txt”, per non andare a sovrascrivere il precedente, nella callback readASCIIFcn. Dopodich´e,

`e necessario andare ad eseguire il codice attraverso il pushbutton Run.

(45)

Chapter 9

Schema elettrico di connessione del dispositivo WiFi e la Scheda Renesas

In questo capitolo verr`a mostrato lo schema elettrico del dispositivo Wi-fi e la scheda Renesas.

Renesas ESP − 32

P in24J 8 P in21J 8

V cc

GN D V cc GN D

RX2 T X2

(46)
(47)

9.1 Tabella interconnessione PIN WiFi e Rene- sas

Di seguito, si mostrano i pin di interconnessione tra il modulo Wi-Fi e la scheda Renesas.

ESP-WROOM-32 Scheda Renesas Pin Rx2 Pin 21 Connettore J8 Pin Tx2 Pin 24 Connettore J8

Pin Vcc Pin 1 JN1

Pin GND Pin 2 JN1

(48)

Chapter 10

Conclusioni

In conclusione, `e possibile affermare che `e stato raggiunto lo scopo che ci si era prefissati inizialmente, andando a migliorare la comunicazione implemen- tata precedentemente.

Arrivati a questo punto, `e possibile sia ricevere che trasmettere dati dalla scheda Renesas attraverso i cinque comandi definiti nel file wifi command.h. Sono stati decisi tali comandi pensando alle possibili esigenze che potrebbero avere coloro che andranno a trattare il controllo di sterzo e di trazione dell’e-Bike. Nonos- tante ci`o, in caso di necessit`a sar`a possibile aggiungerne di altri con estrema facilit`a, andando a modificare il file sopra citato e la funzione di parsing del comando, ovvero parse command(). Alla ricezione del comando da parte del micro-controller, verr`a stampato a schermo la stringa corrispondente, per avere un riscontro del successo o meno della comunicazione, come deciso in precedenza da colleghi.

Si conclude cos`ı tale elaborato, lasciando la possibilit`a a chi verr`a in seguito di sviluppare il controllo dello sterzo e della trazione dell’e-Bike con l’ausilio della comunicazione Wi-Fi, per rendere pi`u agevole il compito.

(49)

Appendice

(50)

Chapter 11

Codice WiFi Renesas

main.c

#include <stdint.h>

#include <stdbool.h>

#include <stdio.h>

#include <machine.h>

#include "platform.h"

#include "r_switches.h"

#include "./encoders/encoder_1.h" /* encoder header file */

#include "./encoders/encoder_2.h"

#include "./imu/SetupAHRS.h"

#include "./imu/AHRS.h"

#include "./imu/imu.h"

#include "CMT.h" /* Control time unit */

#include "PWM.h" /* Output control */

#include "./imu/i2c.h"

#include "./sensCurr/sens_current.h"

#include "PID.h" /* PID struct and method */

#include "utility.h"

#include "filters.h"

#include "./wifi/bike_uart.h"

#include "./wifi/bike_command.h"

#include "S12ADC.h"

unsigned char Enable_lcd_enc = 1;

/* This variable are used to store data used trough many function */

float result_adc;

(51)

float ref_curr=0;

short PID_ON=0;

posReg position;

extern struct encoder_data enc;

extern struct encoder_2_data enc_2;

/*AHRS per IMU*/

AHRS_out ahrs;

extern unsigned int TX_Flag_CSTART;

extern unsigned int TX_Flag_BSTART;

extern unsigned int TX_Flag_FORCED;

/***************************************

* Function name: main

* Description : Main program function

* Arguments : none

* Return value : none

****************************************/

void main(void) {

/* Local variable */

float voltaggio;

float appoggio=0, appoggio1=0, appoggio2=0;

float speed, current, spd_mot, spd_ruota, speed_ref, balance;

float c0_filt;

float cntrlVoltage[2]= {0,0}; //offset[2];

short res=0;

struct sens_cur SdC0;

speed_ref=0.00;

//speed_ref = 0.56; // m/s = 2 km/h (conv 1:3.6) //speed_ref = 1.11; // m/s = 4 km/h

//speed_ref=1.67; // m/s = 6 km/h //speed_ref= 2.22; // ms = 8 km/h float tens=0;

float offset;

float newVsen=0; //current value read unsigned int old=0;

unsigned int new=0;

unsigned int i=0;

unsigned short int state=0;

uint8_t pc_buffer[100];

(52)

/* PIDs struct, decleared one at time and stored in array */

pidSt pos0, pos1, spd0, spd1, cur0, cur1, bal0, bal1;

pidSt * pid_pos[2] = {&pos0, &pos1};

pidSt * pid_speed[2] = {&spd0, &spd1};

pidSt * pid_current[2] = {&cur0, &cur1};

pidSt * pid_balance[2] = {&bal0, &bal1};

uint8_t lcd_buffer[20];

/* Initialize LCD */

lcd_initialize();

/* Clear LCD */

lcd_clear();

/* Display message on LCD */

lcd_display(LCD_LINE1, " RENESAS ");

lcd_display(LCD_LINE2, " YRDKRX63N ");

/* The three pushbuttons on the YRDK board are tied to interrupt lines, set them up here */

R_SWITCHES_Init();

/* Initialize and start the Compare Match Timer */

CMT_initialize();

/* initializing PWM 1 2 => MTU4*/

PWM_Init(1); //trazione PWM_Init(2); //sterzo

/* Initialize of control struct and direction pin */

//init_controlstruct();

init_dirPin();

/*initialize Encoder 1 2 and their needed peripherials */

encoder_1_init();

encoder_2_init();

/* Initialization of PID struct, 3 for each motor. */

//init_pid_pos(pid_pos[0]);

init_pid_pos(pid_pos[1]);

init_pid_speed(pid_speed[0]);

init_pid_speed_1(pid_speed[1]);

(53)

//init_pid_curr(pid_current[0]);

init_pid_curr(pid_current[1]);

init_pid_balance(pid_balance[0]);

/*initialization of Wi-Fi*/

uart_init();

/*init i2c */

i2c_init();

/* init IMU */

Setup_MARG(&ahrs);

/*Initialize AD 12bit Converter */

S12ADC_init();

/* init sens current */

sens_curr_init(&SdC0, 0);

unsigned int t;

for (int i=0; i<400; i++) { t=general_timer_mS;

while (general_timer_mS < t+10);

if(Manage_ADC() == 1){

/* Fetch the results from the ADC12 */

newVsen = S12ADC_read( );

/* Using a software filter*/

offset = MovingAvgFilter(newVsen,2);

} }

/* This is the main loop. */

while (1) {

if(Tc_5mS) { Tc_5mS = false;

// Fetch the encoder state for motor 1 if(Manage_ADC() == 1)

{

/*Fetch the results from the ADC12 */

newVsen = S12ADC_read( );

(54)

/* Using a software filter */

//tens = MovingAvgFilter(Low_pass_filter(newVsen),2);

//tens = Low_pass_filter(newVsen);

//tens=newVsen;

tens = MovingAvgFilter(newVsen,2);

/*from voltage to ampere

sensitivity : max_current = k : voltage*/

result_adc = (tens-offset)*8.19;

} }

if (Tc_10mS) { Tc_10mS = false;

Query_Enc_2();

appoggio1=enc_2.position_in_pigreek_radians_units * 3.1415 ; if (res == 1) {

lcd_display(LCD_LINE7, "error SdC");

}

//calculate pid result channel 2 if(PID_ON==1){

//controllo con pid di coppia, velocit`a e posizione //speed = calcPID ( 0.174533, appoggio1 , pid_pos[1]);

//current = calcPID ( 3.0, enc_2.speed_in_rad_per_sec , // pid_speed[1]);

//cntrlVoltage[1] = calcPID ( 0.8, result_adc, pid_current[1]);

//cntrlVoltage[1] = 12;

//controllo con PID di posizione, poich`e non `e possibile controllare lo sterzo attraverso il PID di coppia.

cntrlVoltage[1] = calcPID ( balance , appoggio1 , pid_pos[1]);

appoggio2 = cntrlVoltage[1];

}

else{cntrlVoltage[1]=0;}

cntrlVoltage[1] = rescale(cntrlVoltage[1], 2);

(55)

if(TX_Flag_FORCED==1){

Volt_to_duty(0,2);

}else {

Volt_to_duty(cntrlVoltage[1]/2, 2);

} }

if (Tc_20mS) { Tc_20mS = false;

Query_Enc_1();

if(state == 1) {

res = read_curr(&SdC0);

c0_filt = MovingAvgFilter(SdC0.curr/1000, 0);

state = 0;

} else {

sens_curr_init(&SdC0, 0);

state = 1;

}

appoggio = (enc.position_in_pigreek_radians_units * 3.1415);

//calculate pid result channel 1

//speed = calcPID ( position.gradual[0], appoggio, pid_pos[0]);

spd_mot = enc.speed_in_rad_per_sec;

// ruota dentata minore : maggiore = 36 mm : 54 mm = //=54/36 = 1,5

spd_ruota = spd_mot * 1.5;

//diametro ruota 355.6 mm

voltaggio = - calcPID ( speed_ref, spd_ruota*0.3556/2 , pid_speed[0]);

if (voltaggio > 0) { voltaggio = 0; } cntrlVoltage[0] = voltaggio;

//rescale signal to pwm and update

cntrlVoltage[0] = rescale(cntrlVoltage[0], 1);

if(TX_Flag_FORCED==1){

Volt_to_duty(0,1);

} else {

Volt_to_duty(cntrlVoltage[0], 1);

} }

if(Tc_50mS){

Tc_50mS = false;

new=get_ms();

(56)

i=new-old;

old=new;

Read_MARG(&ahrs);

balance = calcPID( 0.0, ahrs.ahrs_data.RollRad, pid_balance[0]);

}

if (Tc_100mS) {

Tc_100mS = false;

sprintf((char*)lcd_buffer, "time = %d", i);

lcd_display(LCD_LINE8, lcd_buffer);

// sprintf((char*)lcd_buffer, "%f", speed);

// lcd_display(LCD_LINE4, lcd_buffer);

// sprintf((char*)lcd_buffer, "%f", enc_2.speed_in_rad_per_sec);

// lcd_display(LCD_LINE5, lcd_buffer);

// sprintf((char*)lcd_buffer, "%.3f", result_adc);

// lcd_display(LCD_LINE6, lcd_buffer);

// sprintf((char*)lcd_buffer, "%f",cntrlVoltage[1] );

// lcd_display(LCD_LINE7, lcd_buffer);

// sprintf((char *)lcd_buffer, " p= %.1f" , // enc_2.position_in_degree);

// lcd_display(LCD_LINE6, lcd_buffer);

//Read_Enc_1();

//Read_Enc_2();

IMU_Display(ahrs.ahrs_data);

if(TX_Flag_CSTART == 1) { //sprintf((char *)pc_buffer,

"%d\t%.3f\t%.3f\t%.3f\t%.3f\t%.3f\t%.3f\t%.3f\n" , //(get_ms()/1000),ahrs.ahrs_data.RollDeg,

ahrs.ahrs_data.PitchDeg,

// ahrs.ahrs_data.YawDeg,enc.speed_in_rad_per_sec, enc.position_in_degree,

//enc_2.speed_in_rad_per_sec,enc_2.position_in_degree);

//sprintf((char *)pc_buffer, "%u\t%.3f\t%.3f\t%.3f\n" , get_ms(),ahrs.ahrs_data.RollDeg,

// ahrs.ahrs_data.PitchDeg, ahrs.ahrs_data.YawDeg);

//sprintf((char *)pc_buffer, "%u\t%.3f\t%.3f\t%.3f\n" ,

get_ms(), result_adc, appoggio2, enc_2.speed_in_rad_per_sec );

//sprintf((char *)pc_buffer, "%u\t%.3f\t\n" , get_ms(),

(57)

enc_2.position_in_degree );\\

sprintf((char *)pc_buffer, "%u\t%.3f\t%.3f\n" , get_ms(), enc_2.position_in_degree, ahrs.ahrs_data.RollDeg );

send_data((char*)pc_buffer, str_length((char*)pc_buffer));

}

if(TX_Flag_BSTART==1){

speed_ref = 2.22; // m/s = 8 km/h (conv 1:3.6) } else {speed_ref=0.00;}

}

} /* end while */

} /* End of function main() */

/*************************************************

* Function name: sw1_callback

* Description : Callback function that is executed when SW1 is pressed.

* Called by sw1_isr in r_switches.c

* Arguments : none

* Return value : none

**************************************************/

void sw1_callback(void) {

PID_ON=1;

} /* End of function sw1_callback() */

/*************************************************

* Function name: sw2_callback

* Description : Callback function that is executed when SW2 is pressed.

* Called by sw2_isr in r_switches.c

* Arguments : none

* Return value : none

**************************************************/

void sw2_callback(void) {

PID_ON=0;

} /* End of function sw2_callback() */

/**************************************************

* Function name: sw3_callback

(58)

* Description : Callback function that

is executed when SW3 is pressed.

* Called by sw3_isr in r_switches.c

* Arguments : none

* Return value : none

**************************************************/

void sw3_callback(void) {

nop(); /* Add your code here. Note: this is executing inside an ISR. */

} /* End of function sw3_callback() */

wifi settings.h

#ifndef WIFI_SETTINGS_H_

#define WIFI_SETTINGS_H_

/*************************************************

Macro definitions

*************************************************/

///* Initial commands that the renesas sends for setting the wifi module */

//#define WIFI_COMMAND1 "AT+CWMODE=3\r\n"

//#define WIFI_COMMAND2 "AT+CIPMUX=1\r\n"

//#define WIFI_COMMAND3 "AT+CIPSERVER=1\r\n"

#define SPLITTER ’:’ /* String splitter between header and command*/

#define DIM_HEADER 8 /* Dimension of the correct command’s header */

#define DIM_COMMAND 3 /* Dimension of the correct command */

#define DIM_BUFFER 100 /* Dimension of the data buffer for the communication */

#define CORRECT_HEADER "+IPD,0,3" /* Sample of the correct header of a command */

#define OK_SETTING "OK\r\n\0\0\0\0" /* Ok response from wifi Module to correct command */

#define ERROR_SETTING "ERROR\r\n\0" /* Error response from WiFi module */

typedef struct {

char header[DIM_HEADER]; /* vector containing the header of the packet */

(59)

char command[DIM_BUFFER]; /* vector containing the command of the packet */

int n; /* dimension of the command, for a correct command n=DIM_COMMAND */

} packet; /* Struct for managing commands

sent by wifi serial communication */

#endif /* WIFI_SETTINGS_H_ */

bike command.h

#ifndef BIKE_COMMAND_H_

#define BIKE_COMMAND_H_

/* Received command for bike function START_BIKE, FORCED_STOP_BIKE , STOP_BIKE , START_COMMUNICATION , STOP_COMMUNICATION*/

#define START_BIKE "bON" /*Command to start the traction of bike */

#define FORCED_STOP_BIKE "bFO" /*Command to stop

immediately the traction of bike */

#define STOP_BIKE "bOF" /*Command to stop

the traction of bike */

#define START_COMMUNICATION "bSE" /*Command to acquire data from bike */

#define STOP_COMMUNICATION "bND" /*Command to stop acquiring

data from bike */

#endif /* BIKE_COMMAND_H_ */

bike uart.h

#ifndef BIKE_UART_H_

#define BIKE_UART_H_

#include <stdint.h>

#include <stdbool.h>

#include <stdio.h>

#include <machine.h>

#include "platform.h"

#include "data_parser.h"

#include "wifi_settings.h"

/*****************************************************

Riferimenti

Documenti correlati

Se la nostra coda di attesa non ` e vuota e a un peer ` e stata inviata nel round 10 corrente una certa quantit` a di dati (determinata come specificato nella tabella 2.5), esso

L’esame si svolge a scelta dello studente in modalità scritta, attraverso una prova costituita da 23 domande a risposta chiusa e 2 domande a risposta aperta con eventuale

La prima attività svolta è stata quella di tarare la videocamera, utilizzata con un’acquisizione a 50000 frame, tramite l’uso dei tondi in lexan. Il ricorso a

L’intervallo QT indica invece la durata della depolarizzazione e ripolarizzazione ventricolare, è misurato dall’inizio del complesso QRS fino alla fine dell’onda T, dipende

Le domande sono di pura autovalutazione e non influenzeranno il giudizio finale dell’esame; ciononostante è necessario che lo studente risponda a tali domande (a cui il

Per quanto riguarda la soluzione per la posizione dell’utensile nello spazio di lavoro si può usare la Cinematica Diretta, mentre per quanto concerne la soluzione della posizione

I sistemi di somministrazione di farmaci si basano su polimeri biocompatibili, un sottoinsieme di materiali polimerici con biocompatibilità sufficiente e proprietà

Dopo aver versato il metallo liquido nella lingottiera, inizia il raffreddamento con conseguente trasmissione di calore per conduzione da parte del fuso alle pareti della forma e