本项目主控改为ESP32-C3,沿用之前的L298N电机驱动、12.6v 18650电池组、LM7805降压模块的方案。电机改用1:19减速比的,使用130mm车轮,主要考虑越野用途。
遥控方面,本项目使用HC-14模块,实测连接到电脑可以通过串口接收遥控器数据,遥控器有线连接底盘上的主控也能正常使用,但通过HC-14模块接收数据时没有响应,需要更换其它方案,但本质上都是通过串口透传来控制。
两边车轮的转速由遥控器计算得到。遥控器程序有两种模式,第一种模式通过测量两个摇杆y轴电压分别控制两边电机pwm占空比,第二种模式通过左摇杆y轴控制速度,通过右摇杆x轴控制转向。通过左摇杆x轴控制模式切换(连续3次检测到电压达到目标值再切换)。数据换算为两侧电机pwm占空比,遥控器发出的两边占空比增加了1023以避免取负值,在底盘上的主控进行切换。另外,遥控器连接OLED屏幕,可以显示当前控制小车的两个摇杆轴的位置以辅助操作。
遥控器程序
#导入Pin模块
from machine import Pin
from machine import ADC
from machine import Timer
from machine import SoftI2C
from ssd1306 import SSD1306_I2C #I2C的oled选该方法
#定义ADC控制对象
adc1=ADC(Pin(1))
adc1.atten(ADC.ATTN_11DB) #开启衰减,量程增大到3.3V
adc2=ADC(Pin(2))
adc2.atten(ADC.ATTN_11DB) #开启衰减,量程增大到3.3V
adc3=ADC(Pin(3))
adc3.atten(ADC.ATTN_11DB) #开启衰减,量程增大到3.3V
adc4=ADC(Pin(4))
adc4.atten(ADC.ATTN_11DB) #开启衰减,量程增大到3.3V
#创建软件I2C对象
i2c = SoftI2C(sda=Pin(12), scl=Pin(13))
#创建OLED对象,OLED分辨率、I2C接口
oled = SSD1306_I2C(128, 64, i2c)
mode=1
flag=0
#定时器0中断函数
def time0_irq(time0):
global mode
global flag
a=adc1.read()*2046//4095
b=adc2.read()*2046//4095
c=adc3.read()*2046//4095
d=adc4.read()*2046//4095
if mode==0: #直接通过两边摇杆y轴控制底盘两边电机转速
l=b
r=d
print("%04d%04d"%(l,r))
oled.fill(0)
oled.fill_rect(20,-b//32+63,16,5,1) #画填充矩形
oled.fill_rect(90,-d//32+63,16,5,1) #画填充矩形
oled.show()
if a<46: #通过左摇杆x轴控制模式切换
flag+=1
if flag>2:
mode=1
flag=0
if a>46:
flag=0
if mode==1:
l=int(b-c*0.25+290) #左摇杆y轴控制速度,右摇杆x轴控制转向。考虑实际调试时发现的偏差,增减的值不是256
r=int(b+c*0.25-290)
if l<0: #防止超出取值范围
l=0
if l>2046:
l=2046
if r<0:
r=0
if r>2046:
r=2046
print("%d%04d"%(l,r))
oled.fill(0)
oled.fill_rect(10,-b//32+63,16,5,1) #画填充矩形
oled.fill_rect(-c//32+110,25,5,16,1) #画填充矩形
oled.show()
if a>2000: #通过左摇杆x轴控制模式切换
flag+=1
if flag>2:
mode=0
flag=0
if a<2000:
flag=0
#程序入口
if __name__=="__main__":
time0=Timer(0) #创建time0定时器对象
time0.init(period=100,mode=Timer.PERIODIC,callback=time0_irq)
while True:
pass
底盘程序(由于目前ESP32-C3的MicroPython固件最多支持6个pwm通道,同侧车轮同方向引脚相连,只用到4路pwm)
#导入Pin模块
from machine import Pin
from machine import PWM
import time
#定义motor1控制对象
motor1=PWM(Pin(9),freq=1000,duty=0)
motor2=PWM(Pin(8),freq=1000,duty=0)
motor3=PWM(Pin(4),freq=1000,duty=0)
motor4=PWM(Pin(5),freq=1000,duty=0)
duty_mix=10231023
#程序入口
if __name__=="__main__":
while True:
try:
duty_mix=int(input('input'))
except:
pass
duty_l=duty_mix//10000-1023 #前四位为左侧pwm占空比
duty_r=duty_mix%10000-1023 #后四位为右侧pwm占空比
if duty_l>0:
motor1.duty(duty_l)
motor2.duty(0)
if duty_l<0:
motor1.duty(0)
motor2.duty(-duty_l)
if duty_l==0:
motor1.duty(0)
motor2.duty(0)
if duty_r>0:
motor3.duty(duty_r)
motor4.duty(0)
if duty_r<0:
motor3.duty(0)
motor4.duty(-duty_r)
if duty_r==0:
motor3.duty(0)
motor4.duty(0)
time.sleep_ms(50)