社区导航

 

搜索
查看: 6581|回复: 6

Micropython pyboard USB数据采集(二)

[复制链接]

127

TA的帖子

0

TA的资源

一粒金砂(高级)

Rank: 3Rank: 3

荣誉会员勋章

发表于 2016-5-6 11:10 | 显示全部楼层 |阅读模式
本帖最后由 allankliu 于 2016-5-6 16:04 编辑

快捷键切换REPL/用户代码

无意中体会了micropython REPL的快捷键的用法。

  1. Control commands:
  2.   CTRL-A        -- on a blank line, enter raw REPL mode
  3.   CTRL-B        -- on a blank line, enter normal REPL mode
  4.   CTRL-C        -- interrupt a running program
  5.   CTRL-D        -- on a blank line, do a soft reset of the board
  6.   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通道的。一个定时器对应一个通道。
  1. >>> adc = pyb.ADC(pyb.Pin.board.X19)
  2. >>> tim = pyb.Timer(6, freq=10)
  3. >>> buf = bytearray(100)
  4. >>> adc.read_timed(buf, tim)
  5. 100
  6. >>> buf
  7. 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。

  1. >>> import array
  2. >>> adc = pyb.ADC(pyb.Pin.board.X19)
  3. >>> tim = pyb.Timer(6, freq=10)
  4. >>> buf = array.array('i',[0 for i in range(100)])
  5. >>> adc.read_timed(buf, tim)
  6. 100
  7. >>> buf
  8. 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大家共享。但是没有来得及察看底层代码。

如果要采集多个模拟数据,最笨的办法就是我现在做的:

  1. adc_x = pyb.ADC(pyb.Pin('X19'))
  2. adc_y = pyb.ADC(pyb.Pin('X20'))
  3. adc_z = pyb.ADC(pyb.Pin('X21'))
  4. adc_a = pyb.ADC(pyb.Pin('Y11'))
  5. adc_b = pyb.ADC(pyb.Pin('Y12'))
  6. adc_c = pyb.ADC(pyb.Pin('X11'))
  7. x = adc_x.read()
  8. y = adc_y.read()   
  9. z = adc_z.read()
  10. tilt = adc_a.read()
  11. pan = adc_b.read()
  12. roll = adc_c.read()
复制代码



分别采集加速度计和陀螺仪的三路ADC,共计六路ADC。此外的方法是采用pyb.ADCAll(),然后访问对应ADC通道。

  1. >>> resolution = 12 # 12bit ADC
  2. >>> adc = pyb.ADCAll(resolution)
  3. >>> adc
  4. <ADCAll>
  5. >>> for i in range(32):
  6. ...     adc.read_channel(i)
  7. ...
  8. ...
  9. ...
  10. 1002
  11. 1025
  12. 976
  13. 1053
  14. 512
  15. 404
  16. 708
  17. 901
  18. 1075
  19. 1058
  20. 1304
  21. 1125
  22. 987
  23. 995
  24. 1100
  25. 1189
  26. 941
  27. 1485
  28. 272
  29. 262
  30. 212
  31. 240
  32. 280
  33. 215
  34. 266
  35. 196
  36. 210
  37. 226
  38. 258
  39. 180
  40. 180
  41. 179
  42. >>>
复制代码



未来得及核实ADC究竟有多少通路。

现在的例子:
  1. # main.py -- put your code here!
  2. import pyb
  3. #import select
  4. import ujson

  5. led = pyb.LED(1)

  6. adc_x = pyb.ADC(pyb.Pin('X19'))
  7. adc_y = pyb.ADC(pyb.Pin('X20'))
  8. adc_z = pyb.ADC(pyb.Pin('X21'))
  9. adc_a = pyb.ADC(pyb.Pin('Y11'))
  10. adc_b = pyb.ADC(pyb.Pin('Y12'))
  11. adc_c = pyb.ADC(pyb.Pin('X11'))

  12. #usb is identical channel of print()
  13. #usb = pyb.USB_VCP()

  14. def setup():
  15.     pass

  16. def loop():
  17.     global led, usb
  18.     global adc_x, adc_x, adc_z
  19.     global adc_a, adc_b, adc_c

  20.     x = adc_x.read()
  21.     y = adc_y.read()   
  22.     z = adc_z.read()
  23.     tilt = adc_a.read()
  24.     pan = adc_b.read()
  25.     roll = adc_c.read()

  26.     #i = x // 33
  27.     #j = y // 33
  28.     js = ujson.dumps({'x':x,'y':y,'z':z, 'tilt':tilt, 'pan':pan, 'roll':roll})
  29.     #usb.write(js)
  30.     #usb.write('\r\n')
  31.     print(js)
  32.     led.toggle()
  33.     pyb.delay(250)

  34. setup()
  35. while True:
  36.     loop()
复制代码


下一步准备利用timer callback可以将其作为多路采集的例子。

多模块编程
为了测试这个功能,我假设一个Modem类(日后再升级支持真正的3G/4G Modem的AT指令集)。保存在flash根目录modem.py文件中。

  1. #!/usr/bin/env python

  2. class Modem(object):
  3.     def __init__(self, ser):
  4.         self.part = "Virtual modem for IoT"
  5.         self.serial = ser

  6.     def setup(self):
  7.         print ("%s:ATE0\r\n"%repr(self.serial))

  8.     def shutdown(self):
  9.         print ("%s:AT+PWRDWN\r\n"%repr(self.serial))
