5、Pico Robot 机器人课程

5.1 小车前进

注意:电机速度受到电池电量影响,例程是在电池电量较高(电量数值在26000以上)的情况下,如果电池电量较低需要及时充电或者修改电机速度。

一、学习目标

1. 学习树莓派Pico主板和小车扩展板的电机结合进行实验。

2. 了解电机的使用。

二、硬件使用

本次课程使用PICO主板以及小车扩展板的电机,注意,运行例程会让小车向前跑1s,请避免前方有台阶,或者拿起小车以免损坏

image-20220302144157953

在小车的扩展板上我们集成了电机驱动电路,只需要使用PWM即可控制电机方向和转速,通过调整PWM的占空比,高电平时间越长电机速度越快。在电机内部,通过线圈将电流变成磁场,在磁铁的作用下实现电机的转动。

三、程序分析

完整程序位置:Pico Robot配套资料 -> 附件 -> 课程程序源码 -> 3.机器人课程 -> 1.小车前进.py

 
1 from pico_car import pico_car
2 import time
3 
4 Motor = pico_car()
5 #Car forward,parameter(Left motor speed,Right motor speed),speed 0-255
6 Motor.Car_Run(255,255)
7 time.sleep(1)
8 #Car stop
9 Motor.Car_Stop()

 

from pico_car import pico_car

使用pico_car 的pico_car,这是我们封装好的电机驱动库。

import time

“time”库。 这个库处理所有与时间有关的事情,从测量它到将延迟插入到程序中。单位为秒。

Motor = pico_car()

初始化电机驱动。

Motor.Car_Run(255,255)

控制小车前进,速度设置为255,参数分别为(左电机速度,右电机速度),速度范围0-255。

Motor.Car_Stop()

控制小车停止。

四、实验现象

程序下载完成之后,小车会以最大速度向前前进1s,然后停止。

 

5.2 小车花式动作

在上一节,我们实现了小车的前进,在这一节我们会让小车前后左右运行。

注意:电机速度受到电池电量影响,例程是在电池电量较高(电量数值在26000以上)的情况下,如果电池电量较低需要及时充电或者修改电机速度。

一、学习目标

1. 学习树莓派Pico主板和小车扩展板的电机结合进行实验。

2. 了解电机的使用。

二、硬件使用

本次课程使用PICO主板以及小车扩展板的电机,注意,运行例程会让小车前后左右运动,请在空旷的地方,或者拿起小车运行程序,以免损坏

image-20220302144157953

在小车的扩展板上我们集成了电机驱动电路,只需要使用PWM即可控制电机方向和转速,通过调整PWM的占空比,高电平时间越长电机速度越快。在电机内部,通过线圈将电流变成磁场,在磁铁的作用下实现电机的转动。

三、程序分析

完整程序位置:Pico Robot配套资料 -> 附件 -> 课程程序源码 -> 3.机器人课程 -> 2.小车花式动作.py

 
 1 from pico_car import pico_car
 2 import time
 3 
 4 Motor = pico_car()
 5 #Car forward,parameter(Left motor speed,Right motor speed),speed 0-255
 6 Motor.Car_Run(255,255)
 7 time.sleep(1)
 8 #Car back
 9 Motor.Car_Back(255,255)
10 time.sleep(1)
11 #left
12 Motor.Car_Run(0,255)
13 time.sleep(1)
14 #right
15 Motor.Car_Run(255,0)
16 time.sleep(1)
17 #Turn left
18 Motor.Car_Left(255,255)
19 time.sleep(1)
20 #Turn right
21 Motor.Car_Right(255,255)
22 time.sleep(1)
23 #Car stop
24 Motor.Car_Stop()

 

from pico_car import pico_car

使用pico_car 的pico_car,这是我们封装好的电机驱动库。

import time

“time”库。 这个库处理所有与时间有关的事情,从测量它到将延迟插入到程序中。单位为秒。

Motor = pico_car()

初始化电机驱动。

Motor.Car_Run(255,255)

控制小车前进,速度设置为255,参数分别为(左电机速度,右电机速度),速度范围0-255。

Motor.Car_Stop()

控制小车停止。

Motor.Car_Back(255,255)

控制小车后退。

Motor.Car_Run(0,255)

控制小车左转。

Motor.Car_Run(255,0)

控制小车右转。

Motor.Car_Left(255,255)

控制小车左旋。

Motor.Car_Right(255,255)

控制小车右旋。

四、实验现象

程序下载完成之后,小车会以最大速度向前前进1s,然后向后1s,左转1s,右转1s,左旋1s,右旋1s,最后停止。

 

5.3 小车唱歌跳舞

在上一节,我们实现了小车前后左右运行,在这一节我们把运动和3.3节的蜂鸣器音乐播放结合起来。

注意:电机速度受到电池电量影响,例程是在电池电量较高(电量数值在26000以上)的情况下,如果电池电量较低需要及时充电或者修改电机速度。

一、学习目标

1. 学习树莓派Pico主板和小车扩展板的电机、蜂鸣器、可编程RGB灯结合进行实验,在这一节我们会让小车一边运行一边播放音乐。

2. 了解电机和蜂鸣器的使用。

二、硬件使用

本次课程使用PICO主板以及小车扩展板的电机、可编程RGB灯和蜂鸣器,注意,运行例程会让小车前后左右运动,请在空旷的地方,或者拿起小车运行程序,以免损坏

三、程序分析

完整程序位置:Pico Robot配套资料 -> 附件 -> 课程程序源码 -> 3.机器人课程 -> 3.小车唱歌跳舞.py

 
  1 from pico_car import pico_car, ws2812b
  2 import time
  3 from machine import Pin, PWM
  4 
  5 Motor = pico_car()
  6 # set buzzer pin
  7 BZ = PWM(Pin(22))
  8 BZ.freq(1000)
  9 num_leds = 8  # Number of NeoPixels
 10 # Pin where NeoPixels are connected
 11 pixels = ws2812b(num_leds, 0)
 12 # Set all led off
 13 pixels.fill(0,0,0)
 14 pixels.show()
 15 # Initialize music
 16 CM = [0, 330, 350, 393, 441, 495, 556, 624] 
 17 song = [CM[1],CM[1],CM[5],CM[5],CM[6],CM[6],CM[5],
 18         CM[4],CM[4],CM[3],CM[3],CM[2],CM[2],CM[1],]
 19 beat = [ 0.5,0.5,0.5,0.5,0.5,0.5,1,0.5,0.5,0.5,0.5,0.5,0.5,1,]
 20 # music   
 21 def music_Run():
 22     for i in range(0,2):
 23         BZ.duty_u16(500)
 24         BZ.freq(song[i])
 25         time.sleep(beat[i]) 
 26         BZ.duty_u16(0)
 27         time.sleep(0.01)  
 28 def music_Back():
 29     for i in range(2,4):
 30         BZ.duty_u16(500)
 31         BZ.freq(song[i])
 32         time.sleep(beat[i]) 
 33         BZ.duty_u16(0)
 34         time.sleep(0.01)  
 35 def music_Left():
 36     for i in range(4,7):
 37         BZ.duty_u16(500)
 38         BZ.freq(song[i])
 39         time.sleep(beat[i]) 
 40         BZ.duty_u16(0)
 41         time.sleep(0.01) 
 42 def music_Right():
 43     for i in range(7,9):
 44         BZ.duty_u16(500)
 45         BZ.freq(song[i])
 46         time.sleep(beat[i]) 
 47         BZ.duty_u16(0)
 48         time.sleep(0.01) 
 49 def music_TLeft():
 50     for i in range(9,11):
 51         BZ.duty_u16(500)
 52         BZ.freq(song[i])
 53         time.sleep(beat[i]) 
 54         BZ.duty_u16(0)
 55         time.sleep(0.01) 
 56 def music_TRight():
 57     for i in range(11,14):
 58         BZ.duty_u16(500)
 59         BZ.freq(song[i])
 60         time.sleep(beat[i]) 
 61         BZ.duty_u16(0)
 62         time.sleep(0.01) 
 63 #Car forward
 64 Motor.Car_Run(255,255)
 65 for i in range(num_leds):
 66     pixels.set_pixel(i,255,255,0)
 67 pixels.show()
 68 music_Run()
 69 #Car back
 70 Motor.Car_Back(255,255)
 71 for i in range(num_leds):
 72     pixels.set_pixel(i,0,255,255)
 73 pixels.show()
 74 music_Back()
 75 #left
 76 Motor.Car_Run(0,255)
 77 for i in range(num_leds):
 78     pixels.set_pixel(i,255,0,255)
 79 pixels.show()
 80 music_Left()
 81 #right
 82 Motor.Car_Run(255,0)
 83 for i in range(num_leds):
 84     pixels.set_pixel(i,255,0,0)
 85 pixels.show()
 86 music_Right()
 87 #Turn left
 88 Motor.Car_Left(255,255)
 89 for i in range(num_leds):
 90     pixels.set_pixel(i,0,255,0)
 91 pixels.show()
 92 music_TLeft()
 93 #Turn right
 94 Motor.Car_Right(255,255)
 95 for i in range(num_leds):
 96     pixels.set_pixel(i,0,0,255)
 97 pixels.show()
 98 music_TRight()
 99 #Car stop
100 Motor.Car_Stop()
101 for i in range(num_leds):
102     pixels.set_pixel(i,0,0,0)
103 pixels.show()

 

from pico_car import pico_car, ws2812b

使用pico_car 的pico_car和 ws2812b,封装了电机驱动和RGB灯库。

import time

“time”库。 这个库处理所有与时间有关的事情,从测量它到将延迟插入到程序中。单位为秒。

from machine import Pin, PWM

机器库包含MicroPython需要与Pico和其他MicroPython兼容的设备通信的所有指令,扩展了物理计算的语言,这里用了Pin和PWM的库。

Motor = pico_car()

初始化电机驱动。

Motor.Car_Run(255,255)

控制小车前进,速度设置为255,参数分别为(左电机速度,右电机速度),速度范围0-255。

Motor.Car_Stop()

控制小车停止。

Motor.Car_Back(255,255)

控制小车后退。

Motor.Car_Run(0,255)

控制小车左转。

Motor.Car_Run(255,0)

控制小车右转。

Motor.Car_Left(255,255)

控制小车左旋。

Motor.Car_Right(255,255)

控制小车右旋。

pixels = ws2812b(num_leds, 0)

初始化RGB灯,我们有8个RGB灯,这里num_leds设置为8。

pixels.fill(0,0,0)

把所有的灯设置为0,0,0,也就是关闭所有灯,参数分别是(红色,绿色,蓝色),颜色亮度是0-255。

pixels.show()

把设置的灯显示出来。

pixels.set_pixel(i,255,255,0)

使用for循环把所有车灯设置为黄色。

music_Run()

在这个函数中我们把之前蜂鸣器的播放音乐切成6个部分,每一部分分别运行小车不同的动作。

四、实验现象

程序下载完成之后,小车会踩点音乐,先前进并且RGB灯亮黄色,然后后退RGB灯亮青色,左转RGB灯亮紫色,右转RGB灯亮红色,左旋RGB灯亮绿色,右旋RGB灯亮蓝色,最后停止并关闭RGB灯。

image-20220302153955260

 

5.4 巡线小车

在4.3节,我们把巡线传感器的检测结果显示在OLED上,这一节我们将利用巡线传感器来实现控制小车巡线。

注意:巡线传感器会受到光线影响,请在室内无太阳光照的环境下运行程序,以减少太阳光对巡线传感器的干扰。并且在巡线时需保持室内光线充足。

电机速度受到电池电量影响,例程是在电池电量较高(电量数值在26000以上)的情况下,如果电池电量较低需要及时充电或者修改电机速度。

一、学习目标

1. 学习树莓派Pico主板和小车扩展板的电机、OLED、巡线传感器、可编程RGB灯结合实现巡线。

2. 了解如何通过巡线传感器控制小车巡线。

二、硬件使用

