https://mc.dfrobot.com.cn/thread-2660-1-1.html

Firmata是一个PC与MCU通讯的一个常用协议。我们可以直接在咱们的Arduino Expansion Shield for Raspberry Pi扩展板上下载一个StandardFirmata代码,然后通过在树莓派上编写串口软件可以直接访问并控制扩展板上Arduino的GPIO、PWM、ADC等资源。
微信截图_20230821015710.png

arduino端下载

微信截图_20230821020404.png

树莓派上Firmata的安装与测试

在这里我们使用pyfirmata进行测试,首先安装pyfirmata模块,然后进入python交互界面导入模块看看是否报错,如果报错说明没有安装好

root@raspberrypi:/home/pi# pip3 install pyfirmata

然后看看你的Raspberry Pi Meet Arduino 扩展板 USB串口是什么号码,当前的USB串口是 ttyACM1

root@raspberrypi:/home/pi# ls -l /dev/tty*
crw------- 1 root root      4,  8 Jan  1  1970 /dev/tty8
crw------- 1 root root      4,  9 Jan  1  1970 /dev/tty9
crw-rw---T 1 root dialout 166,  1 Jun 22 12:56 /dev/ttyACM1
crw-rw---- 1 root tty     204, 64 Jun 22 12:17 /dev/ttyAMA0
crw-rw---T 1 root dialout   5,  3 Jan  1  1970 /dev/ttyprintk

进入python命令界面 输入命令测试下通信是否正确 ,这里的串口是ttyACM1
下面测试了使板上D13口的LED闪烁,然后又测试了模拟口上LM35温度传感器输入的电压,0.0567是电压值

root@raspberrypi:/home/pi# python
<pre>>>>from pyfirmata import Arduino, util
>>> board = Arduino('/dev/ttyACM1')
>>> board.digital[13].write(1)
>>> board.digital[13].write(0)
>>> it = util.Iterator(board)
>>> it.start()
>>> board.analog[0].enable_reporting()
>>> board.analog[0].read()
0.0567

至此说明Firmata运行起来了,你可以看看相关《Firmata详解》 和 pyFirmata 的操作格式,即可通过串口连接Raspberry Pi Meet Arduino 扩展板,从而使树莓派增加多个GPIO、PWM、ADC等功能。

在测试中我发现速度并没有简单协议快,我觉得如果是固定功能,制定一个小巧的私有协议是更方便快捷的,可以看看咱们前面测试的 ADC采集通信例子

游戏手柄遥控小车程序

import pygame
import time
from pyfirmata import Arduino, PWM

# 连接到Arduino
board = Arduino('/dev/ttyACM0')  # 根据实际情况修改串口地址

# 设置5号引脚为PWM输出
motor1_forward = board.get_pin(f'p:{5}:p')
motor1_reverse = board.get_pin(f'p:{6}:p')
motor2_forward = board.get_pin(f'p:{9}:p')
motor2_reverse = board.get_pin(f'p:{10}:p')

# 初始化pygame
pygame.init()

# 初始化手柄
controller = pygame.joystick.Joystick(0)
controller.init()

def control_motors(x_axis, y_axis):
    motor1_speed = y_axis + x_axis
    motor2_speed = y_axis - x_axis
    
    # Ensure motor speeds are within the valid range of -1 to 1
    motor1_speed = max(-1, min(1, motor1_speed))
    motor2_speed = max(-1, min(1, motor2_speed))
    
    # Control motor directions based on speed values
    if motor1_speed >= 0:
        motor1_forward.write(motor1_speed)
        motor1_reverse.write(0)
    else:
        motor1_forward.write(0)
        motor1_reverse.write(-motor1_speed)
    
    if motor2_speed >= 0:
        motor2_forward.write(motor2_speed)
        motor2_reverse.write(0)
    else:
        motor2_forward.write(0)
        motor2_reverse.write(-motor2_speed)

# 主循环
while True:
    # 从事件队列中获取事件
    for event in pygame.event.get():
        if event.type == pygame.JOYAXISMOTION:
            # 获取左摇杆的X和Y轴值
            left_stick_x = controller.get_axis(0)
            left_stick_y = controller.get_axis(1)
            
            # 获取右摇杆的X和Y轴值
            right_stick_x = controller.get_axis(3)
            right_stick_y = controller.get_axis(4)
            
            # 打印摇杆数值
            print("Left Stick X: {:.2f}, Left Stick Y: {:.2f}".format(left_stick_x, left_stick_y))
            print("Right Stick X: {:.2f}, Right Stick Y: {:.2f}".format(right_stick_x, right_stick_y))
            control_motors(left_stick_x, left_stick_y)
            time.sleep(0.01)

发表评论