首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在很长一段时间内,Arduino停止将数据发送到串口。

在很长一段时间内,Arduino停止将数据发送到串口。
EN

Stack Overflow用户
提问于 2011-12-05 17:37:06
回答 4查看 25.5K关注 0票数 10

我使用Arduino Uno rev2设备作为永久连接的设备,有时向PC (Windows7 x64)发送信号。用arduino.cc的Arduino 1.0软件编译的代码

关于arduino.cc,http://arduino.cc/forum/index.php/topic,81822.0.html的主题

源码

它工作完美,但有时,经过很长一段时间,个人电脑停止接收数据从Arduino设备。这不是PC软件的问题,因为所有的软件(putty,telnet等等)同样,我可以将数据发送给Arduino (设备响应命令);我只是无法接收回它。

http://arduino.cc/forum/index.php?topic=77828.0中也描述了类似的问题,但没有提出解决方案。

断开/连接设备暂时解决了这个问题,但这不可能是一个解决方案,因为设备应该是永久和完全自动使用的。

使用板重置按钮,重置程序&所有的值,它的开始不会有帮助。PC机没有开始接收数据。

备注:

  1. millis()滚转错误不能在Arduino Uno板上用Arduino 1.0软件进行复制--我猜这是固定的,millis()现在只在50天内才能进行滚转,就像文档中所说的那样。此外,代码也有没有响应的millis()独立码
  2. 在向PC发送数据的过程中,LED还在闪烁。
  3. 字符串的使用可能会增加内存使用量,但是这个程序太小了,不会有问题。在10+程序运行几个小时后,没有使用任何额外的内存,所以我不想用其他东西替换String,因为串口问题要严重得多。

如果您认为问题是在arduino程序错误,请考虑如何解释TX闪烁和重置没有帮助。

EN

回答 4

Stack Overflow用户

发布于 2015-05-23 07:33:10

也许做一个软件重置你的问题将得到解决。我运行了以下代码,以确定软件重置是否会重置时钟,从而重新设置millis()函数:

代码语言:javascript
运行
复制
void setup()
{
  Serial.begin(9600);
  Serial.println("Will start sending millis values in 5 seconds...");
  delay(5000);
}

void loop()
{
  Serial.println(String(millis()));

  if (Serial.available() > 0)
  {
    if (Serial.read() == '@')
    {
      Serial.println("Rebooting. . .");
      delay(100); // Give the computer time to receive the "Rebooting. . ." message, or it won't show up
      void (*reboot)(void) = 0; // Creating a function pointer to address 0 then calling it reboots the board.
      reboot();
    }
  }
}

正如代码中所解释的那样,要使软件重新启动,只需创建一个函数指针来寻址0并调用它。我确实取得了令人满意的结果:

代码语言:javascript
运行
复制
Will start sending clock values in 5 seconds...
5000
5000
5000
5001
5001
5001
5002
5002
5002
. . .
6804
Rebooting...
Will start sending millis value in 5 seconds...
5000
5000
5000
5001
5001
5001
5002
5002
5002
5003
5003
. . .

我希望这能解决你的问题:)

票数 2
EN

Stack Overflow用户

发布于 2011-12-09 11:33:56

如果您经常轮询Arduino,那么作为解决办法,您可以在Arduino中实现一个看门狗,如果它很长时间没有将数据输出到PC上,就会重新设置Arduino。你可以监视Arduino TX引脚,把它带到另一个输入引脚,使用中断.重点是在每次TX活动之后重置看门狗。

票数 0
EN

Stack Overflow用户

发布于 2011-12-09 11:43:49

钟有可能会折叠起来。

previousclock = millis()可能在折叠之前被卡在一个很高的值上。您可以将测试扩展到以下情况:(currentmilis < previousmillis)加上/减去一些模糊因子。

顺便说一句,它使用了ignas的源代码( OP源代码未经注册是不可读的,我不想注册)

编辑:我从wakkerbot复制了下面的片段,并对其进行了一些编辑。这仅仅是为了演示如何使last_action时间戳停留在int间隔的顶部(如果凸值不是int_max的除数),您可能会简化上面/下面的逻辑,因为您只对内部/外部间隔测试感兴趣。当然,邮票的类型应该适应millis() (无符号的长?)类型?并删除fakemillis(),并将对它的引用替换为millis()。

代码语言:javascript
运行
复制
#include <stdio.h>

#define STAMP_INSIDE 0
#define STAMP_BELOW -1
#define STAMP_ABOVE 1
#define STAMP_BEYONDO -1

    /* Intentionally very small, for fast wraparound
    ** Intentionally signed to stress test the logig.
    */
typedef signed char Stamp;

    /* fake clock, returns incrementing value, but folds around
    */
