Donkey Car 基于Arduino L298N DIY小车

本文是原创作品,欢迎大家进行转载

这段时间开始研究一些无人驾驶,无意间发现Donkey Car 这个开源的入门级的无人驾驶例子,觉得还不错,便开始了研究,发现其还是比较简单的,主要的参数输入仅仅只有图像,油门,以及转向三个值进行训练即可。但是网上大都例子都是控制普通的RC 小车,而我们有自己DIY的小车,其底盘的硬件为树莓派4 + Arduino + L298N + 舵机 + 直流碳刷电机,而donkey car 源码中需要使用 PC9685 这张板子来驱动无刷电调,因此无法使用。经过网上翻墙搜索了半天,也没有发现相对应的解决办法,因此只好自己动手修改源码,经过一个下午的折腾,终于搞定了,因此写一遍博客方便如有需求的同学们也可以修改。

烧入Arduino程序

Donkey Car Arduino 测试页面,按照页面所示烧入往Arduino板子烧入通用程序。
在这里插入图片描述
Standard Firmata是Python 与Arduino串口通信的通用协议,因此他适用于任何一张Arduino的板子。

测试舵机校准程序

将舵机的电源线接5V,地线和arduino GND链接,pwm信号线链接 Pin 6,打开terminal运行如下:

$ donkey calibrate --arduino --channel 6
using donkey v2.6.0t ...

pymata_aio Version 2.33 Copyright (c) 2015-2018 Alan Yorinks All rights reserved.

Using COM Port:/dev/ttyACM0

Initializing Arduino - Please wait...
Arduino Firmware ID: 2.5 StandardFirmata.ino
Auto-discovery complete. Found 30 Digital Pins and 12 Analog Pins


Enter a PWM setting to test(0-180)95
Enter a PWM setting to test(0-180)90
Enter a PWM setting to test(0-180)85
...

这个时候你便可以测试舵机的转角了,根据自己小车情况,输入值在0 ~ 180 之间,找到一个左转最小值以及右转最大值,并记录下来。

L298N驱动代码修改

L298N接线方式

Donkey Car 默认的控制只有steering( -1 ~ 1) throttle(-1 ~ 1),而L298N可以同时输出两路电机控制,为了简化,我们将两个电机接到通一个输出。将L298N ENA和5V用跳线冒短接,然后将IN1 IN2 分别接入到arduino 的两路PWM信号口上。下面代码经过实测是可以驱动的,如果驱动不了L298N,那估计就是接线问题或者是配置问题,再或者就是arduino的管脚有问题了,我们在测试的时候就遇到了比较坑的Arduino的管脚有问题,一开始我们使用pin9来输出PWM信号,但是怎么试都有问题,后来换了一个PWM管脚以后就没有问题了。(这里吐槽一下,对于我们这些学习软件开发的同学来说简直就是莫名其妙啊,因为我们以前只关心代码而已,从来没有考虑过硬件出问题导致无法实现效果。。。)

Donkey Car actuator.py 代码修改

找到Donkey Car 源码目录,打开Parts文件夹中的actuator.py文件,将 ArduinoFirmata,ArdPWMThrottle 这两个类做如下修改(可直接复制代码)

class ArduinoFirmata:
    '''
    PWM controller using Arduino board.
    This is particularly useful for boards like Latte Panda with built it Arduino.
    Standard Firmata sketch needs to be loaded on Arduino side.
    Refer to docs/parts/actuators.md for more details
    '''
	#Leo:新增加一个pwm引脚 esc2_pin
    def __init__(self, servo_pin = 6, esc_pin = 5, esc2_pin = 9):
        from pymata_aio.pymata3 import PyMata3
        from pymata_aio.constants import Constants


        self.board = PyMata3()
        self.board.sleep(0.015)
        self.servo_pin = servo_pin
        self.esc_pin = esc_pin
        self.esc2_pin = esc2_pin
        self.board.servo_config(servo_pin)
        #Leo:新增加一个pwm引脚,将模式修改为pwm模式
        self.board.set_pin_mode(esc_pin,Constants.PWM)
        self.board.set_pin_mode(esc2_pin,Constants.PWM)
        #########################################

    def set_pulse(self, pin, angle):
        try:
            self.board.analog_write(pin, int(angle))
        except:
            self.board.analog_write(pin, int(angle))

    def set_servo_pulse(self, angle):
        self.set_pulse(self.servo_pin, int(angle))

    def set_esc_pulse(self, angle):
        self.set_pulse(self.esc_pin, int(angle))
    
    def set_esc2_pulse(self, angle):
        self.set_pulse(self.esc2_pin, int(angle))

