Article Records: Geek Navigation
This project is an embedded project in the Geek Navigation Tutorial, a remote control system for smart cars
Code is open source (end of article).
The design system mainly includes (as shown in the diagram)
- Car owners (51 and STM32)
- Hardware remote control (master STM32)
- Mobile phone remote control software (Android design)
- Computer Control Software (QT Design)
This design does not add too many sensors in the car. First, it mainly implements the main function of the car, which is remote control. For ranging, display, gyroscope, tracing and so on, it can be added after the basic function is realized. In the follow-up of the tutorial, you will write articles such as tracked car, balanced car, exquisite robot, etc., which can refer to the Geek Navigation tutorial system.
Here's a cart made in the past. Now it looks a little ugly. Cars and remote controls can draw PCB and 3D models, which will look good. If you're interested, you can see the auxiliary design section of this tutorial.
Previously designed posters now look and feel good.
I won't say much here. If you're interested, you can support it. In the future, I will also record and make tutorial videos. If you find the articles dull, you can watch videos.
Car owners (51)
The main modules of the car body are L298N motor drive module and ESP8266WiFi module.
L298N motor drive
Core Knowledge Points
- Channel A and Channel B connect two motors, positive and negative.
- The 5V input is powered to L298N chips. Some chips will be powered on after the positive pole of the main power supply is connected, so no external connection is needed. Then you can use this voltage to power other single-chip computers.
- Voltage output from the positive pole of the main power supply to the motor, up to 12V
- Input 1,2,3,4 controls the forward and reverse of the motor, such as 1 for high level and 2 for low level, the motor will turn and the reverse motor will turn. 12 controls one motor and 34 controls one motor.
- The A-phase enabler and the B-phase enabler enable the motor. If we do not adjust the speed, we directly connect the high level and the next pin on L298N. The speed is determined by the voltage of the motor. If we need to adjust the speed, the two pins need to be connected to the single-chip pin, and the PWM output is done through the program design.
51 Code settings, how do we define how to connect.
//Enabler, speed control using PWM wave sbit ENA = P1^4; sbit ENB = P1^5;
sbit IN1 = P1^0; //Define right control pin sbit IN2 = P1^1; sbit IN3 = P1^2; //Define left control pin sbit IN4 = P1^3;
How to control the motor rotation?
Above we have set the pin, you can make the enabled pin connect to the high level first, or make the enabled pin equal to the high level.
If you want the motor on the right to turn, you can IN1 = 1, IN2 = 0, the motor will turn, if IN1 = 0, IN2 = 1, the motor will reverse. If IN1 = 1, IN2 = 1; IN1 = 0, IN2 = 0, the motor will stop.
How to adjust the speed of the motor?
Motor speed control involves PWM output, and timer, duty cycle, is involved in 51.
So let's start with the timer configuration, which mainly includes initialization and interruption functions.
Timer Base Register
- There is no basis to look at registers which are more demanding, and I don't delve into it here. Just ask what I need, skip what I don't want to know, just look at the application.
Interrupt System Diagram
TMOD Register
TCON Timer Control Register
TR0:TR0=1 means that T0 starts to run. (T1 pin in single-chip computer needs high and low level driver)
TR1:TR1=1 indicates that T1 starts to run. (T0 pin in single-chip computer needs high and low level driver)
Interrupt Source Priority and Interrupt Number
I'll list what I need here. As for register specifics, I can look them up by myself. I don't want the article to be too cumbersome.
Timer Initialization Process
- 1. Select the mode of timer and set TMOD, for example, we set TMOD=0X01;As you can see from the figure above, M1 = 0, M0 = 1; Choose Mode 1. Remember that the last four bits are Timer 0 and the first four bits are Timer 1. Choose Mode is the number of registers that determine the timing and count.
- 2. Given the initial value of the timer, determine the time for each register overflow
How to feed in initial values:
from TMOD Mode selection, mode 1 is a 16-bit timer/Counter 16 Bit register capacity is 65535 Once the timer starts, the register is added to the original value by 1, each time adding 1 is a machine cycle A machine cycle equals 12 clock cycles, which are related to the frequency of the crystal oscillation If the crystal frequency is 12 HZ,Then the time of a clock cycle is 1/12us So a machine cycle is 1 us This means that each count of registers requires 1 us Time 10000us == 10ms If we set the initial value of the register to 65535 - 10000 = 55535 So starting at 55535, when you reach 65535, you need to count 10,000 times, which is 10 ms We can control the number of register overflows to get the exact time If we set 10 for each overflow ms,So 100 times is 1 s How to set the initial value of the register? If we want to set the initial value to 55535 1,For 55535 / 256 = 216; 216 The corresponding hexadecimal number is 1101,000 = 0xd8 finish writing sth. TH0=0Xd8; 2,For 55535 more % 256 = 239; 239 Corresponding hexadecimal 110 1111 = 0xef finish writing sth. TL0=0Xf0;
- 3. Open interrupt permission, ET0, EA
ET0=1;//Turn on timer 0 interrupt allow EA=1;//Open Total Interrupt
- 4. Start time TR0=1;
Sharing logic based on interrupt system diagrams is clearer, and the following video tutorials are mainly summarized.
From the analysis above, we can write
Initialization function for timer 0
//Timer 0 Initialization Function void Timer0Config() { TMOD &= 0xF0; //Clear mode of timer 0 TMOD |= 0x01; //Set timer 0 mode TH0 = 0xFF; //Input Initial Value (65536 - 130) / 256 65536 - 65406 TL0 = 0x7E; //(65536 - 130) % 256 EA = 1; //Open Total Interrupt ET0 = 1; //Turn on timer 0 interrupt allow TR0 = 1; //Timer 0 Allow Control Bits }
Timer 0 interrupt function
//Timer 0 interrupt function interrupt number is 1 void InterruptTimer0() interrupt 1 { //The initial value needs to be reset after each overflow TH0 = 0xFF; //Given an initial timer value, timer 130us TL0 = 0x7E; cnt++; //Add 1 cnt per overflow and 1 130us per overflow if(cnt >= 100) //Clear 0 when cnt is greater than or equal to 100 { cnt = 0; } //Here is to define a period of 130 * 100 = 13000us, 13ms }
Timer initialization function and interrupt function are both written, how to control the motor?
Not yet, because we still have to write PWM functions.
We analyze it with a piece of code
IN3 = 1; if(cnt <= DutyCycle) //DutyCycle is a duty cycle { IN4 = 0; } else { IN4 = 1; }
Because of the timer interrupt function, the cnt variable loops between 0 and 100, overflowing 100 cycles; analyzing the code above, when DutyCycle = 60, we execute the program above 100 times, cnt increments. You will find that IN3 100 times are 1, IN4 60 times are 0, 40 times are 1, the speed is%60 at full speed; when DutyCycle = 60At 100, IN3 is all 1, IN4 is all 0 and the speed is full. So we can adjust the speed by modifying the duty cycle.
The above analysis may be vague, because there is no subjective understanding, you can use single-chip computer and motor drive to test, to modify the duty cycle, to see the speed changes, I will also demonstrate in the video tutorial.
We encapsulate the function that adjusts the duty cycle.
/* Parameter Definition: ReverOrCoro Pass Forward and Reverse, 1 Forward and 0 Reverse DutyCycle Duty Cycle Parameter */ void Motor_Right(bit ReverOrCoro, unsigned char DutyCycle) { if(ReverOrCoro == 1) { IN3 = 1; if(cnt <= DutyCycle) { IN4 = 0; } else { IN4 = 1; } } else { IN4 = 1; if(cnt <= DutyCycle) { IN3 = 0; } else { IN3 = 1; } } }
How do we call it in the program?
Motor_Right(0, 0); //Duty ratio 0, stop Motor_Right(0, 50); //Duty cycle 50, medium speed Motor_Right(0, 100); //Duty cycle 100, full speed
The above is the function to control the right motor, and the same is true for the left motor, but it is modified to IN1, IN2.
Through timer initialization, interrupt function, PWM motor speed control function. We can already control the motor's turn and rotation speed. If we want to achieve remote control car, it is to receive data from the remote control and make judgments. You can see the writing in the program, the program will be analyzed below.
if(receiveTable[9]==0x31) //When character 1 is entered, go forward { Motor_Left(1, number), Motor_Right(0, number); } if(receiveTable[9]==0x32) //Backward when character 2 is entered { Motor_Left(0, number), Motor_Right(1, number); } if(receiveTable[9]==0x33) //Turn left when entering character 3 { Motor_Left(1, number), Motor_Right(0, 0); }
That's all for the motor-driven part here. To review what we need to know.
- 1. The footer meaning of L298N motor driver chip, it is necessary to distinguish the control motors, control the motor turn, power supply and enable each part.
- 2. Timer-related registers, TMON, TCON, and interrupt system diagrams.
- 3. Steps of timer 0 initialization, setting mode, feeding initial value and turning on timer.
- 4. Timer interrupt function, we can control the time of each overflow, what we need to consider each overflow.
- 5. PWM output function, through the configuration of timer 0, we need to know how to set the duty cycle and adjust the speed.
ESP8266
There are two WiFi modules above, the first one is ESP8266 -01s, and the next one is Esp8266(NodeMCU). We are just using it for data transmission and the effect is the same.
Principle of ESP8266
ESP8266 mode:
AP Mode Server STA Mode Client AP + STA Pattern
Test ESP8266
Serial assistant can be used for AT instruction testing.
Communication Structure Diagram
51 and STM32 work the same way.
Configuration ideas
- If single-chip computer acts as a server, ESP8266 is AP mode, open hot spot, has IP address and port number. When other TCP clients want to connect to the server, they need to connect hot spot first, then bind IP address and port number to connect.
- If it's STA mode, you need to connect to the server's hotspot, bind the IP address to the port number, and connect
Connection Range
- Because it uses WIFI local communication, but only works within the local network, to achieve wide area network communication, you can connect to the cloud server, you need to use WIFI or traffic configuration
ESP8266 Configured as Server (Instruction)
ESP8266 Configure as a server ( PC Or single chip sends instructions: (1) test AT Directives: AT (2) Change Module Baud Rate: AT+CIOBAUD=9600 (Set other baud rates after successful baud rate settings) (3) Reset the restart module: AT+RST (4) Set to AP Pattern: AT+CWMODE=2 (5) Set up name password,Encryption method: AT+CWSAP="esp8266","123456789",11,4 (6) View Host Side ip Address: AT+CIFSR(Here's the IP Address is the module itself IP,No ST Assigned when a router is added to a mode IP) (7) Set module transfer mode to TCP Pattern: AT+CIPMODE=0 (8) Set to multi-connection mode, start module: AT+CIPMUX=1 (9) Setup port for server: AT+CIPSERVER=1,8090 (TCP client Connect server Keep port numbers consistent)
Instruction Test
Set up AP mode, account password, and then you can search for the WIFI module.
TCP client data transfer test.
The TCP client written by himself communicated successfully.
Through the serial assistant we can test the instructions, I tested them once above, set the AP mode, then set the account password, and then use the TCP client to connect for data transfer test.
The above is to test ESP8266 on the serial assistant, and we want to use ESP8266 on the single chip computer. Through the AT instruction test, we also found that on the serial assistant, we also send related instructions to the serial assistant, and then send them to the ESP8266 through the serial port.
Below, we also need to use the serial port of single-chip computer to send instructions to ESP8266 for configuration.
So here we describe the configuration and use of the 51 Serial Port.
Serial Port Initialization Function
//Serial Port Initialization Function void UartInit(void) //Serial Port Initialization Function { TMOD &= 0x0F; //Clear configuration of timer 1 TMOD |= 0x20; //Timer works in 2,8-bit auto overload (0010 0000) TL1 = 0xfd; //Load Initial Value TH1 = 0xfd; //Load Initial Value IP = 0; //Interrupt priority is the same TR1 = 1; //Start timer 1 REN=1; //Allow serial port to receive data SM0=0; //Working mode 1,10-bit asynchronous transceiver SM1=1; EA = 1; //Turn on global interrupt control ES=1; //Open Serial Port Interrupt }
Serial port send data (single byte)
//Serial Send Data Single Byte void Sent_ZF(u8 dat) //Send a Byte { ES = 0; //Do not allow serial port to accept or send interrupts TI=0; //Loop waiting for end of send, when end of send, TI=1 SBUF = dat; //Save dat data in SBUF as one byte while(!TI); //When the sending is complete, TI = 1, then!TI false, end cycle TI = 0; //TI Reset ES = 1; //Allow Serial Port to Accept and Send Interrupts }
Serial port send data (string)
//Serial port send data, string void AT_Send_String(u8 *string) //Send String { while(*string) //'\0'ends the loop when it reaches the end of the character { Sent_ZF(*string++);//Call Send Single Byte Function Delay_ms(5); } }
Serial interrupt function
//Serial interrupt function receives data void uart() interrupt 4 { if(RI == 1) //Indicates receipt of data { RI = 0; //Clear the serial receive flag bits, only if cleared, can receive data next time receiveTable[i] = SBUF; //Store data in an array if(receiveTable[0] == '+') //Determines whether the data is invalid because the WiFi module automatically adds a string starting with "+PID." //Valid data is tenth //If the external data is sent 5 to 51 via ESP8266 //Then 51 serial port receives "+PID...5" 5 is the tenth //So receiveTable[9] is our real data { i++; } else { i = 0; } if(i == 10) { i = 0; } } }
ESP8266 Initialization Function
//ESP8266 Initialization Function void ESP8266_Init() //esp8266 9600 baud rate { Delay_ms(1000); // = 2 is AP mode, = 1 is client mode AT_Send_String("AT+CWMODE=2\r\n"); Delay_ms(1000); //Create WiFi Hotspots AT_Send_String("AT+CWSAP=esp8266,0123456789,11,4\r\n"); Delay_ms(1000); AT_Send_String("AT+RST\r\n"); //Restart Module Delay_ms(1000); //Set to multi-connection mode, start module AT_Send_String("AT+CIPMUX=1\r\n"); Delay_ms(1000); //Setup Port for Server AT_Send_String("AT+CIPSERVER=1,8090\r\n"); }
ESP8266 Configuration Client
Configure server instructions ( STA Mode) 1,AT+CWMODE=1 To configure STA Pattern 2,AT+RST Restart takes effect 3,AT+CWJAP="wifi Name","WiFi Password" Connect WIFI 4,AT+CIPSTART="TCP","192.168.4.1",8090 Connect to Server 5,AT+CIPSEND=4 Send instructions 6,AT+CIPMODE=1 Turn on transfer mode 7,AT+CIPSEND Start Transmitting
Code Link
Links: Code Link
Extraction Code: 1314