本次课程使用PICO主板以及小车扩展板的电机、OLED、巡线传感器、可编程RGB灯,并且需要巡线地图

image-20220302161101679

在程序中我们通过判断每个巡线传感器接收到的数据值,将结果分成七种不同的情况,确定小车的运行状态,从而实现小车巡线。

三、程序分析

完整程序位置:Pico Robot配套资料 -> 附件 -> 课程程序源码 -> 3.机器人课程 -> 4.巡线小车.py

 
  1 from machine import Pin, I2C
  2 from pico_car import pico_car, ws2812b, SSD1306_I2C
  3 import time
  4 
  5 Motor = pico_car()
  6 num_leds = 8  # Number of NeoPixels
  7 # Pin where NeoPixels are connected
  8 pixels = ws2812b(num_leds, 0)
  9 # Set all led off
 10 pixels.fill(0,0,0)
 11 pixels.show()
 12 #initialization oled
 13 i2c=I2C(1, scl=Pin(15),sda=Pin(14), freq=100000)
 14 oled = SSD1306_I2C(128, 32, i2c)
 15 #Define the tracking sensor, 1-4 from left to right
 16 #recognize that black is 0 and white is 1
 17 #Tracing_1 Tracing_2 Tracing_3 Tracing_4
 18 #    2         3        4          5     
 19 Tracing_1 = machine.Pin(2, machine.Pin.IN)
 20 Tracing_2 = machine.Pin(3, machine.Pin.IN)
 21 Tracing_3 = machine.Pin(4, machine.Pin.IN)
 22 Tracing_4 = machine.Pin(5, machine.Pin.IN)
 23 
 24 while True:
 25     
 26     #四路循迹引脚电平状态
 27     #Four channel tracking pin level status
 28     # 0 0 X 0
 29     # 1 0 X 0
 30     # 0 1 X 0
 31     #处理右锐角和右直角的转动
 32     #Handle the rotation of right acute angle and right right right angle
 33     if (Tracing_1.value() == 0 or Tracing_2.value() == 0) and Tracing_4.value() == 0:
 34         Motor.Car_Right(120,120)
 35         for i in range(num_leds):
 36             pixels.set_pixel(i,0,255,0)
 37         oled.text('Turn Right', 0, 0)
 38         #time.sleep(0.08)
 39         
 40     #四路循迹引脚电平状态
 41     #Four channel tracking pin level status
 42     # 0 X 0 0       
 43     # 0 X 0 1 
 44     # 0 X 1 0       
 45     #处理左锐角和左直角的转动
 46     #Handle the rotation of left sharp angle and left right angle
 47     elif Tracing_1.value() == 0 and (Tracing_3.value() == 0 or Tracing_4.value() == 0):
 48         Motor.Car_Left(120,120)
 49         for i in range(num_leds):
 50             pixels.set_pixel(i,0,0,255)
 51         oled.text('Turn Left', 0, 0)
 52         #time.sleep(0.08)
 53         
 54     # 0 X X X
 55     #最左边检测到
 56     #Leftmost detected
 57     elif Tracing_1.value() == 0:
 58         Motor.Car_Left(100,100)
 59         for i in range(num_leds):
 60             pixels.set_pixel(i,0,0,255)
 61         oled.text('Turn Left', 0, 0)
 62     
 63     # X X X 0
 64     #最右边检测到
 65     #Rightmost detected
 66     elif Tracing_4.value() == 0:
 67         Motor.Car_Right(100,100)
 68         for i in range(num_leds):
 69             pixels.set_pixel(i,0,255,0)
 70         oled.text('Turn Right', 0, 0)
 71 
 72     # X 0 1 X
 73     #处理左小弯
 74     #Deal with small left bend
 75     elif Tracing_2.value() == 0 and Tracing_3.value() == 1:
 76         Motor.Car_Run(0,100)
 77         for i in range(num_leds):
 78             pixels.set_pixel(i,0,0,255)
 79         oled.text('Left', 0, 0)
 80 
 81     # X 1 0 X  
 82     #处理右小弯
 83     #Handle small right bend
 84     elif Tracing_2.value() == 1 and Tracing_3.value() == 0:
 85         Motor.Car_Run(100,0)
 86         for i in range(num_leds):
 87             pixels.set_pixel(i,0,255,0)
 88         oled.text('Right', 0, 0)
 89 
 90     # X 0 0 X
 91     #处理直线
 92     #Processing line
 93     elif Tracing_2.value() == 0 and Tracing_3.value() == 0:
 94         Motor.Car_Run(200,200)
 95         for i in range(num_leds):
 96             pixels.set_pixel(i,255,255,255)
 97         oled.text('Run', 0, 0)
 98         
 99     pixels.show()
100     oled.show()
101     oled.fill(0)
102 #其他时小车保持上一个小车运行状态
103 #In other cases, the trolley keeps the previous trolley running

 

from pico_car import pico_car, ws2812b, SSD1306_I2C

使用pico_car 的pico_car、ws2812b、SSD1306_I2C,封装了电机驱动和RGB灯、OLED库。

import time

“time”库。 这个库处理所有与时间有关的事情,从测量它到将延迟插入到程序中。单位为秒。

from machine import Pin, I2C

机器库包含MicroPython需要与Pico和其他MicroPython兼容的设备通信的所有指令,扩展了物理计算的语言,这里用了Pin和I2C的库。

Motor = pico_car()

初始化电机驱动。

pixels = ws2812b(num_leds, 0)

初始化RGB灯,我们有8个RGB灯,这里num_leds设置为8。

pixels.fill(0,0,0)

把所有的灯设置为0,0,0,也就是关闭所有灯,参数分别是(红色,绿色,蓝色),颜色亮度是0-255。

pixels.show()

把设置的灯显示出来。

pixels.set_pixel(i,0,255,0)

使用for循环把所有车灯设置为绿色。

i2c=I2C(1, scl=Pin(15),sda=Pin(14), freq=100000)

设置IIC 1引脚为SCL 15,SDA 14,频率为100000。

oled = SSD1306_I2C(128, 32, i2c)

初始化OLED的大小为128*32,并把前面设置的IIC参数传进去。

oled.text('Turn Right', 0, 0)

设置OLED在0,0的位置显示'Turn Right'。

oled.show()

把设置的OLED内容显示出来。

oled.fill(0)

清除设置的内容,准备下一次显示。

Motor.Car_Run(200,200)

控制小车前进,速度设置为200,参数分别为(左电机速度,右电机速度),速度范围0-255。

Motor.Car_Run(0,100)

控制小车左转。

Motor.Car_Run(100,0)

控制小车右转。

Motor.Car_Left(100,100)

控制小车左旋。

Motor.Car_Right(100,100)

控制小车右旋。

Tracing_1 = machine.Pin(2, machine.Pin.IN)

初始化引脚2作为巡线传感器1的脚,设置为输入。

Tracing_1.value()

Tracing_1.value()函数用来检测对应端口的电平高低。

四、实验现象

程序下载完成之后,小车会巡黑线移动,并且右转时亮绿灯OLED显示'Turn Right',左转时亮蓝灯OLED显示'Turn Left',右旋时亮绿灯OLED显示'Turn Right',左旋时亮蓝灯OLED显示'Turn Left',前进的时候亮白色灯OLED显示'Run'。

image-20220302154012923

注意:巡线传感器会受到光线影响,请在室内无太阳光照的环境下运行程序,以减少太阳光对巡线传感器的干扰。并且在巡线时需保持室内光线充足,如果运行的时候出现偏离黑线,可以通过调节小车的速度、拐弯延时来提高小车的巡线稳定性。

另外配两个传感器版本的程序:Pico Robot配套资料 -> 附件 -> 课程程序源码 -> 3.机器人课程 -> 4.巡线小车-两个传感器版本.py

 

5.5 悬崖检测

在上一节,我们使用巡线传感器完成了小车巡黑线,其实位于小车前方的巡线传感器还有更多的功能,这一节我们就用这些巡线传感器来实现悬崖检测。

注意:巡线传感器会受到光线影响,请在室内无太阳光照的环境下运行程序,以减少太阳光对巡线传感器的干扰。并且在巡线时需保持室内光线充足。

电机速度受到电池电量影响,例程是在电池电量较高(电量数值在26000以上)的情况下,如果电池电量较低需要及时充电或者修改电机速度。

一、学习目标

1. 学习树莓派Pico主板和小车扩展板的电机、OLED、巡线传感器、可编程RGB灯结合实现悬崖检测。

2. 了解如何通过巡线传感器控制小车悬崖检测。

二、硬件使用

本次课程使用PICO主板以及小车扩展板的电机、OLED、巡线传感器、可编程RGB灯,可以将小车放在没有障碍物的桌子上运行程序,检测到桌子边缘的时候,小车会自动后退。

image-20220302160143290

在程序中我们通过判断每个巡线传感器接收到的数据值,在底下是悬崖时,因为巡线传感器接收管无法收到发射管返回的光,所以和识别到黑色一样数值为0,将结果分成三种不同的情况,确定小车的运行状态,从而实现小车悬崖检测。

三、程序分析

完整程序位置:Pico Robot配套资料 -> 附件 -> 课程程序源码 -> 3.机器人课程 -> 5.悬崖检测.py

 
 1 from machine import Pin, I2C
 2 from pico_car import pico_car, ws2812b, SSD1306_I2C
 3 import time
 4 
 5 Motor = pico_car()
 6 num_leds = 8  # Number of NeoPixels
 7 # Pin where NeoPixels are connected
 8 pixels = ws2812b(num_leds, 0)
 9 # Set all led off
10 pixels.fill(0,0,0)
11 pixels.show()
12 #initialization oled
13 i2c=I2C(1, scl=Pin(15),sda=Pin(14), freq=100000)
14 oled = SSD1306_I2C(128, 32, i2c)
15 #Define the tracking sensor, 1-4 from left to right
16 #recognize that black is 0 and white is 1
17 #Tracing_1 Tracing_2 Tracing_3 Tracing_4
18 #    2         3        4          5     
19 Tracing_1 = machine.Pin(2, machine.Pin.IN)
20 Tracing_2 = machine.Pin(3, machine.Pin.IN)
21 Tracing_3 = machine.Pin(4, machine.Pin.IN)
22 Tracing_4 = machine.Pin(5, machine.Pin.IN)
23 
24 while True:
25     
26     #四路循迹引脚电平状态
27     #Four channel tracking pin level status
28     # 0 0 0 X
29     if Tracing_1.value() == 0 and Tracing_2.value() == 0:
30         for i in range(num_leds):
31             pixels.set_pixel(i,255,0,0)
32         oled.text('Cliff', 0, 0)
33         Motor.Car_Back(150,150)
34         time.sleep(0.5)
35         Motor.Car_Right(150,150)
36         time.sleep(0.5)
37         #time.sleep(0.08)
38         
39     #四路循迹引脚电平状态
40     #Four channel tracking pin level status
41     # X 0 0 0
42     elif Tracing_3.value() == 0 and Tracing_4.value() == 0:
43         for i in range(num_leds):
44             pixels.set_pixel(i,255,0,0)
45         oled.text('Cliff', 0, 0)
46         Motor.Car_Back(150,150)
47         time.sleep(0.5)
48         Motor.Car_Left(150,150)
49         time.sleep(0.5)
50         #time.sleep(0.08)
51       
52     else:
53         Motor.Car_Run(100,100)
54         for i in range(num_leds):
55             pixels.set_pixel(i,255,255,255)
56         oled.fill(0)
57         
58     pixels.show()
59     oled.show()
60 #其他时小车保持上一个小车运行状态
61 #In other cases, the trolley keeps the previous trolley running

 

from pico_car import pico_car, ws2812b, SSD1306_I2C

使用pico_car 的pico_car、ws2812b、SSD1306_I2C,封装了电机驱动和RGB灯、OLED库。

import time

“time”库。 这个库处理所有与时间有关的事情,从测量它到将延迟插入到程序中。单位为秒。

from machine import Pin, I2C

