RT
手里这块ESP8266是涂鸦的板子,咸鱼上三块一个买了一堆,看ESP8266-12F引脚都差不多的。裸焊了个最小系统,加两个按钮(一个烧录,一个复位)
1. 准备工作
搜索过程中发现 DRV8833四路输入口需要PWM,而8266中的PWM口有4个IO口。但是我看到网上有人说“RSP8266中基本上数字IO都可以作为PWM复用引脚”,我不清楚。
之前我把GPIO15接地了。因为网上一些人说要接地,以及涂鸦文档中有说GPIO15涉及到初始化过程,所以我以为这个引脚是不能用的
试着去掉后,发现可以正常烧录和运行。那就这么着了,反正你引脚都引出来了,我应该可以随便折腾,我也不用wifi功能,至于GPIO15能不能用还得等后续验证。
下面是现在的烧录和复位最小系统图:去掉GPIO15到GND这条线
2. PWM 呼吸灯测试
因为实在RTOS下开发的,所以手册先放上来。esp8266-rtos-sdk PWM
RTOS下也有示例代码:ESP8266_RTOS_SDKexamplesperipheralspwm
PWM重要参数:
频率:1/Ts(周期)
占空比:Ton/Ts
在频率一定时,可通过不同占空比来改变LED亮度,就达到呼吸灯效果了。
#include <stdio.h> #include <string.h> #include <stdlib.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/queue.h" #include "esp_log.h" #include "esp_system.h" #include "esp_err.h" #include "esp8266/gpio_register.h" #include "esp8266/pin_mux_register.h" #include "driver/pwm.h" //#define PWM_0_OUT_IO_NUM 12 //#define PWM_1_OUT_IO_NUM 13 //#define PWM_2_OUT_IO_NUM 14 #define PWM_3_OUT_IO_NUM 15 // PWM period 1000us(1Khz), same as depth // 周期 #define PWM_PERIOD (1000) static const char *TAG = "pwm_example"; // pwm pin number const uint32_t pin_num[1] = { // PWM_0_OUT_IO_NUM, // PWM_1_OUT_IO_NUM, // PWM_2_OUT_IO_NUM, PWM_3_OUT_IO_NUM }; // duties table, real_duty = duties[x]/PERIOD // 占空比 uint32_t duties[1] = { // 10000, 10000, 10000, 500, }; // phase table, delay = (phase[x]/360)*PERIOD // 相位 float phase[1] = { 0 }; // #define configTICK_RATE_HZ 1000 void app_main() { pwm_init(PWM_PERIOD, duties, 1, pin_num); pwm_set_phases(phase); pwm_start(); char flag = 0; uint16_t count = 1; while (1) { if(flag){ count--; }else{ count++; } if(count>=1000){ flag=1; ESP_LOGI(TAG, "PWM 1000n"); }else if(count<=1){ flag = 0; ESP_LOGI(TAG, "PWM 0n"); // 熄灭后停留 vTaskDelay(pdMS_TO_TICKS(300)); } // 设置占空比 pwm_set_duty(0, count); pwm_start(); vTaskDelay(pdMS_TO_TICKS(2)); } }
15号引脚上的PWM呼吸灯如下:
测试PWM的呼吸灯
3. DRV8833 驱动板连接
网上找到接线图,来试试
放在我的电路中的接线图
焊接,焊接完成后,串口信息报错
Fatal exception (0): epc1=0x4013ffff, epc2=0x00000000, epc3=0x00000000, excvaddr=0x00000000, depc=0x00000000
应该是焊的时候碰到以前的引脚了或者新焊接的线影响了运行
重新烧录下程序,烧录按钮按下,按复位毫无反应,排查下问题。
最后发现是GPIO2影响了,因为GPIO2在模块启动的时候如果拉低会启动失败。我也搞不懂为什么现在接的是VCC但是是低电平。和GPIO15换个位置吧。
4. 代码部分
供电
首先GPIO15要供电,输出高电平:
#include "driver/gpio.h" #define GPIO_15 15 void app_main() { // 不是RTOS中的配置方式 // 配置 IO15 为 GPIO功能 // PIN_FUNC_SELECT(PERIPHS_GPIO_MUX_REG(15), FUNC_GPIO15); // 设置高电平 // GPIO_OUTPUT_SET(15, 1); // 配置IO15为输出 gpio_config_t ioConf; ioConf.intr_type = GPIO_INTR_DISABLE; ioConf.mode = GPIO_MODE_OUTPUT; ioConf.pin_bit_mask = (1ULL<<GPIO_15); ioConf.pull_down_en = 0; ioConf.pull_up_en = 0; gpio_config(&ioConf); // 输出高电平 gpio_set_level(GPIO_15, 0);
供电后,驱动板上的LED亮了。
四路PWM输出
#define PWM_0_OUT_IO_NUM 12 #define PWM_1_OUT_IO_NUM 13 #define PWM_2_OUT_IO_NUM 14 #define PWM_3_OUT_IO_NUM 2 // PWM period 1000us(1Khz), same as depth // 周期 #define PWM_PERIOD (1000) // pwm pin number const uint32_t pin_num[4] = { PWM_0_OUT_IO_NUM, PWM_1_OUT_IO_NUM, PWM_2_OUT_IO_NUM, PWM_3_OUT_IO_NUM }; // duties table, real_duty = duties[x]/PERIOD // 占空比 uint32_t duties[4] = { 500, 500, 500, 500, }; // phase table, delay = (phase[x]/360)*PERIOD // 相位 float phase[4] = { 0, 0, 0, 0, }; void app_main() { ... // 配置四路PWM口 pwm_init(PWM_PERIOD, duties, 4, pin_num); pwm_set_phases(phase); pwm_start();
串口日志输出:
gpio: GPIO[15]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [0m gpio: GPIO[2]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [0m gpio: GPIO[12]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [0m gpio: GPIO[13]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [0m gpio: GPIO[14]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [0m pwm: --- PWM v3.4
现在通电后,电机没转动,但是有响声。
是因为驱动方式不对,看看DRV8833的逻辑控制:
现在IO12和IO13都是PWM输出,就会肯定就动不了的。将IO13设为低电平就可以了。
速度不够快,先把占空比调大一些。确实快了。再将频率设置为10Khz,速度相比1Khz好像没提升。如果还想增加转速是不是只能增加电压?现在只是3.3的电压太小了。
不过现在总算是转起来了
以及总览图:
完整代码:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/queue.h" #include "esp_log.h" #include "esp_system.h" #include "esp_err.h" #include "esp8266/gpio_register.h" #include "esp8266/pin_mux_register.h" #include "driver/pwm.h" #include "driver/gpio.h" #define PWM_0_OUT_IO_NUM 12 #define GPIO_15 15 #define GPIO_13 13 // PWM period 1000us(1Khz), same as depth // 周期 1ms=1Khz 100us=10Khz #define PWM_PERIOD (1000) // pwm pin number const uint32_t pin_num[1] = { PWM_0_OUT_IO_NUM, }; // duties table, real_duty = duties[x]/PERIOD // 占空比 uint32_t duties[1] = { 999, }; // phase table, delay = (phase[x]/360)*PERIOD // 相位 float phase[1] = { 0 }; void app_main() { // 配置IO15为输出 gpio_config_t ioConf; ioConf.intr_type = GPIO_INTR_DISABLE; ioConf.mode = GPIO_MODE_OUTPUT; ioConf.pin_bit_mask = (1ULL<<GPIO_15); ioConf.pull_down_en = 0; ioConf.pull_up_en = 0; gpio_config(&ioConf); // 输出高电平 gpio_set_level(GPIO_15, 1); // 配置IO13为输出 ioConf.intr_type = GPIO_INTR_DISABLE; ioConf.mode = GPIO_MODE_OUTPUT; ioConf.pin_bit_mask = (1ULL<<GPIO_13); ioConf.pull_down_en = 0; ioConf.pull_up_en = 0; gpio_config(&ioConf); // 输出高电平 gpio_set_level(GPIO_13, 0); // 配置一路PWM口 pwm_init(PWM_PERIOD, duties, 1, pin_num); pwm_set_phases(phase); pwm_start(); }
其他参考: