前言:本实验为CW32L012作为主控驱动路径大师(小车)按指定路线循迹的实验
一、实物展示:
二、模块介绍:
本实验基于CW32开发板,搭载了众多传感器来实现路径大师功能。其中包括驱动电机的TB6612,蓝牙模块,WIFI模块,超声波传感器模块,mpu6050模块,舵机模块,循迹模块,摄像头模块,oled显示屏模块等。
本实验用到的模块有:TB6612电机驱动模块;循迹模块;oled显示屏模块。本实验的循迹模块外接的是CW32L010为主控的开发板,上面搭载了五路灰度传感器,分别为D1,D2,D3,D4,D5。通过这5路灰度传感器搭配算法,可以精准地使小车行驶在路径中央并完成赛道的循迹,下面重点介绍本实验用到的模块。
循迹模块:一共5路灰度检测,每一路搭配一个发白光的LED常量持续照射地面,还搭配一个无灯光敏接收管负责接收地面返回的光本身不发光。每一路的循迹工作原理为:当照射到黑线时,因为黑色吸收绝大多数白光,反射回去的光微弱,感光管工作后模块输出电平为1高电平,此时感应到黑线并在这一路(我们假设为D1)设定D1=1,此时我们的路径大师在黑线的右侧,需要通过电机的差速向左偏移角度使之回到中央位置。相同原理的5路灰度检测。当检测到白光时,由于白光的反射能力强,反射光充足,感光管饱和,模块输出低电平置0此时对应的是D1=0,说明此时这一路的灰度传感器不在黑线上面。上面提到过,我们这个循迹模块一共有5路,那么分别对应为左D1,左中D2,中D3,右中D4,右D5。这5路传感器具体的运行逻辑见下表:
| 只有 D1=1(最左压黑线) | 左轮慢 30,右轮全速 500 → 车子向左拐,修正位置 |
| 只有 D2=1(左中压黑线) | 左轮减速 500-130,右轮全速 → 小幅向左微调 |
| 只有 D3=1(中间压黑线) | 左右都是 500,笔直往前走 |
| 只有 D4=1(右中压黑线) | 右轮减速,左轮全速 → 小幅向右微调 |
| 只有 D5=1(最右压黑线) | 右轮慢 30,左轮全速 → 车子向右大角度修正 |
TB6612 |
5路灰度模块 |
下面介绍TB6612模块的工作原理及其在路径大师上的应用:
TB6612 是双路 H 桥电机驱动,一块芯片同时驱动 2 个直流减速电机,最大持续电流 1.2A,峰值 3.2A,支持正转、反转、刹车、停机,搭配 PWM 调速。对应的引脚分组见下表:
| VM | 电源动力电源 |
| VCC | 芯片逻辑电源 |
| GND | 公共地 |
| A通道(左轮电机MA) | AIN1,AIN2(方向控制IO)PA12,PB5。PWMA(左轮调速)PB0。AO1,AO2(输出接电机两根线) |
| B 通道(右轮电机 MB) | BIN1,BIN2(方向控制 IO)PB3、PB4。PWMB(右轮 PWM 调速)PB1。BO1、BO2(输出接右电机两根线) |
H桥换向逻辑:每一组AIN1/AIN2构成一个H桥,通过高低电平组合决定转向,见下表。
| AIN1 | AIN2 | 电机A状态 | 左轮代码逻辑 |
| 高1 | 低0 | 正转前进 | duty>0:PA12=1,PB5=0 |
| 低0 | 高1 | 反转后退 | duty<0:PA12=0,PB5=1 |
| 低0 | 低0 | 刹车(短接制动) | 速度 0 停机 |
B 通道 BIN1/BIN2 规则完全一样,对应右轮 PB3/PB4:正转:BIN1=1,BIN2=0,反转:BIN1=0,BIN2=1
三、软件讲解:
下面附上代码在keil工程里的实现:
motor.c和motor.h
#include "main.h"/* 电机方向控制 (CW32L012) 左轮 PA12/PB5, 右轮 PB3/PB4* 左轮: 方向脚 PA12 / PB5 , 速度 PWM_SetCompare_L (在 pwm.c, GTIM CHx -> PB0)* 右轮: 方向脚 PB3 / PB4 , 速度 PWM_SetCompare_R (在 pwm.c, GTIM CHy -> PB1)*/void Motor_Init(void){__SYSCTRL_GPIOA_CLK_ENABLE();__SYSCTRL_GPIOB_CLK_ENABLE();GPIO_InitTypeDef GPIO_InitStruct = {0};GPIO_InitStruct.IT = GPIO_IT_NONE;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pins = GPIO_PIN_12; /* PA12 左方向 */GPIO_Init(CW_GPIOA, &GPIO_InitStruct);GPIO_InitStruct.Pins = GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5; /* PB3/4 右, PB5 左 */GPIO_Init(CW_GPIOB, &GPIO_InitStruct);PWM_Init(); /* 初始化 PB0/PB1 的 PWM */}void Motor_Setduty_L(int16_t duty) /* 左轮 PA12 / PB5 */{if (duty >= 0){GPIO_WritePin(CW_GPIOA, GPIO_PIN_12, GPIO_Pin_SET);GPIO_WritePin(CW_GPIOB, GPIO_PIN_5, GPIO_Pin_RESET);PWM_SetCompare_L(duty);}else{GPIO_WritePin(CW_GPIOB, GPIO_PIN_5, GPIO_Pin_SET);GPIO_WritePin(CW_GPIOA, GPIO_PIN_12, GPIO_Pin_RESET);PWM_SetCompare_L(-duty);}}void Motor_Setduty_R(int16_t duty) /* 右轮 PB3 / PB4 */{if (duty >= 0){GPIO_WritePin(CW_GPIOB, GPIO_PIN_3, GPIO_Pin_SET);GPIO_WritePin(CW_GPIOB, GPIO_PIN_4, GPIO_Pin_RESET);PWM_SetCompare_R(duty);}else{GPIO_WritePin(CW_GPIOB, GPIO_PIN_4, GPIO_Pin_SET);GPIO_WritePin(CW_GPIOB, GPIO_PIN_3, GPIO_Pin_RESET);PWM_SetCompare_R(-duty);}}void car_stop(void){Motor_Setduty_R(0);Motor_Setduty_L(0);}void Motor_Left_Run(int16_t value) { Motor_Setduty_L(value); }void Motor_Right_Run(int16_t value) { Motor_Setduty_R(value); }void Car_Stop(void) { car_stop(); }#ifndef __MOTOR_H#define __MOTOR_H#include <stdint.h>void Motor_Init(void);void Motor_Setduty_L(int16_t duty); /* 左轮 PA12 / PB5 */void Motor_Setduty_R(int16_t duty); /* 右轮 PB3 / PB4 */void car_stop(void);/* 灰度循迹用的别名(转接到 Setduty) */void Motor_Left_Run(int16_t value);void Motor_Right_Run(int16_t value);void Car_Stop(void);#endif
Gs.c和Gs.h
#include "main.h"/* 5 路灰度循迹 (CW32L012) D1~D5 = PB12/PB13/PB14/PB15/PB8* (想更快就往 300~600 加), 30/130 这些差速量也一起按比例调。 */extern uint8_t State;uint8_t Num = 0, last_Num = 0;extern int8_t Speed, Speed2;void GrayscaleSensor_Init(void){__SYSCTRL_GPIOB_CLK_ENABLE();PB12_AFx_GPIO();PB13_AFx_GPIO();PB14_AFx_GPIO();PB15_AFx_GPIO();PB08_AFx_GPIO();GPIO_InitTypeDef GPIO_InitStruct = {0};GPIO_InitStruct.IT = GPIO_IT_NONE;GPIO_InitStruct.Mode = GPIO_MODE_INPUT; /* 上拉输入 */GPIO_InitStruct.Pins = GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15 | GPIO_PIN_8;GPIO_Init(CW_GPIOB, &GPIO_InitStruct);}int16_t Basic_speed = 500;void GrayscaleSensor_fun(void){if (State == 1){if (D1==1 && D2==0 && D3==0 && D4==0 && D5==0){ Motor_Left_Run(30); Motor_Right_Run(Basic_speed); }else if (D1==0 && D2==1 && D3==0 && D4==0 && D5==0){ Motor_Left_Run(Basic_speed - 130); Motor_Right_Run(Basic_speed); }else if (D1==0 && D2==0 && D3==1 && D4==0 && D5==0){ Motor_Left_Run(Basic_speed); Motor_Right_Run(Basic_speed); }else if (D1==0 && D2==0 && D3==0 && D4==1 && D5==0){ Motor_Left_Run(Basic_speed); Motor_Right_Run(Basic_speed - 130); }else if (D1==0 && D2==0 && D3==0 && D4==0 && D5==1){ Motor_Left_Run(Basic_speed); Motor_Right_Run(30); }else if (D1==1 && D2==1 && D3==0 && D4==0 && D5==0) /* 左直角 */{ Motor_Left_Run(60); Motor_Right_Run(200);while (1) if (D4) break; /* 注意: 无超时, 等不到会卡死 */}else if (D1==0 && D2==0 && D3==0 && D4==1 && D5==1) /* 右直角 */{ Motor_Left_Run(200); Motor_Right_Run(60);while (1) if (D2) break; /* 注意: 无超时, 等不到会卡死 */}else{ Motor_Left_Run(Basic_speed); Motor_Right_Run(Basic_speed); }}}#ifndef __GS_H#define __GS_H#include <stdint.h>/* 5 路灰度读脚: 1=该路压线, 0=未压。 D1~D5 = PB12/PB13/PB14/PB15/PB8 */#define D1 GPIO_ReadPin(CW_GPIOB, GPIO_PIN_12)#define D2 GPIO_ReadPin(CW_GPIOB, GPIO_PIN_13)#define D3 GPIO_ReadPin(CW_GPIOB, GPIO_PIN_14)#define D4 GPIO_ReadPin(CW_GPIOB, GPIO_PIN_15)#define D5 GPIO_ReadPin(CW_GPIOB, GPIO_PIN_8)extern uint8_t Num, last_Num;void GrayscaleSensor_Init(void);void GrayscaleSensor_fun(void);void task4(void);#endif
四、总结与建议:
1.使用循迹小车要注意电池的电压,太低会影响电机运动。
2.对灰度模块要进行校准,长按直到led红灯闪烁,再短按一下放到黑线上进行校准。
3.使用灰度模块的D1-D5在OLED显示屏上面显示出来,注意观察,如偏差太大可以自行调整。
扫码加入QQ群3群| 610403240
1029