机器库包含MicroPython需要与Pico和其他MicroPython兼容的设备通信的所有指令,扩展了物理计算的语言,这里用了Pin和I2C的库。

Motor = pico_car()

初始化电机驱动。

pixels = ws2812b(num_leds, 0)

初始化RGB灯,我们有8个RGB灯,这里num_leds设置为8。

pixels.fill(0,0,0)

把所有的灯设置为0,0,0,也就是关闭所有灯,参数分别是(红色,绿色,蓝色),颜色亮度是0-255。

pixels.show()

把设置的灯显示出来。

pixels.set_pixel(i,255,0,0)

使用for循环把所有车灯设置为红色。

i2c=I2C(1, scl=Pin(15),sda=Pin(14), freq=100000)

设置IIC 1引脚为SCL 15,SDA 14,频率为100000。

oled = SSD1306_I2C(128, 32, i2c)

初始化OLED的大小为128*32,并把前面设置的IIC参数传进去。

oled.text('Cliff', 0, 0)

设置OLED在0,0的位置显示'Cliff'。

oled.show()

把设置的OLED内容显示出来。

oled.fill(0)

清除设置的内容,准备下一次显示。

Motor.Car_Run(100,100)

控制小车前进,速度设置为100,参数分别为(左电机速度,右电机速度),速度范围0-255。

Motor.Car_Back(255,255)

控制小车后退。

Motor.Car_Left(255,255)

控制小车左旋。

Motor.Car_Right(255,255)

控制小车右旋。

Tracing_1 = machine.Pin(2, machine.Pin.IN)

初始化引脚2作为巡线传感器1的脚,设置为输入。

Tracing_1.value()

Tracing_1.value()函数用来检测对应端口的电平高低。

四、实验现象

程序下载完成之后,小车遇到悬崖时,当传感器1和2检测到悬崖时,小车亮红色灯后退然后右旋,OLED显示'Cliff',当传感器3和4检测到悬崖时,小车亮红色灯后退然后左旋,OLED显示'Cliff',其他情况小车亮白色灯前进。

image-20220302161214551

注意:巡线传感器会受到光线影响,请在室内无太阳光照的环境下运行程序,以减少太阳光对巡线传感器的干扰。并且在巡线时需保持室内光线充足,如果运行的时候出现无法及时停住的情况,可以通过调节小车的速度来提高稳定性。

 

5.6 超声波避障

在4.4节,我们使用超声波传感器进行测距,并把结果显示在OLED上,在这一节,我们利用这个测距结果来实现超声波避障。

注意:电机速度受到电池电量影响,例程是在电池电量较高(电量数值在26000以上)的情况下,如果电池电量较低需要及时充电或者修改电机速度。

一、学习目标

1. 学习树莓派Pico主板和小车扩展板的电机、OLED、超声波传感器、可编程RGB灯、蜂鸣器结合实现超声波避障。

2. 了解如何通过超声波传感器实现避障。

二、硬件使用

本次课程使用PICO主板以及小车扩展板的电机、OLED、超声波传感器、可编程RGB灯、蜂鸣器,可以将小车放在地上,地面障碍物不要太密集,小车遇到障碍物会自动后退。

image-20220302162747138

在程序中我们通过读取超声波传感器数值,对不同的距离数值做出不同的动作。

三、程序分析

完整程序位置:Pico Robot配套资料 -> 附件 -> 课程程序源码 -> 3.机器人课程 -> 6.超声波避障.py

 
 1 import time
 2 from machine import Pin, I2C, PWM
 3 from pico_car import SSD1306_I2C, ultrasonic, pico_car, ws2812b
 4 
 5 Motor = pico_car()
 6 Motor.Car_Stop()
 7 num_leds = 8  # Number of NeoPixels
 8 # Pin where NeoPixels are connected
 9 pixels = ws2812b(num_leds, 0)
10 pixels.fill(0,0,0)
11 pixels.show()
12 # set buzzer pin
13 BZ = PWM(Pin(22))
14 BZ.freq(1000)
15 # Initialize music
16 CM = [0, 330, 350, 393, 441, 495, 556, 624]
17 #initialization ultrasonic
18 ultrasonic = ultrasonic()
19 #initialization oled
20 i2c=I2C(1, scl=Pin(15),sda=Pin(14), freq=100000)
21 oled = SSD1306_I2C(128, 32, i2c)
22 
23 while True:
24     #get distance
25     distance = ultrasonic.Distance_accurate()
26     print("distance is %d cm"%(distance) )
27     #display distance
28     oled.text('distance:', 0, 0)
29     oled.text(str(distance), 75, 0)
30     oled.show()
31     oled.fill(0)
32     #Control action
33     if distance < 10:
34         for i in range(num_leds):
35             pixels.set_pixel(i,255,0,0)
36         pixels.show()
37         Motor.Car_Back(150,150)
38         BZ.duty_u16(500)
39         BZ.freq(CM[7])
40         time.sleep(0.2)
41         Motor.Car_Right(150,150)
42         BZ.duty_u16(500)
43         BZ.freq(CM[5])
44         time.sleep(0.2)
45         BZ.duty_u16(0)
46     elif distance >= 10 and distance < 30:
47         for i in range(num_leds):
48             pixels.set_pixel(i,255,255,0)
49         pixels.show()
50         Motor.Car_Run(100,100)
51     else:
52         for i in range(num_leds):
53             pixels.set_pixel(i,0,255,0)
54         pixels.show()
55         Motor.Car_Run(100,100)
56     time.sleep(0.1)

 

from pico_car import SSD1306_I2C, ultrasonic, pico_car, ws2812b

使用pico_car 的SSD1306_I2C、ultrasonic、pico_car、ws2812b,封装了电机驱动和RGB灯、OLED、超声波库。

import time

“time”库。 这个库处理所有与时间有关的事情,从测量它到将延迟插入到程序中。单位为秒。

from machine import Pin, I2C, PWM

机器库包含MicroPython需要与Pico和其他MicroPython兼容的设备通信的所有指令,扩展了物理计算的语言,这里用了Pin、PWM和I2C的库。

Motor = pico_car()

初始化电机驱动。

pixels = ws2812b(num_leds, 0)

初始化RGB灯,我们有8个RGB灯,这里num_leds设置为8。

pixels.fill(0,0,0)

把所有的灯设置为0,0,0,也就是关闭所有灯,参数分别是(红色,绿色,蓝色),颜色亮度是0-255。

pixels.show()

把设置的灯显示出来。

pixels.set_pixel(i,255,0,0)

使用for循环把所有车灯设置为红色。

i2c=I2C(1, scl=Pin(15),sda=Pin(14), freq=100000)

设置IIC 1引脚为SCL 15,SDA 14,频率为100000。

oled = SSD1306_I2C(128, 32, i2c)

初始化OLED的大小为128*32,并把前面设置的IIC参数传进去。

oled.show()

把设置的OLED内容显示出来。

oled.fill(0)

清除设置的内容,准备下一次显示。

Motor.Car_Run(100,100)

控制小车前进,速度设置为150,参数分别为(左电机速度,右电机速度),速度范围0-255。

Motor.Car_Back(150,150)

控制小车后退。

Motor.Car_Right(150,150)

控制小车右旋。

Motor.Car_Stop()

控制小车停止。

BZ = PWM(Pin(22))

将IO22设置为PWM输出引脚,用于控制蜂鸣器。

BZ.freq(1000)

将PWM频率设置为1000。

BZ.duty_u16(0)

数值为0的时候关闭声音,为500的时候开启声音。

ultrasonic = ultrasonic()

初始化超声波测距。

distance = ultrasonic.Distance_accurate()

将超声波测距返回的数值,赋值给变量distance 。

oled.text(str(distance), 75, 0)

将距离转换为字符串,显示在OLED的75,0位置上。

四、实验现象

程序下载完成之后,我们可以看到OLED显示 'distance: ' 和测量出来的距离,数值会根据测量结果改变,同时Shell也会显示测量的距离,当距离小于10(遇到障碍物),RGB灯亮红色,小车后退右旋,同时蜂鸣器发出“滴滴”声;当距离在10-30之间,RGB灯亮黄色,小车前进;当距离超过30,RGB灯亮绿色,小车前进。

image-20220302162817422

注意,超声波最短测量距离在2-3cm,程序中使用10cm的距离进行避障,如果障碍物过密集,可以修改这个数值。

 

5.7 超声波跟随

在上一节,我们使用超声波传感器进行测距,实现了超声波避障,在这一节我们换一种用法,使用超声波来实现跟随。

注意:电机速度受到电池电量影响,例程是在电池电量较高(电量数值在26000以上)的情况下,如果电池电量较低需要及时充电或者修改电机速度。

一、学习目标

1. 学习树莓派Pico主板和小车扩展板的电机、OLED、超声波传感器、可编程RGB灯、蜂鸣器结合实现超声波跟随。

2. 了解如何通过超声波传感器实现跟随。

二、硬件使用

本次课程使用PICO主板以及小车扩展板的电机、OLED、超声波传感器、可编程RGB灯、蜂鸣器,可以将小车放在空旷的地面上,如果有障碍物可能会影响跟随效果。

image-20220302165728937

在程序中我们通过读取超声波传感器数值,对不同的距离数值做出不同的动作。

三、程序分析

完整程序位置:Pico Robot配套资料 -> 附件 -> 课程程序源码 -> 3.机器人课程 -> 7.超声波跟随.py

 
  1 import time
  2 from machine import Pin, I2C, PWM
  3 from pico_car import SSD1306_I2C, ultrasonic, pico_car, ws2812b
  4 
  5 Motor = pico_car()
  6 Motor.Car_Stop()
  7 num_leds = 8  # Number of NeoPixels
  8 # Pin where NeoPixels are connected
  9 pixels = ws2812b(num_leds, 0)
 10 pixels.fill(0,0,0)
 11 pixels.show()
 12 # set buzzer pin
 13 BZ = PWM(Pin(22))
 14 BZ.freq(1000)
 15 # Initialize music
 16 CM = [0, 330, 350, 393, 441, 495, 556, 624]
 17 song = [CM[1],CM[1],CM[5],CM[5],CM[6],CM[6],CM[5],CM[4],CM[4],CM[3],CM[3],CM[2],CM[2],CM[1],]
 18 beat = [ 0.5,0.5,0.5,0.5,0.5,0.5,1,0.5,0.5,0.5,0.5,0.5,0.5,1,]
 19 #initialization ultrasonic
 20 ultrasonic = ultrasonic()
 21 #initialization oled
 22 i2c=I2C(1, scl=Pin(15),sda=Pin(14), freq=100000)
 23 oled = SSD1306_I2C(128, 32, i2c)
 24 #Define variables
 25 global time_ul, music_i, t_turn, i_turn, t_turn, music_back
 26 music_i = 0
 27 time_ul = 0
 28 i_run = 0
 29 i_turn = 0
 30 t_turn = 0
 31 music_back = 0
 32 
 33 while True:
 34     #get distance
 35     distance = ultrasonic.Distance_accurate()
 36     print("distance is %d cm"%(distance) )
 37     #display distance
 38     oled.text('distance:', 0, 0)
 39     oled.text(str(distance), 75, 0)
 40     oled.show()
 41     oled.fill(0)
 42     #Control action
 43     if distance < 9:
 44         for i in range(num_leds):
 45             pixels.set_pixel(i,255,0,0)
 46         pixels.show()
 47         Motor.Car_Back(100,100)
 48         if music_back < 5:
 49             BZ.duty_u16(500)
 50             BZ.freq(624)
 51         else:
 52             BZ.duty_u16(0)
 53     elif distance >= 9 and distance < 20:
 54         if i_run == 0:
 55             pixels.set_pixel(6,0,0,0)
 56             pixels.set_pixel(7,0,0,0)
 57             pixels.set_pixel(2,150,0,150)
 58             pixels.set_pixel(3,150,0,150)
 59             i_run = 1
 60         elif i_run == 1:
 61             pixels.set_pixel(2,0,0,0)
 62             pixels.set_pixel(3,0,0,0)
 63             pixels.set_pixel(1,150,0,150)
 64             pixels.set_pixel(4,150,0,150)
 65             i_run = 2
 66         elif i_run == 2:
 67             pixels.set_pixel(1,0,0,0)
 68             pixels.set_pixel(4,0,0,0)
 69             pixels.set_pixel(0,150,0,150)
 70             pixels.set_pixel(5,150,0,150)
 71             i_run = 3
 72         elif i_run == 3:
 73             pixels.set_pixel(0,0,0,0)
 74             pixels.set_pixel(5,0,0,0)
 75             pixels.set_pixel(6,150,0,150)
 76             pixels.set_pixel(7,150,0,150)
 77             i_run = 4
 78         elif i_run == 4:
 79             pixels.set_pixel(0,0,0,0)
 80             pixels.set_pixel(5,0,0,0)
 81             pixels.set_pixel(6,150,0,150)
 82             pixels.set_pixel(7,150,0,150)
 83             i_run = 0
 84         pixels.show()
 85         Motor.Car_Run(100,100)
 86         BZ.duty_u16(500)
 87         BZ.freq(song[music_i])
 88         time.sleep(beat[music_i]/2)
 89         BZ.duty_u16(0)  
 90             
 91     else:
 92         BZ.duty_u16(0)
 93         if i_turn == 0:
 94             pixels.set_pixel(7,0,0,0)
 95             pixels.set_pixel(0,0,150,150)
 96         else:
 97             pixels.set_pixel(i_turn-1,0,0,0)
 98             pixels.set_pixel(i_turn,0,150,150)
 99         pixels.show()