class ArdPWMThrottle:

    """
    Wrapper over Arduino Firmata controller to convert -1 to 1 throttle
    values to PWM pulses.
    """
    MIN_THROTTLE = -1
    MAX_THROTTLE = 1

    def __init__(self,
                 controller=None,
                 max_pulse=105,
                 min_pulse=75,
                 zero_pulse=90):

        self.controller = controller
        self.max_pulse = max_pulse
        self.min_pulse = min_pulse
        self.zero_pulse = zero_pulse
        self.pulse = zero_pulse
        
        #Leo: PWM默认最大值为255
        self.max_con_pulse = 255
        #Leo: 两个引脚pwm输出来控制电机正反转
        self.pulse1 = min_pulse
        self.pulse2 = min_pulse
        ###################################
        
        # send zero pulse to calibrate ESC
        print("Init ESC")
        self.controller.set_esc_pulse(self.max_pulse)
        time.sleep(0.01)
        self.controller.set_esc_pulse(self.min_pulse)
        time.sleep(0.01)
        self.controller.set_esc_pulse(self.zero_pulse)
        time.sleep(0.01)
        #Leo: 引脚初始化
        self.controller.set_esc2_pulse(self.max_pulse)
        time.sleep(0.01)
        self.controller.set_esc2_pulse(self.min_pulse)
        time.sleep(0.01)
        self.controller.set_esc2_pulse(self.zero_pulse)
        ############################
        time.sleep(1)
        self.running = True
        print('Arduino PWM Throttle created')

    def run(self, throttle):
        if throttle > 0:
            self.pulse = dk.utils.map_range(throttle, 0, self.MAX_THROTTLE,
                                            self.zero_pulse, self.max_pulse)
            #Leo: 将pulse映射到两个引脚上
            self.pulse1 = dk.utils.map_range(self.pulse, self.zero_pulse, self.max_pulse,
                                            0, self.max_con_pulse)
            self.pulse2 = 0
            #########################################
        #elif abs(throttle) < 0.0001:
        #    self.pulse1 = 0
        #    self.pulse2 = 0
        else:
            self.pulse = dk.utils.map_range(throttle, self.MIN_THROTTLE, 0,
                                           self.min_pulse, self.zero_pulse)
            #Leo: 将pulse映射到两个引脚上
            self.pulse1 = 0
            self.pulse2 = dk.utils.map_range(self.pulse, self.zero_pulse, self.min_pulse,
                                           0, self.max_con_pulse)
            #########################################
        #self.controller.set_esc_pulse(self.pulse)
        self.controller.set_esc_pulse(self.pulse1)
        self.controller.set_esc2_pulse(self.pulse2)
        ######################################
    def shutdown(self):
        # stop vehicle
        self.run(0)
        self.running = False

Donkey Car manage.py 代码修改

找到mycar目录或者其他你自定义的donkeycar 安装目录,打开manage.py文件,搜索9685关键字,找到如下代码:

        else:
            from donkeycar.parts.actuator import PCA9685, PWMSteering, PWMThrottle

            steering_controller = PCA9685(cfg.STEERING_CHANNEL, cfg.PCA9685_I2C_ADDR, busnum=cfg.PCA9685_I2C_BUSNUM)
            steering = PWMSteering(controller=steering_controller,
                                            left_pulse=cfg.STEERING_LEFT_PWM,
                                            right_pulse=cfg.STEERING_RIGHT_PWM)

            throttle_controller = PCA9685(cfg.THROTTLE_CHANNEL, cfg.PCA9685_I2C_ADDR, busnum=cfg.PCA9685_I2C_BUSNUM)
            throttle = PWMThrottle(controller=throttle_controller,
                                            max_pulse=cfg.THROTTLE_FORWARD_PWM,
                                            zero_pulse=cfg.THROTTLE_STOPPED_PWM, 
                                            min_pulse=cfg.THROTTLE_REVERSE_PWM)

            V.add(steering, inputs=['angle'], threaded=True)
            V.add(throttle, inputs=['throttle'], threaded=True)

将其替换成如下代码:

        else:
            from donkeycar.parts.actuator import ArduinoFirmata, ArdPWMSteering, ArdPWMThrottle
            from donkeycar.parts.controller import get_js_controller

            arduino_controller = ArduinoFirmata(servo_pin=cfg.STEERING_ARDUINO_PIN, esc_pin=cfg.THROTTLE_ARDUINO_PIN,esc2_pin=cfg.THROTTLE_ARDUINO_PIN2)

            steering = ArdPWMSteering(controller=arduino_controller,
                              left_pulse=cfg.STEERING_ARDUINO_LEFT_PWM,
                              right_pulse=cfg.STEERING_ARDUINO_RIGHT_PWM)

            throttle = ArdPWMThrottle(controller=arduino_controller,
                              max_pulse=cfg.THROTTLE_ARDUINO_FORWARD_PWM,
                              zero_pulse=cfg.THROTTLE_ARDUINO_STOPPED_PWM,
                              min_pulse=cfg.THROTTLE_ARDUINO_REVERSE_PWM)

            V.add(steering, inputs=['angle'])
            V.add(throttle, inputs=['throttle'])

Donkey Car config.py 代码修改

找到mycar目录或者其他你自定义的donkeycar 安装目录,打开config.py文件,在文件末尾添加:

STEERING_ARDUINO_PIN = 3
THROTTLE_ARDUINO_PIN = 5
THROTTLE_ARDUINO_PIN2 = 6
STEERING_ARDUINO_LEFT_PWM = 0
STEERING_ARDUINO_RIGHT_PWM = 120
THROTTLE_ARDUINO_FORWARD_PWM = 180
THROTTLE_ARDUINO_STOPPED_PWM = 90
THROTTLE_ARDUINO_REVERSE_PWM = 0

到此为止,所有的代码修改完毕。

Donkey Car 运行

修改完代码以后,就可以按照去Donkey Car Drive页面页面进行操作测试了。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值