复制代码



然后,重新编写了一个demo2.py,并将boot.py中第一个运行的代码指向demo2.py。

  1. # main.py -- put your code here!
  2. import pyb
  3. #import select
  4. import ujson
  5. import modem

  6. led = pyb.LED(1)
  7. usb = pyb.USB_VCP()
  8. mdm = modem.Modem('uart1')

  9. def setup():
  10.     pass

  11. def loop():
  12.     global led, usb, mdm
  13.     mdm.setup()
  14.     mdm.shutdown()
  15.     led.toggle()
  16.     pyb.delay(500)

  17. setup()
  18. while True:
  19.     loop()
复制代码



结论是和桌面Python没有区别。可以开发较为复杂的设计。

pyboard pin layout

pyboard pin layout

评分

1

查看全部评分



回复

使用道具 举报

9889

TA的帖子

133

TA的资源

管理员

Rank: 13Rank: 13Rank: 13Rank: 13

发表于 2016-6-17 11:31 | 显示全部楼层
汇总在此:
【MicroPython】——by allankliu
http://bbs.eeworld.com.cn/forum. ... 2739&fromuid=536508

玩板看这里:

http://bbs.eeworld.com.cn/elecplay.html

EEWorld测评频道众多好板等你来玩,还可以来频道许愿树许愿说说你想要玩的板子,我们都在努力为大家实现!



回复

使用道具 举报

9809

TA的帖子

14

TA的资源

版主

Rank: 6Rank: 6

测评达人

发表于 2016-5-6 11:36 | 显示全部楼层
Ctrl-A/B的用法我也没有搞懂。


回复

使用道具 举报

1445

TA的帖子

2

TA的资源

纯净的硅(中级)

Rank: 5Rank: 5

测评达人

发表于 2016-5-6 15:04 | 显示全部楼层
高手驾到啊,有没有什么合适的入门python书推荐的?


回复

使用道具 举报

127

TA的帖子

0

TA的资源

一粒金砂(高级)

Rank: 3Rank: 3

荣誉会员勋章

 楼主| 发表于 2016-5-6 16:22 | 显示全部楼层
johnrey 发表于 2016-5-6 15:04
高手驾到啊,有没有什么合适的入门python书推荐的?

我也是刚入门,斗胆推荐网络教程:廖雪峰Python教程。满实用的。

大部头的Python太多了(我积累了大约120多本D版慢慢看)。看过廖的教程后,直入:
Python Tutorial
Python Library Reference
Python HowTo
Python Extending and Embedding
Python/C APi

这些您在安装Python runtime后,在Windows安装路径中C:\Python\Doc\*.chm里面都有(英文)。为何推荐英文,因为翻译的关系,容易混淆多个语言之间的细微差异。比如set,collections,list,array。此外,网络上有中英对照的文档,很棒。

至于技巧方面,推荐Python Cookbook。基于标准库及第三方库展开。

micropython很不错,属于深嵌入式Python。就是目前还没有像样的工程应用。虽然作者已经配合欧洲航天局把micropython设计到航天器中。

此外,树莓派的python基于标准版Linux CPython。如果面对外来的IOT设备(网关),和硬件有关的书倒是需要先看Linux Device Driver,3rd Edition。此外,与硬件相关的Python,不得不要搞懂C API,ctypes,cffi.....等扩展技术。比如如何用ctypes来调用Windows DLL和Linux so 库做二次开发。

入门书必须搞懂Python与C的类型区别。否则容易写出C风格的Python代码。同时注意有意识地加入OOP和AOP,函数式编程。渐渐地,这种思路反过来会促使自己在C/C++中引入类似思维。

很快,在服务器方面,会用到Twisted/Tornado/Flask.......

点评

感谢楼主的推荐,很受用。  详情 回复 发表于 2016-5-6 18:26


回复

使用道具 举报

713

TA的帖子

0

TA的资源

纯净的硅(初级)

Rank: 4

发表于 2016-5-6 18:26 | 显示全部楼层
allankliu 发表于 2016-5-6 16:22
我也是刚入门,斗胆推荐网络教程:廖雪峰Python教程。满实用的。

大部头的Python太多了(我积累了大约 ...

感谢楼主的推荐,很受用。


回复

使用道具 举报

12

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

发表于 2017-3-2 17:15 | 显示全部楼层
结论是和桌面Python没有区别。可以开发较为复杂的设计。

过了这么久,LZ再现一些大作吧。


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

关闭

站长推荐上一条 /5 下一条

  • 论坛活动 E手掌握

    扫码关注
    EEWORLD 官方微信

  • EE福利  唾手可得

    扫码关注
    EE福利 唾手可得

Archiver|手机版|小黑屋|电子工程世界 ( 京ICP证 060456 )

GMT+8, 2020-2-20 13:14 , Processed in 0.230604 second(s), 21 queries , Gzip On, MemCache On.

快速回复 返回顶部 返回列表