1. P6 is simple. It is an input. It must be receiving the return value of the infrared tracking module. There is no doubt about it.
2. P4 and P1 control the motor together. What is the purpose of P1? This is related to the working mode of L298N. There is a diagram of L298N below. Let's compare it with that diagram.
Output A and output B are connected to the motors, whether they are connected in series or in parallel. The logic input is connected to P4, which controls the forward and reverse rotation of each motor. This is also available in the logic table, so there is no problem.
Output channel A and B enable terminals, what does enable mean? It means giving rights so that it can work. Let's ignore P1, that is, do not connect P1. When the jumper cap is connected, both enable terminals A and B are high level, or understood as 3.3V. At this time, output channels A and B can work. Combined with the logic input of P4 above, the car will move forward at full speed whether it is moving forward, backward or turning, and there is no way to control the speed. If you want to control the speed, you have to use PWM. At this time, unplug the jumper cap of the enable terminal and connect P1, which is the two PWM output terminals. By controlling the duty cycle of the output of P1, you can achieve speed regulation instead of moving forward and backward at full speed all the time. There is also a comment in the code that says that when turning, sometimes you can't react because the speed is too fast. What should I do? When turning left, let the left side reverse and the right side turn forward, and the turning speed will be increased.
----------------------------Manual split line-----------------------------
2019.08.08 Supplement:
This blog has been visited quite frequently recently.
1. The track that the car follows is made of black insulating tape.
2. The project needs to add the Config.h file, which contains the clock configuration. The file is at the bottom. Copy a copy and import it into the project.
3. The microcontroller model I use is MSP430f149. The registers of different series may be different, but the principle of PWM remains unchanged.
4. The tracking system uses an infrared sensor placed at the front of the car, with four-way tracking, as shown in the picture below.
-------------------------------------------------- -------------------------------------------------- ----------
The infrared obstacle avoidance module is used for three-way tracking. The car uses a DC motor, and uses L298N to drive the motor and power the microcontroller. Since the tracking module is not used for infrared, the return value of the middle module for black is 1, and the return value of white is 0, while the return value of the modules on both sides for black is 0, and the return value of white is 1. (Of course, the infrared connection is a module with AD conversion function);
The motor is controlled using the PWM square wave generated by MSP430, and the speed can be adjusted.
Code:
#include <msp430x14x.h>
#include "Config.h"
uchar count = 0;
void Init_PWM(void)
{
P1SEL |= BIT2; //TA1 outputs from P1.2
P1DIR |= BIT2; //TA1 outputs from P1.2
P1SEL |= BIT3; //TA2 outputs from P1.3
P1DIR |= BIT3; //TA2 outputs from P1.3
P6SEL = 0x00;
P6DIR = 0x00; //Set P6 to input mode, read information from infrared obstacle avoidance module
TACTL |= MC_1 + TASSEL_1; //Clock source selects ACLK, up counting mode TA sets
TACCTL1 = OUTMOD_7; //Mode 7 high level PWM output PWM sets
TACCTL2 = OUTMOD_7; //Mode 7 high level PWM output
TACCR0 = 33-1; //Total PWM period = 32 ACLK periods, approximately equal to 1000Hz Set PWM period
//TACCR1 = 16; //TA1 duty cycle = 16/32=50% Set duty cycle
//TACCR2 = 16; //TA2 duty cycle = 16/32=50%
}
void Set_PWM1_Duty(uchar duty) //Set PWM duty cycle
{
TACCR1 = duty;
}
void Set_PWM2_Duty(uchar duty)
{
TACCR2 = duty;
}
void stop()
{
P4OUT=0X0f;
}
void zhizou(char D)
{
if(D==1)
{
P4OUT = 0X05;
Set_PWM1_Duty(12);
Set_PWM2_Duty(12);
}
if(D==2)
{
P4OUT = 0x0a;
Set_PWM1_Duty(10);
Set_PWM2_Duty(10);
}
}
void left(char L)
{
P4OUT = 0x09;
if(L==1)
{
Set_PWM1_Duty(24); //To turn left, use the left wheel reverse and right wheel forward method. This turning method is faster. The same applies to turning right.
Set_PWM2_Duty(32);
}
if(L==2)
{
Set_PWM1_Duty(50);
Set_PWM2_Duty(50);
}
}
void right(char R)
{
P4OUT = 0x06;
if(R==1)
{
Set_PWM1_Duty(32);
Set_PWM2_Duty(24);
}
if(R==2)
{
Set_PWM1_Duty(50);
Set_PWM2_Duty(50);
}
}
void main()
{
WDTCTL = WDTPW + WDTHOLD ; //Turn off the door dog
Clock_Init();
UART_Init();
Init_PWM();
P4SEL = 0x00;
P4DIR = 0xff; //Set to output mode to control the motor
//Set_PWM1_Duty(16);
//Set_PWM2_Duty(16);
while(1)
{
//zhizou(1);
switch(P6IN&0x0e)
{
case 0x0e:zhizou(1);break;
//case 0x1c:left(2);break;
case 0x02:left(1);break;
//case 0x07:right(2);break;
case 0x08:right(1);break;
default:zhizou(1); break;
}
}
}
Config.h
*****************************************************************/
//Delay function, built-in IAR, often used
#define CPU_F ((double)8000000) //External high frequency crystal 8MHZ
//#define CPU_F ((double)32768) //External low frequency crystal 32.768KHZ
#define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0))
#define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0))
//Custom data structure, easy to use
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
//8 LED lights, connected to P6 port, can be stopped by disconnecting the power supply. Disconnect the power supply when ADC is in use
#define LED8DIR P6DIR
#define LED8 P6OUT //P6 port is connected to LED lights, 8
//4 independent keys are connected to P10~P13
#define KeyPort P1IN //Independent keyboard is connected to P10~P13
//Serial port baud rate calculation, when BRCLK=CPU_F, the following formula can be used to calculate, otherwise the division coefficient must be added according to the setting
#define baud 9600 //Set the baud rate
#define baud_setting (uint)((ulong)CPU_F/((ulong)baud)) //Baud rate calculation formula
#define baud_h (uchar)(baud_setting>>8) //Extract high bit
#define baud_l (uchar)(baud_setting) //Low bit
//RS485 control pin, CTR is used to control RS485 in receiving or sending state
#define RS485_CTR1 P5OUT |= BIT2; //Control line high, RS485 sending status
#define RS485_CTR0 P5OUT &= ~BIT2; //Control line low, RS485 receiving status//
2.8-inch TFT color screen display control related hardware configuration
#define RS_CLR P5OUT &= ~BIT5 //RS low
#define RS_SET P5OUT |= BIT5 //RS high
#define RW_CLR P5OUT &= ~BIT6 //RW low
#define RW_SET P5OUT |= BIT6 //RW high
#define RD_CLR P5OUT &= ~BIT7 //E low
#define RD_SET P5OUT |= BIT7 //E high
#define CS_CLR P5OUT &= ~BIT0 //CS low
#define CS_SET P5OUT |= BIT0 //CS high
#define RST_CLR P5OUT &= ~BIT3 //RST set low
#define RST_SET P5OUT |= BIT3 //RST set high
#define LE_CLR P5OUT &= ~BIT1 //LE set low
#define LE_SET P5OUT |= BIT1 //LE set high
//2.8 inch TFT color touch screen control related hardware configuration
#define PEN_CLR P2OUT &= ~BIT0 //PEN set low, when the touch screen is touched, the Penirq pin changes from the high level when not touched to the low level
#define PEN_SET P2OUT |= BIT0 //PEN set high
#define PEN (P2IN & 0x01) //P2.0 input value
#define TPDO_CLR P2OUT &= ~BIT1 //TPDO set low
#define TPDO_SET P2OUT |= BIT1 //TPDO set high
#define TPDOUT ((P2IN>>1)&0x01) //P2.1 input value
#define BUSY_CLR P2OUT &= ~BIT3 //BUSY set low
#define BUSY_SET P2OUT |= BIT3 //BUSY set high
#define TPDI_CLR P2OUT &= ~BIT4 //TPDI set low
#define TPDI_SET P2OUT |= BIT4 //TPDI set high
#define TPCS_CLR P2OUT &= ~BIT5 //TPCS set low#define
TPCS_SET P2OUT |= BIT5 //TPCS set high
#define TPCLK_CLR P2OUT &= ~BIT6 //TPCLK set low
#define TPCLK_SET P2OUT |= BIT6 //TPCLK set high
//Data port for color screen/12864 LCD/1602 LCD, shared by three LCDs
#define DataDIR P4DIR //Data port direction
#define DataPort P4OUT //P4 port is the data port
//12864/1602 LCD control pin
#define RS_CLR P5OUT &= ~BIT5 //RS set low
#define RS_SET P5OUT |= BIT5 //RS set high
#define RW_CLR P5OUT &= ~BIT6 //RW set low
#define RW_SET P5OUT |= BIT6 //RW set high
#define EN_CLR P5OUT &= ~BIT7 //E set low
#define EN_SET P5OUT |= BIT7 //E set high
#define PSB_CLR P5OUT &= ~BIT0 //PSB set low, serial port mode
#define PSB_SET P5OUT |= BIT0 //PSB set high, parallel port mode
#define RESET_CLR P5OUT &= ~BIT1 //RST set low
#define RESET_SET P5OUT |= BIT1 //RST is set high
//12864 application instruction set
#define CLEAR_SCREEN 0x01 //Clear screen instruction: clear the screen and AC value is 00H
#define AC_INIT 0x02 //Set AC to 00H. And the cursor moves to the origin
#define CURSE_ADD 0x06 //Set the cursor movement direction and the overall image movement direction (the default cursor moves right, and the image does not move as a whole)
#define FUN_MODE 0x30 //Working mode: 8-bit basic instruction set
#define DISPLAY_ON 0x0c //Display on, display cursor, and the cursor position is reversed
#define DISPLAY_OFF 0x08 //Display off
#define CURSE_DIR 0x14 //Cursor moves right: AC=AC+1
#define SET_CG_AC 0x40 //Set AC, range: 00H~3FH
#define SET_DD_AC 0x80 //Set DDRAM AC
#define FUN_MODEK 0x36 //Working mode: 8-bit extended instruction set
//Color code, TFT display
#define White 0xFFFF //Display color code
#define Black 0x0000
#define Blue 0x001F
#define Blue2 0x051F
#define Red 0xF800
#define Magenta 0xF81F
#define Green 0x07E0
#define Cyan 0x7FFF
#define Yellow 0xFFE0
//NRF2401 module control line
#define RF24L01_CE_0 P1OUT &=~BIT5 //CE at P15
#define RF24L01_CE_1 P1OUT |= BIT5
#define RF24L01_CSN_0 P2OUT &=~BIT7 //CS at P27
#define RF24L01_CSN_1 P2OUT |= BIT7
#define RF24L01_SCK_0 P3OUT &=~BIT3 //SCK at P33
#define RF24L01_SCK_1 P3OUT |= BIT3
#define RF24L01_MISO_0 P3OUT &=~BIT2 //MISO at P32
#define RF24L01_MISO_1 P3OUT |= BIT2
#define RF24L01_MOSI_0 P3OUT &=~BIT1 //MOSI at P31
#define RF24L01_MOSI_1 P3OUT |= BIT1
#define RF24L01_IRQ_0 P1OUT &=~BIT4 //IRQ at P14
#define RF24L01_IRQ_1 P1OUT |= BIT4
//DS18B20 control pin, single-pin control
#define DQ_IN P1DIR &= ~BIT7 //Set input, DS18B20 connected to MCU P53 port
#define DQ_OUT P1DIR |= BIT7 //Set output
#define DQ_CLR P1OUT &= ~BIT7 //Set low level
#define DQ_SET P1OUT |= BIT7 //Set high level
#define DQ_R P1IN & BIT7 //Read level
//Infrared receiver H1838 control pin, single-pin control
#define RED_IN P1DIR &= ~BIT6 //Set input, infrared receiver connected to MCU PE3 port
#define RED_OUT P1DIR |= BIT6 //Set output
#define RED_L P1OUT &= ~BIT6 //Set low level
#define RED_H P1OUT |= BIT6 //Set to high level
#define RED_R (P1IN & BIT6) //Read level
//************************************************************************
// System clock initialization, external 8M crystal oscillator
//************************************************************************
void Clock_Init()
{
uchar i;
BCSCTL1&=~XT2OFF; //Turn on XT2 oscillator
BCSCTL2|=SELM1+SELS; //MCLK is 8MHZ, SMCLK is 8MHZ
do{
IFG1&=~OFIFG; //Clear oscillator error flagfor
(i=0;i<100;i++)
_NOP();
}
while((IFG1&OFIFG)!=0); //If the flag is 1, continue to loop and
waitIFG1&=~OFIFG;
}
//***************************************************************************
// System clock initialization, internal RC crystal oscillator
//************************************************************************
void Clock_Init_Inc()
{
uchar i;
// DCOCTL = DCO0 + DCO1 + DCO2; // Max DCO
// BCSCTL1 = RSEL0 + RSEL1 + RSEL2; // XT2on, max RSEL
DCOCTL = 0x60 + 0x00; //DCO about 3MHZ, 3030KHZ
BCSCTL1 = DIVA_0 + 0x07;
BCSCTL2 = SELM_2 + DIVM_0 + SELS + DIVS_0;
}
//***********************************************************************
// System clock initialization, external 32.768K crystal oscillator
//***********************************************************************
void Clock_Init_Ex32768()
{
uchar i;
BCSCTL2|=SELM1 + SELM0 + SELS; //MCLK is 32.768KHZ, SMCLK is 8MHZ
do{
IFG1&=~OFIFG; //Clear oscillator error flag
for(i=0;i<100;i++)
_NOP();
}
while((IFG1&OFIFG)!=0); //If the flag is 1, continue to loop and wait
IFG1&=~OFIFG;
}
//***************************************************************************
// MSP430 internal watchdog initialization
//***************************************************************************
void WDT_Init()
{
WDTCTL = WDTPW + WDTHOLD; //Turn off watchdog
}
|