100         if t_turn < 5:
101             Motor.Car_Right(120,120)
102         elif t_turn >= 5 and t_turn < 10:
103             Motor.Car_Left(120,120)
104           
105     time_ul = time_ul + 1
106     music_i = music_i + 1
107     if music_i >= len(song):
108         music_i = 0
109     i_turn = i_turn + 1
110     if i_turn == 8:
111         i_turn = 0
112     t_turn = t_turn + 1
113     if t_turn >= 10:
114         t_turn = 0
115     music_back = music_back + 1
116     if music_back >= 10:
117         music_back = 0
118     time.sleep(0.01)

 

在这个程序里做了RGB灯效,前进的时候会一边播放音乐一边流水灯,旋转寻找跟随目标的时候也有流水灯效果,在单线程只能顺序执行的程序里要实现同时运行多种效果,就需要把音乐、流水灯、小车运行切成一小块一小块,每一小块中都包含音乐、流水灯、小车运行的片段,所以我们在程序里做了多个变量来实现这种效果。

from pico_car import SSD1306_I2C, ultrasonic, pico_car, ws2812b

使用pico_car 的SSD1306_I2C、ultrasonic、pico_car、ws2812b,封装了电机驱动和RGB灯、OLED、超声波库。

import time

“time”库。 这个库处理所有与时间有关的事情,从测量它到将延迟插入到程序中。单位为秒。

from machine import Pin, I2C, PWM

机器库包含MicroPython需要与Pico和其他MicroPython兼容的设备通信的所有指令,扩展了物理计算的语言,这里用了Pin、PWM和I2C的库。

Motor = pico_car()

初始化电机驱动。

pixels = ws2812b(num_leds, 0)

初始化RGB灯,我们有8个RGB灯,这里num_leds设置为8。

pixels.fill(0,0,0)

把所有的灯设置为0,0,0,也就是关闭所有灯,参数分别是(红色,绿色,蓝色),颜色亮度是0-255。

pixels.show()

把设置的灯显示出来。

pixels.set_pixel(i,255,0,0)

使用for循环把所有车灯设置为红色。

i2c=I2C(1, scl=Pin(15),sda=Pin(14), freq=100000)

设置IIC 1引脚为SCL 15,SDA 14,频率为100000。

oled = SSD1306_I2C(128, 32, i2c)

初始化OLED的大小为128*32,并把前面设置的IIC参数传进去。

oled.show()

把设置的OLED内容显示出来。

oled.fill(0)

清除设置的内容,准备下一次显示。

Motor.Car_Run(100,100)

控制小车前进,速度设置为100,参数分别为(左电机速度,右电机速度),速度范围0-255。

Motor.Car_Back(100,100)

控制小车后退。

Motor.Car_Left(120,120)

控制小车左旋。

Motor.Car_Right(120,120)

控制小车右旋。

Motor.Car_Stop()

控制小车停止。

BZ = PWM(Pin(22))

将IO22设置为PWM输出引脚,用于控制蜂鸣器。

BZ.freq(1000)

将PWM频率设置为1000。

BZ.duty_u16(0)

数值为0的时候关闭声音,为500的时候开启声音。

ultrasonic = ultrasonic()

初始化超声波测距。

distance = ultrasonic.Distance_accurate()

将超声波测距返回的数值,赋值给变量distance 。

oled.text(str(distance), 75, 0)

将距离转换为字符串,显示在OLED的75,0位置上。

四、实验现象

程序下载完成之后,我们可以看到OLED显示 'distance: ' 和测量出来的距离,数值会根据测量结果改变,同时Shell也会显示测量的距离,当距离小于9(距离跟随物体过近),RGB灯亮红色,小车后退,同时蜂鸣器发出“滴滴”声;当距离在9-20之间,RGB灯以两个为一组,亮紫色流水灯,小车前进,并且同时播放音乐;当距离超过20,RGB灯亮青色流水灯,小车右旋左旋寻找跟随物体。

image-20220302165856033

注意,超声波最短测量距离在2-3cm,如果跟随效果不好,可以适当修改距离,或者修改小车运行速度。

 

5.8 寻光跟随

在4.1节,我们使用光敏传感器检测光线强度,并把结果显示在OLED上,在这一节,我们利用这个光线强度结果来实现寻光跟随。

注意,寻光受到环境光线影响,请在室内光线变化不大或者较暗的地方使用。

电机速度受到电池电量影响,例程是在电池电量较高(电量数值在26000以上)的情况下,如果电池电量较低需要及时充电或者修改电机速度。

一、学习目标

1. 学习树莓派Pico主板和小车扩展板的电机、OLED、光敏传感器、可编程RGB灯结合实现小车寻光。

2. 了解小车寻光的实现。

二、硬件使用

本次课程使用PICO主板以及小车扩展板的电机、OLED、光敏传感器、可编程RGB灯,小车放在前方没有障碍物的空旷位置,运行之前请把跳线帽接到Light排针,准备好光源(手电筒或手机的相机灯)。

image-20220302165728937

image-20220302122626662

在程序中我们通过读取两个光敏传感器的数值,比较两个数值大小,判断光源位置,从而控制小车寻光。

三、程序分析

完整程序位置:Pico Robot配套资料 -> 附件 -> 课程程序源码 -> 3.机器人课程 -> 8.寻光跟随.py

 
 1 import time
 2 from machine import Pin, I2C, PWM, ADC
 3 from pico_car import SSD1306_I2C, pico_car, ws2812b
 4 
 5 Motor = pico_car()
 6 Motor.Car_Stop()
 7 num_leds = 8  # Number of NeoPixels
 8 # Pin where NeoPixels are connected
 9 pixels = ws2812b(num_leds, 0)
10 pixels.fill(0,0,0) 
11 pixels.show()
12 #Light1 -> GP27
13 #Light2 -> GP26
14 light1 = machine.ADC(27)
15 light2 = machine.ADC(26)
16 #initialization oled
17 i2c=I2C(1, scl=Pin(15),sda=Pin(14), freq=100000)
18 oled = SSD1306_I2C(128, 32, i2c)
19 light_down = 0.9
20 light_up = 1.1
21 
22 while True:
23     #get value
24     LightS1 = light1.read_u16()
25     LightS2 = light2.read_u16()
26     print("light1 is %d"%(LightS1) )
27     print("light2 is %d"%(LightS2) )
28     #Display sound on OLED
29     oled.text('Light1:', 0, 0)
30     oled.text(str(LightS1), 60, 0)
31     oled.text('Light2:', 0, 10)
32     oled.text(str(LightS2), 60, 10)
33     #Control action
34     if LightS1 > (LightS2*light_down) and LightS1 < (LightS2*light_up):
35         Motor.Car_Run(120,120)
36         for i in range(num_leds):
37             pixels.set_pixel(i,150,150,150)
38         pixels.show()
39     elif LightS2 > (LightS1*light_down) and LightS2 < (LightS1*light_up):
40         Motor.Car_Run(120,120)
41         for i in range(num_leds):
42             pixels.set_pixel(i,150,150,150)
43         pixels.show()
44     elif LightS1 > (LightS2*light_up) or LightS2 < (LightS1*light_down):
45         Motor.Car_Run(120,0)
46         pixels.fill(0,0,0) 
47         pixels.set_pixel(0,150,0,150)
48         pixels.set_pixel(1,150,0,150)
49         pixels.set_pixel(2,150,0,150)
50         pixels.set_pixel(7,150,0,150)
51         pixels.show()
52     elif LightS2 > (LightS1*light_up) or LightS1 < (LightS2*light_down):
53         Motor.Car_Run(0,120)
54         pixels.fill(0,0,0) 
55         pixels.set_pixel(3,150,0,150)
56         pixels.set_pixel(4,150,0,150)
57         pixels.set_pixel(5,150,0,150)
58         pixels.set_pixel(6,150,0,150)
59         pixels.show()
60     else:
61         Motor.Car_Stop()
62     oled.show()
63     oled.fill(0)
64     time.sleep(0.01)

 

from pico_car import SSD1306_I2C, pico_car, ws2812b

使用pico_car 的SSD1306_I2C、pico_car、ws2812b,封装了电机驱动和RGB灯、OLED库。

import time

“time”库。 这个库处理所有与时间有关的事情,从测量它到将延迟插入到程序中。单位为秒。

from machine import Pin, I2C, ADC, PWM

机器库包含MicroPython需要与Pico和其他MicroPython兼容的设备通信的所有指令,扩展了物理计算的语言,这里用了Pin、PWM、ADC和I2C的库。

Motor = pico_car()

初始化电机驱动。

pixels = ws2812b(num_leds, 0)

初始化RGB灯,我们有8个RGB灯,这里num_leds设置为8。

pixels.fill(0,0,0)

把所有的灯设置为0,0,0,也就是关闭所有灯,参数分别是(红色,绿色,蓝色),颜色亮度是0-255。

pixels.show()

把设置的灯显示出来。

pixels.set_pixel(0,150,0,150)

设置第一个车灯为紫色。

i2c=I2C(1, scl=Pin(15),sda=Pin(14), freq=100000)

设置IIC 1引脚为SCL 15,SDA 14,频率为100000。

oled = SSD1306_I2C(128, 32, i2c)

初始化OLED的大小为128*32,并把前面设置的IIC参数传进去。

Motor.Car_Run(120,120)

控制小车前进,速度设置为120,参数分别为(左电机速度,右电机速度),速度范围0-255。

Motor.Car_Stop()

控制小车停止。

light1 = machine.ADC(27)

初始化ADC端口27,光敏传感器一共两个,分别设置了27和26脚。

oled.text(str(LightS1), 60, 0)

将光敏的值转换成字符串显示在OLED的60,0位置。

oled.show()

把设置的OLED内容显示出来。

oled.fill(0)

清除设置的内容,准备下一次显示。

LightS1 = light1.read_u16()

light1.read_u16()函数用来检测声音传感器的值,赋值给变量LightS1。

四、实验现象

程序下载完成之后,我们可以看到OLED第一行显示光敏传感器1的值 ,第二行显示光敏传感器2的值,同时Shell也会打印光敏传感器数值,使用手电筒对着小车前方左右移动,可以控制小车左右运动。

image-20220302172725024

因为光敏传感器容易受到环境光线影响,请在室内光线变化不大或者较暗的地方使用,若寻光效果不好,可以适当调整检测范围,即变量light_down和light_up。

 

