用Arduino与Mathematica编写世界
作者:Ian Johnson, Wolfram Research
原文:http://community.wolfram.com/groups/-/m/t/315748
大家好,今天我来给大家演示一下Mathematica写的Arduino驱动,
使用了Mathematica 10中的新函数。下面的演示用到了以下工具:
- Mathematica 10
- Arduino IDE
- Arduino板(推荐使用Uno)
- 220Ω电阻
- 10kΩ电阻
- LED
- 瞬时按压按钮
- 两个电位计
上面当中的硬件都可以在Arduino官方的新手包找到,市面上几乎所有的Arduino包也都有这些东西。
我开发的函数理论上是和操作系统无关的,也就是说,Linux、Mac OS X、Windows等等都可以跑。但是我在开发时是用的Windows,所以我只能保证它在Windows上好使。很欢迎其他同好在Linux和Mac OS X上试试,并把结果贴出来。
第一步是把我给Arduino写的程序(Arduino sketch)上传到Arduino上,你可以用Arduino IDE来做这一步。
想要下载Arduino程序的话,请看帖子附件。我把文件扩展名从.ino改成.txt了,所以你得把它改回来,才能让Arduino读取。
然后选择你的Arduino型号(我这个是给Uno做的,我只能保证它在Uno上正常工作,就像前面说的,理论上可以在任何Arduino型号上运行),打开你下载的.ino文件,把它上传到板子上。
程序上传完成后,连接Arduino,确定你的Arduino接到了哪个串口上。有一个简单的方法:打开Arduino IDE,在菜单中找“工具→端口”。在Windows系统上,端口名是"COMXX"
,"XX"
是一个非负整数。在Mac上,一般是"/dev/tty.usbmodemXXXXXX"
,或者"/dev/tty.usbserialXXXXXX"
,“X”是由字母和数字组成的字符串。在Linux中,一般是"/dev/ttyXXXX"
,“X”也是字母和数字构成的字符串。把这个串口名记住,过一会我们要用。
最后一步是安装驱动。可以在帖子附件下载到。下载之后用Mathematica 10打开,然后运行:
1 | << "文件路径/ArduinoDriver.m" |
“文件路径”即你下载的文件所在路径,比如在Windows上,可能是C:\Users\Ian\Downloads\ArduinoDriver.m
。
现在打开我们正在使用设备的连接:
1 | arduinoObject = DeviceOpen["Arduino", "COM4"] |
“COM4”是我的串口,把它换成你的Arduino连接的串口。为了实现基本的设备控制,我们可以用:
1 | DeviceWrite[arduinoObject, <|pinNumber -> 1|>] |
这样就可以控制pinNumber的数字状态。pinNumber可以是2到13的整数,也可以是代表模拟针脚的字符串,即“A0”到“A5”,注意首字母必须大写。
按照下面的Fritzing图接好LED:
然后就可以在Mathematica中写LED闪烁的代码了:
1 | Do[( |
这么做会使连接在pinNumber
的LED闪烁5次,每次1秒钟。注意pinNumber
必须在别处定义过,对于上述代码应该是11。
我们也可以使用DeviceWrite
函数向Arduino发送信息,使Arduino模拟输出。语法如下:
1 | DeviceWrite[arduinoObject, {pinNumber, "analogOutput", state}] |
pinNumber
是一个有效的针脚数值,state
是从0到255的整数,对应着PWM针脚的8位输出。
如果你的LED正如上图连接着,下面的代码可以让你调节LED亮度。注意,当数值大幅变化时,亮度会回跳,这是一个已知的bug。
1 | Manipulate[DeviceWrite[arduinoObject, {11, "analogOutput", analogWriteValue} ], { {analogWriteValue, 0, "Value"}, 0, 255, 1}] |
我们也可以从Arduino读取针脚状态,使用DeviceRead
函数。但是在我们可以读取数据之前,我们需要用DeviceConfigure
函数配置数据读取。通过以下语句将pinNumber
针脚配置为一个数字输入:
1 | DeviceConfigure[arduinoObject, <|pinNumber -> "digitalInput"|>] |
模拟针脚同样适用。语法相同,只需要把“digitalInput
”改成“analogInput
”。注意,在使用多个针脚时,上面的语句是可以扩充的,用了一个关联(association,Mathematica 10引入的新特性,类似于其他语言中的“字典”,译者注)。在这种情况下,我们只需要在联合中增加新的键值对就行了。
我们来试一试在下面的简单电路中读取一个针脚,用到了一个按钮和一个电阻:
对上面的电路,为了读取数值,用如下语句:
1 | DeviceRead[arduinoObject, pinNumber] |
这条语句返回针脚的数值,0代表低电平,1代表高电平。如果就按上面的电路图搭建的话,按钮按下时表达式估值返回1,没有按下时返回0。在表达式第一次估值时,串口读取缓存可能一次会读取两个数值再更新,但是这之后就会变得正常起来。
如果pinNumber
指定了一个模拟输入针脚,返回值应该是0到1023的一个数,对应着Arduino模拟针脚上的10位输出。这一函数同样可以使用一个针脚编号列表作为参数,返回值就成了一个由多个针脚与对应读到数值构成的关联(association)。注意,pinNumber
既可以是2到13的非负整数,也可以是一个字符串表示“AX”,X是0到5的非负整数。
如下所示:
1 | DeviceRead[arduinoObject, {pinNumber1, pinNumber2, ...}] |
返回为一个关联<|pinNumber1->state1, pinNumber2->state2, ... |>
。
下面的电路演示模拟输入函数。最理想的是用游戏摇杆做这个,但是下面我们仅仅用两个电位器就可以实现(其实游戏摇杆就是电位器)。
下面的代码可以在Mathematica中显示一个坐标系,由两个电位计控制。首先要做的事是初始化模拟输入的针脚。我们可以从DeviceRead中通过关联(association)读取两个电位器,然后用Values函数得到数值,再将坐标系单位除以1023,使圆的坐标映射到0和1之间。我们也同样将中间值从0.5移到原点。
1 | DeviceConfigure[arduinoObject, <|"A0" -> "analogInput", "A1" -> "analogInput"|>]; |
谢谢!