STM32 smart car-Bluetooth controlled and speed measuring car, wife controlled car, 4g controlled car, voice controlled car

Table of Contents

1. Bluetooth controlled car

2. Bluetooth control and speed measuring car

3. WiFi controlled speed measuring car

4. 4g controlled car

5. Voice control car

5.1 Voice module configuration:

5.2 Voice control car development and debugging code


1. Bluetooth control car

  • Using Bluetooth module, serial port transparent transmission
  • Bluetooth module, also called Bluetooth serial port module

Serial port transparent transmission technology:

  • Transparent transmission means that during the data transmission process, the set of data does not undergo any form of change through wireless means, as if the transmission process is transparent, while ensuring the quality of the transmission, intact at the final reception in hands.
  • Ethernet, Bluetooth, Zigbee, GPRS and other modules play the same way. For embedded programmers, there is no need to care about the internal data of the communication module and the working principle of the protocol stack. They only need to obtain the data through serial port programming.

Code:

Integrate the front serial port control car code and connect to the Bluetooth module

if (!strcmp(UART1_RX_Buffer, "M1"))
{
    goForward();
    HAL_Delay(10);
}
else if (!strcmp(UART1_RX_Buffer, "M2"))
{
    goBack();
    HAL_Delay(10);
}
else if (!strcmp(UART1_RX_Buffer, "M3"))
{
    goLeft();
    HAL_Delay(10);
}
else if (!strcmp(UART1_RX_Buffer, "M4"))
{
    goRight();
    HAL_Delay(10);
}
else
    stop();

2. Bluetooth controlled and speed measuring car

Principle:

Use Bluetooth module and speed measurement module to integrate the two codes

Code:

usart.c

#include "usart.h"

#include "string.h"
#include "stdio.h"
#include "motor.h"

//Serial port receiving buffer (1 byte)
uint8_t buf=0;

//Define the maximum number of received bytes 200, which can be adjusted according to needs
#define UART1_REC_LEN 200

//Receive buffer, the data received by the serial port is placed in this array, the maximum is UART1_REC_LEN bytes
uint8_t UART1_RX_Buffer[UART1_REC_LEN];

//receive status
// bit15, reception completion flag
// bit14, received 0x0d
// bit13~0, the number of valid bytes received
uint16_t UART1_RX_STA=0;

#define SIZE 12

char buffer[SIZE];

// Reception completion callback function, after receiving a data, process it here
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
// Determine which serial port the interrupt was triggered by
if(huart->Instance == USART1)
{
// Determine whether the reception is completed (UART1_RX_STA bit15 is 1)
if((UART1_RX_STA & 0x8000) == 0)
{
// If 0x0d (carriage return) has been received,
if(UART1_RX_STA & 0x4000)
{
// Then determine whether 0x0a (line feed) is received
if(buf == 0x0a)
{
// If both 0x0a and 0x0d are received, set bit15 to 1
UART1_RX_STA |= 0x8000;

//Light control instructions
if(!strcmp(UART1_RX_Buffer, "M1"))
goForward();
else if(!strcmp(UART1_RX_Buffer, "M2"))
goBack();
else if(!strcmp(UART1_RX_Buffer, "M3"))
goLeft();
else if(!strcmp(UART1_RX_Buffer, "M4"))
goRight();
else
stop();
\t\t\t\t\t
memset(UART1_RX_Buffer, 0, UART1_REC_LEN);
UART1_RX_STA = 0;
}
else
// Otherwise, consider receiving error and start again
UART1_RX_STA = 0;
}
else // If 0x0d (carriage return) is not received
{
//Then first determine whether the received character is 0x0d (carriage return)
if(buf == 0x0d)
{
// If yes, set bit14 to 1
UART1_RX_STA |= 0x4000;
}
else
{
// Otherwise, save the received data in the cache array
UART1_RX_Buffer[UART1_RX_STA & 0X3FFF] = buf;
UART1_RX_STA + + ;
\t\t\t\t\t
// If the received data is larger than UART1_REC_LEN (200 bytes), restart receiving
if(UART1_RX_STA > UART1_REC_LEN - 1)
UART1_RX_STA = 0;
}
}
}
// Re-enable interrupts
HAL_UART_Receive_IT( & amp;huart1, & amp;buf, 1);
}
}

