Arduino串行打印不希望地改变了程序的行为


10

我正在使用在标头中声明的循环计数器:

int loop_counter = 0;

我经常使用此计数器触发事件​​。我曾经对这种类型的行为使用模,但是我简化了它,因此使用起来更容易(它仍然会导致相同的行为)

void loop() {
    if(loop_counter > 100) loop_counter = 0;
    else loop_counter++;

    //Serial.println("hey");

    if(loop_counter == 0) {
         //do_something_important();
    }      
}

一切都很好,直到我尝试Serial取消注释//Serial.println("hey");"hey"在此示例中,因为对我而言,这种行为是荒谬的)来与之交流。

这将导致loop_counter永远不会触发do_something_important();代码部分。我尝试声明loop_countervolatile,但没有任何改变。我尝试了Serial.printing loop_counter,而且我也得到了奇怪的行为(它将冻结循环)。 Serial.println("hey");在串行监视器中,我得到很多“嘿”的意思(即很快超过100个“嘿”,这是另一部分代码应触发的迭代次数)

是什么原因导致的使用Serial,而数据(据我所知)并未loop_counter完全阻止其正常运行?

编辑:这是最终导致问题的主文件部分(嗯,为它做出了最大的贡献(使用过多的内存)):



void display_state() {
  int i,j,index=0;
  short alive[256][2];

 for(i=0;i<num_rows;i++) { 
   for(j=0;j<num_cols;j++) {
     if(led_matrix[i][j]==1) { 
       alive[index][0]=i;
       alive[index][1]=j;
       index++;
     }
   }
 }
 alive[index][0]=NULL; //Null-terminate.
 alive[index][1]=NULL;

 //383 is a great number
 for(int idx=0;idx < index; idx++) {
   display(alive[idx][0],alive[idx][1]);
   delayMicroseconds(283);
 }
}

这是“ letters.h”:


    #ifndef _MY_LETTERS_H
    #define _MY_LETTERS_H

#define nrows 4
#define ncols 4

#define num_rows 16
#define num_cols 16

#define MAX_WORD_LENGTH 16
#define NUMBER_OF_CHARACTERS 26

#include <stdlib.h>

int loop_counter = 0 ; 简短的led_matrix [ num_rows ] [ num_cols ];

常量letter_a [ NROWS ] [ NCOLS ] = {{ 0 1 1 0 },{ 1 0 0 1 },{ 1 1 1 1 },{ 1 0 0 1 } }; const short letter_b [ nrows ] [ ncols ] = {{ 1 0 0 0 },{ 1 1 1 0 },{ 1 0 1 0 },{ 1 1 1 0 }}; 常量letter_c [ NROWS ] [ NCOLS ] = {{ 0 1 1 1 },{ 1 0 0 0 },{ 1 0 0 0 },{ 0 1 1 1 }}; 常量letter_t [ NROWS ] [ NCOLS ] = {{ 1 1 1 1 },{ 0 1 0 0 },{ 0 1 0 0 },{ 0 1 0 0 } };

typedef struct letter_node { const short * data ; letter_node * 下一个整数x ; INT ÿ ; } letter_node ;

letter_node aa = {&letter_a[0][0],NULL,1,1}; letter_node bb = {&letter_b[0][0],NULL,1,1}; letter_node cc = {&letter_c[0][0],NULL,1,1}; letter_node tt = {&letter_t[0][0],NULL 1 1 };

letter_node letter_map [ NUMBER_OF_CHARACTERS ]; #万一

一些更多信息:-我正在使用Uno(ATMega328)


你的纸叠大小是多少?您是否有可能绘画堆栈并查看堆栈是否已损坏。串行打印是否使用中断,您的代码是否可重入?
Ktc 2012年

串行打印不会被任何中断触发,我仅在loop()函数中使用它。如果我只有(Serial.print())的输出方法使我失败,我应该如何绘画我的堆栈?
eqzx 2012年

2
为了消除看似微不足道的更改可能造成的错误和误解,请使用简略,字符精确的副本替换问题中的代码,并将其缩减至触发问题所需的最小数量。不是“这是我的程序,如果我..会失败”,而是“最小程序”以这种方式失败。
克里斯·斯特拉顿

Answers:


2

我也有类似的问题,并且非常确定您的空间也与堆栈空间无关。尝试尽可能缩小代码。

在我的情况下,当我有串行消息时,代码有时会运行,但是当我没有串行消息时,它似乎就不会运行。我也遇到过这样的情况:发送串行消息会导致arduino无休止地重置。

我也在使用arduino328。如果阵列的大小可以减小到可接受的最小大小,则应该减小阵列的大小。


谢谢,您和Dave Tweed明白了。我将display_state()函数重构为不需要额外分配。我很少做嵌入式处理,我想我们都必须在某个时候碰到内存壁!
eqzx 2012年

您好,我也有类似情况。我将数组的大小从128更改为96,并且我的程序运行正常。但是我认为这个问题确实无法调试,因为我的数组的大小小于声明堆栈的大小。您知道我在哪里可以找到解决此类问题的信息吗?
莱Lion

4

您的代码是否初始化了串行端口?例如。

void setup()
{
    Serial.begin(9600);
}

