分类目录归档:Arduino

ProtoThread 协程复习笔记

近一年没用 ProtoThread 了,忘得差不多了。这次搞硬件密码器重新学习了下,同时记录下来笔记,方便下次使用。

ProtoThread 是一个资源占用极少的多线程协程库,可以在51、avr等资源极其有限的硬件上面运行。

ProtoThread 有几种实现方式,这里只考虑存c switch 实现。这个实现其实就是用1byte存放当前执行到的位置,下次恢复这个线程的时候通过 switch 跳转到上次执行的位置继续执行。每个线程就只占用2byte存放当前位置(当前代码行号)即可。伪代码:

这种实现的几个特点:
• 纯c实现,无硬件依赖,方便移植
• 不能在函数内再次使用switch
• 资源占用极少,每线程仅占用2字节
• 支持阻塞操作,没有栈的切换
• 运行在单一c函数中,无法跨函数是用。弥补措施是被调用函数也写成单独的Protothread
• 线程切换时不保存局部变量,弥补措施是使用静态局部变量,造成单个函数不能多线程同时执行。另一个弥补措施是实现自己的 pt 结构,将需要保存的局部变量保存到 pt 结构里面。

附几个函数:
PT_INIT(pt) 初始化任务变量,只在初始化函数中执行一次就行
PT_BEGIN(pt) 启动任务处理,放在函数开始处
PT_END(pt) 结束任务,放在函数的最后
PT_WAIT_UNTIL(pt, condition) 等待某个条件(条件可以为时钟或其它变量,IO等)成立,否则直接退出本函数,下一次进入本 函数就直接跳到这个地方判断
PT_WAIT_WHILE(pt, cond) 和上面一个一样,只是条件取反了
PT_WAIT_THREAD(pt, thread) 等待一个子任务执行完成
PT_SPAWN(pt, child, thread) 新建一个子任务,并等待其执行完退出
PT_RESTART(pt) 重新启动某个任务执行
PT_EXIT(pt) 任务后面的部分不执行,直接退出重新执行
PT_YIELD(pt) 锁死任务
PT_YIELD_UNTIL(pt, cond) 锁死任务并在等待条件成立,恢复执行
在pt中一共定义四种线程状态,在任务函数退出到上一级函数时返回其状态
PT_WAITING 等待
PT_EXITED 退出
PT_ENDED 结束
PT_YIELDED 锁死

