Firmata是一个PC与MCU通讯的一个常用协议。其遵旨是能与任何主机PC软件包兼容。到目前为止,已经得到不少语言的支持,这样可方便地将对协议的支持加入软件系统中。Firmata起初是针对于PC与Arduino通讯的固件(Firmware),其目标是让开发者可以通过PC软件完全地控件Arduino。

​ 对于一些刚刚接触软件和单片机实现通讯的同学,可能大部分时间都会画在数据的调试上面。如果有一个程序,能让你像写软件一样的来写单片机,实在是爽歪歪。StandardFirmata是我当是在学校做项目,用到了LattePanda的开发板,这是一款具备完整Win10系统的嵌入式迷你主机,这款板子在上面集成了一块Arduino Leonardo,在它提供的资料当中,第一次接触到了StandardFirmata的强大。传送门

​ 我在C#和Python当中经常用到StandardFirmata,关于它们的API函数使用,我会在这里为大家分享一些我的经验。

单片机的数字与模拟、输入与输出

​ 这里是对一些懂软件不懂硬件的朋友提供一个参考。单片机,单芯片微型计算机,MCU。我们通过编程来操作它,可以让它的引脚产生或接收一个电信号。

​ 根据信号类型的不同,我们将它分为数字信号和模拟信号。数字信号反应的就是高电平和低电平,表达的是有和无、0和1的关系;模拟信号反应的程度,通过对这个引脚进行电压值的采样分析来获得程度量。天黑了我们要开灯,灯的亮和灭就是数字量;晚上我们睡觉觉得温度低,这个温度值就是模拟量。

​ 根据信号流向的不同,我们将它分为输入信号和输出信号。输入信号是通过传感器获得一个电信号,单片机对这个单片机进行了一次读取的操作;输出信号则是单片机产生信号去控制这个传感器或者元件,从而实现一定的功能。我们通过碰撞传感器可以检测当前是否发生碰撞,或者我们通过引脚去驱动一个蜂鸣器来发出声音。

​ 在这里,我们可以简单的理解为,信号基本分为数字输入(读取个开关,Arduino任意口)、数字输出(点亮个LED,Arduino任意口)、模拟输入(读取个光敏传感器,Arduino的A口)、模拟输出(控制灯的亮度,Arduino的PWM口)。而这些,对应的函数如下所示。

读取pin引脚的数字量并保存到整型变量val内(数字输入) int val = digitalRead(pin)
设置pin引脚的电平状态为高电平(数字输出) digitalWrite(pin,HIGH)
读取pin引脚的模拟数值并保存到整型变量val内(模拟输入,仅对A口有效) int val = analogRead(pin)
设置pin引脚的输出值为val(模拟输出,仅对PWM口有效) analogWrite(pin,val)

​ 在使用这些个引脚之前,我们需要先对这个引脚的状态进行一个声明,我们要告知单片机这个引脚是作为输入还是作为输出,当然,使用analogRead模拟输入的时候,不需要声明(别问我为啥,我也不知道QAQ)。

设置pin引脚为输入模式 pinMode(pin,OUTPUT)
设置pin引荐为输出模式 pinMode(pin,INPUT)

​ 在上面一共提到了五个函数,pinMode来设定引脚的模式,analogRead来读取引脚的模拟数值,analogWrite向引脚输出一个模拟值,digitalRead来读取引脚的数字数值,digitalWrite向引脚输出一个高低电平。

Python使用Firmata的pyFirmata库

​ 不管何时何地,Python这玩意是真的香,搞界面人家能接C++的Qt(PyQt),搞服务器人家有微型服务器框架(Flask、Django等),搞单片机人家还有MicroPython,甚至人工智能的计算现在好多都是Python。

​ 关于Firmata协议,Python目前最强的应该是pymata4(传送门,大家有兴趣的话可以自己来研究一下),PyMata是支持完整StandardFirmata协议的高性能、多线程、非阻塞 python第三方功能包。我这利使用的pyFirmata,大家可以通过pip在自己的电脑上面(Win10和Linux都可以)进行安装。

​ 我们先来看一组python调用Firmata协议点灯的代码。

from pyfirmata import Arduino,util	#从pyfirmata中导入Arduino、util模块
import time	#导入time模块·

board = Arduino('COM3')	#实例化对象,传入串口号作为参数

#死循环闪灯
 while True:
 	board.digital[13].write(0) #向端口13写入0,0代表灭灯
 	time.sleep(1)	#延时1秒
 	board.digital[13].write(1) #向端口13写入1,1代表亮灯
 	time.sleep(1)	#延时1秒

​ 这里的board.digital[13].write(0),和我们上面的digitalWrite是一样的,前者是Python下的代码,后者是Arduino内的代码。


class pyfirmata.pyfirmata.Board(port, layout=None, baudrate=57600, name=None, timeout=None)

​ firmata协议的默认波特率是57600,大家在使用的时候如果波特率发生变化,比如修改为115200,则声明模式如下:


board = Arduino("COM3",baudrate=115200)

​ 这部分语句用于实例化一个硬件对象。

​ 在我们程序执行结束之后,我们通过下面的语句可以释放掉这个设备。


board.exit()

​ 关于Firmata比较复杂的地方在这里不详细的说明,这里只会给大家将IO的使用给大家分析到,其他内容大家可以去参考我们提供的文档来进行学习。

​ board.digital[pin].write(val),数字输出,设置pin引脚的状态为val(0低电平,1高电平)。

​ board.digital[pin].read(),数字输入,读取pin引脚的数字量。

​ board.analog[pin].write(val),模拟输出,设置pin引脚的模拟量状态值为val,val范围0~1

​ board.analog[pin].read(),模拟输入,读取pin引脚的模拟量,范围0~1。

​ 这四个语句大家可以自己试一下,看下效果如何。Firmata对舵机也有着很好的支持,如下:


board.servo_config(pin, min_pulse, max_pulse, angle)

​ pin是舵机所使用的引脚;min_pulse是当前舵机的最小脉冲,max_pulse是当前舵机的最大脉冲,angle是当前舵机的角度。Arduino默认的min_pulse为544,默认的max_pulse为2400(不知道咋算的,管用)。我们此次的机械臂主要就是使用这个函数。

​ 关于其他内容,大家可以去看我们提供的文档来进行尝试。

C#使用StandardFirmata

​ C#使用Firmata的内容是从LattePanda开发板资料学习到的,大家可以在这里下载到C#使用Firmata的函数文件。传送门

​ 在这里你会下载得到一个Arduino.cs的文件,大家可以先来看一下内容。

​ 我在这里以一个简单的Demo给大家做演示。这个Demo实现是四路继电器控制、一路PWM条件灯光强弱、一路LM35数字温度传感器。它看起来是这个样子的。

​ 这部分是我所使用的Arduino.cs文件,因为这个我在ROS下用的较多,所以将命名空间修改为了ROS_Firmata,这个名字无所谓。

​ 从右侧可以看到我导入了Firmata的cs文件,而在我的Form1.cs(主界面)下可以看到相关的实例化以及引脚的初始化。

​ 然后是我们的Firmata驱动函数的组成,如下所示。

​ 这个位置显示的不是很完整,大家可以自行打开项目进行查看,代码也给大家提供有注释。

​ 此次机械臂使用了StandardFirmata协议,对应的C#上位机软件也会在此次一并向大家提供。同时也有一个小的Demo,关于示波器和信号产生器(OASG)的Demo也供大家查阅(精度垃圾的很,只是抓了数据就显示,没处理)。

JavaScript使用Firmata

​ 呃呃呃,本人在前端方面是菜鸡,参考链接吧!传送门