本帖最后由 allankliu 于 2016-4-20 11:50 编辑
第二贴:micropython使用中遇到的懵圈问题(待续)
感谢再感谢
感谢EEWorld编辑和dcexpert,刚刚拿到他们提供的micropython pybV1.0版本。说说我上手使用的心得。
EEWorld版本保留了George的大多数原始设计,包括USB,TF,按键和扩展口,但移除了3D加速度计,增加了LED。我可以理解dcexpert这么做的原因。因为小批量的PCBA要焊接QFN或者更小封装IC/传感器需要额外的人力。不过从焊接工艺来看,应该使用了MASK+回流焊的工艺。按理来说,QFN应该问题不大。但是发现板上
实际上,我已经在NUCLEO F401上运行了micropython REPL(交互式环境)。但是要评估micropython的其他特性,如内置文件系统和TF卡中的文件系统,必须要有USB和SDCard接口。而大部分NUCLEO 64(QFP64)都没有板载USB接插件,甚至连USB必须的8MHz晶体和电容都没有焊接。所以这些PCBA上只可以使用REPL交互环境进行评估,而无法评估文件系统和USB串口。所以,再次感谢EEWorld/dcexpert让我省了时间来构建硬件,这也是开源的魅力。
为什么我纠结Python in Embedded
最近我在写一本书,在第二章部分介绍了Python的基础知识,包括内建类型,数据结构,函数,模块,控制流,OOP,进程,线程.......确切地说,我几乎迷失在Python的内部实现中了。在这个过程中,逐渐进一步体会了作为嵌入式C语言到嵌入式Python编程所需要花费的努力。难怪George会将micropython的最初版本设在20美刀,的确是个艰难的过程。只有甘之如饴的人才能够挺过这个苦行的过程。
如果资源足够,如Linux单板机中,ARM9至少有64MB RAM+128MB ROM,那么Python可以为我们带来以下好处:
- Python容易学习,容易入门,所以C语言开发者可以很容易入门。;
- Python可以节省代码,其内置类型(和数据结构)、内置函数和标准库帮助开发者解决了不少日常的问题;
- Python标准库太丰富了;
- Python提供更加丰富的内置类型,可用于高层应用相关的数据结构;
- Python内部所有类型都是对象,不仅是类型,对象,包括函数,代码等等,所以OOP很自然;
- Python不仅可以面对过程编程,面向对象,还可以做更高抽象度的函数式编程,甚至可以在一句话里实现算法和迭代。
对应地,Python在深嵌入式(尤其是RAM有限的MCU系统中)是艰难的。必须正确理解、并使用所有的内置类型。否则等着Stack/Heap爆掉和死机吧。
Python与C的区别(EE背景工程师必须要了解)
仅具备C语言开发的工程师看Python有个类比,如果台湾省工程师初到大陆,会认为字好像,但是仔细看看存在很多不同。
对于C语言开发者来说,Python的区别在于:
- 类型丰富,不仅有数值类型,还有字符串,Unicode字符串,tuple/list/set/dict等类型,还有许多其他类型;
- 类型分类多样,从不同角度,类型有可变,不可变,可迭代,序列类型,还有迭代器,生成器......分类方式;
- 可变和不可变类型在C中没有,C语言中不可变的是常量,恰恰在Python中没有对应实现。
- Python中只有整数和长整数,没有unsigned char,word,double word的区别。
- Python浮点数规定为双精度型,(micropython却为单精度型)。
- Python有复数,C语言必须采用struct来实现。
- 变量在系统中的表达不一样,不是传值,而是传引用(暂可以理解为指针)。所以,x,y=y,x这种交换是合法的,而在C中必须有中间变量;
- 函数也是变量,可以有别名和默认参数等,还可以把函数作为参数,也可以返回参数,形成闭包等。
- 函数可以返回多个变量。所以完成 a,b,c,_,e,f = myfunc()这种方式。
- 序列如tuple/list可以切片,切断...配合匿名函数,map(), reduce(), filter(), sorted()可以部分实现函数式编程,节省代码。
- ......还有好多区别,无法列举。
就目前在嵌入式系统中,大致需要完成从数据采集到数据后处理的过程。需要对于内建类型,内建函数,变量,控制流,函数(即函数式编程),面向对象编程,模块,类型迭代等只是重点了解一下。才不会发生以C语言思路编Python代码现象出现。
举例来说,在C/Java中,for循环都是基于数组下标进行迭代。而Python却可以在所有可迭代类型(包括用户类)中进行迭代。当然,你可以在Python中以数组下标方式迭代,没有问题。但是浪费资源和代码空间。
C:
int i;
for (i = 0; i < 100; i++)
print("%d",i);
Python迭代整数
for i in range(100):
print("%d",i)
Python迭代字符串
>>> for i in "helloworld":
... print(i),
...
h e l l o w o r l d
Python3 与micropython的区别
不过在我的测试过程中,发现micropython并没有实现一些我所期待的方法。比如说列表切片。
>>> a = 'hello world'
>>> b = a[0:-2]
>>> b
'hello wor'
>>> c = a[0:-1:2]
Traceback (most recent call last):
File "", line 1, in
NotImplementedError: only slices with step=1 (aka None) are supported
>>>
在a[0:-2:2]中使用步长为2的切片就抛出一个NotImplementedError。
如何切换REPL、内置文件系统代码和外置TF卡系统代码
一开始对于这个问题有些懵圈。后来发现他们之间存在优先级:
TF>Flash,而Flash>REPL。
用户可以在REPL中测试一些性能和算法。更新Flash中的main.py后,REPL就不在运行了。必须将main.py内容清空(我还是保留main.py文件),才可以再切换会REPL测试代码。
是否支持模块化编程?
对于micropython能够编写何种复杂度和规模的应用代码没有底。这个对于实际工程使用还是有影响的。所以我需要针对多模块的micropython做些实验。留待后文分享。
物联网常见任务
- 数据采集:从ADC,GPIO或者透过SPI/I2C总线读取传感器数据,由于非常贴近硬件,读取的数据都是硬件寄存器数值,宽度为字节,字,双字,8~32位宽无符号整数。
- 数据缓冲:任何数据从一个实体传输到下一个实体,往往需要将数据进行缓冲。这些都是在系统RAM中实施。
- 数据多路复用和解多路复用:主要用于将多组数据打包后在通讯通道中传输。
- 数据序列化和解序列化:在逻辑通道传输前将数据对象串行化,传输后解析到数据对象。
- 数据压缩和解压缩:为了减少冗余数据对于通道带宽占用,而实现的压缩和解压缩。
- 数据传输:通过各种协议将数据传输给对等实体。
- 数据后处理:主要指对于原始数据进行类型转换,缩放,归一化,频域转化等。
- 数据持久化:RAM是有限的,必须将数据持久化到磁盘中,以后才可以再利用。
- 数据检索:通过某种手段如数据库,对已有数据进行检索。
- 数据分析:统计、融合、挖掘,对原始数据进行统计分析,合并其他数据,提炼出内在模式,挖掘出商业价值;
- 数据可视化:将原始数据和统计数据通过图表、动画形式提供给用户。
- 数据转发:包括推送,异步通知等都归类于此。
上文提到了micropython与Python的区别。所以需要针对micropython的应用场景:数据采集~数据持久化,利用micropython的内置类型和内置函数,以及标准micro库做些实验来测试。