5.9 声控小车

在4.2节,我们使用声音传感器进行声音检测,在这一节我们将用检测的声音控制小车。

注意:为了防止误触发,声音传感器设置的检测基准值较大,识别效果不好的话可以适当修改检测基准值,或者对声音传感器吹气来触发。

电机速度受到电池电量影响,例程是在电池电量较高(电量数值在26000以上)的情况下,如果电池电量较低需要及时充电或者修改电机速度。

一、学习目标

1. 学习树莓派Pico主板和小车扩展板的电机、OLED、声音传感器、可编程RGB灯、蜂鸣器结合实现声控小车。

2. 了解声控小车的实现。

二、硬件使用

本次课程使用PICO主板以及小车扩展板的电机、OLED、声音传感器、可编程RGB灯、蜂鸣器,小车放在前方没有障碍物的空旷位置,运行之前请把跳线帽接到Voice排针

image-20220302165728937

image-20220302110753097

在程序中我们通过读取声音的数值,当数值超过基准时,控制小车运行一段时间。

三、程序分析

完整程序位置:Pico Robot配套资料 -> 附件 -> 课程程序源码 -> 3.机器人课程 -> 9.声控小车.py

 
 1 from pico_car import SSD1306_I2C, pico_car, ws2812b
 2 from machine import Pin, I2C, ADC, PWM
 3 import time
 4 
 5 Motor = pico_car()
 6 Motor.Car_Stop()
 7 num_leds = 8  # Number of NeoPixels
 8 # Pin where NeoPixels are connected
 9 pixels = ws2812b(num_leds, 0)
10 pixels.fill(0,0,0)
11 pixels.show()
12 # set buzzer pin
13 BZ = PWM(Pin(22))
14 BZ.freq(1000)
15 CM = [0, 330, 350, 393, 441, 495, 556, 624]
16 #initialization oled
17 i2c=I2C(1, scl=Pin(15),sda=Pin(14), freq=100000)
18 oled = SSD1306_I2C(128, 32, i2c)
19 #initialization ADC
20 Sound = machine.ADC(27)
21 
22 while True:
23     #get value
24     sounds = Sound.read_u16()
25     print(sounds)
26     oled.text('Sound:', 0, 0)
27     oled.text(str(sounds), 50, 0)
28     #Control action
29     if sounds > 20000:
30         while sounds > 10000:
31             Motor.Car_Stop()
32             sounds = Sound.read_u16()
33             print(sounds)
34             time.sleep(0.001)
35         Motor.Car_Run(255,255)
36         BZ.duty_u16(500)
37         BZ.freq(CM[1])
38         pixels.set_pixel(2,150,0,150)
39         pixels.set_pixel(3,150,0,150)
40         pixels.show()
41         time.sleep(0.03)
42         BZ.duty_u16(500)
43         BZ.freq(CM[2])
44         pixels.set_pixel(2,0,0,0)
45         pixels.set_pixel(3,0,0,0)
46         pixels.set_pixel(1,150,0,150)
47         pixels.set_pixel(4,150,0,150)
48         pixels.show()
49         time.sleep(0.03)
50         BZ.duty_u16(500)
51         BZ.freq(CM[3])
52         pixels.set_pixel(1,0,0,0)
53         pixels.set_pixel(4,0,0,0)
54         pixels.set_pixel(0,150,0,150)
55         pixels.set_pixel(5,150,0,150)
56         pixels.show()
57         time.sleep(0.03)
58         BZ.duty_u16(500)
59         BZ.freq(CM[4])
60         pixels.set_pixel(0,0,0,0)
61         pixels.set_pixel(5,0,0,0)
62         pixels.set_pixel(6,150,0,150)
63         pixels.set_pixel(7,150,0,150)
64         pixels.show()
65         time.sleep(0.03)
66         BZ.duty_u16(500)
67         BZ.freq(CM[5])
68         pixels.set_pixel(0,0,0,0)
69         pixels.set_pixel(5,0,0,0)
70         pixels.set_pixel(6,150,0,150)
71         pixels.set_pixel(7,150,0,150)
72         pixels.show()
73         time.sleep(0.03)
74         BZ.duty_u16(500)
75         BZ.freq(CM[6])
76         pixels.set_pixel(6,0,0,0)
77         pixels.set_pixel(7,0,0,0)
78         pixels.show()
79         BZ.duty_u16(0)
80         sounds = 0
81         oled.show()
82         oled.fill(0)
83     else:
84         Motor.Car_Stop()
85         oled.show()
86         oled.fill(0)
87     time.sleep(0.01)

 

声音传感器检测值会受到电池电量的影响,建议先测试再调整比较值,测试的时候建议关闭电机、RGB灯等功耗较高的负载,在程序中检测基准值(30000)之后,防止小车前进时间过长,使用一个while过滤掉多余的数值保证一次检测只执行一次前进。

from pico_car import SSD1306_I2C, pico_car, ws2812b

使用pico_car 的SSD1306_I2C、pico_car、ws2812b,封装了电机驱动和RGB灯、OLED库。

import time

“time”库。 这个库处理所有与时间有关的事情,从测量它到将延迟插入到程序中。单位为秒。

from machine import Pin, I2C, ADC, PWM

机器库包含MicroPython需要与Pico和其他MicroPython兼容的设备通信的所有指令,扩展了物理计算的语言,这里用了Pin、PWM、ADC和I2C的库。

Motor = pico_car()

初始化电机驱动。

pixels = ws2812b(num_leds, 0)

初始化RGB灯,我们有8个RGB灯,这里num_leds设置为8。

pixels.fill(0,0,0)

把所有的灯设置为0,0,0,也就是关闭所有灯,参数分别是(红色,绿色,蓝色),颜色亮度是0-255。

pixels.show()

把设置的灯显示出来。

pixels.set_pixel(i,255,0,0)

使用for循环把所有车灯设置为红色。

i2c=I2C(1, scl=Pin(15),sda=Pin(14), freq=100000)

设置IIC 1引脚为SCL 15,SDA 14,频率为100000。

oled = SSD1306_I2C(128, 32, i2c)

初始化OLED的大小为128*32,并把前面设置的IIC参数传进去。

oled.show()

把设置的OLED内容显示出来。

oled.fill(0)

清除设置的内容,准备下一次显示。

Motor.Car_Run(150,150)

控制小车前进,速度设置为150,参数分别为(左电机速度,右电机速度),速度范围0-255。

Motor.Car_Stop()

控制小车停止。

BZ = PWM(Pin(22))

将IO22设置为PWM输出引脚,用于控制蜂鸣器。

BZ.freq(1000)

将PWM频率设置为1000。

BZ.duty_u16(0)

数值为0的时候关闭声音,为500的时候开启声音。

oled.text(str(sounds), 50, 0)

将距离转换为字符串,显示在OLED的50,0位置上。

Sound = machine.ADC(27)

初始化ADC端口27。

sounds = Sound.read_u16()

Sound.read_u16()函数用来检测声音传感器的值,赋值给变量sounds。

四、实验现象

程序下载完成之后,我们可以看到OLED第一行显示 Sound的值 ,对着声音传感器吹气小车会一边鸣笛一边前进一段距离,同时底下有流水灯效果,同时Shell也会打印声音传感器数值。

image-20220302174524312

 

5.10 红外控制

在4.5节,我们学习了如何接收红外遥控器的值并显示在OLED上,在这一节我们使用红外遥控来实现小车的多种控制。

注意:电机速度受到电池电量影响,例程是在电池电量较高(电量数值在26000以上)的情况下,如果电池电量较低需要及时充电或者修改电机速度。

一、学习目标

1. 学习树莓派Pico主板和小车扩展板的电机、OLED、红外接收、可编程RGB灯、蜂鸣器结合实现红外遥控。

2. 了解如何通过红外遥控控制小车。

二、硬件使用

本次课程使用PICO主板以及小车扩展板的电机、OLED、红外接收、可编程RGB灯、蜂鸣器,可以将小车放在空旷的地面上,在这个例程里我们还需要使用红外遥控器来发射红外数值给红外接收。

image-20220302165728937

image-20220321093338725

在程序中我们通过遥控按键远程控制小车运动、亮灯、鸣笛等。

三、程序分析

完整程序位置:Pico Robot配套资料 -> 附件 -> 课程程序源码 -> 3.机器人课程 -> 10.红外控制.py

 
  1 import time
  2 from machine import Pin, I2C, PWM, Timer
  3 from pico_car import SSD1306_I2C, ir, pico_car, ws2812b
  4 
  5 Motor = pico_car()
  6 Motor.Car_Stop()
  7 num_leds = 8  # Number of NeoPixels
  8 # Pin where NeoPixels are connected
  9 pixels = ws2812b(num_leds, 0)
 10 # Set all led off
 11 pixels.fill(0,0,0)
 12 pixels.show()
 13 # set buzzer pin
 14 BZ = PWM(Pin(22))
 15 BZ.freq(1000)
 16 #initialization ir
 17 Ir = ir()
 18 #initialization oled
 19 i2c=I2C(1, scl=Pin(15),sda=Pin(14), freq=100000)
 20 oled = SSD1306_I2C(128, 32, i2c)
 21 #define Timer
 22 tim = Timer()
 23 times_ = 0
 24 def tick(timer):
 25     global times_
 26     times_ = times_ + 1
 27     if times_ > 100:
 28         times_ = 0
 29 #set timer frequency 20
 30 tim.init(freq = 20,mode = Timer.PERIODIC,callback = tick)
 31 
 32 while True:
 33     #get value
 34     value = Ir.Getir()
 35     time.sleep(0.01)
 36     if value != None:
 37         print(value)
 38         #display press
 39         if value == 1:
 40             i = 0
 41             while value == 1:
 42                 value = Ir.Getir()
 43                 Motor.Car_Run(255,255)
 44                 if times_ > 1:
 45                     times_ = 0
 46                     if i == 0:
 47                         pixels.set_pixel(2,150,0,150)
 48                         pixels.set_pixel(3,150,0,150)
 49                         i = 1
 50                     elif i == 1:
 51                         pixels.set_pixel(2,0,0,0)
 52                         pixels.set_pixel(3,0,0,0)
 53                         pixels.set_pixel(1,150,0,150)
 54                         pixels.set_pixel(4,150,0,150)
 55                         i = 2
 56                     elif i == 2:
 57                         pixels.set_pixel(1,0,0,0)
 58                         pixels.set_pixel(4,0,0,0)
 59                         pixels.set_pixel(0,150,0,150)
 60                         pixels.set_pixel(5,150,0,150)
 61                         i = 3
 62                     elif i == 3:
 63                         pixels.set_pixel(0,0,0,0)
 64                         pixels.set_pixel(5,0,0,0)
 65                         pixels.set_pixel(6,150,0,150)
 66                         pixels.set_pixel(7,150,0,150)
 67                         i = 4
 68                     elif i == 4:
 69                         pixels.set_pixel(0,0,0,0)
 70                         pixels.set_pixel(5,0,0,0)
 71                         pixels.set_pixel(6,150,0,150)
 72                         pixels.set_pixel(7,150,0,150)
 73                         i = 5
 74                     elif i == 5:
 75                         pixels.set_pixel(6,0,0,0)
 76                         pixels.set_pixel(7,0,0,0)
 77                         i = 0
 78                     pixels.show()
 79             Motor.Car_Stop()
 80             oled.text('Run', 0, 0)
 81             oled.show()
 82             oled.fill(0)
 83         elif value == 4:
 84             i = 0
 85             while value == 4:
 86                 value = Ir.Getir()
 87                 Motor.Car_Left(130,130)
 88                 if times_ > 1:
 89                     times_ = 0
 90                     if i == 0:
 91                         pixels.set_pixel(7,0,0,0)
 92                         pixels.set_pixel(0,150,0,150)
 93                         i = i + 1
 94                     else:
 95                         pixels.set_pixel(i-1,0,0,0)
 96                         pixels.set_pixel(i,150,0,150)
 97                         i = i + 1
 98                         if i == 8:
 99                             i = 0
