Malc 发表于 2012-3-21 21:43:07

ProtoThreads多线程实例

发一个我前段时间用ProtoThreads写的一个读取Serial角度并用模拟的方式驱动舵机
关于ProtoThreads的介绍:
http://www.geek-workshop.com/forum.php?mod=viewthread&tid=610&extra=page%3D1
代码如下#include <PT_timer.h>
#include <pt.h>
int servopin=8;//定义舵机接口数字接口7
int myangle=100;//定义角度变量
int val=0;
static struct pt pt1,pt2;
PT_timer servotimer;
static int servoMove(struct pt *pt)
{
PT_BEGIN(pt);
while(1)
{
        servotimer.setTimer(25);
        PT_WAIT_UNTIL(pt,servotimer.Expired());
      int pulsewidth;//定义脉宽变量
        myangle%=156;//视舵机而定,防止越界
        pulsewidth=myangle*11+500;//将角度转化为500-2205的脉宽值
        digitalWrite(servopin,HIGH);//将舵机接口电平至高
        delayMicroseconds(pulsewidth);//延时脉宽值的微秒数
        digitalWrite(servopin,LOW);//将舵机接口电平至低
}
PT_END(pt);
}

String inString = "";
static int angleRead(struct pt *pt)
{
PT_BEGIN(pt);
while(1) {   
    PT_WAIT_UNTIL(pt, Serial.available()>0);
        int inChar = Serial.read();
    if (isDigit(inChar))
      inString += (char)inChar;
    if (inChar == ' '||inChar=='\n') {
      myangle=inString.toInt();
          Serial.print("myangle=");
          Serial.println(myangle);
      inString = "";
        }
}
PT_END(pt);
}
void setup()
{
pinMode(servopin,OUTPUT);//设定舵机接口为输出接口
PT_INIT(&pt1);
PT_INIT(&pt2);
Serial.begin(9600);
}
void loop()//
{
    servoMove(&pt1);
    angleRead(&pt2);
}
ServoMove呢就是自己模拟出来的舵机函数,为什么不用servo库呢?因为arduino自身的servo库有很多限制,第一PWM不能用了,第二最小角度只有1度,当然这个程序里舵机的精度也是1度,只要把相应的变量改成float就能精确到小数了,不过最大的好处是舵机脚可以任意设定
servomove中限定了最大角度为155度,这个与舵机有关
angleRead中使用了stringtoInt,每次可以输入一个角度,角度可以以 空格 或 回车 结尾(操蛋的VC2010 SerialMonitor发送数据不带 回车的。。那就空格了)
程序中使用了定时器,自己用C++写的,第一次写库,照葫芦画瓢了。。。
感谢czad的扩展库翻译http://www.geek-workshop.com/forum.php?mod=viewthread&tid=184
这个库用起来非常简单:
PT_Timer t;//定义一个定时器
t.setTimer(unsinged long time) //定时时间,单位ms
t.Expired()//判断定时器是否溢出,是返回值>0
在上面的代码中,一个舵机周期是20ms,前面的约2.5毫秒是信号周期,剩下的10多ms全是无用的低电平,然而又必不可少,所以果断用定时器取代delay
ok
附上

开心就好 发表于 2012-3-23 08:38:26

不错,学习了

大连好人 发表于 2012-7-20 22:02:12

这个可以顶一下,感谢楼主分享。。。。

提线木偶 发表于 2012-8-20 10:42:59

前辈,我想使用定时器在一定的时间内对外部的脉冲进行计数不知可以吗?希望指点一下

Malc 发表于 2012-8-20 11:56:31

提线木偶 发表于 2012-8-20 10:42 static/image/common/back.gif
前辈,我想使用定时器在一定的时间内对外部的脉冲进行计数不知可以吗?希望指点一下

额。。我不是什么前辈。。
我觉得可以采用外部中断+定时器实现,伪代码:
attachInterrupt(interrupt, function, mode)
pmillis=millis();
Interrupts()
...
if(millis()-pmillis>1000)//假设1秒
{
counter=0;//counter就是计数器,清零
noInterrupts();
}
中断函数、中断计数你可以参考坛里的WIKI

提线木偶 发表于 2012-8-22 09:48:17

Malc 发表于 2012-8-20 11:56 static/image/common/back.gif
额。。我不是什么前辈。。
我觉得可以采用外部中断+定时器实现,伪代码:
attachInterrupt(interrupt,...

如果一直用外部中断会不会影响整个程序的执行呀,如果来一个脉冲进一次中断的话,不停地有脉冲的话程序的其他部分就没法执行了,我是想能不能用定时器来产生一个中断,在执行定时期间采集脉冲数,定时结束发一个中断来进行处理

Malc 发表于 2012-8-22 12:10:47

提线木偶 发表于 2012-8-22 09:48 static/image/common/back.gif
如果一直用外部中断会不会影响整个程序的执行呀,如果来一个脉冲进一次中断的话,不停地有脉冲的话程序的 ...

我上面的代码就可以改成你说的这样,定时器计时到某一时刻,开中断Interrupts(),过一段时间,再关闭中断noInterrupts(),其他你不想计数的时候中断是一直关闭的

Pizzro 发表于 2012-10-8 09:37:37

mark一下mark一下mark一下

nengcai0313 发表于 2012-10-8 11:35:59

mark一下。

jszsj 发表于 2012-11-20 16:03:59

好啊,又是这个库的例子,学一个

yettoo54 发表于 2013-2-12 20:41:05

赞!!! 是直接调用在 IDE硬件的文件夹里用的 WIRING.C这个现有文件啊,看来 ARDUINO 还是作了一些中间件来操作 AVR 底层 硬件寄存器!!!

zhangyanbo3 发表于 2013-4-28 23:59:43

mark一下。

frankmcu 发表于 2013-5-22 13:34:05

好东东,谢谢分享。

friskit 发表于 2013-5-22 17:22:03

马克。。。以及头像的妹纸不错~

八硝基立方烷 发表于 2014-2-14 19:00:06

马克。。。。。。。。。。。。。。
页: [1] 2
查看完整版本: ProtoThreads多线程实例