arduino uno r3 驱动和 Arduino micro只是大小不同吗?哪个好玩些?

Python 与嵌入式系统系列 - Arduino选型 - 知乎专栏
{"debug":false,"apiRoot":"","paySDK":"/api/js","wechatConfigAPI":"/api/wechat/jssdkconfig","name":"production","instance":"column","tokens":{"X-XSRF-TOKEN":null,"X-UDID":null,"Authorization":"oauth c3cef7c66aa9e6a1e3160e20"}}
{"database":{"Post":{"":{"contributes":[{"sourceColumn":{"lastUpdated":,"description":"有趣的Python小知识。","permission":"COLUMN_PUBLIC","memberId":2154281,"contributePermission":"COLUMN_PUBLIC","translatedCommentPermission":"all","canManage":true,"intro":"有趣的Python小知识。","urlToken":"python-dev","id":6691,"imagePath":"9f2cbe8b7a1e5ef55d5da8.png","slug":"python-dev","applyReason":"","name":"蛇之魅惑","title":"蛇之魅惑","url":"/python-dev","commentPermission":"COLUMN_ALL_CAN_COMMENT","canPost":true,"created":,"state":"COLUMN_NORMAL","followers":3082,"avatar":{"id":"9f2cbe8b7a1e5ef55d5da8","template":"/{id}_{size}.png"},"activateAuthorRequested":false,"following":false,"imageUrl":"/9f2cbe8b7a1e5ef55d5da8_l.png","articlesCount":28},"state":"accepted","targetPost":{"titleImage":"/4adf15e091f957b0ced814_r.jpg","lastUpdated":,"imagePath":"4adf15e091f957b0ced814.jpg","permission":"ARTICLE_PUBLIC","topics":[10388],"summary":"摘要:万金油Python在嵌入式领域同样大有作为。这一系列的文章,主要聊一聊如何使用Python与现实世界的电子电路进行交互。 ############################################################## 花一顿工作餐的钱,买一块小电路板,再花十几分钟看看文档就能迅…","copyPermission":"ARTICLE_COPYABLE","translatedCommentPermission":"all","likes":0,"origAuthorId":2154281,"publishedTime":"T22:54:02+08:00","sourceUrl":"","urlToken":,"id":246910,"withContent":false,"slug":,"bigTitleImage":false,"title":"Python 与嵌入式系统系列 - Arduino选型","url":"/p/","commentPermission":"ARTICLE_ALL_CAN_COMMENT","snapshotUrl":"","created":,"comments":0,"columnId":6691,"content":"","parentId":0,"state":"ARTICLE_PUBLISHED","imageUrl":"/4adf15e091f957b0ced814_r.jpg","author":{"bio":"Brony","isFollowing":false,"hash":"ea31ec803eef405b08c99a1e38ba7439","uid":24,"isOrg":false,"slug":"jho-jerry","isFollowed":false,"description":"消灭人类暴政","name":"Jerry Jho","profileUrl":"/people/jho-jerry","avatar":{"id":"b803b6ce6cebf7e90e2eddbe","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false,"isBanned":false},"memberId":2154281,"excerptTitle":"","voteType":"ARTICLE_VOTE_CLEAR"},"id":283010}],"title":"Python 与嵌入式系统系列 - Arduino选型","author":"jho-jerry","content":"摘要:万金油Python在嵌入式领域同样大有作为。这一系列的文章,主要聊一聊如何使用Python与现实世界的电子电路进行交互。############################################################## 花一顿工作餐的钱,买一块小电路板,再花十几分钟看看文档就能迅速上手一个可编程的电子小玩具——Arduino的出现让这段话成为了现实。正如Python在非计算机专业领域大放光彩一样,Arduino在非电子工程领域也得到了广泛应用,尤其受到交互设计艺术家们的青睐。Arduino是一系列基于AVR以及ARM单片机的开发板、一整套软件开发环境以及一个活跃的开发社区的共用品牌。除了芯片本身以及驱动程序外,所有开发板设计、编译器、集成开发环境以及示例、库都是开源的。玩转Arduino,你只需要支付一点点硬件物料费用即可。Arduino的设备以及扩展板非常丰富,所有Arduino或其兼容设备均使用统一的软件平台。本篇文章谈一谈Arduino设备的选型。这张表格列出了当前(2015年中)主流的Arduino硬件平台。当代集成电路技术已经能够把计算机系统的主要部件CPU、SRAM、Flash以及USB接口等集成到一块芯片当中,即System-on-a-Chip(SoC)。Arduino的SoC主要使用两款:不带USB接口的ATmega 328和带USB接口的 ATmega 32U系列。此外最后一行Arduino DUE是最近才推出的ARM单片机版。USB接口不是必须的,除了SoC本身能够提供,一些开发板还利用第三方的USB转串口芯片。Arduino通常不是为了独立运行而设计,而是需要和各种外围电子电路交互,故每一款产品都提供了相当数量的IO管脚。当代的SoC还提供可编程的PWM输出,供连接舵机等设备。IO管脚的数量和所选用的具体SoC有关。下面分别介绍不同产品的定位。这张表格列出了当前(2015年中)主流的Arduino硬件平台。当代集成电路技术已经能够把计算机系统的主要部件CPU、SRAM、Flash以及USB接口等集成到一块芯片当中,即System-on-a-Chip(SoC)。Arduino的SoC主要使用两款:不带USB接口的ATmega 328和带USB接口的 ATmega 32U系列。此外最后一行Arduino DUE是最近才推出的ARM单片机版。USB接口不是必须的,除了SoC本身能够提供,一些开发板还利用第三方的USB转串口芯片。Arduino通常不是为了独立运行而设计,而是需要和各种外围电子电路交互,故每一款产品都提供了相当数量的IO管脚。当代的SoC还提供可编程的PWM输出,供连接舵机等设备。IO管脚的数量和所选用的具体SoC有关。下面分别介绍不同产品的定位。1. Arduino UNO -学习型开发板 Arduino UNO是Arduino的标准硬件平台。作为一款练习用的Arduino开发板,Arduino UNO把IO接口的位置定义成了标准。玩家可以继续购买符合IO标准的第三方模块,例如,SD卡、WiFi等,形成堆叠式的设计方案(如本文的题图)。推荐给初学者的模块是下面这个面包板扩展板(卖Arduino 的商家一般都有出售),然后再购买一些电阻、LED等进行连接,价格也非常便宜。作为一款练习用的Arduino开发板,Arduino UNO把IO接口的位置定义成了标准。玩家可以继续购买符合IO标准的第三方模块,例如,SD卡、WiFi等,形成堆叠式的设计方案(如本文的题图)。推荐给初学者的模块是下面这个面包板扩展板(卖Arduino 的商家一般都有出售),然后再购买一些电阻、LED等进行连接,价格也非常便宜。Arduino UNO开发板上除了一块双列直插的单片机,还有用于程序烧写和一般通信的串口,并使用ATmega 16U将串口转为USB。在Mac OS X和主流Linux发行版中,系统自带了它的驱动程序,并将其映射成了一个串口设备。在Windows中,安装Arduino的软件开发环境的过程中会自动安装好它的驱动程序。正是因为Arduino UNO是标准的开发环境,Arduino社区给予之最好的支持。Arduino UNO开发板上除了一块双列直插的单片机,还有用于程序烧写和一般通信的串口,并使用ATmega 16U将串口转为USB。在Mac OS X和主流Linux发行版中,系统自带了它的驱动程序,并将其映射成了一个串口设备。在Windows中,安装Arduino的软件开发环境的过程中会自动安装好它的驱动程序。正是因为Arduino UNO是标准的开发环境,Arduino社区给予之最好的支持。由于Arduino的图纸是开放的,任何人都可以大量生产。通常淘宝上的售价不到30元一块,只要认准主芯片和USB芯片的型号就不会有兼容性问题。如果对质量有一定要求可以购买DFRobot的黑板,去亚马逊买原装代购就没有必要了。Arduino UNO使用USB B口,也就是USB打印机常用的口。一般商家会送一根USB线。如果嫌质量不好可以去某东上买。除了使用USB供电,它还可以用2.1mm中心正极的变压器供电。但一般来说USB提供的电流已经足够。2. Arduino PRO MINI - 应用型核心板Arduino PRO MINI非常小巧,它的电路板面积受限于2.54mm插针的约束。小得不能再小了。Arduino PRO MINI一般称为ATmega 328的最小系统。除了必备的电源、滤波电容和Arduino必须的Pin13 LED外不再有其他附属器件。在购买的时候,卖家也不会把插针焊接在板子上,而是要求买家自行根据应用场景决定焊在哪一边。Arduino PRO MINI适合作为应用型最小系统板,通常在你的创意成品中使用,比如作为系统的一部分与其他设备连接,它的体积小、元件少,价格也最便宜。Arduino 官方的PRO MINI的版型是这样的:即A4~A7这4个PIN位于板子的内部。这种板子在淘宝上也能买的到(关键词 Arduino PRO MINI原版),但是价格比较贵,并且用起来并不方便。即A4~A7这4个PIN位于板子的内部。这种板子在淘宝上也能买的到(关键词 Arduino PRO MINI原版),但是价格比较贵,并且用起来并不方便。淘宝上大量出售的是这个所谓改进版:所改进之处是减小了Reset按键,然后把A6、A7放在板子边缘,这样更加方便。所改进之处是减小了Reset按键,然后把A6、A7放在板子边缘,这样更加方便。向Arduino PRO MINI烧写程序需要带有DTS信号的6脚串口转USB小板,卖家也会一并出售。这种串口转USB小板通常需要安装独立的驱动程序,购买之前需看清用了哪款芯片,并在厂家官方网站得到驱动程序或向卖家索取。 Arduino PRO MINI 根据电源管理器的不同配置,有独立的3.3V版本和5V的版本。可根据实际电压需要进行选择。之所以称为 Arduino PRO MINI,是因为它是Arduino PRO 的尺寸简化版,而电路功能完全一致。 3. Arduino PRO MICRO - 应用型USB核心板Arduino PRO MICRO采用了内建USB的ATmega 32U芯片,除此之外,保持了与MINI类似的小巧体积。由于继承了USB供电,它的引脚电压是5V。在产品上,Arduino PRO MICRO适合与需要由于继承了USB供电,它的引脚电压是5V。在产品上,Arduino PRO MICRO适合与需要保持与上位机USB进行连接的产品。这样比较方便。很多交互艺术作品多使用树莓派作为上位机,使用Arduino PRO MICRO,一条USB线就能搞定两者的连接,特别方便。(当然也可以用5V版的Arduino PRO MINI进行串口直连)在开发过程中, Arduino PRO MICRO要使用Arduino Leonardo相同的配置。特别的,由于ATmega 32U直接与上位机互联,Arduino PRO MICRO可以被配置为一个USB键盘。Arduino PRO MICRO也适合学习之用。Arduino PRO MICRO的版型引脚与Arduino PRO MINI几乎完全相同。将插针方向向下焊接,得到的板子可以插到面包板上,与其他电路相连接。4. Arduino NANO - 应用型USB核心板,慎购!把一块Arduino PRO MINI加上一款第三方的串口转USB芯片就得到了Arduino NANO。这款Arduino NANO采用了FTDI的串口转USB方案 猫腻就出在这第三方的串口转USB芯片上。由于淘宝卖家的素质参差不齐,如果你运气不好,很容易买到稳定性和兼容性都很差的串口转USB芯片。不仅驱动很难装上,或者装好了过段时间用不了,而且会出现数据丢失等各种坑爹问题。所以没有必要为了省几块钱浪费宝贵的时间。5. Arduino DUE - 高性能的土豪级选择作为一款新品,Arduino DUE采用了ARM核心的SoC。不过,这个ARM和咱们智能手机里用的ARM等级是不一样的。Arduino DUE中SoC的ARM核心是Cortex-M3,属于ARM家族的单片机序列(智能手机里的ARM核心是Cortex-A,属于应用处理器序列)。但尽管如此, Arduino DUE的性能要比ATmega版Arduino强大许多,适合于网络编解码等密集型运算。但是毕竟是单片机,让它做个视频编解码还是困难了点。原装的Arduino DUE非常贵,300多块钱,都能买个树莓派了。感谢勤劳智慧的中国人民,把它的售价降到了100块钱以内。原装的Arduino DUE非常贵,300多块钱,都能买个树莓派了。感谢勤劳智慧的中国人民,把它的售价降到了100块钱以内。虽然处理器不同,Arduino DUE仍然使用与Arduino标准版相同的软件开发环境。6. 其他产品当前,Arduino社区还提供了适用于可穿戴设备的LilyPAD,它非常小巧还带了锂电池充电模块。但国内卖的不多。价格也稍贵。性价比不高。","updated":"T14:54:02.000Z","canComment":false,"commentPermission":"anyone","commentCount":4,"collapsedCount":0,"likeCount":27,"state":"published","isLiked":false,"slug":"","isTitleImageFullScreen":false,"rating":"none","titleImage":"/4adf15e091f957b0ced814_r.jpg","links":{"comments":"/api/posts//comments"},"reviewers":[],"topics":[{"url":"/topic/","id":"","name":"Arduino"}],"adminClosedComment":false,"titleImageSize":{"width":700,"height":467},"href":"/api/posts/","excerptTitle":"","column":{"slug":"python-dev","name":"蛇之魅惑"},"tipjarState":"inactivated","annotationAction":[],"sourceUrl":"","pageCommentsCount":4,"hasPublishingDraft":false,"snapshotUrl":"","publishedTime":"T22:54:02+08:00","url":"/p/","lastestLikers":[{"bio":"拖廷症+松鼠症","isFollowing":false,"hash":"2b220ee28d28cdce1e524f3a35ddb62d","uid":16,"isOrg":false,"slug":"joe-joe-95","isFollowed":false,"description":"个人简介","name":"sheldon","profileUrl":"/people/joe-joe-95","avatar":{"id":"v2-de6e54dcf8bb62db41a1f","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false,"isBanned":false},{"bio":"赛车、足球、滑板、动画、极限运动、街舞、Dota","isFollowing":false,"hash":"0df53ecc352ad1deb483d8fb0bd08494","uid":72,"isOrg":false,"slug":"liu-yue-74-19","isFollowed":false,"description":"我就是我,喜爱打啵儿的我~","name":"McLaren","profileUrl":"/people/liu-yue-74-19","avatar":{"id":"93b0adc77bbf94fa85b8764adf332795","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false,"isBanned":false},{"bio":"嘟嘟嘟,嘟嘟嘟,啦!","isFollowing":false,"hash":"da2adcb673e1db3e7deeb66fe094aba4","uid":88,"isOrg":false,"slug":"si-gan-51","isFollowed":false,"description":"","name":"斯干","profileUrl":"/people/si-gan-51","avatar":{"id":"v2-292cefbd44672a61aec8e0e4","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false,"isBanned":false},{"bio":"skywalker.","isFollowing":false,"hash":"3c615a1eec6b74b8ad6b351","uid":44,"isOrg":false,"slug":"whisperwind_jacky","isFollowed":false,"description":"人生往往如此:你没那么差,也没那么好。你就是还行。","name":"沈昊亮","profileUrl":"/people/whisperwind_jacky","avatar":{"id":"01a92c144","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false,"isBanned":false},{"bio":"回归","isFollowing":false,"hash":"a9988edfe71daba14ccfcbc","uid":12,"isOrg":false,"slug":"adamofatom","isFollowed":false,"description":"","name":"叶书亚","profileUrl":"/people/adamofatom","avatar":{"id":"v2-cf55b6e85eab8dc15c4e","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false,"isBanned":false}],"summary":"摘要:万金油Python在嵌入式领域同样大有作为。这一系列的文章,主要聊一聊如何使用Python与现实世界的电子电路进行交互。 ############################################################## 花一顿工作餐的钱,买一块小电路板,再花十几分钟看看文档就能迅…","reviewingCommentsCount":0,"meta":{"previous":{"isTitleImageFullScreen":false,"rating":"none","titleImage":"","links":{"comments":"/api/posts//comments"},"topics":[{"url":"/topic/","id":"","name":"Python"}],"adminClosedComment":false,"href":"/api/posts/","excerptTitle":"","author":{"bio":"Brony","isFollowing":false,"hash":"ea31ec803eef405b08c99a1e38ba7439","uid":24,"isOrg":false,"slug":"jho-jerry","isFollowed":false,"description":"消灭人类暴政","name":"Jerry Jho","profileUrl":"/people/jho-jerry","avatar":{"id":"b803b6ce6cebf7e90e2eddbe","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false,"isBanned":false},"column":{"slug":"python-dev","name":"蛇之魅惑"},"content":"摘要:模块ctypes是Python内建的用于调用动态链接库函数的功能模块,一定程度上可以用于Python与其他语言的混合编程。由于编写动态链接库,使用C/C++是最常见的方式,故ctypes最常用于Python与C/C++混合编程之中。=================================================================1. ctypes 的原理以及优缺点从ctypes的文档中可以推断,在各个平台上均使用了对应平台动态加载动态链接库的方法,并通过一套类型映射的方式将Python与二进制动态链接库相连接。通过阅读ctypes本身的代码也可以印证这个推断(/Modules/_ctypes/_ctypes.c和/Modules/_ctypes/callproc.c)。在Windows平台下,最终调用的是Windows API中LoadLibrary函数和GetProcAddress函数,在Linux和Mac OS X平台下,最终调用的是Posix标准中的dlopen和dlsym函数。ctypes 实现了一系列的类型转换方法,Python的数据类型会包装或直接推算为C类型,作为函数的调用参数;函数的返回值也经过一系列的包装成为Python类型。也就是说,PyObject* &-& C types的转换是由ctypes内部完成的,这和SWIG是同一个原理。从ctypes的实现原理不难看出:ctypes 有以下优点:Python内建,不需要单独安装可以直接调用二进制的动态链接库 在Python一侧,不需要了解Python内部的工作方式在C/C++一侧,也不需要了解Python内部的工作方式对基本类型的相互映射有良好的支持ctypes 有以下缺点:平台兼容性差不能够直接调用动态链接库中未经导出的函数或变量对C++的支持差 就个人的经验来看,ctypes 适合于“中轻量级”的Python C/C++混合编程。特别是遇到第三方库提供动态链接库和调用文档,且没有编译器或编译器并不互相兼容的场合下,使用ctypes特别方便。值得注意的是,对于某种需求,在Python本身就可以实现的情况下(例如获取系统时间、读写文件等),应该优先使用Python自身的功能而不要使用操作系统提供的API接口,否则你的程序会丧失跨平台的特性。2. 一个简单的例子作为Python文档的一部分,ctypes 提供了完善的文档。但没有Windows API编程经验的初学者读ctypes文档仍然会晕头转向。这里举一个小例子,尽力避开Windows API以及POSIX本身的复杂性,读者只需要了解C语言即可。在尝试本节例子之前,依然要搭建Python扩展编程环境。见 首先我们写一个C语言的小程序,然后把它编译成动态链接库。//great_module.c\n#include &nmmintrin.h&\n\n#ifdef _MSC_VER\n
#define DLL_EXPORT __declspec( dllexport ) \n#else\n
#define DLL_EXPORT\n#endif\n\nDLL_EXPORT int great_function(unsigned int n) {\n
return _mm_popcnt_u32(n);\n}\n这个源文件中只有一个函数 great_function,它会调用Intel SSE4.2指令集的POPCNT指令(封装在_mm_popcnt_u32中),即计算一个无符号整数的二进制表示中“1”的个数。如果你的电脑是2010年前购买的,那么很可能不支持SSE4.2指令集,你只需要把return这一行改为 return n+1;即可,同样能够说明问题。调用_mm_popcnt_u32需要包含Intel 指令集头文件nmmintrin.h,它虽然不是标准库的一部分,但是所有主流编译器都支持。中间还有一坨#ifdef...#else...#endif,这个是给MSVC准备的。因为在MSVC下,动态链接库导出的函数必须加 __declspec( dllexport ) 进行修饰。而gcc(Linux和Mac OS X的默认编译器)下,所有函数默认均导出。接下来把它编译为动态链接库。Windows下动态链接库的扩展名是dll,Linux下是so,Mac OS X下是dylib。这里为了方便起见,一律将扩展名设定为dll。Windows MSVC 下编译命令:(启动Visual Studio命令提示)cl /LD great_module.c /o great_module.dll \nWindows GCC、Linux、Mac OS X下编译命令相同:gcc -fPIC -shared -msse4.2 great_module.c -o great_module.dll\n写一个Python程序测试它,这个Python程序是跨平台的:from ctypes import *\ngreat_module = cdll.LoadLibrary('./great_module.dll')\nprint great_module.great_function(13)\n整数13是二进制的1101,所以应该输出33. 类型映射:基本类型对于数字和字符串等基本类型。ctypes 采用”中间类型“的方式在Python和C之间搭建桥梁。对于C类型Tc,均有ctypes类型Tm,将其转换为Python类型Tp。具体地说,例如某动态链接库中的函数要求参数具有C类型Tc,那么在Python ctypes 调用它的时候,就给予对应的ctypes类型Tm。Tm的值可以通过构造函数的方式传递对应的Python类型Tp。或者,使用它的可修改成员 Tm.value。Tm(ctypes type)、Tc(C type)、Tp (Python type) 之对应关系见下表。上面一段话比较绕。下面举个例子。大家熟知的printf函数位于C标准库中。在C代码中调用printf是标准化的,但是,C标准库的实现不是标准化的。在Windows中,printf 函数位于%SystemRoot%\\System32\\msvcrt.dll,在Mac OS X中,它位于 /usr/lib/libc.dylib,在Linux中,一般位于 /usr/lib/libc.so.6。下面一段代码可以在三大平台上运行:from ctypes import *\nfrom platform import *\n\ncdll_names = {\n
'Darwin' : 'libc.dylib',\n
: 'libc.so.6',\n
'Windows': 'msvcrt.dll'\n
}\n\nclib = cdll.LoadLibrary(cdll_names[system()])\nclib.printf(c_char_p(\"Hello %d %f\"),c_int(15),c_double(2.3))\n我们只关注最后一行。printf的原型是int printf (const char * format,...)\n所以,第一个参数我们用c_char_p创建一个C字符串,并以构造函数的方式用一个Python字符串初始化它。其后,我们给予printf一个int型和一个double型的变量,相应的,我们用c_int和c_double创建对应的C类型变量,并以构造函数的方式初始化它们。如果不用构造函数,还可以用value成员。以下代码与 clib.printf(c_char_p(\"Hello %d %f\"),c_int(15),c_double(2.3)) 等价:str_format = c_char_p()\nint_val = c_int()\ndouble_val = c_double()\n\nstr_format.value = \"Hello %d %f\"\nint_val.value = 15\ndouble_val.value = 2.3\nclib.printf(str_format,int_val,double_val)\n 一些C库函数接受指针并修改指针所指向的值。这种情况下相当于数据从C函数流回Python。仍然使用value成员获取值。from ctypes import *\nfrom platform import *\n\ncdll_names = {\n
'Darwin' : 'libc.dylib',\n
: 'libc.so.6',\n
'Windows': 'msvcrt.dll'\n
}\n\nclib = cdll.LoadLibrary(cdll_names[system()])\ns1 = c_char_p('a')\ns2 = c_char_p('b')\ns3 = clib.strcat(s1,s2)\nprint s1.value #ab\n最后,当 ctypes 可以判断类型对应关系的时候,可以直接将Python类型赋予C函数。ctypes 会进行隐式类型转换。例如:s1 = c_char_p('a')\ns3 = clib.strcat(s1,'b') # 等价于 s3 = clib.strcat(s1,c_char_p('b'))\nprint s1.value #ab\n 但是,当 ctypes 无法确定类型对应的时候,会触发异常。clib.printf(c_char_p(\"Hello %d %f\"),15,2.3)\n 异常:Traceback (most recent call last):\n
File \"test_printf.py\", line 12, in &module&\n
clib.printf(c_char_p(\"Hello %d %f\"),15,2.3)\nctypes.ArgumentError: argument 3: &type 'exceptions.TypeError'&: Don't know how to convert parameter 3\n4. 高级类型映射:数组在C语言中,char 是一种类型,char [100]是另外一种类型。ctypes 也是一样。使用数组需要预先生成需要的数组类型。为了方便我们用great_module,增加一个函数 array_get//great_module.c\n#ifdef _MSC_VER\n
#define DLL_EXPORT __declspec( dllexport ) \n#else\n
#define DLL_EXPORT\n#endif \nDLL_EXPORT int array_get(int a[], int index) {\n
return a[index];\n}\n下面我们在Python里产生数组类型。ctypes 类型重载了操作符 *,因此产生数组类型很容易:from ctypes import *\ngreat_module = cdll.LoadLibrary('./great_module.dll')\n\ntype_int_array_10 = c_int * 10\n\nmy_array = type_int_array_10()\nmy_array[2] = c_int(5)\nprint great_module.array_get(my_array,2)\ntype_int_array_10 即为创建的数组类型,如果想得到数组变量,则需要例化这个类型,即my_array。my_array的每一个成员的类型应该是 c_int,这里将它索引为2的成员赋予值 c_int(5)。当然由于隐式转换的存在,这里写 my_array[2] = 5也完全没有问题。至于函数返回值的类型,ctypes 规定,总是假设返回值为int。对于array_get而言,碰巧函数返回值也是int,所以具体的数值能被正确的取到。如果动态链接库中的C函数返回值不是int,需要在调用函数之前显式的告诉ctypes返回值的类型。例如:from ctypes import *\nfrom platform import *\n\ncdll_names = {\n
'Darwin' : 'libc.dylib',\n
: 'libc.so.6',\n
'Windows': 'msvcrt.dll'\n
}\n\nclib = cdll.LoadLibrary(cdll_names[system()])\ns3 = clib.strcat('a','b')\nprint s3 # an int value like 5444948\nclib.strcat.restype = c_char_p\ns4 = clib.strcat('c','d')\nprint s4 # cd\n定义一个“高维数组”的方法类似。之所以加了引号,是因为C语言里并没有真正的高维数组,ctype也一样——都是利用数组的数组实现的。from ctypes import *\ntype_int_array_10 = c_int * 10\ntype_int_array_10_10 = type_int_array_10 * 10\nmy_array = type_int_array_10_10()\nmy_array[1][2] = 3\n5. 高级类型映射:简单类型指针ctypes 和C一样区分指针类型和指针变量。复习这两个概念:C语言里,int *是指针类型。用它声明的变量就叫指针变量。指针变量可以被赋予某个变量的地址。在ctypes中,指针类型用 POINTER(ctypes_type) 创建。例如创建一个类似于C语言的int *:type_p_int = POINTER(c_int)\nv = c_int(4)\np_int = type_p_int(v)\nprint p_int[0]\nprint p_int.contents\n其中,type_p_int是一个类型,这个类型是指向int的指针类型。只有将指针类型例化之后才能得到指针变量。在例化为指针变量的同时将其指向变量v。这段代码在C语言里相当于typedef int * type_p_int;\nint v = 4;\ntype_p_int p = &v;\nprintf(\"%d\",p[0]);\nprintf(\"%d\",*p);\n当然,由于Python是依靠绑定传递类型的语言,可以直接使用 ctypes 提供的pointer()得到一个变量的指针变量from ctypes import *\n\ntype_p_int = POINTER(c_int)\nv = c_int(4)\np_int = type_p_int(v)\nprint type(p_int)\nprint p_int[0]\nprint p_int.contents\n#-------\np_int = pointer(v)\nprint type(p_int)\nprint p_int[0]\nprint p_int.contents\n\"#-------\" 之前和之后输出的内容是一样的。6. 高级类型映射:函数指针函数指针并没有什么特别之处。如果一个动态链接库里的某个C函数需要函数指针,那么可以遵循以下的步骤将一个Python函数包装成函数指针:查看文档,将C函数指针的原型利用ctypes的CFUNCTYPE包装成ctypes函数指针类型。 利用刚才得到的函数指针类型之构造函数,赋予其Python函数名,即得到函数指针变量。我们这里举两个例子。第一个例子来源于ctypes官方文档。它调用的是C标准库中的qsort函数。我们先观察qsort的文档: 它的函数原型是void qsort (void* base, size_t num, size_t size,\n
int (*compar)(const void*,const void*));\n第三个参数即为函数指针作为回调函数,用于给出元素之间大小的判断方法。我们这里使用整数作为判断类型。那么qsort的函数原型可以理解为:void qsort (int* base, size_t num, size_t size,\n
int (*compar)(const int*,const int*));\n其中,回调函数的原型为:int compar(const int*,const int*)\n使用CFUNCTYPE创建ctypes的函数指针类型:CMPFUNC = CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int))\nCFUNCTYPE的第一个参数是函数的返回值,函数的其他参数紧随其后。接下来用Python写回调函数的实现:def py_cmp_func(a, b):\n
print type(a)\n
print \"py_cmp_func\", a[0], b[0]\n
return a[0] - b[0]\n最后,用刚才得到的函数指针类型CMPFUNC,以Python回调函数的函数名作为构造函数的参数,就得到了可以用于C函数的函数指针变量:p_c_cmp_func = CMPFUNC(py_cmp_func)\n完整的代码如下:from ctypes import *\nfrom platform import *\n\ncdll_names = {\n
'Darwin' : 'libc.dylib',\n
: 'libc.so.6',\n
'Windows': 'msvcrt.dll'\n
}\n\nclib = cdll.LoadLibrary(cdll_names[system()])\n\nCMPFUNC = CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int))\n\ndef py_cmp_func(a, b):\n
print type(a)\n
print \"py_cmp_func\", a[0], b[0]\n
return a[0] - b[0]\n\ntype_array_5 = c_int * 5\nia = type_array_5(5, 1, 7, 33, 99)\nclib.qsort(ia, len(ia), sizeof(c_int), CMPFUNC(py_cmp_func)) \n注意到,Python函数得到的参数a和b的类型都是 POINTER(c_int) (显示为&class '__main__.LP_c_int'&),对指针变量解引用的方法是之前提到的[0]或者.contents。我们这里应用了ctypes的隐式类型转换,所以a[0]和b[0]可以当成Python的int类型使用。有趣的是,这段代码在*nix(Linux、Mac OS X)下调用和在Windows下调用,比较的次数是不一样的。Windows似乎更费事。 第二个例子比较实用,但只能在Windows下运行。我们要利用的是Windows API EnumWindows枚举系统所有窗口的句柄,再根据窗口的句柄列出各个窗口的标题。EnumWindows的文档见调用Windows API有特殊之处。由于Windows API函数不使用标准C的调用约定(微软一贯的尿性)。故在LoadLibrary时不能够使用cdll.LoadLibrary而使用windll.LoadLibrary。在声明函数指针类型的时候,也不能用CFUNCTYPE而是用WINFUNCTYPE。关于调用约定的问题参见Windows API有很多内建类型,ctypes也对应地提供了支持。代码如下:from ctypes import *\nfrom ctypes import wintypes\n\nWNDENUMPROC = WINFUNCTYPE(wintypes.BOOL,\n
wintypes.HWND,\n
wintypes.LPARAM)\nuser32 = windll.LoadLibrary('user32.dll')\n\ndef EnumWindowsProc(hwnd, lParam):\n
length = user32.GetWindowTextLengthW(hwnd) + 1\n
buffer = create_unicode_buffer(length)\n
user32.GetWindowTextW(hwnd, buffer, length)\n
print buffer.value\n
return True\n\nuser32.EnumWindows(WNDENUMPROC(EnumWindowsProc), 0)\n7. 其他ctypes 还对C语言中的结构体、联合体等提供支持。这部分代码比较繁琐,可参见ctypes的文档 ","state":"published","sourceUrl":"","pageCommentsCount":0,"canComment":false,"snapshotUrl":"","slug":,"publishedTime":"T09:33:26+08:00","url":"/p/","title":"聊聊Python ctypes 模块","summary":"摘要:模块ctypes是Python内建的用于调用动态链接库函数的功能模块,一定程度上可以用于Python与其他语言的混合编程。由于编写动态链接库,使用C/C++是最常见的方式,故ctypes最常用于Python与C/C++混合编程之中。========================================…","reviewingCommentsCount":0,"meta":{"previous":null,"next":null},"commentPermission":"anyone","commentsCount":12,"likesCount":70},"next":{"isTitleImageFullScreen":false,"rating":"none","titleImage":"","links":{"comments":"/api/posts//comments"},"topics":[{"url":"/topic/","id":"","name":"Python"},{"url":"/topic/","id":"","name":"Arduino"},{"url":"/topic/","id":"","name":"嵌入式系统"}],"adminClosedComment":false,"href":"/api/posts/","excerptTitle":"","author":{"bio":"Brony","isFollowing":false,"hash":"ea31ec803eef405b08c99a1e38ba7439","uid":24,"isOrg":false,"slug":"jho-jerry","isFollowed":false,"description":"消灭人类暴政","name":"Jerry Jho","profileUrl":"/people/jho-jerry","avatar":{"id":"b803b6ce6cebf7e90e2eddbe","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false,"isBanned":false},"column":{"slug":"python-dev","name":"蛇之魅惑"},"content":"摘要:虽然Arduino已经把嵌入式开发的门槛降得很低很低,但Processing以及Arduino的开发环境对于很多软件工程师而言依然非常陌生。如果一行嵌入式代码都不要写那该多好吖,本文就是为这样的需求而准备的。===============================================================================================================================1. Firmata 中间协议 Firmata ()是一个连接嵌入式系统和上位机的中间协议,协议通道默认使用串口。Arduino平台是Firmata的标准参考实现。Arduino IDE自带对Firmata的支持。在上下文不至于混淆的情况下,我们不加以区分的用“Firmata”代表Firmata协议或者Firmata的实现。两者的关系类似于Python和CPython。Firmata 作为中间件,对“下层”(指嵌入式系统一方)和“上层”(指上位机一方)都引出了编程接口。也就是说,严格来说,使用Firmata,在嵌入式系统一边也是需要编程的。不过,Arduino提供了一个全面将数字、模拟以及伺服(Servo)、脉宽调制(PWM)导出给Firmata的“标准应用实现”,故若你使用的是Arduino单片机以上几种功能(已经能够覆盖很多应用场景),确实可以只使用“标准应用实现”。2. Firmata 的标准应用实现 既然说好了“一行嵌入式代码都不要写”,那么本文将不再介绍Firmata的下层。使用Arduino的Firmata标准应用实现的方法很简单:购买开发板。安装Arduino IDE()。将开发板使用USB线连接到电脑上。找到开发板对应的串口。* Mac OS X启动命令行(打开任意Finder窗口,输入Shift+Command+U),双击“终端”。先把板子拔掉,输入 ls /dev/cu*\n一般会搜索出两个蓝牙串口。再把板子插上,运行同样的命令。比较一下就能够得知开发板所对应的串口:记下串口的名称,在本例里是 /dev/cu.usbmodemfa121。 * Windows (Windows 2000 - Windows 10)按 Windows + R,输入 devmgmt.msc,打开设备管理器。展开“端口”节点,用插拔Arduino的方法找到对应的串口: 记下串口的名称,在本例里是 COM3。
5. 在开发板连接的状态下启动Arduino IDE。在【工具】菜单中选择你的开发板和所连接的端口。
6. Arduino IDE会默认新建一个新的“工程”,不理它,选择【文件】-&【示例】-&【Firmata】-& 【StandardFirmata】
7. 这时候会打开StandardFirmata的源文件。选择【项目】-&【上传】,此时会自动编译源文件并烧写入Ardunio开发板中。
8. 先不着急写Python,我们来测试一下Firmata好不好用。首先去 下载一个firmata_test。方便起见这里贴上链接:* Mac OS X: * Windows:
9. 启动firmata_test,在【Port】菜单中选择开发板连接的串口。这时候firmata开始和Arduino通讯并显示一个控制界面。 10. 官方所有的Arduino开发板中,逻辑管脚#13(并不是ATmega芯片的真实管脚)都会连接一个LED,高电平有效(即输出1时亮)。Arduino UNO的这个LED在这个位置: 在firmata_test里点击Pin13一栏的 High/Low 按钮,这个LED应该跟随你的点击而亮灭。下面试一试输入。用一根导线将开发板的A0口与3.3V的电源相连接。(如果你的开发板是3.3V的,那么可以找一节5号电池,5号电池的负极连接开发板的GND,正极连接开发板的A0)对于Analog输入而言,最大电压映射到1024,最小电压映射到0。所以3.3V对对应的值成比例换算就是 如果你用了3.3V的板子,连接的是5号电池,那么对应的值就是 firmata_test的A0会实时显示这个值,见下图Pin14一行。3. 使用pyFirmata 说好的Python来啦!先安装pyFirmata:easy_install pyfirmata\n在Mac OS X下面要加sudo并输入管理员密码。新建一个Python源文件:#blink.py\nfrom pyfirmata import Arduino\nimport time\nimport sys\n\ncom_port = sys.argv[1]\nboard = Arduino(com_port)\nprint \"Blink Start\"\nfor i in xrange(10):\n
board.digital[13].write(i % 2)\n
time.sleep(1)\n这段代码中,首先根据串口的名字(从命令行获取)初始化Arduino对象,然后反复调用它的成员digital[13]之write方法,给予一个的序列。每一次写入后延时1秒,LED就会闪烁了。由于串口是独占的(无论在Windows下还是Mac OS X下),故在运行这段Python程序之前,需要关闭所有占用Arduino串口的软件,比如firmata_test。python blink.py /dev/cu.usbmodemfa121\n 串口名称的参数就是刚才得到的Arduino板子连接的串口设备名称。在Windows下把它替换成COMx,x是你在设备管理器看到的串口编号。用pyFirmata读取Analog端口的数值稍稍繁琐:from pyfirmata import Arduino,util\nimport time\nimport sys\n\ncom_port = sys.argv[1]\nboard = Arduino(com_port)\nit = util.Iterator(board)\nit.start()\nboard.analog[0].enable_reporting()\nprint \"Read Start\"\nfor i in xrange(10):\n
time.sleep(1)\n
print board.analog[0].read()\nboard.analog[0].disable_reporting()
\n和写操作不同的是,首先启动一个轮询线程。在进行read操作前,需要打开对应pin的report。这个和firmata协议本身的定义是一致的。轮询线程会在后台更新数据,当执行read()操作时,会拾取缓存中的数据。4. 结论虽然Arduino是一种实时嵌入式系统,但是由于Windows和Mac OS X都不是实时系统,由Arduino和上位机组成的系统就不再是实时的了。换句话说,如果打算用Python操纵Arduino,整个系统的瓶颈就不应该在firmata这个高层串口协议上。对于实时性要求很高的场合(例如操作四轴飞行器),Python-firmata的方案是行不通的。比较适合的场合有智能家居。比如你用Python搭建一个Web服务器,Arduino连接一个继电器以远程控制家里的电灯。Web访问的延时要远远大于firmata的延时,所以这样的系统是可行的。","state":"published","sourceUrl":"","pageCommentsCount":0,"canComment":false,"snapshotUrl":"","slug":,"publishedTime":"T10:11:38+08:00","url":"/p/","title":"Python 与嵌入式系统系列 - Firmata","summary":"摘要:虽然Arduino已经把嵌入式开发的门槛降得很低很低,但Processing以及Arduino的开发环境对于很多软件工程师而言依然非常陌生。如果一行嵌入式代码都不要写那该多好吖,本文就是为这样的需求而准备的。================================================…","reviewingCommentsCount":0,"meta":{"previous":null,"next":null},"commentPermission":"anyone","commentsCount":2,"likesCount":16}},"annotationDetail":null,"commentsCount":4,"likesCount":27,"FULLINFO":true}},"User":{"jho-jerry":{"isFollowed":false,"name":"Jerry Jho","headline":"消灭人类暴政","avatarUrl":"/b803b6ce6cebf7e90e2eddbe_s.jpg","isFollowing":false,"type":"people","slug":"jho-jerry","bio":"Brony","hash":"ea31ec803eef405b08c99a1e38ba7439","uid":24,"isOrg":false,"description":"消灭人类暴政","badge":{"identity":null,"bestAnswerer":null},"profileUrl":"/people/jho-jerry","avatar":{"id":"b803b6ce6cebf7e90e2eddbe","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false,"isBanned":false}},"Comment":{},"favlists":{}},"me":{},"global":{"experimentFeatures":{"ge3":"ge3_9","ge2":"ge2_1","nwebStickySidebar":"sticky","newMore":"new","liveReviewBuyBar":"live_review_buy_bar_2","liveStore":"ls_a2_b2_c1_f2","isOffice":"false","homeUi2":"default","answerRelatedReadings":"qa_recommend_with_ads_and_article","remixOneKeyPlayButton":"headerButton","asdfadsf":"asdfad","qrcodeLogin":"qrcode","newBuyBar":"livenewbuy3","isShowUnicomFreeEntry":"unicom_free_entry_off","newMobileColumnAppheader":"new_header","zcmLighting":"zcm","favAct":"default","appStoreRateDialog":"close","mobileQaPageProxyHeifetz":"m_qa_page_nweb","iOSNewestVersion":"4.2.0","default":"None","wechatShareModal":"wechat_share_modal_show","qaStickySidebar":"sticky_sidebar","androidProfilePanel":"panel_b","nwebWriteAnswer":"experiment"}},"columns":{"next":{},"python-dev":{"following":false,"canManage":false,"href":"/api/columns/python-dev","name":"蛇之魅惑","creator":{"slug":"jho-jerry"},"url":"/python-dev","slug":"python-dev","avatar":{"id":"9f2cbe8b7a1e5ef55d5da8","template":"/{id}_{size}.png"}}},"columnPosts":{},"columnSettings":{"colomnAuthor":[],"uploadAvatarDetails":"","contributeRequests":[],"contributeRequestsTotalCount":0,"inviteAuthor":""},"postComments":{},"postReviewComments":{"comments":[],"newComments":[],"hasMore":true},"favlistsByUser":{},"favlistRelations":{},"promotions":{},"switches":{"couldAddVideo":false},"draft":{"titleImage":"","titleImageSize":{},"isTitleImageFullScreen":false,"canTitleImageFullScreen":false,"title":"","titleImageUploading":false,"error":"","content":"","draftLoading":false,"globalLoading":false,"pendingVideo":{"resource":null,"error":null}},"drafts":{"draftsList":[],"next":{}},"config":{"userNotBindPhoneTipString":{}},"recommendPosts":{"articleRecommendations":[],"columnRecommendations":[]},"env":{"edition":{},"isAppView":false,"appViewConfig":{"content_padding_top":128,"content_padding_bottom":56,"content_padding_left":16,"content_padding_right":16,"title_font_size":22,"body_font_size":16,"is_dark_theme":false,"can_auto_load_image":true,"app_info":"OS=iOS"},"isApp":false},"sys":{},"message":{"newCount":0},"pushNotification":{"newCount":0}}}

我要回帖

更多关于 arduino uno r3资料 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信