一、在PWM示例程序的基础上,编写moto_control.h moto_control.cpp。
pwm.h、pwm.cpp 包含两个函数,一个是初始化,一个是设置占空比。这可以直接拿来控制电机用。
#ifndef _pwm_H
#define _pwm_H
#include "public.h"
//函数声明
void pwm_init(u8 pin,u8 chanel,u8 freq,u8 resolution);
void pwm_set_duty(u8 chanel,u16 duty);
#endif
#include "pwm.h"
//PWM初始化
//pin:引脚号
//chanel:PWM输出通道0-15
//freq:PWM输出频率,单位HZ
//resolution:PWM占空比的分辨率1-16,比如设置8,分辨率范围0-255
void pwm_init(u8 pin,u8 chanel,u8 freq,u8 resolution)
{
ledcSetup(chanel, freq, resolution);// PWM初始化
ledcAttachPin(pin, chanel);// 绑定PWM通道到GPIO上
}
//PWM占空比设置
void pwm_set_duty(u8 chanel,u16 duty)
{
ledcWrite(chanel,duty);// 改变PWM的占空比
}
moto_control.h moto_control.cpp 代码如下:
#ifndef _MOTO_CONTROL_H
#define _MOTO_CONTROL_H
#include "public.h"
#include "pwm.h"
//控制管脚定义
#define MOTO_A1 15
#define MOTO_A2 4
#define MOTO_B1 16
#define MOTO_B2 17
//PWM通道定义
#define PWM0 0
#define PWM1 1
#define PWM2 2
#define PWM3 3
//函数声明
void moto_init(void);
void turn_left(void);
void turn_right(void);
void stop_A(void);
void stop_B(void);
void stop_all(void);
void Forward(void);
void Backward(void);
#endif
#include "moto_control.h"
//led初始化
void moto_init(void)
{
pinMode(MOTO_A1, OUTPUT);//设置引脚为输出模式
pinMode(MOTO_A2, OUTPUT);//设置引脚为输出模式
pinMode(MOTO_B1, OUTPUT);//设置引脚为输出模式
pinMode(MOTO_B2, OUTPUT);//设置引脚为输出模式
}
void turn_left(void){ //左轮反转、右轮正转
pwm_set_duty(PWM0,1000);
pwm_set_duty(PWM1,0); //MOTO_A2设为低电平
pwm_set_duty(PWM2,0); //MOTO_B1设为低电平
pwm_set_duty(PWM3,0); //MOTO_B1设为低电平
// for(int i=0;i<1000;i+=10){ //调节MOTO_A1占空比 MOTO_A1 MOTO_A2 = 10 电机反转 可变速
// pwm_set_duty(PWM0,i);
// pwm_set_duty(PWM3,i);
// delay(10);
// }
delay(100);//调节延时,可控制转弯角度
stop_all();
}
void turn_right(void){ //左轮正转、右轮反转
pwm_set_duty(PWM0,0);
pwm_set_duty(PWM1,0); //MOTO_A2设为低电平
pwm_set_duty(PWM2,1000); //MOTO_B1设为低电平
pwm_set_duty(PWM3,0); //MOTO_B1设为低电平
// for(int i=0;i<1000;i+=10){ //调节MOTO_A2占空比 MOTO_A1 MOTO_A2 = 01 电机正转 可变速
// pwm_set_duty(PWM1,i);
// pwm_set_duty(PWM2,i);
// delay(10);
// }
delay(100);//调节延时,可控制转弯角度
stop_all();
}
void stop_A(void){
pwm_set_duty(PWM0,0);
pwm_set_duty(PWM1,0);
}
void stop_B(void){
pwm_set_duty(PWM2,0);
pwm_set_duty(PWM3,0);
}
void stop_all(){
stop_A();
stop_B();
}
void Forward(void){
pwm_set_duty(PWM0,0); //MOTO_A2设为低电平
pwm_set_duty(PWM2,0); //MOTO_B1设为低电平
//MOTO_A1 MOTO_A2 & MOTO_B1 MOTO_B2 = 01 电机正转
pwm_set_duty(PWM1,750);
pwm_set_duty(PWM3,750);
delay(500);
stop_all();
}
void Backward(void){
pwm_set_duty(PWM1,0); //MOTO_A2设为低电平
pwm_set_duty(PWM3,0); //MOTO_B1设为低电平
//MOTO_A1 MOTO_A2 & MOTO_B1 MOTO_B2 = 10 电机反转
pwm_set_duty(PWM0,750);
pwm_set_duty(PWM2,750);
delay(500);
stop_all();
}
二、测试蓝牙控制led程序,并改写为电机控制的程序。
/* 深圳市普中科技有限公司(PRECHIN 普中)
技术支持:www.prechin.net
*
* 实验名称:蓝牙实验--控制LED
*
* 接线说明:LED模块-->ESP32 IO
* D1-->15
*
* 实验现象:程序下载成功后,手机预先安装工程目录下“蓝牙串口调试助手.apk”,打开软件,连接蓝牙名称为“ESP32test”,然后发送字符串“on”和"off"
开关LED指示灯。
*
* 注意事项:
*/
#include "public.h"
#include "BluetoothSerial.h"
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif
#if !defined(CONFIG_BT_SPP_ENABLED)
#error Serial Bluetooth not available or not enabled. It is only available for the ESP32 chip.
#endif
BluetoothSerial SerialBT;
//定义LED1管脚
#define LED1 15
char buf[9];
void setup() {
Serial.begin(115200);
SerialBT.begin("ESP32test"); //Bluetooth device name
Serial.println("The device started, now you can pair it with bluetooth!");
//设置LED1引脚为输出模式
pinMode(LED1, OUTPUT);
}
void loop() {
if (Serial.available()) {
SerialBT.write(Serial.read());
}
if (SerialBT.available()) {
// Serial.write(SerialBT.read());
for(u8 i=0;i<9;i++)
{
buf[i]=SerialBT.read();
Serial.print(buf[i]); //串口输出蓝牙接收数据
}
if(buf[0]=='o' && buf[1]=='n')
digitalWrite(LED1, HIGH);//LED1引脚输出高电平,点亮
else if(buf[0]=='o' && buf[1]=='f' && buf[2]=='f')
digitalWrite(LED1, LOW);//LED1引脚输出低电平,熄灭
}
delay(20);
}
改写后的main.ino如下:
/*
Gyro.h 陀螺仪
pwm.h PWM函数
moto_control.h 电机控制
main.ino 主函数
*/
#include "public.h"
#include "moto_control.h"
#include "pwm.h"
#include "Gyro.h"
#include "oled.h"
#include "BluetoothSerial.h"
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif
#if !defined(CONFIG_BT_SPP_ENABLED)
#error Serial Bluetooth not available or not enabled. It is only available for the ESP32 chip.
#endif
//定义LED1管脚
#define LED1 15
BluetoothSerial SerialBT;
char buf[9];
// SSD1306Wire *disp;
//定义全局变量
Adafruit_MPU6050 mpu;//定义陀螺仪 在库管理中搜索adafruit mpu6050
/*L9110S二路电机驱动模块: 供电电压2.5-12V 最大工作电流0.8A 尺寸2.8cm*2.1cm 安装孔直径3mm
本程序中VCC、GND分别接ESP32板VIN、GND
MOTOA的两个接线端子: A1-A A1-B : 10正转 01反转 本程序中定义为: MOTO_A1 MOTO_A2
MOTOB的两个接线端子: B1-A B2-A : 10正转 01反转 本程序中定义为: MOTO_B1 MOTO_B2
*/
void setup() {
//PWM初始化
//pin:引脚号
//chanel:PWM输出通道0-15
//freq:PWM输出频率,单位HZ
//resolution:PWM占空比的分辨率1-16,比如设置8,分辨率范围0-255
pwm_init(MOTO_A1,PWM0,1000,10);
pwm_init(MOTO_A2,PWM1,1000,10);
pwm_init(MOTO_B1,PWM2,1000,10);
pwm_init(MOTO_B2,PWM3,1000,10);
Gyro_init();//初始化陀螺仪
SerialBT.begin("跑跑卡丁车"); //Bluetooth device name
Serial.println("The device started, now you can pair it with bluetooth!");
display_setup();
Serial.println("The device started");
}
void loop() {
/* 通过读数获取新的传感器事件 */
sensors_event_t a, g, temp;
mpu.getEvent(&a, &g, &temp);
/* 打印出值 */
#if 0
Serial.print("加速度 X: ");
Serial.print(a.acceleration.x);
Serial.print(", Y: ");
Serial.print(a.acceleration.y);
Serial.print(", Z: ");
Serial.print(a.acceleration.z);
Serial.println(" m/s^2");
Serial.print("角度 X: ");
Serial.print(g.gyro.x);
Serial.print(", Y: ");
Serial.print(g.gyro.y);
Serial.print("温度: ");
Serial.print(temp.temperature);
Serial.println(" degC");
#endif
Serial.print(", Z: ");
// Serial.println(g.gyro.x);
// SerialBT.write(g.gyro.x);
// Serial.println(g.gyro.y);
Serial.println(g.gyro.z);
//Serial.println(" rad/s");
if (Serial.available()) {
SerialBT.write(Serial.read());
}
if (SerialBT.available()) {
// Serial.write(SerialBT.read());
for(u8 i=0;i<9;i++)
{
buf[i]=SerialBT.read();
Serial.print(buf[i]); //串口输出蓝牙接收数据
}
if(buf[0]=='o' && buf[1]=='n'){
digitalWrite(LED1, HIGH);//LED1引脚输出高电平,点亮
Forward();
}
else if(buf[0]=='o' && buf[1]=='f' && buf[2]=='f'){
digitalWrite(LED1, LOW);//LED1引脚输出低电平,熄灭
Backward();
}
else if(buf[0]=='t' && buf[1]=='r')
{
digitalWrite(LED1, LOW);//LED1引脚输出低电平,熄灭
turn_right();
}
else if(buf[0]=='t' && buf[1]=='l')
{
digitalWrite(LED1, LOW);//LED1引脚输出低电平,熄灭
turn_left();
}
else if(buf[0]=='s' && buf[1]=='t')
{
stop_all();
}
}
drawFontFaceDemo();
// delay(20);
#if 0
//平衡控制 测试能否站住 尝试二轮平衡,简单控制效果不佳,算法暂时没搞 000
if(g.gyro.z<-0.05){
Backward();
}
// delay(10000);
if(g.gyro.z>0.05){
Forward();
}
delay(10);
#endif
}
以上代码中包含了oled显示的,直接注释掉即可。
三、总体测试
网上下载了蓝牙串口SSP,选择键盘模式,设置发送五个字符串:off(前进)、on(后退)、tr(turn right)、tl(turn left)、st(stop),可控制小车实现基本的运动。