(下面的是定时器,该宏是 http://www.cnblogs.com/xiaowuyi/p/4319720.html 写的,用之前请在#include “pt.h” 的前面,前面啊!加上一句#define PT_USE_TIMER)

先说明一下,下面的定时不一定完全准确的,可能会有点点的误差,可能偏后。如果遇上了很烦的任务,有可能会使延时延后。但是正常情况下,直接用就好了。

如果要很精确的延时,请用delay语句或者计时器,但是,绝大多数情况下,绝大多数情况!绝大多数情况!请用下面的语句代替delay延时!这样才能把CPU让给别的任务使用。

PT_TIMER_DELAY(pt,延时毫秒数);
字面上的意思,不用多说了吧?最大值约为49.7天,估计没人会延时辣么久吧……

PT_TIMER_MICRODELAY(pt,延时微秒数);
字面上的意思,不用多说了吧?注意,最小精度与arduino的版本有关,与micros()有精度一致。

PT_TIMER_WAIT_TIMEOUT(pt,条件,毫秒数);
如果条件成立了,或者超时了,就继续运行,否则切换任务。

要用的话,请在#include “pt.h”前面加上一句 #define PT_USE_SEM

首先要创建一个信号量,这个一定是全局变量:
static struct pt_sem 信号量名;

接着请在setup()函数里面给它初始化:
PT_SEM_INIT(&信号量名,数量);
信号量名前面有个&,别忘了。数量就相当于停车场的总车位数。

然后要用啦。任务要停一辆车进去:
PT_SEM_WAIT(pt,&信号量名);
信号量名前面有个&,别忘了。一个语句只能停一辆车,土豪好多车就用多次。

任务要开一辆车出来:
PT_SEM_SIGNAL(pt,&信号量名);
信号量名前面有个&,别忘了。用一次出一辆。

参考:
• http://dunkels.com/adam/pt/
• Protothread机制文档 http://blog.csdn.net/tietao/article/details/8507455
• 一个“蝇量级” C 语言协程库 http://coolshell.cn/articles/10975.html
• ProtoThreads http://blog.csdn.net/utopiaprince/article/details/6041385

python 与 arduino 串口通信

参考:
http://www.geek-workshop.com/thread-5733-1-1.html
http://wiki.geek-workshop.com/doku.php?id=arduino:arduino_language_reference:serial
http://pythonhosted.org//pyserial/pyserial_api.html

ARDUINO 最小系统

atmeg328 内置复位电路,不需要外接复位电路。虽然也有内置晶振,但是 ARDUINO 只支持 16M 或 8M 的频率,所以最小系统还得用 16M 晶振接到9、10口(XTAL1、XTAL2),然后再分别接2个22p的电容到地就可以了。

全新的 atmeg328 没有 ARDUINO 的bootloader(引导程序) ,得用 IPS 接口写进去。之后就可以用串口写程序了。
熔丝位之类的设置不用管,ARDUINO IDE 写bootloader时会自动设置。对了,ARDUINO 的“使用编程器下载”功能会清除 ARDUINO 的bootloader(引导程序),除非资源太紧张,不建议使用。

如果需要复位按钮,可以用一个10K上拉电阻接到1(RESET)脚,然后弄个按钮,一端接到地,一段也接到1(RESET)脚。

还有一个问题,atmeg328 有两个 VCC 口(一个是 A/D 转换器的电源,这个必须接,不然芯片跑不起来,各个脚都是0.5V电压),建议都接到电源上面,如果只接7脚的 VCC ,会悲剧的跑不起来… 今天一上午都弄这个问题了。

附参考:
ARDUINO_V2

atmega328w

Arduino_Uno_Rev3-schematic

Arduino 下 Nokia 5110 LCD + DS18B20 多点测温

温度库:http://milesburton.com/Dallas_Temperature_Control_Library
5110库:https://github.com/adafruit/Adafruit-PCD8544-Nokia-5110-LCD-library

资料上显示 DS18B20 可以使用 3-5v 电源供电,可以做到9-12位精度。不过12位精度比9位精度测温慢多了。而1820只能5V供电,9位精度。

注意,需要使用arduino-1.52以上版本,arduino-1.05的会出现以下错误:

\arduino-1.0.5-windows\arduino-1.0.5\libraries\Robot_Control\ArduinoRobot.cpp: In constructor 'RobotControl::RobotControl()':
\arduino-1.0.5-windows\arduino-1.0.5\libraries\Robot_Control\ArduinoRobot.cpp:8: error: 'LCD_CS' was not declared in this scope
\arduino-1.0.5-windows\arduino-1.0.5\libraries\Robot_Control\ArduinoRobot.cpp:8: error: 'DC_LCD' was not declared in this scope
\arduino-1.0.5-windows\arduino-1.0.5\libraries\Robot_Control\ArduinoRobot.cpp:8: error: 'RST_LCD' was not declared in this scope
\arduino-1.0.5-windows\arduino-1.0.5\libraries\Robot_Control\ArduinoRobot.cpp: In member function 'void RobotControl::begin()':
\arduino-1.0.5-windows\arduino-1.0.5\libraries\Robot_Control\ArduinoRobot.cpp:18: error: 'MUXA' was not declared in this scope
\arduino-1.0.5-windows\arduino-1.0.5\libraries\Robot_Control\ArduinoRobot.cpp:18: error: 'MUXB' was not declared in this scope
\arduino-1.0.5-windows\arduino-1.0.5\libraries\Robot_Control\ArduinoRobot.cpp:18: error: 'MUXC' was not declared in this scope
\arduino-1.0.5-windows\arduino-1.0.5\libraries\Robot_Control\ArduinoRobot.cpp:18: error: 'MUXD' was not declared in this scope
\arduino-1.0.5-windows\arduino-1.0.5\libraries\Robot_Control\ArduinoRobot.cpp:19: error: 'MUX_IN' was not declared in this scope
\arduino-1.0.5-windows\arduino-1.0.5\libraries\Robot_Control\ArduinoRobot.cpp:22: error: 'BUZZ' was not declared in this scope
\arduino-1.0.5-windows\arduino-1.0.5\libraries\Robot_Control\ArduinoRobot.cpp:25: error: 'Serial1' was not declared in this scope