int fputc(int ch, FILE *f)
{
unsigned char temp[1]={ch};
HAL_UART_Transmit( & amp;huart1,temp,1,0xffff);
return ch;
}

oled.c

#include "oled.h"
#include "i2c.h"
#include "oledfont.h"

void Oled_Write_Cmd(uint8_t dataCmd)
{
\t
HAL_I2C_Mem_Write( & amp;hi2c1, 0x78, 0x00, I2C_MEMADD_SIZE_8BIT,
&dataCmd, 1, 0xff);
}

void Oled_Write_Data(uint8_t dataData)
{
HAL_I2C_Mem_Write( & amp;hi2c1, 0x78, 0x40, I2C_MEMADD_SIZE_8BIT,
&dataData, 1, 0xff);
}

void Oled_Init(void){
Oled_Write_Cmd(0xAE);//--display off
Oled_Write_Cmd(0x00);//---set low column address
Oled_Write_Cmd(0x10);//---set high column address
Oled_Write_Cmd(0x40);//--set start line address
Oled_Write_Cmd(0xB0);//--set page address
Oled_Write_Cmd(0x81); // contract control
Oled_Write_Cmd(0xFF);//--128
Oled_Write_Cmd(0xA1);//set segment remap
Oled_Write_Cmd(0xA6);//--normal / reverse
Oled_Write_Cmd(0xA8);//--set multiplex ratio(1 to 64)
Oled_Write_Cmd(0x3F);//--1/32 duty
Oled_Write_Cmd(0xC8);//Com scan direction
Oled_Write_Cmd(0xD3);//-set display offset
Oled_Write_Cmd(0x00);//
\t
Oled_Write_Cmd(0xD5);//set osc division
Oled_Write_Cmd(0x80);//
\t
Oled_Write_Cmd(0xD8);//set area color mode off
Oled_Write_Cmd(0x05);//
\t
Oled_Write_Cmd(0xD9);//Set Pre-Charge Period
Oled_Write_Cmd(0xF1);//
\t
Oled_Write_Cmd(0xDA);//set com pin configuartion
Oled_Write_Cmd(0x12);//
\t
Oled_Write_Cmd(0xDB);//set Vcomh
Oled_Write_Cmd(0x30);//
\t
Oled_Write_Cmd(0x8D);//set charge pump enable
Oled_Write_Cmd(0x14);//
\t
Oled_Write_Cmd(0xAF);//--turn on oled panel
}

void Oled_Screen_Clear(void){
char i,n;
Oled_Write_Cmd (0x20); //set memory addressing mode
Oled_Write_Cmd (0x02); //page addressing mode

for(i=0;i<8;i + + ){
Oled_Write_Cmd(0xb0 + i);
Oled_Write_Cmd(0x00);
Oled_Write_Cmd(0x10);
for(n=0;n<128;n + + )Oled_Write_Data(0x00);
}
}

void Oled_Show_Char(char row,char col,char oledChar){ //row*2-2
unsigned int i;
Oled_Write_Cmd(0xb0 + (row*2-2)); //page 0
Oled_Write_Cmd(0x00 + (col & amp;0x0f)); //low
Oled_Write_Cmd(0x10 + (col>>4)); //high
for(i=((oledChar-32)*16);i<((oledChar-32)*16 + 8);i + + ){
Oled_Write_Data(F8X16[i]); //Write data oledTable1
}

Oled_Write_Cmd(0xb0 + (row*2-1)); //page 1
Oled_Write_Cmd(0x00 + (col & amp;0x0f)); //low
Oled_Write_Cmd(0x10 + (col>>4)); //high
for(i=((oledChar-32)*16 + 8);i<((oledChar-32)*16 + 8 + 8);i + + ){
Oled_Write_Data(F8X16[i]); //Write data oledTable1
}
}


