目录
前言
笔者有幸在这数月时间参加由山东大学、百度飞桨、海尔·海纳云、中科曙光、四川城乡融合人才培养基金会青少儿教育公益基金共同发起的引航计划实训项目。引航计划是为了普及人工智能通识,培养人工智能人才的人工智能教育计划,共分为六门课程:四门线上课——人工智能应用零基础入门与零代码实战(EasyDL),Python编程入门和数据可视化项目实战,深度学习基础,深度学习高级。两门线下课——无人驾驶综合实训项目,智慧城市综合实训项目。笔者全程参与并结束了前四门课程的线上学习,不论是知识的获取还是引航计划老师们的负责任都让笔者感到收获颇多。很遗憾,由于学习四门线上课时涉及学校课程的学习以及考核,笔者没能及时记录下自己的学习进程。八月至,笔者如愿参加此次为期14天的最后两期线下实训,故记录每日学习进展以及心得,以勉自身。
环境安装及配置
环境需要java,arduino软件,安装好老师在飞桨平台发布的安装包后将后续下载的ino文件默认为arduino打开即可。
认识元器件
引航计划无人驾驶小车所使用的核心器件为基于AI Thinker ESP32-CAM的开发板,实图及详细功能如下:
几个程序
1、控制红灯绿灯交替闪烁
const int led_pin_1 = 32; //灯1接口32(见电路板实物图)
const int led_pin_2 = 33; //灯2接口33
void setup() {
pinMode(led_pin_1, OUTPUT);
pinMode(led_pin_2, OUTPUT);
}
void loop() {
digitalWrite(led_pin_1, LOW); //Write:写 LOW:亮
digitalWrite(led_pin_2, HIGH); //HIGH:灭
delay(100); //持续100ms
digitalWrite(led_pin_1, HIGH);
digitalWrite(led_pin_2, LOW);
delay(100);
}
该程序可实现100ms交替的蓝绿灯转换。效果如下:
红绿灯交替闪烁
2、实现按下按钮时红灯绿灯切换
const int led32 = 32;
const int led33 = 33;
const int button35 = 35;
boolean change = false; // 通过按钮来改变change的值
void setup(){
pinMode(led32,OUTPUT);
pinMode(led33,OUTPUT);
pinMode(button35,INPUT);
Serial.begin(115200);
}
void loop(){
/*while 用来暂停程序,保持button的当前状态,按一下按钮退出循环。*/
while (digitalRead(button35) == HIGH){
}
if (change == true){
digitalWrite(led32,LOW);// 亮
digitalWrite(led33,HIGH);
change = !change;
}else{
digitalWrite(led32,HIGH);// 灭
digitalWrite(led33,LOW);
change = !change;
}
Serial.println(change);
delay(500);
}
/*这一步至关重要,如果没有 while 来暂停程序、等待输入的话,按钮会失灵,
因为loop循环得很快,你在按下按钮的瞬间,程序首先会退出while循环,
然后执行了很多次loop里的程序,所以在你松开按钮时我们不确定loop
运行的循环是亮着的LED还是熄灭的LED*/
该程序可实现按下按钮时实现红绿灯转换。
3、呼吸灯实现
//https://espressif-docs.readthedocs-hosted.com/projects/arduino-esp32/en/latest/api/ledc.html
// servo pwm input pin
const int pwm_pin = 33;
// setting PWM properties
const int freq = 1000; //频率
const int pwm_channel = 0; //通道数(受硬件限制)
const int resolution = 8; //分辨率
void setup() {
// put your setup code here, to run once:
// configure PWM functionalities
ledcSetup(pwm_channel, freq, resolution);
// attach the channel to the GPIO to be controlled
ledcAttachPin(pwm_pin, pwm_channel);
}
void loop() {
// put your main code here, to run repeatedly:
for (int duty_cycle=0; duty_cycle<=255; duty_cycle+=20){
ledcWrite(pwm_channel, duty_cycle);
delay(50);
}
for (int duty_cycle=255; duty_cycle>=0; duty_cycle-=20){
ledcWrite(pwm_channel, duty_cycle);
delay(50);
}
}
该程序可实现红灯由弱变强、由强变弱的呼吸灯效果。
4、电机工作
电机是小车中核心的运动器件。该步需要电源以及电机:
// https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/mcpwm.html#operate
// https://electronics.stackexchange.com/questions/360390/what-is-the-difference-between-mcpwm-and-ledc-pwm
// https://github.com/espressif/esp-idf/blob/master/examples/peripherals/mcpwm/mcpwm_servo_control/main/mcpwm_servo_control_example_main.c
#include "driver/mcpwm.h"
esp_err_t esp_err;
void setup() {
Serial.begin(115200);
mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM0A, 26);
mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM0B, 27);
mcpwm_config_t motor_pwm_config = {
.frequency = 1000,
.cmpr_a = 0,
.cmpr_b = 0,
.duty_mode = MCPWM_DUTY_MODE_0,
.counter_mode = MCPWM_UP_COUNTER,
};
esp_err = mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_0, &motor_pwm_config);
Serial.println(esp_err);
}
void loop() {
// PWM
mcpwm_set_duty(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_OPR_A, 60); //60:活动强度百分比
mcpwm_set_duty(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_OPR_B, 0);
mcpwm_start(MCPWM_UNIT_0, MCPWM_TIMER_0);
delay(2000);
mcpwm_stop(MCPWM_UNIT_0, MCPWM_TIMER_0);
mcpwm_set_duty(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_OPR_A, 0);
mcpwm_set_duty(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_OPR_B, 60);
mcpwm_start(MCPWM_UNIT_0, MCPWM_TIMER_0);
delay(2000);
mcpwm_stop(MCPWM_UNIT_0, MCPWM_TIMER_0);
}
该程序可实现电机60%强度工作,且2000ms后换向。
5、舵机工作
舵机是小车中核心的转动器件:
实物连接图如下:
代码如下:
#include "driver/mcpwm.h"
esp_err_t esp_err;
void setup() {
Serial.begin(115200);
// servo pwm config
mcpwm_gpio_init(MCPWM_UNIT_1, MCPWM1A, 15);
// mcpwm_config_t servo_pwm_config = {
// .frequency = 50,
// .cmpr_a = 0,
// .duty_mode = MCPWM_DUTY_MODE_0,
// .counter_mode = MCPWM_UP_COUNTER,
// };
mcpwm_config_t servo_pwm_config;
servo_pwm_config.frequency = 50;
servo_pwm_config.cmpr_a = 0;
servo_pwm_config.duty_mode = MCPWM_DUTY_MODE_0;
servo_pwm_config.counter_mode = MCPWM_UP_COUNTER;
esp_err = mcpwm_init(MCPWM_UNIT_1, MCPWM_TIMER_1, &servo_pwm_config);
if (esp_err == 0)
Serial.println("Setting motor pwm success!");
else {
Serial.print("Setting motor pwm fail, error code: ");
Serial.println(esp_err);
}
mcpwm_start(MCPWM_UNIT_1, MCPWM_TIMER_1);
}
void loop() {
mcpwm_set_duty(MCPWM_UNIT_1, MCPWM_TIMER_1, MCPWM_OPR_A, 7.5);
delay(1000);
mcpwm_set_duty(MCPWM_UNIT_1, MCPWM_TIMER_1, MCPWM_OPR_A, 2.5);
delay(1000);
mcpwm_set_duty(MCPWM_UNIT_1, MCPWM_TIMER_1, MCPWM_OPR_A, 7.5);
delay(1000);
mcpwm_set_duty(MCPWM_UNIT_1, MCPWM_TIMER_1, MCPWM_OPR_A, 12.5);
delay(1000);
}
该程序可实现舵机的换向运动。
总结
今天主要进行的是无人小车的概论知识学习、环境配备、简单的小灯程序控制以及智能小车运动需要的核心部件——电机和舵机的编程,笔者学到了一些arduino新的函数,进行了第一次小程序的运行,切实体验到了软硬件结合的过程,同时为未来几天的智能小车项目打好了基础。明天我们将进行剩余核心部件的学习以及智能小车的拼装。