100                     pixels.show()
101             Motor.Car_Stop()
102             oled.text('Left', 0, 0)
103             oled.show()
104             oled.fill(0)
105         elif value == 6:
106             i = 8
107             while value == 6:
108                 value = Ir.Getir()
109                 Motor.Car_Right(130,130)
110                 if times_ > 1:
111                     times_ = 0
112                     if i == 8:
113                         pixels.set_pixel(7,150,0,150)
114                         pixels.set_pixel(0,0,0,0)
115                         i = i - 1
116                     else:
117                         pixels.set_pixel(i-1,150,0,150)
118                         pixels.set_pixel(i,0,0,0)
119                         i = i - 1
120                         if i == 0:
121                             i = 8
122                     pixels.show()
123             Motor.Car_Stop()
124             oled.text('Right', 0, 0)
125             oled.show()
126             oled.fill(0)
127         elif value == 5:
128             while value == 5:
129                 value = Ir.Getir()
130                 BZ.duty_u16(500)
131                 BZ.freq(624)
132             BZ.duty_u16(0)
133             oled.text('Buzzer', 0, 0)
134             oled.show()
135             oled.fill(0)
136         elif value == 9:
137             i = 0
138             while value == 9:
139                 value = Ir.Getir()
140                 Motor.Car_Back(255,255)
141                 if times_ > 1:
142                     times_ = 0
143                     if i == 0:
144                         pixels.set_pixel(6,150,0,150)
145                         pixels.set_pixel(7,150,0,150)
146                         i = 1
147                     elif i == 1:
148                         pixels.set_pixel(6,0,0,0)
149                         pixels.set_pixel(7,0,0,0)
150                         pixels.set_pixel(0,150,0,150)
151                         pixels.set_pixel(5,150,0,150)
152                         i = 2
153                     elif i == 2:
154                         pixels.set_pixel(0,0,0,0)
155                         pixels.set_pixel(5,0,0,0)
156                         pixels.set_pixel(1,150,0,150)
157                         pixels.set_pixel(4,150,0,150)
158                         i = 3
159                     elif i == 3:
160                         pixels.set_pixel(1,0,0,0)
161                         pixels.set_pixel(4,0,0,0)
162                         pixels.set_pixel(2,150,0,150)
163                         pixels.set_pixel(3,150,0,150)
164                         i = 4
165                     elif i == 4:
166                         pixels.set_pixel(1,0,0,0)
167                         pixels.set_pixel(4,0,0,0)
168                         pixels.set_pixel(2,150,0,150)
169                         pixels.set_pixel(3,150,0,150)
170                         i = 5
171                     elif i == 5:
172                         pixels.set_pixel(2,0,0,0)
173                         pixels.set_pixel(3,0,0,0)
174                         i = 0
175                     pixels.show()
176             Motor.Car_Stop()
177             oled.text('Back', 0, 0)
178             oled.show()
179             oled.fill(0)
180         elif value == 16:
181             while value == 16:
182                 value = Ir.Getir()
183             for i in range(num_leds):
184                 pixels.set_pixel(i,255,0,0)
185             pixels.show()
186             oled.text('Red', 0, 0)
187             oled.show()
188             oled.fill(0)
189         elif value == 17:
190             while value == 17:
191                 value = Ir.Getir()
192             for i in range(num_leds):
193                 pixels.set_pixel(i,0,255,0)
194             pixels.show()
195             oled.text('Green', 0, 0)
196             oled.show()
197             oled.fill(0)
198         elif value == 18:
199             while value == 18:
200                 value = Ir.Getir()
201             for i in range(num_leds):
202                 pixels.set_pixel(i,0,0,255)
203             pixels.show()
204             oled.text('Blue', 0, 0)
205             oled.show()
206             oled.fill(0)
207         elif value == 20:
208             while value == 20:
209                 value = Ir.Getir()
210             for i in range(num_leds):
211                 pixels.set_pixel(i,255,255,0)
212             pixels.show()
213             oled.text('Yellow', 0, 0)
214             oled.show()
215             oled.fill(0)
216         elif value == 21:
217             while value == 21:
218                 value = Ir.Getir()
219             for i in range(num_leds):
220                 pixels.set_pixel(i,0,255,255)
221             pixels.show()
222             oled.text('Cyan', 0, 0)
223             oled.show()
224             oled.fill(0)
225         elif value == 22:
226             while value == 22:
227                 value = Ir.Getir()
228             for i in range(num_leds):
229                 pixels.set_pixel(i,255,0,255)
230             pixels.show()
231             oled.text('Purple', 0, 0)
232             oled.show()
233             oled.fill(0)
234         elif value == 24:
235             while value == 24:
236                 value = Ir.Getir()
237             for i in range(num_leds):
238                 pixels.set_pixel(i,255,255,255)
239             pixels.show()
240             oled.text('White', 0, 0)
241             oled.show()
242             oled.fill(0)
243         elif value == 25:
244             while value == 25:
245                 value = Ir.Getir()
246             for i in range(num_leds):
247                 pixels.set_pixel(i,100,100,100)
248             pixels.show()
249             oled.text('White', 0, 0)
250             oled.show()
251             oled.fill(0)
252         elif value == 26:
253             while value == 26:
254                 value = Ir.Getir()
255             for i in range(num_leds):
256                 pixels.set_pixel(i,0,0,0)
257             pixels.show()
258             oled.text('Black', 0, 0)
259             oled.show()
260             oled.fill(0)
261         value = None

 

在5.7超声波跟随的程序里,我们介绍了如何实现蜂鸣器、RGB灯、小车运动同时控制,在这个程序里我们也做了相似的处理,同时还加了定时器中断Timer来实现RGB灯切换速度控制。

我们使用 while value == 按键值:来实现遥控器按一下松开再执行的效果。

from pico_car import SSD1306_I2C, ir, pico_car, ws2812b

使用pico_car 的SSD1306_I2C、ir、pico_car、ws2812b,封装了电机驱动和RGB灯、OLED、红外遥控库。

import time

“time”库。 这个库处理所有与时间有关的事情,从测量它到将延迟插入到程序中。单位为秒。

from machine import Pin, I2C, PWM, Timer

机器库包含MicroPython需要与Pico和其他MicroPython兼容的设备通信的所有指令,扩展了物理计算的语言,这里用了Pin、PWM、Timer和I2C的库。

Motor = pico_car()

初始化电机驱动。

pixels = ws2812b(num_leds, 0)

初始化RGB灯,我们有8个RGB灯,这里num_leds设置为8。

pixels.fill(0,0,0)

把所有的灯设置为0,0,0,也就是关闭所有灯,参数分别是(红色,绿色,蓝色),颜色亮度是0-255。

pixels.show()

把设置的灯显示出来。

pixels.set_pixel(2,150,0,150)

把第三个灯设置为紫色。

i2c=I2C(1, scl=Pin(15),sda=Pin(14), freq=100000)

设置IIC 1引脚为SCL 15,SDA 14,频率为100000。

oled = SSD1306_I2C(128, 32, i2c)

初始化OLED的大小为128*32,并把前面设置的IIC参数传进去。

oled.show()

把设置的OLED内容显示出来。

oled.fill(0)

清除设置的内容,准备下一次显示。

oled.text('Green', 0, 0)

在OLED的0,0位置显示'Green'。

Motor.Car_Run(255,255)

控制小车前进,速度设置为150,参数分别为(左电机速度,右电机速度),速度范围0-255。

Motor.Car_Back(255,255)

控制小车后退。

Motor.Car_Left(130,130)

控制小车左旋。

Motor.Car_Right(130,130)

控制小车右旋。

Motor.Car_Stop()

控制小车停止。

BZ = PWM(Pin(22))

将IO22设置为PWM输出引脚,用于控制蜂鸣器。

BZ.freq(1000)

将PWM频率设置为1000。

BZ.duty_u16(0)

数值为0的时候关闭声音,为500的时候开启声音。

tim = Timer()

初始化定时中断。

tick(timer)

定时中断函数,在函数中使用变量times_做时间控制,从而控制RGB等切换速度。

tim.init(freq = 1000,mode = Timer.PERIODIC,callback = tick)

设置定时中断函数和频率。

Ir = ir()

初始化红外遥控。

value = Ir.Getir()

读取红外遥控数值,赋值给变量value。

四、实验现象

image-20220321095747956

程序下载完成之后,按照以下协议运行小车。

按键Shell打印键值OLED显示效果
向上 1 Run 小车前进,底部向前流水灯效果
向左 4 Left 小车左旋,底部逆时针流水灯效果
向右 6 Right 小车右旋,底部顺时针流水灯效果
向下 9 Back 小车后退,底部向后流水灯效果
声音 5 Buzzer 小车蜂鸣器响
1 16 Red RGB灯亮红色
2 17 Green RGB灯亮绿色
3 18 Blue RGB灯亮蓝色
4 20 Yellow RGB灯亮黄色
5 21 Cyan RGB灯亮青色
6 22 Purple RGB灯亮紫色
7 24 White RGB灯亮白色
8 25 White RGB灯亮低亮度白色
9 26 Black RGB灯关灯

 

 

5.11 蓝牙控制

在这一节,我们将学习如何通过蓝牙控制小车,我们将会把前面学习到的巡线、超声波避障、声控、OLED控制、蜂鸣器控制、可编程RGB灯等都集成到一起,全都可以通过蓝牙控制。

注意:电机速度受到电池电量影响,例程是在电池电量较高(电量数值在26000以上)的情况下,如果电池电量较低需要及时充电或者修改电机速度。

一、学习目标

1. 学习树莓派Pico主板和小车扩展板的电机、OLED、蓝牙、可编程RGB灯、蜂鸣器、超声波、声音传感器结合实现蓝牙控制。

2. 了解如何通过蓝牙控制小车。

二、硬件使用

本次课程使用PICO主板以及小车扩展板的电机、OLED、蓝牙、可编程RGB灯、蜂鸣器、超声波、声音传感器。

注意:请将小车放在地面上。运行电机、可编程RGB灯时,声音传感器和电池电量数值波动是正常的。运行巡线模式的时候,必须在室内无太阳光照的环境下进行,以减少太阳光对巡线传感器的干扰,并且在巡线时需保持室内光线充足,否则需要根据5.4节的方法修改程序。运行超声波避障模式的时候,需要确保障碍物不会过于密集,如果障碍物过于密集可以按5.6节的方法修改程序。运行声控模式的时候,需要在较安静的环境下运行。OLED一行最多显示16个字符,只支持数字和英文显示。使用之前请确保电池电量(电量数值在26000以上),否则可能运行异常。

三、下载程序和蓝牙连接

1. 按照1.3节组装步骤把小车组装完成,注意要接上蓝牙模块和OLED模块,把跳线帽插到Voice排针上

image-20220302110753097

2. 按照2.4节将库文件导入到PICO开发板中。

3. 打开程序:Pico Robot配套资料 -> 附件 -> 课程程序源码 -> 3.机器人课程 -> 11.蓝牙控制.py 按照2.3开机自启动部分,把程序设置成开机自启动(调试的时候可以不用开机自启动),注意文件名要设置成main.py。

image-20220302094245344

4. 拔掉和电脑连接的USB线,重启一下小车,此时蓝牙模块的红灯闪烁,准备连接手机。

image-20220302110629378

5. Android/IOS手机用户扫描下方二维码下载软件。IOS用户也可以在苹果应用商城搜索并下载【YahboomRobot】

image-20220302100523063

6. 下载完成蓝牙遥控APP之后, 我们要进行安装。安装期间如果手机提示需要获取位置权限,需要点击同意获取位置权限。

7. 打开手机蓝牙,打开已经安装好的YahboomRobot,选择 智能小车 -> PICO ROBOT,进入蓝牙连接界面,当手机靠近小车时蓝牙会自动连接上,如果没有自动连接的话,我们需要点击【搜索蓝牙】,成功连接之后,APP将会跳转到控制界面。

