|
Micropython pyboard USB数据采集(二)
[复制链接]
本帖最后由 allankliu 于 2016-5-6 16:04 编辑
快捷键切换REPL/用户代码
无意中体会了micropython REPL的快捷键的用法。
- Control commands:
- CTRL-A -- on a blank line, enter raw REPL mode
- CTRL-B -- on a blank line, enter normal REPL mode
- CTRL-C -- interrupt a running program
- CTRL-D -- on a blank line, do a soft reset of the board
- CTRL-E -- on a blank line, enter paste mode
复制代码
CTRL-C可以中断REPL以及Flash中运行的程序。这意味着即使在某些占用USB串口的场景(比如数据采集)中也可以很方便地中断并切换回REPL。
同时,用户代码必须没有运行时bug/未捕捉的异常,否则系统会切换到REPL。此时,开发者可以更新Flash代码,使用CTRL-D进行软启动,此时,数据采集程序可以从REPL处获得USB串口的访问权。
日后,再体会Ctrl-A/B/E的妙处。
ADC引脚图
查阅micropython pyboard最简单的方式就是察看原版Pin Layout图。查原理图和丝网太费时间。下拉到底可以看到布局图。
ADC定时采集
查阅文档后,发现还蛮多讲究的。首先内置库中定时器采集是针对某个ADC通道的。一个定时器对应一个通道。
- >>> adc = pyb.ADC(pyb.Pin.board.X19)
- >>> tim = pyb.Timer(6, freq=10)
- >>> buf = bytearray(100)
- >>> adc.read_timed(buf, tim)
- 100
- >>> buf
- bytearray(b'>/\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x04\x03\x04\x03\x03\x03\x03\x03\x04\x03\x03\x03\x03\x03\x03\x03\x03\x04\x04\x03\x03\x03\x03\x04\x04\x03\x04\x03\x03\x04\x03\x04')
复制代码
这里发现几个问题:
1)adc.read_timed()是堵塞型的,输入adc.read_timed()之后,需要等待10秒才返回100个字节。适合批量采样的场景。
2)buf采用了bytearray,而ADC本身是12bit。所以精度丢失了。所以必须采用Python中的数组array。
- >>> import array
- >>> adc = pyb.ADC(pyb.Pin.board.X19)
- >>> tim = pyb.Timer(6, freq=10)
- >>> buf = array.array('i',[0 for i in range(100)])
- >>> adc.read_timed(buf, tim)
- 100
- >>> buf
- array('i', [1001, 166, 100, 105, 104, 100, 99, 98, 102, 103, 98, 98, 101, 102, 98, 101, 101, 99, 100, 96, 93, 98, 99, 93, 92, 98, 94, 97, 94, 90, 96, 96, 92, 90, 94, 92, 90, 89, 88, 93, 93, 90, 87, 92, 92, 93, 87, 91, 86, 85, 88, 90, 85, 84, 87, 85, 82, 88, 82, 86, 87, 81, 81, 85, 86, 80, 84, 84, 84, 84, 80, 78, 83, 83, 80, 83, 82, 78, 82, 78, 76, 80, 80, 76, 75, 78, 75, 80, 74, 80, 81, 77, 74, 79, 78, 74, 78, 77, 73, 78])
复制代码
array要比list节省资源,但我这里代码利用了列表生成式(list comprehesions),还真不好说是否节省了资源。另外一种替代方案是buf = array.array('i', range(100)),但是数组初始值并非全零。
这在少量ADC采样可行,但是多个通道就有点儿耗费定时器,而且还居然是堵塞式的。除非这个Timer tigger大家共享。但是没有来得及察看底层代码。
如果要采集多个模拟数据,最笨的办法就是我现在做的:
- adc_x = pyb.ADC(pyb.Pin('X19'))
- adc_y = pyb.ADC(pyb.Pin('X20'))
- adc_z = pyb.ADC(pyb.Pin('X21'))
- adc_a = pyb.ADC(pyb.Pin('Y11'))
- adc_b = pyb.ADC(pyb.Pin('Y12'))
- adc_c = pyb.ADC(pyb.Pin('X11'))
- x = adc_x.read()
- y = adc_y.read()
- z = adc_z.read()
- tilt = adc_a.read()
- pan = adc_b.read()
- roll = adc_c.read()
复制代码
分别采集加速度计和陀螺仪的三路ADC,共计六路ADC。此外的方法是采用pyb.ADCAll(),然后访问对应ADC通道。
- >>> resolution = 12 # 12bit ADC
- >>> adc = pyb.ADCAll(resolution)
- >>> adc
- <ADCAll>
- >>> for i in range(32):
- ... adc.read_channel(i)
- ...
- ...
- ...
- 1002
- 1025
- 976
- 1053
- 512
- 404
- 708
- 901
- 1075
- 1058
- 1304
- 1125
- 987
- 995
- 1100
- 1189
- 941
- 1485
- 272
- 262
- 212
- 240
- 280
- 215
- 266
- 196
- 210
- 226
- 258
- 180
- 180
- 179
- >>>
复制代码
未来得及核实ADC究竟有多少通路。
现在的例子:
- # main.py -- put your code here!
- import pyb
- #import select
- import ujson
- led = pyb.LED(1)
- adc_x = pyb.ADC(pyb.Pin('X19'))
- adc_y = pyb.ADC(pyb.Pin('X20'))
- adc_z = pyb.ADC(pyb.Pin('X21'))
- adc_a = pyb.ADC(pyb.Pin('Y11'))
- adc_b = pyb.ADC(pyb.Pin('Y12'))
- adc_c = pyb.ADC(pyb.Pin('X11'))
- #usb is identical channel of print()
- #usb = pyb.USB_VCP()
- def setup():
- pass
- def loop():
- global led, usb
- global adc_x, adc_x, adc_z
- global adc_a, adc_b, adc_c
- x = adc_x.read()
- y = adc_y.read()
- z = adc_z.read()
- tilt = adc_a.read()
- pan = adc_b.read()
- roll = adc_c.read()
- #i = x // 33
- #j = y // 33
- js = ujson.dumps({'x':x,'y':y,'z':z, 'tilt':tilt, 'pan':pan, 'roll':roll})
- #usb.write(js)
- #usb.write('\r\n')
- print(js)
- led.toggle()
- pyb.delay(250)
- setup()
- while True:
- loop()
复制代码
下一步准备利用timer callback可以将其作为多路采集的例子。
多模块编程
为了测试这个功能,我假设一个Modem类(日后再升级支持真正的3G/4G Modem的AT指令集)。保存在flash根目录modem.py文件中。
- #!/usr/bin/env python
- class Modem(object):
- def __init__(self, ser):
- self.part = "Virtual modem for IoT"
- self.serial = ser
- def setup(self):
- print ("%s:ATE0\r\n"%repr(self.serial))
- def shutdown(self):
- print ("%s:AT+PWRDWN\r\n"%repr(self.serial))
复制代码
然后,重新编写了一个demo2.py,并将boot.py中第一个运行的代码指向demo2.py。
- # main.py -- put your code here!
- import pyb
- #import select
- import ujson
- import modem
- led = pyb.LED(1)
- usb = pyb.USB_VCP()
- mdm = modem.Modem('uart1')
- def setup():
- pass
- def loop():
- global led, usb, mdm
- mdm.setup()
- mdm.shutdown()
- led.toggle()
- pyb.delay(500)
- setup()
- while True:
- loop()
复制代码
结论是和桌面Python没有区别。可以开发较为复杂的设计。
|
赞赏
-
1
查看全部赞赏
-
|