否则,可能会导致首次使用串行设备时崩溃。


是的,我有。
eqzx 2012年

3

也许您的内存不足了?使用Serial.print(“ something”)打印的所有字符串都在SRAM中发生,等于该字符串的字符数+ \ 0终止符的1。即使您的草图的编译大小比Arduino闪存小得多,也可能会出现内存不足的情况,因为SRAM对于Atmega328来说只有2048字节,对于Atmega 168来说只有1024字节。文本并删除不必要的调试消息。


嗯 我在标头中声明了几个多维数组,也许这是问题所在吗?它们存储在SRAM中吗?
eqzx 2012年

1
@ nrhine1:在这种情况下,您可能应该向我们展示您的整个草图,而不仅是认为问题所在的部分。
戴夫·特威德

@DaveTweed是的,会的。
eqzx 2012年

1
我注意到您在头文件中定义了很多存储,而不是简单地在其中声明(如果您不了解区别,请参阅本页)。这在C程序中是不寻常的。这是Arduino的正常做法吗?您可能最终会获得这些结构的多个副本。另外,您还要定义一些非常大的自动变量,例如display_state()中的“活动”数组,该数组需要超过1024个字节的堆栈空间。我很确定您的内存不足。
戴夫·特威德

@DaveTweed谢谢您,您和Reza知道了。我将display_state()函数重构为不需要额外分配。我很少做嵌入式处理,我想我们都必须在某个时候碰到内存壁!
eqzx 2012年

1

您尚未显示初始化变量“ loop_counter”的代码。那是在loop()例程之外吗?

您是否可能以这样的方式声明了该声明,使其与另一个超出声明大小运行的内存存储区相邻,并且在loop_counter变量中出现了错误?


我尝试过在许多不同地方以多种不同方式声明它。在标题的正上方loop()等,您是否在说Serial.print()方法可能会以某种方式覆盖它?
eqzx 2012年

我之前的评论的意思是,对于将“不良”行为与Serial.print()的存在隔离开来,我几乎是肯定的。如果不存在,一切正常。
eqzx 2012年

@ nrbine1-在我看来,您的全局变量变量“ loop_counter”正像我在回答中建议的那样被Serial.print()方法踩到。在posipiet的回答中,您被询问是否已正确初始化Serial对象。如果尚未执行此操作,则Serial.print()尝试使用未正确分配和设置的缓冲区时,可能会在计数器上解释“踩”。
Michael Karas 2012年

我已经添加了所有来源。
eqzx 2012年

1

我在您的代码中看不到您要拨打的电话loop()。它看起来也不像您在loop_counter该函数之外使用。您是否有理由将其声明为全局?我假设这是因为您希望它在两次调用之间保留其值。您可以使用静态局部变量来代替。

void loop() {
    static int loop_counter = 0;

    if(loop_counter > 100)
    {
        loop_counter = 0;
    }
    else
    {
        loop_counter++;
    }

    Serial.println("hey");

    if(loop_counter == 0)
    {
         //do_something_important();
    }      
}

那应该确保没有其他外部功能可以踩踏它。您应该始终在尽可能小的范围内声明变量,以避免不必要的行为。

如果这不起作用,则需要真正分析内存使用情况。检查此EE.SE问答以获取各种示例代码,以在Arduino中执行此操作。


我已经尝试使其静态。它没有帮助。这是一个不同的迭代。setup()并且loop()是通过默认的Arduino运行,功能setup()的第一,loop()第二。 loop()本质上类似于main(),不同之处在于它被反复调用。参考:arduino.cc/en/Reference/loop 我将检查该链接。
eqzx 2012年

再次,正如我在其他评论中提到的那样,我无法使用进行调试Serial.print()processing如果我想能够使用GDB ,似乎必须在普通IDE 之外
eqzx 2012年

@ nrhine1您说它Serial.print()工作得很好,因为它可以打印很多“嘿”。这loop_counter就是给您带来问题。尝试删除if(loop_counter == 0)代码并放入get_free_memory()代码(保留loop_counter增量)并运行它。这至少可以告诉您内存分配是否有重大问题。
Embedded.kyle

1

Arduino软件串行库使用中断。(请参阅“ softwareSerial.cpp,.h”)。您可能会遇到ISR在主代码上“步进”的问题(反之亦然)。尝试使用互锁标志,以便代码在打印操作完成时等待。


0

一段时间以前,我曾有过同样问题的印象。那时,我通过在serial.println之前或之后添加延迟(1)来解决该问题。那是Linux上的Arduino 0022。不知道是哪个板,可能是Boarduino系列。不能重现它。

目前,它可以在Windows上使用Arduino 1.01的boarduino USB上使用:

int loop_counter = 0;
int led = 13;

void setup() {
  Serial.begin(9600);
  pinMode(led, OUTPUT);}

void loop() {
    if(loop_counter > 100) {
      loop_counter = 0;
    }
    else {
      loop_counter++;
    }

    Serial.println(loop_counter);

    if(loop_counter == 0) {
      Serial.println("hey hey orange, hey hey!");
    }      
}

谢谢你的建议。不幸的是它没有解决问题。
eqzx 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.