Screenshot_20220224_094931_com.yahboomrobot

image-20220302100714213

8. 连接成功后,蓝牙模块的红灯变成长亮,提示bluetooth connect successful!,我们就可以通过手机控制小车了,如果蓝牙断了红灯会重新变成闪烁。

image-20220308141919510

image-20220302110924791

 

四、蓝牙遥控界面介绍

1. 基础功能

image-20220321100951044

2. 音乐选项

image-20220322120242152

3. 车灯选项

image-20220321102021095

4. 车灯灯效

image-20220321102034225

5. 模式选择

image-20220321102223027

五、程序分析

完整程序位置:Pico Robot配套资料 -> 附件 -> 课程程序源码 -> 3.机器人课程 -> 11.蓝牙控制.py

 
  1 import time
  2 from machine import Pin, I2C, PWM, Timer, UART, ADC
  3 from pico_car import SSD1306_I2C, pico_car, ws2812b, ultrasonic
  4 
  5 Motor = pico_car()
  6 Motor.Car_Stop()
  7 num_leds = 8  # Number of NeoPixels
  8 # Pin where NeoPixels are connected
  9 pixels = ws2812b(num_leds, 0)
 10 pixels.fill(0,0,0)
 11 pixels.show()
 12 # set buzzer pin
 13 BZ = PWM(Pin(22))
 14 BZ.freq(1000)
 15 # Initialize music
 16 CM = [0, 330, 350, 393, 441, 495, 556, 624]
 17 #initialization ultrasonic
 18 ultrasonic = ultrasonic()
 19 #initialization oled
 20 i2c=I2C(1, scl=Pin(15),sda=Pin(14), freq=100000)
 21 oled = SSD1306_I2C(128, 32, i2c)
 22 #initialization Bluetooth
 23 uart = UART(0, 9600, bits=8, parity=None, stop=1, tx=Pin(16), rx=Pin(17))
 24 dat = 0
 25 #initialization ADC
 26 Quantity_of_electricity = machine.ADC(28)
 27 Sound = machine.ADC(27)
 28 #define Timer
 29 tim = Timer()
 30 def tick(timer):
 31     w_power = int(Quantity_of_electricity.read_u16()/65535*240)
 32     if w_power > 100:
 33         w_power = 100
 34     w_distance = ultrasonic.Distance_accurate()
 35     w_sounds = int(Sound.read_u16()/65535*200)
 36     uart.write('$DAT')
 37     uart.write(str(w_distance))
 38     uart.write(',')
 39     uart.write(str(w_sounds))
 40     uart.write(',')
 41     uart.write(str(w_power))
 42     uart.write('#')
 43 #set timer frequency 0.1
 44 tim.init(freq = 0.1,mode = Timer.PERIODIC,callback = tick)
 45 
 46 #define water lamp
 47 def water():
 48     global i,dat
 49     i = 0
 50     while dat != b'M#':
 51         while uart.any() > 0:
 52             dat = uart.read(2)
 53         if i == 0:
 54             pixels.set_pixel(7,0,0,0)
 55             pixels.set_pixel(0,150,0,150)
 56             i = i + 1
 57         else:
 58             pixels.set_pixel(i-1,0,0,0)
 59             pixels.set_pixel(i,150,0,150)
 60             i = i + 1
 61             if i == 8:
 62                 i = 0
 63         pixels.show()
 64         time.sleep(0.1)
 65     i = 0
 66 
 67 #define breathing lamp
 68 def breathing():
 69     global i,dat
 70     i = 0
 71     brightness = 0
 72     fadeAmount = 1
 73     while dat != b'M#':
 74         while uart.any() > 0:
 75             dat = uart.read(2)
 76         temp = 0
 77         while temp < 400:
 78             for i in range(num_leds):
 79                 pixels.set_pixel(i,0,brightness,brightness)
 80             pixels.show()
 81             brightness = brightness + fadeAmount
 82             if brightness <= 0 or brightness >= 200:
 83                 fadeAmount = -fadeAmount
 84             temp+=1
 85             time.sleep(0.005)
 86 
 87         temp = 0
 88         while temp < 400:
 89             for i in range(num_leds):
 90                 pixels.set_pixel(i,brightness,0,brightness)
 91             pixels.show()
 92             brightness = brightness + fadeAmount
 93             if brightness <= 0 or brightness >= 200:
 94                 fadeAmount = -fadeAmount
 95             temp+=1
 96             time.sleep(0.005)
 97             
 98         temp = 0
 99         while temp < 400:
100             for i in range(num_leds):
101                 pixels.set_pixel(i,brightness,brightness,0)
102             pixels.show()
103             brightness = brightness + fadeAmount
104             if brightness <= 0 or brightness >= 200:
105                 fadeAmount = -fadeAmount
106             temp+=1
107             time.sleep(0.005)
108 
109         temp = 0
110         while temp < 400:
111             for i in range(num_leds):
112                 pixels.set_pixel(i,brightness,0,0)
113             pixels.show()
114             brightness = brightness + fadeAmount
115             if brightness <= 0 or brightness >= 200:
116                 fadeAmount = -fadeAmount
117             temp+=1
118             time.sleep(0.005)
119 
120         temp = 0
121         while temp < 400:
122             for i in range(num_leds):
123                 pixels.set_pixel(i,0,brightness,0)
124             pixels.show()
125             brightness = brightness + fadeAmount
126             if brightness <= 0 or brightness >= 200:
127                 fadeAmount = -fadeAmount
128             temp+=1
129             time.sleep(0.005)
130 
131         temp = 0
132         while temp < 400:
133             for i in range(num_leds):
134                 pixels.set_pixel(i,0,0,brightness)
135             pixels.show()
136             brightness = brightness + fadeAmount
137             if brightness <= 0 or brightness >= 200:
138                 fadeAmount = -fadeAmount
139             temp+=1
140             time.sleep(0.005)
141     i = 0
142 
143 #define horse lamp
144 def horse():
145     global dat
146     while dat != b'M#':
147         while uart.any() > 0:
148             dat = uart.read(2)
149         for i in range(num_leds):
150             for j in range(num_leds):
151                 #pixel_num, red, green, blue
152                 pixels.set_pixel(j,abs(i+j)%10,abs(i-(j+3))%10,abs(i-(j+6))%10)
153             pixels.show()
154             time.sleep(0.05)
155 
156 #Define the tracking sensor, 1-4 from left to right
157 #recognize that black is 0 and white is 1
158 #Tracing_1 Tracing_2 Tracing_3 Tracing_4
159 #    2         3        4          5     
160 Tracing_1 = machine.Pin(2, machine.Pin.IN)
161 Tracing_2 = machine.Pin(3, machine.Pin.IN)
162 Tracing_3 = machine.Pin(4, machine.Pin.IN)
163 Tracing_4 = machine.Pin(5, machine.Pin.IN)
164 #define line
165 def line():
166     global dat
167     oled.fill(0)
168     while dat != b'V#':
169         while uart.any() > 0:
170             dat = uart.read(2)
171                 
172         #四路循迹引脚电平状态
173         #Four channel tracking pin level status
174         # 0 0 X 0
175         # 1 0 X 0
176         # 0 1 X 0
177         #处理右锐角和右直角的转动
178         #Handle the rotation of right acute angle and right right right angle
179         if (Tracing_1.value() == 0 or Tracing_2.value() == 0) and Tracing_4.value() == 0:
180             Motor.Car_Right(120,120)
181             for i in range(num_leds):
182                 pixels.set_pixel(i,0,255,0)
183             oled.text('Turn Right', 0, 0)
184             #time.sleep(0.08)
185             
186         #四路循迹引脚电平状态
187         #Four channel tracking pin level status
188         # 0 X 0 0       
189         # 0 X 0 1 
190         # 0 X 1 0       
191         #处理左锐角和左直角的转动
192         #Handle the rotation of left sharp angle and left right angle
193         elif Tracing_1.value() == 0 and (Tracing_3.value() == 0 or Tracing_4.value() == 0):
194             Motor.Car_Left(120,120)
195             for i in range(num_leds):
196                 pixels.set_pixel(i,0,0,255)
197             oled.text('Turn Left', 0, 0)
198             #time.sleep(0.08)
199             
200         # 0 X X X
201         #最左边检测到
202         #Leftmost detected
203         elif Tracing_1.value() == 0:
204             Motor.Car_Run(0,130)
205             for i in range(num_leds):
206                 pixels.set_pixel(i,0,0,255)
207             oled.text('Turn Left', 0, 0)
208         
209         # X X X 0
210         #最右边检测到
211         #Rightmost detected
212         elif Tracing_4.value() == 0:
213             Motor.Car_Run(130,0)
214             for i in range(num_leds):
215                 pixels.set_pixel(i,0,255,0)
216             oled.text('Turn Right', 0, 0)
217         # X 0 0 X
218         #处理直线
219         #Processing line
220         elif Tracing_2.value() == 0 and Tracing_3.value() == 0:
221             Motor.Car_Run(100,100)
222             for i in range(num_leds):
223                 pixels.set_pixel(i,255,255,255)
224             oled.text('Run', 0, 0)
225             
226         pixels.show()
227         oled.show()
228         oled.fill(0)
229     #其他时小车保持上一个小车运行状态
230     #In other cases, the trolley keeps the previous trolley running
231     pixels.fill(0,0,0)
232     Motor.Car_Stop()
233     BZ.duty_u16(0)
234 
235 #define ultrasonic avoid    
236 def avoid():
237     global dat
238     oled.fill(0)
239     while dat != b'V#':
240         while uart.any() > 0:
241             dat = uart.read(2)
242         #get distance
243         distance = ultrasonic.Distance_accurate()
244         print("distance is %d cm"%(distance) )
245         #display distance
246         oled.text('distance:', 0, 0)
247         oled.text(str(distance), 75, 0)
248         oled.show()
249         oled.fill(0)
250         #Control action
251         if distance < 10:
252             for i in range(num_leds):
253                 pixels.set_pixel(i,255,0,0)
254             pixels.show()
255             Motor.Car_Back(150,150)
256             BZ.duty_u16(500)
257             BZ.freq(CM[7])
258             time.sleep(0.2)
259             Motor.Car_Right(150,150)
260             BZ.duty_u16(500)
261             BZ.freq(CM[5])
262             time.sleep(0.2)
263             BZ.duty_u16(0)
264         elif distance >= 10 and distance < 30:
265             for i in range(num_leds):
266                 pixels.set_pixel(i,255,255,0)
267             pixels.show()
268             Motor.Car_Run(100,100)
269         else:
270             for i in range(num_leds):
271                 pixels.set_pixel(i,0,255,0)
272             pixels.show()
273             Motor.Car_Run(100,100)
274         time.sleep(0.1)
275     pixels.fill(0,0,0)
276     Motor.Car_Stop()
277     BZ.duty_u16(0)
278 
279 #define ultrasonic voice    
280 def voice():
281     global dat
282     oled.fill(0)
283     while dat != b'V#':
284         while uart.any() > 0:
285             dat = uart.read(2)
286         #get value
287         sounds = Sound.read_u16()
288         print(sounds)
289         oled.text('Sound:', 0, 0)
290         oled.text(str(sounds), 50, 0)
291         #Control action
292         if sounds > 22000:
293             while sounds > 10000:
294                 Motor.Car_Stop()
295                 sounds = Sound.read_u16()
296                 print(sounds)
297                 time.sleep(0.001)
298             Motor.Car_Run(255,255)
299             BZ.duty_u16(500)
300             BZ.freq(CM[1])
301             pixels.set_pixel(2,150,0,150)
302             pixels.set_pixel(3,150,0,150)
303             pixels.show()
304             time.sleep(0.03)
305             BZ.duty_u16(500)
306             BZ.freq(CM[2])
307             pixels.set_pixel(2,0,0,0)
308             pixels.set_pixel(3,0,0,0)
309             pixels.set_pixel(1,150,0,150)
310             pixels.set_pixel(4,150,0,150)
311             pixels.show()
312             time.sleep(0.03)
313             BZ.duty_u16(500)
314             BZ.freq(CM[3])
315             pixels.set_pixel(1,0,0,0)
316             pixels.set_pixel(4,0,0,0)
317             pixels.set_pixel(0,150,0,150)
318             pixels.set_pixel(5,150,0,150)
319             pixels.show()
320             time.sleep(0.03)
321             BZ.duty_u16(500)
322             BZ.freq(CM[4])
323             pixels.set_pixel(0,0,0,0)
324             pixels.set_pixel(5,0,0,0)
325             pixels.set_pixel(6,150,0,150)
326             pixels.set_pixel(7,150,0,150)
327             pixels.show()
328             time.sleep(0.03)
329             BZ.duty_u16(500)
330             BZ.freq(CM[5])
331             pixels.set_pixel(0,0,0,0)
332             pixels.set_pixel(5,0,0,0)
333             pixels.set_pixel(6,150,0,150)
334             pixels.set_pixel(7,150,0,150)
335             pixels.show()
336             time.sleep(0.03)
337             BZ.duty_u16(500)
338             BZ.freq(CM[6])
339             pixels.set_pixel(6,0,0,0)
340             pixels.set_pixel(7,0,0,0)
341             pixels.show()
342             BZ.duty_u16(0)
343             sounds = 0
344             oled.show()
345             oled.fill(0)
346             while sounds > 10000:
347                 Motor.Car_Stop()
348                 sounds = Sound.read_u16()
349                 print(sounds)
350                 time.sleep(0.001)
351         else:
352             Motor.Car_Stop()
353             oled.show()
354             oled.fill(0)
355         time.sleep(0.01)
356     pixels.fill(0,0,0)
357     Motor.Car_Stop()
358     BZ.duty_u16(0)
359 
360 while True:
361     #receive data
362     while uart.any() > 0:
363         dat = uart.read(2)
364         #OLED display
365         if dat == b'X#':
366             for oledi in range(128):
367                 for oledj in range(10):
368                     oled.pixel(oledi, oledj,0)
369             datoled_1 = uart.read(16)
370             stroled_1 = str(datoled_1)
371             stroled_1 = stroled_1.replace("b'", "")
372             stroled_1 = stroled_1.replace("'", "")
373             stroled_1 = stroled_1.replace("$", "")
374             oled.text(stroled_1, 0, 0)
375             oled.show()
376             print(stroled_1)
377         elif dat == b'Y#':
378             for oledi in range(128):
379                 for oledj in range(10,20):
380                     oled.pixel(oledi, oledj,0)
381             datoled_2 = uart.read(16)
382             stroled_2 = str(datoled_2)
383             stroled_2 = stroled_2.replace("b'", "")
384             stroled_2 = stroled_2.replace("'", "")
385             stroled_2 = stroled_2.replace("$", "")
386             oled.text(stroled_2, 0, 10)
387             oled.show()
388             print(stroled_2)
389         elif dat == b'Z#':
390             for oledi in range(128):
391                 for oledj in range(20,30):
392                     oled.pixel(oledi, oledj,0)
393             datoled_3 = uart.read(16)
394             stroled_3 = str(datoled_3)
395             stroled_3 = stroled_3.replace("b'", "")
396             stroled_3 = stroled_3.replace("'", "")
397             stroled_3 = stroled_3.replace("$", "")
398             oled.text(stroled_3, 0, 20)
399             oled.show()
400             print(stroled_3)
401         elif dat == b'W#':
402             BBuzzer = uart.read(1)
403             if BBuzzer == b'1':
404                 BZ.duty_u16(500)
405                 BZ.freq(277)
406             elif BBuzzer == b'2':
407                 BZ.duty_u16(500)
408                 BZ.freq(311)
409             elif BBuzzer == b'3':
410                 BZ.duty_u16(500)
411                 BZ.freq(370)
412             elif BBuzzer == b'4':
413                 BZ.duty_u16(500)
414                 BZ.freq(415)
415             elif BBuzzer == b'5':
416                 BZ.duty_u16(500)
417                 BZ.freq(466)
418 
419     #car control
420     if dat == b'A#':
421         Motor.Car_Run(255,255)
422     elif dat == b'B#':
423         Motor.Car_Back(255,255)
424     elif dat == b'C#':
425         Motor.Car_Run(0,255)
426     elif dat == b'D#':
427         Motor.Car_Run(255,0)
428     elif dat == b'E#':
429         Motor.Car_Left(255,255)
430     elif dat == b'F#':
431         Motor.Car_Right(255,255)
432     elif dat == b'0#':
433         Motor.Car_Stop()
434     #music control
435     elif dat == b'1#':
436         BZ.duty_u16(500)
437         BZ.freq(262)
438     elif dat == b'2#':
439         BZ.duty_u16(500)
440         BZ.freq(294)
441     elif dat == b'3#':
442         BZ.duty_u16(500)
443         BZ.freq(330)
444     elif dat == b'4#':
445         BZ.duty_u16(500)
446         BZ.freq(349)
447     elif dat == b'5#':
448         BZ.duty_u16(500)
449         BZ.freq(392)
450     elif dat == b'6#':
451         BZ.duty_u16(500)
452         BZ.freq(440)
453     elif dat == b'7#':
454         BZ.duty_u16(500)
455         BZ.freq(494)
456     elif dat == b'8#':
457         BZ.duty_u16(500)
458         BZ.freq(523)
459     elif dat == b'O#':
460         BZ.duty_u16(0)
461     #car light
462     elif dat == b'G#':
463         pixels.fill(255,0,0)
464         pixels.show()
465     elif dat == b'H#':
466         pixels.fill(0,255,0)
467         pixels.show()
468     elif dat == b'I#':
469         pixels.fill(0,0,255)
470         pixels.show()
471     elif dat == b'J#':
472         pixels.fill(255,255,0)
473         pixels.show()
474     elif dat == b'K#':
475         pixels.fill(0,255,255)
476         pixels.show()
477     elif dat == b'L#':
478         pixels.fill(255,0,255)
479         pixels.show()
480     elif dat == b'N#':
481         water()
482     elif dat == b'P#':
483         horse()
484     elif dat == b'Q#':
485         breathing()
486     elif dat == b'M#':
487         pixels.fill(0,0,0)
488         pixels.show()
489         i = 0
490         brightness = 0
491         fadeAmount = 1
492     #mode
493     elif dat == b'S#':
494         line()
495     elif dat == b'T#':
496         avoid()
497     elif dat == b'U#':
498         voice()
499     elif dat == b'V#':
500         oled.fill(0)
501         oled.show()
502         pixels.fill(0,0,0)
503         pixels.show()
504         Motor.Car_Stop()
505         BZ.duty_u16(0)
506     time.sleep(0.01)

 