/****************************************************** *******************************/
// Function name: Oled_Show_Char
//Input parameters: oledChar
// Output parameters: none
// Function: OLED displays a single character
/****************************************************** *******************************/
void Oled_Show_Str(char row,char col,char *str){
while(*str!=0){
Oled_Show_Char(row,col,*str);
str + + ;
col + = 8;
}
}

main.c

extern uint8_t buf;
unsigned int speedCnt = 0;
char speedMes[24]; //The main program sends the string buffer of speed data

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == GPIO_PIN_14)
if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_14) == GPIO_PIN_RESET)
speedCnt + + ;
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
printf("speed: %d\r\\
", speedCnt);
sprintf(speedMes,"speed:- cm/s",speedCnt);//String assembly of serial port data, speed is a grid, each grid is 1cm
Oled_Show_Str(2,2,speedMes);
speedCnt = 0;
}

3. WiFi controlled speed measuring car

  • Wifi module-ESP-01s
  • Bluetooth, ESP-01s, Zigbee, NB-Iot and other communication modules are all designed based on AT commands.

Introduction to AT commands:

  • The AT command set is sent from the terminal equipment (Terminal Equipment, TE) or data terminal equipment (Data Terminal Equipment, DTE) to the terminal adapter (Terminal Adapter, TA) or data circuit terminal equipment (Data Circuit Terminal Equipment, DCE).
  • It has a definition for the size of the transmitted data packet: that is, for the transmission of AT commands, in addition to the two AT characters, a maximum length of 1056 characters (including the last null character) can be received.
  • Each AT command line can only contain one AT command; for the URC indication or response actively reported by the terminal device to the PC, it is also required to have at most one in one line, and multiple instructions or responses in one reported line are not allowed. AT commands end with carriage return, and responses or reports end with carriage return and line change.

Hardware wiring

  • Plug esp8266 into serial port 1

Instructions:

Wifi module-ESP-01s_esp01s baud rate-CSDN Blog

4. 4g controlled car

Principle: Using EC03-DNC4G communication module

Module introduction:

  • Development method based on serial port AT commands
  • There are two working modes. The default is transparent transmission mode. You can enter AT command mode through other methods.
  • Be careful not to make mistakes when inserting the card. The red position in the picture below is the SIM card status light. It is normal if it is on

The code does not need to be modified, it is directly integrated based on the Bluetooth car. The 4g module only needs to do transparent transmission to the external network.

5. Voice control car

5.1 Voice Module Configuration:

Using SU-03T/LD3320

For a detailed introduction, please see the blog I wrote before: The use of SU-03T voice module_Luo Xiaobai’s godfather’s blog-CSDN blog

5.2 Voice control car development and debugging code

Hardware wiring:

Tracking car:

  • Tracking module (left) — PB3
  • Tracking module (right) — PB4

Follow the car:

  • Follow module (left) — PA8
  • Follow module (right) — PA9

Obstacle avoidance car:

  • sg90: PB9
  • Trig:PA10
  • Echo:PA11

OLED module:

  • SCL — PB6
  • SDA — PB7

Voice module:

  • A25 — PA15 (follow)
  • A26 — PA13 (obstacle avoidance)
  • A27 — PA14 (tracking)

cubeMX configuration

Code example:

#include "main.h"
#include "i2c.h"
#include "tim.h"
#include "gpio.h"

#include "sg90.h"
#include "sr04.h"
#include "motor.h"
#include "oled.h"

#define MIDDLE 0
#define LEFT 1
#define RIGHT 2

#define BZ 1
#define XJ 2
#defineGS 3

#define LeftWheel_Value_XJ HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_3)
#define RightWheel_Value_XJ HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_4)

