极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 14814|回复: 13

请教通过无线传输数据控制舵机在一定周期后突然不能正常运转的问题

[复制链接]
发表于 2012-10-26 20:44:47 | 显示全部楼层 |阅读模式
我想通过无线模块APC220将一组数据传给arduino板子,然后板子接受后存在数组中然后控制多个舵机运行。

我现在发送和运动都是可以实现的,但是出现了一个问题,就是比如让舵机以正弦曲线的形式走100个周期,但是实际上走几十个周期就突然没有反应了,完全停了下来。。请教这是怎么一回事呀?迷茫中唉。。

程序是仿的《arduino学习笔记A6(补充)》的程序做的。。其他都还好,就是运行六七十个周期后就停了唉。。好奇怪。。求教~

先行谢谢啦~
回复

使用道具 举报

 楼主| 发表于 2012-10-26 21:08:43 | 显示全部楼层
这里可以@人吗?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-10-26 21:42:26 | 显示全部楼层
重新试了一下,第一次的时候能运行六七十个周期,再发送一次的话又能运行十几个周期。。好奇怪啊。。
回复 支持 反对

使用道具 举报

发表于 2012-10-26 22:33:42 | 显示全部楼层
禁用中断试试
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-10-26 22:35:21 | 显示全部楼层
弘毅 发表于 2012-10-26 22:33
禁用中断试试

???怎么禁用中断。。。好囧。。我一直没有搞过和中断有关的东西。。求指导~~
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-10-26 22:38:20 | 显示全部楼层
这个我把程序贴上来吧。。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-10-26 22:46:03 | 显示全部楼层
  1. //定义一个comdata字符串变量,赋初值为空值
  2. String comdata = "";
  3. //numdata是分拆之后的数字数组
  4. int numdata[9] = {0}, Pin[6] = {2,3,4,5,6,7}, mark = 0;

  5. void servopulse(int port,int time)
  6. {
  7. digitalWrite(port,HIGH);
  8. delayMicroseconds(time);
  9. digitalWrite(port,LOW);
  10. delayMicroseconds(2500-time);
  11. }

  12. void setup()
  13. {
  14. //定义0~6脚是输出
  15.   for(int i = 0; i < 6; i++)
  16.   {
  17.     pinMode(Pin[i], OUTPUT);
  18.     servopulse(Pin[i],1500);
  19.     servopulse(Pin[i],1500);
  20.     servopulse(Pin[i],1500);
  21.     servopulse(Pin[i],1500);
  22.     servopulse(Pin[i],1500);
  23.     servopulse(Pin[i],1500);
  24.     servopulse(Pin[i],1500);
  25.   }
  26.   Serial.begin(9600);
  27. }

  28. void loop()
  29. {
  30. //j是分拆之后数字数组的位置记数
  31.   int j = 0;

  32.   //不断循环检测串口缓存,一个个读入字符串,
  33.   while (Serial.available() > 0)
  34.   {
  35.   //读入之后将字符串,串接到comdata上面。
  36.     comdata += char(Serial.read());
  37.       //延时一会,让串口缓存准备好下一个数字,不延时会导致数据丢失,
  38.     delay(2);
  39.     //标记串口读过数据,如果没有数据的话,直接不执行这个while了。
  40.     mark = 1;
  41.   }

  42.   if(mark == 1)  //如果接收到数据则执行comdata分析操作,否则什么都不做。
  43.   {
  44.   //显示刚才输入的字符串(可选语句)
  45.     Serial.println(comdata);
  46.       //显示刚才输入的字符串长度(可选语句)
  47.     Serial.println(comdata.length());

  48. /*******************下面是重点*******************/
  49. //以串口读取字符串长度循环,
  50.     for(int i = 0; i < comdata.length() ; i++)
  51.     {
  52.     //逐个分析comdata[i]字符串的文字,如果碰到文字是分隔符(这里选择逗号分割)则将结果数组位置下移一位
  53.     //即比如11,22,33,55开始的11记到numdata[0];碰到逗号就j等于1了,
  54.     //再转换就转换到numdata[1];再碰到逗号就记到numdata[2];以此类推,直到字符串结束
  55.       if(comdata[i] == ',')
  56.       {
  57.         j++;
  58.       }
  59.       else
  60.       {
  61.          //如果没有逗号的话,就将读到的数字*10加上以前读入的数字,
  62.          //并且(comdata[i] - '0')就是将字符'0'的ASCII码转换成数字0(下面不再叙述此问题,直接视作数字0)。
  63.          //比如输入数字是12345,有5次没有碰到逗号的机会,就会执行5次此语句。
  64.          //因为左边的数字先获取到,并且numdata[0]等于0,
  65.          //所以第一次循环是numdata[0] = 0*10+1 = 1
  66.          //第二次numdata[0]等于1,循环是numdata[0] = 1*10+2 = 12
  67.          //第三次是numdata[0]等于12,循环是numdata[0] = 12*10+3 = 123
  68.          //第四次是numdata[0]等于123,循环是numdata[0] = 123*10+4 = 1234
  69.          //如此类推,字符串将被变成数字0。
  70.         numdata[j] = numdata[j] * 10 + (comdata[i] - '0');
  71.       }
  72.     }
  73.     //comdata的字符串已经全部转换到numdata了,清空comdata以便下一次使用,
  74.     //如果不请空的话,本次结果极有可能干扰下一次。
  75.     comdata = String("");

  76.     Serial.println("received!");
  77.     delay(1000);
  78.     //循环输出numdata的内容,并且写到PWM引脚
  79.     for(int j=0;j<100;j++)
  80.     {
  81.     for(int i = 0; i < 9; i++)
  82.     {
  83.   
  84.       for(int k=0;k<30;k++)
  85.       {
  86.       servopulse(Pin[2], numdata[i]);
  87.       }
  88.       //numdata[i] = 0;
  89.     }
  90.     //Serial.println(j);
  91.     }
  92.     //输出之后必须将读到数据的mark置0,不置0下次循环就不能使用了。
  93.     delay(1000);
  94.     Serial.println("Done!");
  95.    
  96.     for(int i=0;i<9;i++)
  97.     {
  98.     numdata[i] = 0;
  99.     }
  100.     mark = 0;
  101.   }
  102. }