在这个程序中,整合了之前的课程的程序,例如呼吸灯部分是3.4节的程序,超声波避障部分是5.6节的程序。在这个程序也同样用到了定时中断Timer来做定时上报超声波、声音、电池数据给APP显示。

from pico_car import SSD1306_I2C, pico_car, ws2812b, ultrasonic

使用pico_car 的SSD1306_I2C、ultrasonic、pico_car、ws2812b,封装了电机驱动和RGB灯、OLED、超声波库。

import time

“time”库。 这个库处理所有与时间有关的事情,从测量它到将延迟插入到程序中。单位为秒。

from machine import Pin, I2C, PWM, Timer, UART, ADC

机器库包含MicroPython需要与Pico和其他MicroPython兼容的设备通信的所有指令,扩展了物理计算的语言,这里用了Pin、PWM、Timer、UART、ADC和I2C的库。

Motor = pico_car()

初始化电机驱动。

Motor.Car_Run(255,255)

控制小车前进,速度设置为255,参数分别为(左电机速度,右电机速度),速度范围0-255。

Motor.Car_Stop()

控制小车停止。

Motor.Car_Back(255,255)

控制小车后退。

Motor.Car_Run(0,255)

控制小车左转。

Motor.Car_Run(255,0)

控制小车右转。

Motor.Car_Left(255,255)

控制小车左旋。

Motor.Car_Right(255,255)

控制小车右旋。

pixels = ws2812b(num_leds, 0)

初始化RGB灯,我们有8个RGB灯,这里num_leds设置为8。

pixels.fill(0,0,0)

把所有的灯设置为0,0,0,也就是关闭所有灯,参数分别是(红色,绿色,蓝色),颜色亮度是0-255。

pixels.set_pixel(1,150,0,150)

把第一个灯设置为紫色。

pixels.show()

把设置的灯显示出来。

BZ = PWM(Pin(22))

将IO22设置为PWM输出引脚,用于控制蜂鸣器。

BZ.freq(1000)

将PWM频率设置为1000。

BZ.duty_u16(0)

数值为0的时候关闭声音,为500的时候开启声音。

ultrasonic = ultrasonic()

初始化超声波测距。

distance = ultrasonic.Distance_accurate()

将超声波测距返回的数值,赋值给变量distance 。

i2c=I2C(1, scl=Pin(15),sda=Pin(14), freq=100000)

设置IIC 1引脚为SCL 15,SDA 14,频率为100000。

oled = SSD1306_I2C(128, 32, i2c)

初始化OLED的大小为128*32,并把前面设置的IIC参数传进去。

oled.show()

把设置的OLED内容显示出来。

oled.fill(0)

清除设置的内容,准备下一次显示。

oled.text('Run', 0, 0)

在OLED的0,0位置显示'Run'。

tim = Timer()

初始化定时中断。

tick(timer)

定时中断函数,在函数中使用变量times_做时间控制,从而控制RGB等切换速度。

tim.init(freq = 0.5,mode = Timer.PERIODIC,callback = tick)

设置定时中断函数和频率。

machine.ADC(28)

初始化ADC端口28。

Sound.read_u16()/65535*200

读取声音传感器数值,转换成0-100的范围。

Quantity_of_electricity.read_u16()/65535*240

读取电量数值,转换成0-100的范围。

uart = UART(0, 9600, bits=8, parity=None, stop=1, tx=Pin(16), rx=Pin(17))

初始化蓝牙串口UART 0 ,引脚TX 16, RX 17,波特率9600,数据位8位,停止位1,没有奇偶校验位。

uart.write('$DAT')

通过蓝牙发送$DAT给APP。

uart.any()

读取串口数据,当接到任意数据时会返回数据。

dat = uart.read(2)

读取两个数据,并赋值给变量dat,通过判断这个变量的值来做出不同的动作。

Tracing_1 = machine.Pin(2, machine.Pin.IN)

初始化引脚2作为巡线传感器1的脚,设置为输入。

Tracing_1.value()

Tracing_1.value()函数用来检测对应端口的电平高低。

stroled_1 = stroled_1.replace("b'", "")

把变量stroled_1中的 b' 字符串替换为空,即去掉 b' 字符串。

六、通讯协议

程序下载完成之后,按照以下协议运行小车。

小车运动协议内容
前进 A#
后退 B#
左转 C#
右转 D#
左旋 E#
右旋 F#
停止 0#
音乐播放 协议内容
do 1#
ri 2#
mi 3#
fa 4#
su 5#
la 6#
xi 7#
O#
高Do 8#
do# W#1
ri# W#2
fa# W#3
su# W#4
la# W#5
七彩车灯 协议内容
G#
绿 H#
I#
J#
K#
品红 L#
关闭 M#
七彩灯效 协议内容
流水灯 N#
跑马灯 P#
呼吸灯 Q#
关闭 M#
模式选择 协议内容
巡线模式 S#
超声波避障 T#
声控小车 U#
退出模式 V#
OLED显示(每行data不超过16个字符) 协议内容
第一行 X#data
第二行 Y#data
第三行 Z#data
主动上报数据 协议内容
$DAT120,99,98# 超声波距离:120
  声音值:99
  电量:98
posted @ 2024-03-30 17:36  soliang  阅读(69)  评论(0编辑  收藏  举报