Projet 17 Voiture intelligente Bluetooth polyvalente

1.Description
Dans les projets précédents, la voiture ne réalise qu’une seule fonction. Cependant, dans cette leçon, nous allons intégrer toutes ses fonctions via un Bluetooth.
2.Diagramme de flux

3.Schéma de câblage

1). GND, VCC, SDA et SCL de la carte LED 8*8 sont connectés respectivement à G (GND), V (VCC), A4 et A5 de la carte d’extension.
2). Les broches RXD, TXD, GND et VCC du module Bluetooth sont respectivement connectées à TX, RX, G et 5V sur le Shield moteur 8833, tandis que les broches STATE et BRK du module Bluetooth n’ont pas besoin d’être connectées.
3). Le servo est connecté à G, V et A3. Le fil marron est connecté à Gnd (G), le fil rouge est connecté à 5V (V) et le fil orange est connecté à A3.
4). G, V, S1, S2 et S3 du capteur de suivi de ligne sont connectés respectivement à G (GND), V (VCC), D11, D7 et D8 de la carte d’extension capteur.
5). VCC, Trig, Echo et Gnd du capteur ultrason sont connectés respectivement à 5V (V), D12 (S), D13 (S) et Gnd (G).
6). L’alimentation est connectée au port BAT.
4.Code de test
Remarque : Avant de téléverser le code de test, vous devez retirer le module Bluetooth, sinon le code ne pourra pas être téléversé. Reconnectez le module Bluetooth après avoir téléversé le code avec succès.
//*******************************************************************************
/*
keyestudio 4wd BT Car
lesson 17
Bluetooth Multifunctional Car
http://www.keyestudio.com
*/
#define SCL_Pin A5 //Définir la broche d'horloge sur A5
#define SDA_Pin A4 //Définir la broche de données sur A4
//Tableau, utilisé pour stocker les données du motif, peut être calculé soi-même ou obtenu à partir de l'outil de module
unsigned char start01[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
unsigned char front[] = {0x00,0x00,0x00,0x00,0x00,0x24,0x12,0x09,0x12,0x24,0x00,0x00,0x00,0x00,0x00,0x00};
unsigned char back[] = {0x00,0x00,0x00,0x00,0x00,0x24,0x48,0x90,0x48,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};
unsigned char speed_a[] =
{0x00,0x40,0x20,0x10,0x08,0x04,0x02,0xff,0x02,0x04,0x08,0x10,0x20,0x40,0x00,0x00};
unsigned char speed_d[] =
{0x00,0x02,0x04,0x08,0x10,0x20,0x40,0xff,0x40,0x20,0x10,0x08,0x04,0x02,0x00,0x00};
int left_ctrl = 2;//définir les broches de contrôle de direction du moteur du groupe B
int left_pwm = 5;//définir les broches de contrôle PWM du moteur du groupe B
int right_ctrl = 4;//définir les broches de contrôle de direction du moteur du groupe A
int right_pwm = 6;//définir les broches de contrôle PWM du moteur du groupe A
int speeds = 150; //Définir la vitesse initiale à 150
const int servopin = A3;//définir la broche du servo sur A3
int L_pin = 11; //définir la broche du capteur de suivi gauche comme D11
int M_pin = 7; //définir la broche du capteur de suivi milieu comme D7
int R_pin = 8; //définir la broche du capteur de suivi droite comme D8
int L_val, M_val, R_val;
int trigPin = 12; //Broche TRIG connectée à D12
int echoPin = 13; //Broche ECHO connectée à D13
int distance, distance_l, distance_r;
char BLE_val;
void setup() {
Serial.begin(9600);//Définir le débit en bauds à 9600
pinMode(left_ctrl,OUTPUT);//définir les broches de contrôle de direction du moteur du groupe B en SORTIE
pinMode(left_pwm,OUTPUT);//définir les broches de contrôle PWM du moteur du groupe B en SORTIE
pinMode(right_ctrl,OUTPUT);//définir les broches de contrôle de direction du moteur du groupe A en SORTIE
pinMode(right_pwm,OUTPUT);//définir les broches de contrôle PWM du moteur du groupe A en SORTIE
servopulse(servopin,90);//l'angle du servo est de 90 degrés
delay(300);
pinMode(L_pin, INPUT); //Les broches du capteur de suivi sont configurées en mode entrée
pinMode(M_pin, INPUT);
pinMode(R_pin, INPUT);
pinMode(trigPin, OUTPUT); //définir TRIG en mode sortie
pinMode(echoPin, INPUT); //définir ECHO en mode entrée
pinMode(SCL_Pin,OUTPUT);// Définir la broche d'horloge en sortie
pinMode(SDA_Pin,OUTPUT);//Définir la broche de données en sortie
matrix_display(clear);
matrix_display(start01); //afficher le motif d'expression start01
}
void loop() {
if(Serial.available()>0) {
BLE_val = Serial.read();
Serial.println(BLE_val);
}
switch(BLE_val)
{
case 'F' : car_front();
matrix_display(clear);
matrix_display(front);
break;
case 'B' : car_back();
matrix_display(clear);
matrix_display(back);
break;
case 'L' : car_left();
matrix_display(clear);
matrix_display(left);
break;
case 'R' : car_right();
matrix_display(clear);
matrix_display(right);
break;
case 'S' : car_Stop();
matrix_display(clear);
matrix_display(STOP01);
break;
case 'a' : speeds_a();
matrix_display(clear);
matrix_display(speed_a);
break;
case 'd' : speeds_d();
matrix_display(clear);
matrix_display(speed_d);
break;
case 'U': follow(); //Réception de ‘U’, entrer en mode suivi
break;
case 'Y': avoid(); //Réception de ‘Y’, entrer en mode évitement d'obstacle
break;
case 'G': confinement(); //Réception de ‘G’, entrer en mode confinement
break;
case 'X': tracking(); //Réception de ‘X’, entrer en mode suivi de ligne
break;
}
}
void car_front()//définir l'état d'avancer
{
digitalWrite(left_ctrl,HIGH);
analogWrite(left_pwm,(255-speeds));
digitalWrite(right_ctrl,HIGH);
analogWrite(right_pwm,(255-speeds));
}
void car_back()//définir l'état de recul
{
digitalWrite(left_ctrl,LOW);
analogWrite(left_pwm,speeds);
digitalWrite(right_ctrl,LOW);
analogWrite(right_pwm,speeds);
}
void car_left()//définir l'état de virage à gauche
{
digitalWrite(left_ctrl, LOW);
analogWrite(left_pwm, speeds);
digitalWrite(right_ctrl, HIGH);
analogWrite(right_pwm, (255-speeds));
}
void car_right()//définir l'état de virage à droite
{
digitalWrite(left_ctrl, HIGH);
analogWrite(left_pwm, (255-speeds));
digitalWrite(right_ctrl, LOW);
analogWrite(right_pwm, speeds);
}
void car_Stop()//définir l'état d'arrêt
{
digitalWrite(left_ctrl,LOW);
analogWrite(left_pwm,0);
digitalWrite(right_ctrl,LOW);
analogWrite(right_pwm,0);
}
void speeds_a() { //fonction d'accélération rapide
while (1) {
Serial.println(speeds); //afficher les informations de vitesse
if (speeds < 255) { //Jusqu'à 255
matrix_display(clear);
matrix_display(speed_a);
speeds++;
delay(10); //ajuster la vitesse de croissance
}
BLE_val = Serial.read();
if (BLE_val == 'S') //Réception de 'S', la voiture arrête d'accélérer
break;
}
}
void speeds_d() { //fonction de réduction de vitesse
while (1) {
Serial.println(speeds); //afficher les informations de vitesse
if (speeds > 0) { //jusqu'à 0
matrix_display(clear);
matrix_display(speed_d);
speeds--;
delay(10); //ajuster la vitesse de décélération
}
BLE_val = Serial.read();
if (BLE_val == 'S') //Réception de 'S', la voiture arrête de décélérer
break;
}
}
int get_distance() {
int distance = 0;
digitalWrite(trigPin, LOW); // envoyer une impulsion via Trig/Pin, déclencher la mesure HC-SR04, pour que l'interface du signal ultrasonore soit à un niveau bas pendant 2μs
delayMicroseconds(2);
digitalWrite(trigPin, HIGH); // mettre l'interface du signal ultrasonore à un niveau haut pendant 10μs, ici au moins 10μs
delayMicroseconds(10);
digitalWrite(trigPin, LOW); // maintenir l'interface du signal ultrasonore à un niveau bas
distance = pulseIn(echoPin, HIGH) / 58; // lire la durée de l'impulsion et convertir cette durée en distance (unité : cm)
Serial.println(distance); // afficher la valeur de la distance
return distance;
}
void follow() {
servopulse(servopin,90);
delay(200);
int follow_flag = 1;
while (follow_flag) {
distance = get_distance(); // appeler la fonction de mesure de distance
if (distance < 8 ) {// Si la distance est inférieure à 8
car_back();// la voiture recule
matrix_display(clear);
matrix_display(back);
}
else if (distance >= 8 && distance < 13) { // Si la distance est supérieure ou égale à 8 et inférieure à 13
car_Stop();// arrêt
matrix_display(clear);
matrix_display(STOP01);
}
else if (distance >= 13 && distance <= 35 ) { // Si la distance est supérieure ou égale à 13 et inférieure ou égale à 35
car_front();// la voiture avance
matrix_display(clear);
matrix_display(front);
}
else {// Sinon
car_Stop();// arrêt
matrix_display(clear);
matrix_display(STOP01);
}
BLE_val = Serial.read();
if (BLE_val == 'S') { // Lorsque 'S' est reçu, la voiture s'arrête
follow_flag = 0;
car_Stop();
}
}
}
void avoid() {
int avoid_flag = 1;
while (avoid_flag) {
distance = get_distance(); // Appeler la fonction de mesure de distance
if (distance > 0 && distance < 20) { // Si la distance est inférieure à 20 et supérieure à 0
car_Stop();// arrêt
matrix_display(clear);
matrix_display(STOP01); // la matrice de points affiche un motif d'arrêt
delay(1000);
servopulse(servopin,160); // amener le servo à plus de 180 degrés
delay(500);
distance_l = get_distance(); // obtenir la distance à gauche
delay(100);
servopulse(servopin,20); // tourner le servo à 0 degré
delay(500);
distance_r = get_distance(); // obtenir la distance à droite
delay(100);
if (distance_l > distance_r) { // comparer les distances, si la gauche est plus grande que la droite
car_left(); // la voiture tourne à gauche
matrix_display(clear);
matrix_display(left); // la matrice de points affiche un motif gauche
servopulse(servopin,90);// le servo revient à 90 degrés
delay(700);
matrix_display(clear);
matrix_display(front); // la matrice de points affiche un motif avant
}
else { // Sinon si la droite est plus grande que la gauche
car_right();// la voiture tourne à droite
matrix_display(clear);
matrix_display(right); // la matrice de points affiche un motif droite
servopulse(servopin,90);// le servo revient à 90 degrés
delay(700);
matrix_display(clear);
matrix_display(front); // la matrice de points affiche un motif avant
}
}
else { // Lorsque la distance devant est supérieure ou égale à 20 cm
car_front();// la voiture avance
matrix_display(clear);
matrix_display(front); // la matrice de points affiche un motif avant
}
BLE_val = Serial.read();
if (BLE_val == 'S') {// Lorsque 'S' est reçu, la voiture s'arrête
avoid_flag = 0;
car_Stop();
}
}
}
void confinement() {
int confinement_flag = 1;
while (confinement_flag) {
L_val = digitalRead(L_pin); // lire la valeur du capteur gauche
M_val = digitalRead(M_pin); // lire la valeur du capteur du milieu
R_val = digitalRead(R_pin); // lire la valeur du capteur droit
if ( L_val == 0 && M_val == 0 && R_val == 0 ) { // la voiture avance lorsqu'aucune ligne noire n'est détectée
car_front();
}
else { // Sinon, si l'un des capteurs de suivi détecte une ligne noire, la voiture recule puis tourne à gauche
car_back();
delay(500);
car_left();
delay(800);
}
BLE_val = Serial.read();
if (BLE_val == 'S') { // Lorsque 'S' est reçu, la voiture s'arrête
confinement_flag = 0;
car_Stop();
}
}
}
void tracking() {
int track_flag = 1;
while (track_flag) {
L_val = digitalRead(L_pin); // lire la valeur du capteur gauche
M_val = digitalRead(M_pin); // lire la valeur du capteur du milieu
R_val = digitalRead(R_pin); // lire la valeur du capteur droit
if (M_val == 1) { // Ligne noire détectée au milieu
if (L_val == 1 && R_val == 0) { // Si une ligne noire est détectée à gauche, mais pas à droite, tourner à gauche
car_left();
}
else if (L_val == 0 && R_val == 1) { // Sinon, si une ligne noire est détectée à droite et pas à gauche, tourner à droite
car_right();
}
else { // Sinon, la voiture avance
car_front();
}
}
else { // aucune ligne noire détectée au milieu
if (L_val == 1 && R_val == 0) { // Si une ligne noire est détectée à gauche, mais pas à droite, tourner à gauche
car_right();
}
else if (L_val == 0 && R_val == 1) { // Sinon, si une ligne noire est détectée à droite et pas à gauche, tourner à droite
car_right();;
}
else { // Sinon, s'arrêter
car_Stop();
}
}
BLE_val = Serial.read();
if (BLE_val == 'S') { // Lorsque 'S' est reçu, la voiture s'arrête
track_flag = 0;
car_Stop();
}
}
}
void servopulse(int servopin,int myangle)// Angle de fonctionnement du servo
{
for(int i=0; i<30; i++)
{
int pulsewidth = (myangle*11)+500;
digitalWrite(servopin,HIGH);
delayMicroseconds(pulsewidth);
digitalWrite(servopin,LOW);
delay(20-pulsewidth/1000);
}
}
// cette fonction est utilisée pour l'affichage matriciel
void matrix_display(unsigned char matrix_value[])
{
IIC_start(); // la fonction qui appelle la condition de démarrage du transfert de données
IIC_send(0xc0); // sélectionner l'adresse
for (int i = 0; i < 16; i++) // les données du motif sont sur 16 octets
{
IIC_send(matrix_value[i]); // Transmettre les données du motif
}
IIC_end(); // Fin de la transmission des données du motif
IIC_start();
IIC_send(0x8A); // Contrôle de l'affichage, sélection de la largeur d'impulsion 4/16
IIC_end();
}
// Conditions dans lesquelles la transmission des données commence
void IIC_start()
{
digitalWrite(SDA_Pin, HIGH);
digitalWrite(SCL_Pin, HIGH);
delayMicroseconds(3);
digitalWrite(SDA_Pin, LOW);
delayMicroseconds(3);
digitalWrite(SCL_Pin, LOW);
}
// Indique la fin de la transmission des données
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);
}
// transmettre les données
void IIC_send(unsigned char send_data)
{
for (byte mask = 0x01; mask != 0; mask <<= 1) // Chaque octet contient 8 bits et est vérifié bit par bit en commençant par le bit de poids faible
{
if (send_data & mask) { // Définit les niveaux haut et bas de SDA_Pin selon que chaque bit de l'octet est un 1 ou un 0
digitalWrite(SDA_Pin, HIGH);
} else {
digitalWrite(SDA_Pin, LOW);
}
delayMicroseconds(3);
digitalWrite(SCL_Pin, HIGH); // Met la broche d'horloge SCL_Pin à haut pour arrêter la transmission des données
delayMicroseconds(3);
digitalWrite(SCL_Pin, LOW); // Met la broche d'horloge SCL_Pin à bas pour changer le SIGNAL de SDA
}
}
//*******************************************************************************
5. Résultat du test
Après avoir téléchargé avec succès le code sur la carte V4.0, connectez les câblages selon le schéma de câblage, alimentez l’alimentation externe puis mettez l’interrupteur DIP sur ON.
Après que le module Bluetooth est connecté à l’APP et que l’application mobile est connectée avec succès au Bluetooth, la voiture intelligente peut être contrôlée par l’application mobile. Nous pouvons réaliser les fonctions correspondantes en appuyant sur les boutons correspondants de l’application mobile.