Progetto 13 Auto Intelligente con Evitamento Ostacoli a Ultrasuoni

1. Descrizione
In questo progetto, l’obiettivo è realizzare un’auto intelligente con evitamento ostacoli a ultrasuoni. Utilizzeremo l’ultrasuono per rilevare la distanza dall’ostacolo, che può essere usata per controllare il servo per ruotare e far muovere l’auto. Nel frattempo, la scheda LED 8X16 mostrerà il corrispondente schema di stato.
2. Diagramma di Flusso

La logica specifica dell’auto intelligente con evitamento ostacoli a ultrasuoni è mostrata di seguito:


3. Schema di Collegamento

1). GND, VCC, SDA e SCL del modulo scheda LED 8*8 sono collegati a G (GND), V (VCC), A4 e A5 della scheda di espansione.
2). VCC, Trig, Echo e Gnd del sensore a ultrasuoni sono collegati a 5V (V), D12 (S), D13 (S) e Gnd (G).
3). Il servo è collegato a G, V e A3. Il filo marrone è collegato a Gnd (G), il filo rosso è collegato a 5V (V) e il filo arancione è collegato a A3.
4). L’alimentazione è collegata alla porta BAT.
4. Codice di Test
//*******************************************************************************
/*
keyestudio 4wd BT Car
lesson 13
Avoiding Car
http://www.keyestudio.com
*/
#define SCL_Pin A5 //Imposta il pin clock su A5
#define SDA_Pin A4 //Imposta il pin dati su A4
//Array, usato per memorizzare i dati del pattern, può essere calcolato da soli o ottenuto dallo strumento modulo
unsigned char front[] = {0x00,0x00,0x00,0x00,0x00,0x24,0x12,0x09,0x12,0x24,0x00,0x00,0x00,0x00,0x00,0x00};
unsigned char left[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x28,0x10,0x44,0x28,0x10,0x44,0x28,0x10,0x00};
unsigned char right[] = {0x00,0x10,0x28,0x44,0x10,0x28,0x44,0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00,0x00};
unsigned char STOP01[] = {0x2E,0x2A,0x3A,0x00,0x02,0x3E,0x02,0x00,0x3E,0x22,0x3E,0x00,0x3E,0x0A,0x0E,0x00};
unsigned char clear[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
int left_ctrl = 2;//definisce i pin di controllo direzione del motore gruppo B
int left_pwm = 5;//definisce i pin di controllo PWM del motore gruppo B
int right_ctrl = 4;//definisce i pin di controllo direzione del motore gruppo A
int right_pwm = 6;//definisce i pin di controllo PWM del motore gruppo A
#include "SR04.h"//definisce la libreria del sensore a ultrasuoni
#define TRIG_PIN 12// imposta il pin di uscita segnale del sensore a ultrasuoni su D12
#define ECHO_PIN 13//imposta il pin di ingresso segnale del sensore a ultrasuoni su D13
SR04 sr04 = SR04(ECHO_PIN,TRIG_PIN);
long distance,a1,a2;//definisce tre variabili distanza
const int servopin = A3;//imposta il pin del servo su A3
void setup() {
pinMode(left_ctrl,OUTPUT);//imposta i pin di controllo direzione del motore gruppo B come OUTPUT
pinMode(left_pwm,OUTPUT);//imposta i pin di controllo PWM del motore gruppo B come OUTPUT
pinMode(right_ctrl,OUTPUT);//imposta i pin di controllo direzione del motore gruppo A come OUTPUT
pinMode(right_pwm,OUTPUT);//imposta i pin di controllo PWM del motore gruppo A come OUTPUT
pinMode(TRIG_PIN, OUTPUT); //Imposta il pin trig come output
pinMode(ECHO_PIN, INPUT); //Imposta il pin echo come input
servopulse(servopin,90);//l'angolo del servo è 90 gradi
delay(300);
pinMode(SCL_Pin,OUTPUT);// Imposta il pin clock come output
pinMode(SDA_Pin,OUTPUT);//Imposta il pin dati come output
matrix_display(clear);
}
void loop()
{
avoid();//esegue il programma principale
}
void avoid()
{
distance=sr04.Distance(); //ottiene il valore rilevato dal sensore a ultrasuoni
if((distance < 20)&&(distance != 0))//se la distanza è maggiore di 0 e minore di 10
{
car_Stop();//ferma
matrix_display(clear);
matrix_display(STOP01);//mostra il pattern di stop
delay(1000);
servopulse(servopin,160);//il servo ruota a 160°
delay(500);
a1=sr04.Distance();//misura la distanza
delay(100);
servopulse(servopin,20);//ruota a 20 gradi
delay(500);
a2=sr04.Distance();//misura la distanza
delay(100);
servopulse(servopin,90); //Ritorna alla posizione di 90 gradi
delay(500);
if(a1 > a2)//confronta la distanza, se la distanza a sinistra è maggiore di quella a destra
{
car_left();//gira a sinistra
matrix_display(clear);
matrix_display(left); //mostra il pattern di svolta a sinistra
servopulse(servopin,90);//il servo ruota a 90 gradi
delay(700); //gira a sinistra per 700ms
matrix_display(clear);
matrix_display(front); //mostra il pattern avanti
}
else//se la distanza a destra è maggiore di quella a sinistra
{
car_right();//gira a destra
matrix_display(clear);
matrix_display(right); //mostra il pattern di svolta a destra
servopulse(servopin,90);//il servo ruota a 90 gradi
delay(700);
matrix_display(clear);
matrix_display(front); //mostra il pattern avanti
}
}
else//altrimenti
{
car_front();//avanza
matrix_display(clear);
matrix_display(front); // mostra il pattern avanti
}
}
void car_front()//la macchina avanza
{
digitalWrite(left_ctrl,HIGH);
analogWrite(left_pwm,155);
digitalWrite(right_ctrl,HIGH);
analogWrite(right_pwm,155);
}
void car_back()//va indietro
{
digitalWrite(left_ctrl,LOW);
analogWrite(left_pwm,100);
digitalWrite(right_ctrl,LOW);
analogWrite(right_pwm,100);
}
void car_left()//la macchina gira a sinistra
{
digitalWrite(left_ctrl, LOW);
analogWrite(left_pwm, 100);
digitalWrite(right_ctrl, HIGH);
analogWrite(right_pwm, 155);
}
void car_right()//la macchina gira a destra
{
digitalWrite(left_ctrl, HIGH);
analogWrite(left_pwm, 155);
digitalWrite(right_ctrl, LOW);
analogWrite(right_pwm, 100);
}
void car_Stop()//ferma
{
digitalWrite(left_ctrl,LOW);
analogWrite(left_pwm,0);
digitalWrite(right_ctrl,LOW);
analogWrite(right_pwm,0);
}
void servopulse(int servopin,int myangle)//l'angolo di rotazione del servo
{
for(int i=0; i<20; i++)
{
int pulsewidth = (myangle*11)+500;
digitalWrite(servopin,HIGH);
delayMicroseconds(pulsewidth);
digitalWrite(servopin,LOW);
delay(20-pulsewidth/1000);
}
}
//questa funzione è usata per la visualizzazione sulla matrice di punti
void matrix_display(unsigned char matrix_value[])
{
IIC_start(); //la funzione che chiama la condizione di inizio trasferimento dati
IIC_send(0xc0); //seleziona l'indirizzo
for (int i = 0; i < 16; i++) //i dati del pattern sono 16 byte
{
IIC_send(matrix_value[i]); //Trasmetti i dati del pattern
}
IIC_end(); //Termina la trasmissione dei dati del pattern
IIC_start();
IIC_send(0x8A); //Controllo display, seleziona larghezza impulso 4/16
IIC_end();
}
//Condizioni in cui inizia la trasmissione dei dati
void IIC_start()
{
digitalWrite(SDA_Pin, HIGH);
digitalWrite(SCL_Pin, HIGH);
delayMicroseconds(3);
digitalWrite(SDA_Pin, LOW);
delayMicroseconds(3);
digitalWrite(SCL_Pin, LOW);
}
//Indica la fine della trasmissione dei dati
void IIC_end()
{
digitalWrite(SCL_Pin, LOW);
digitalWrite(SDA_Pin, LOW);
delayMicroseconds(3);
digitalWrite(SCL_Pin, HIGH);
delayMicroseconds(3);
digitalWrite(SDA_Pin, HIGH);
delayMicroseconds(3);
}
//trasmetti dati
void IIC_send(unsigned char send_data)
{
for (byte mask = 0x01; mask != 0; mask <<= 1) //Ogni byte ha 8 bit e viene controllato bit per bit a partire dal livello più basso
{
if (send_data & mask) { //Imposta i livelli alto e basso di SDA_Pin a seconda che ogni bit del byte sia 1 o 0
digitalWrite(SDA_Pin, HIGH);
} else {
digitalWrite(SDA_Pin, LOW);
}
delayMicroseconds(3);
digitalWrite(SCL_Pin, HIGH); //Porta alto il pin clock SCL_Pin per fermare la trasmissione dati
delayMicroseconds(3);
digitalWrite(SCL_Pin, LOW); //Porta basso il pin clock SCL_Pin per cambiare il SEGNALE di SDA
}
}
//*******************************************************************************
5. Risultato del Test
Dopo aver caricato con successo il codice sulla scheda V4.0, collega i cablaggi secondo lo schema elettrico, alimenta la scheda con alimentazione esterna e poi porta l’interruttore DIP su ON.
L’auto intelligente si muove in avanti ed evita automaticamente gli ostacoli. Quando non c’è strada davanti, il servo aziona il sensore ad ultrasuoni per scansionare le distanze a sinistra, centro e destra, e l’auto sterza verso il lato libero. Nel frattempo, la scheda LED 8X16 mostrerà il pattern di stato corrispondente.