#define LeftWheel_Value_GS HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8)
#define RightWheel_Value_GS HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_9)

#define A25 HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_15)
#define A26 HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_13)
#define A27 HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_14)

void SystemClock_Config(void);

char dir;

void xunjiMode()
{
if(LeftWheel_Value_XJ == GPIO_PIN_RESET & amp; & amp; RightWheel_Value_XJ == GPIO_PIN_RESET)
goForward();
if(LeftWheel_Value_XJ == GPIO_PIN_SET & amp; & amp; RightWheel_Value_XJ == GPIO_PIN_RESET)
goLeft();
if(LeftWheel_Value_XJ == GPIO_PIN_RESET & amp; & amp; RightWheel_Value_XJ == GPIO_PIN_SET)
goRight();
if(LeftWheel_Value_XJ == GPIO_PIN_SET & amp; & amp; RightWheel_Value_XJ == GPIO_PIN_SET)
stop();
}

void gensuiMode()
{
if(LeftWheel_Value_GS == GPIO_PIN_RESET & amp; & amp; RightWheel_Value_GS == GPIO_PIN_RESET)
goForward();
if(LeftWheel_Value_GS == GPIO_PIN_SET & amp; & amp; RightWheel_Value_GS == GPIO_PIN_RESET)
goRight();
if(LeftWheel_Value_GS == GPIO_PIN_RESET & amp; & amp; RightWheel_Value_GS == GPIO_PIN_SET)
goLeft();
if(LeftWheel_Value_GS == GPIO_PIN_SET & amp; & amp; RightWheel_Value_GS == GPIO_PIN_SET)
stop();
}

void bizhangMode()
{
double disMiddle;
double disLeft;
double disRight;

if(dir != MIDDLE){
sgMiddle();
dir = MIDDLE;
HAL_Delay(300);
}
disMiddle = get_distance();
\t
if(disMiddle > 35){
\t\t//go ahead
goForward();
}else if(disMiddle < 10){
goBack();
\t\t
}else
{
\t\t//stop
stop();
//Measure the distance to the left
sgLeft();
HAL_Delay(300);
disLeft = get_distance();
\t\t
sgMiddle();
HAL_Delay(300);
\t\t
sgRight();
dir = RIGHT;
HAL_Delay(300);
disRight = get_distance();
\t\t
if(disLeft < disRight){
goRight();
HAL_Delay(150);
stop();
}
if(disRight < disLeft){
goLeft();
HAL_Delay(150);
stop();
}
}
HAL_Delay(50);
}

int main(void)
{
    int mark = 0;

    HAL_Init();


    SystemClock_Config();


    MX_GPIO_Init();
    MX_TIM4_Init();
    MX_TIM2_Init();
    MX_I2C1_Init();

initSG90();
HAL_Delay(1000);
dir = MIDDLE;
Oled_Init();
Oled_Screen_Clear();
Oled_Show_Str(2,2,"-----Ready----");

  while (1)
  {

//Meet the conditions for tracking mode
if(A25 == 1 & amp; & amp; A26 == 1 & amp; & amp; A27 == 0){
if(mark != XJ){
Oled_Screen_Clear();
Oled_Show_Str(2,2,"-----XunJi----");
}
mark = XJ;
xunjiMode();
}
//Meet the conditions for follow mode
if(A25 == 0 & amp; & amp; A26 == 1 & amp; & amp; A27 == 1){
if(mark != GS){
Oled_Screen_Clear();
Oled_Show_Str(2,2,"-----GenSui----");
}
mark = GS;
gensuiMode();
}
//Meet the conditions for obstacle avoidance mode
if(A25 == 1 & amp; & amp; A26 == 0 & amp; & amp; A27 == 1){
if(mark != BZ){
Oled_Screen_Clear();
Oled_Show_Str(2,2,"-----BiZhang----");
}
mark = BZ;
bizhangMode();
}
  }
}