Stamp fakemillis(void)
{
static Stamp ticker =0;
return ticker++;
}

/* Check if "test" is inside or above/below the interval {low,high}
** low and high may have been wrapped around zero (--> low > high)
** return
**      0 := "test" inside interval
**      1 := "test" below interval
**      -1 := "test" above interval (but wrapped)
** The two impossible cases return -2.
*/
static int check_interval(Stamp low, Stamp high, Stamp test)
{
switch (4 *(high >= low)
        +2 *(test >= low)
        +1 *(test > high)
        ) {
        case 0: return STAMP_INSIDE;    /* inside (wrapped) */
        case 1:                 /* outside (wrapped) */
                return ((Stamp)(low - test) < (Stamp)(test - high)) ? STAMP_BELOW : STAMP_ABOVE;
        case 2: break;      /* impossible */
        case 3: return STAMP_INSIDE;    /* inside (wrapped) */
        case 4:                 /* all below */
                return ((Stamp)(low - test) < (Stamp)(test - high)) ? STAMP_BELOW : STAMP_ABOVE;
        case 5: break;      /* impossible */
        case 6: return STAMP_INSIDE;    /* inside normal case */
        case 7:                 /* all above) */
                return ((Stamp)(low - test) < (Stamp)(test - high)) ? STAMP_BELOW : STAMP_ABOVE;
        }   
return STAMP_BEYONDO;
}   

    /* Get new clock value, test if it is inside interval {*old, *old+width)
    ** iff inside: return STAMP_INSIDE;
    ** iff above (or below) return STAMP_ABOVE or STAMP_BELOW
    ** and UPDATE *old
   */
static int test_or_set(Stamp *old, Stamp width)
{
Stamp tick;
int diff;
tick = fakemillis();

diff = check_interval( *old, *old+width, tick);
if (!diff) return 0;
*old = tick;
return diff;
}


int main(void) {
Stamp goodlast=0;
Stamp tick=0;
Stamp badlast=0;
int goodtest;
int badtest;
unsigned uu;

for (uu = 0; uu < 260; uu++) {
    tick= fakemillis();
    if (tick > badlast+10) { badlast=tick; badtest=1; } else {badtest =0;}
    goodtest = test_or_set ( &goodlast, 10);
    printf("%x:Tick=%x bad=%x, badtest=%d good=%x goodtest=%d\n"
    , uu, (unsigned) tick
    , (unsigned) badlast, badtest
    , (unsigned) goodlast, goodtest
    );
    }
return 0;
}

如果您在“普通”计算机上编译并运行上述程序,您可以看到最坏的程序被卡住了。这也是发生在你的arduino身上的事,IMHO。

更新:绝对溢出/翻转。(全球年) http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1200662708

Update2:无关的,但糟糕的编码实践:

代码语言:javascript
运行
复制
#define CMD_SET_SPEED "S"
...
/* Internal configuration */
if(buffer.substring(0,1)==CMD_SET_SPEED) {
  updateSpeed(buffer.substring(1));
  }

你在比较两个字符串。(这可能由c++来处理,但在C语言中,这完全是错误的。我还建议用一个巨型开关语句替换重复的if(.){.},这样至少可以避免重复调用substr()函数。(或者它是内联的?)

更新20111211:下面是一个包装-遗忘的比较和设置函数,它需要一个指针,指向要比较和设置的值,以及预期间隔的宽度:

代码语言:javascript
运行
复制
int test_and_set_if_beyond( unsigned long *pprev, unsigned long width )
{
unsigned long tick, low,high;
low = *pprev;
high = low+width;
tick = millis();

if (low < high) {
    if (tick >= low && tick < high ) return 0; /* normal case */
    }
else { /* interval is wrapped , clock could have wrapped */
    if (tick >= low || tick < high) return 0;
    }
*pprev = tick;
return 1;
}

此函数用于循环()部分,如下所示:

代码语言:javascript
运行
复制
if (test_and_set_if_beyond ( &lightTimer, lightnessCheckPeriod)) {
    int newLightness = analogRead(brightnessPin);
    if(newLightness-lightness > LIGHT_TRESHOLD) {
      say(RESPONSE_FLASH);
    }
    lightness = newLightness;
  }
  if (test_and_set_if_beyond ( &pingTimer, pingTimerPeriod)) {
    say(RESPONSE_PING);
  }
  if (test_and_set_if_beyond ( &pingLEDTimer, pingTimerPeriod*2)) {
    digitalWrite(failPin, HIGH);
  }
  feed();

最后: IMHO重置不起作用的原因是并非所有的全局变量都是在setup()函数中初始化的。另外:我认为您应该去掉字符串的内容(运行时中有GC吗?)并使用普通字符缓冲区代替。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8389426

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档