复制代码




程序就是仿的那篇文章里的,只是把后边一部分改了一下而已。。。因为还是在尝试中,所以很乱没有整理。。各位大大谅解。。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-10-27 14:53:13 | 显示全部楼层
弘毅 发表于 2012-10-26 22:33
禁用中断试试

谢谢啦~我看到你写的帖子了。。之前确实无知了。。汗
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-10-27 15:03:16 | 显示全部楼层
弘毅 发表于 2012-10-26 22:33
禁用中断试试

谢谢你啦!我用了中断的方法,目前可以正常运行了~谢谢谢谢谢谢。。实在太感谢啦~~
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-10-27 16:04:39 | 显示全部楼层
额。。使用中断后确实有机会全部完成了,但是不是每一次都可以唉。。还是有问题。。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-10-27 16:05:43 | 显示全部楼层
之前不是用中断的时候是必定运行不完,现在使用了中断后是有机会跑完,但是也有机会还是跑一半就断掉了。。这是怎么回事呢。。难道是中断的级别不够么。。。汗。。继续纠结啊
回复 支持 反对

使用道具 举报

发表于 2012-12-15 20:55:10 | 显示全部楼层
先抓個小問題
1. 為什麼setup裡面for要有這麼多 servopulse(Pin[i],1500); ??
已經i回圈了, 應該一行就好。
2. 還有for裡面i < 6; 應該改成i<5,因為arduino基於c語言是0 index的。
要是跑到i=6的話會指到隨機的記憶體位置,可能干擾程式正常運行。

這個我感覺也是sram處理的問題, comdata定義在外圍,是全域變數,生命週期是上電到掉電。
C語言沒有String, arduino應該是用陣列模擬的, 堆久了就滿了

試試看用指標的型式:
String *sptr;  //指向string的pointer, 名為sptr
sptr = &comdata; //把comdata的起始記憶體位置給sptr

sptr = String ("");  //清空的時候從頭清
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-12-15 22:53:00 | 显示全部楼层
jack4904 发表于 2012-12-15 20:55
先抓個小問題
1. 為什麼setup裡面for要有這麼多 servopulse(Pin,1500); ??
已經i回圈了, 應該一行就好。
...

嗯,先谢谢你的回复。

1.setup里边有很多servopulse(Pin,1500);是因为有的舵机一个回不了。这个很莫名其妙的,不同批次的舵机就不同,我曾经一个一个的试过。

2.for(int i = 0; i < 6; i++) 这个是从0到5,没有问题呀,确实就是6个数呀~它没有跑到6的,如果改成<5的话就有问题了。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-12-15 22:55:58 | 显示全部楼层
本帖最后由 芷雅焉 于 2012-12-15 22:59 编辑
jack4904 发表于 2012-12-15 20:55
先抓個小問題
1. 為什麼setup裡面for要有這麼多 servopulse(Pin,1500); ??
已經i回圈了, 應該一行就好。
...


至于comdata的问题,这个确实是我应该注意一下的,不过我每次用完都有清零,所以问题应该不大,不过为了规范,我还是会修改到里边的。这个字符串的使用确实有很多的问题,我会一一尝试改正的。多谢!
回复 支持 反对

使用道具 举报

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

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-5-1 18:41 , Processed in 0.068447 second(s), 19 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

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