9
\$\begingroup\$

I'm using a loop counter, declared in a header:

int loop_counter = 0;

I use this counter to trigger an event every so often. I used to use a modulo for this same type of behavior, but I simplified it so it's easier to work with (it still results in the same behavior)

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

    //Serial.println("hey");

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

All is well and good, until I try communicating with Serial by uncommenting the //Serial.println("hey"); ("hey" in this example because, to me, this behavior is absurd).

This results in loop_counter never triggering the do_something_important(); section of code. I tried declaring loop_counter as volatile, that didn't change anything. I tried Serial.print ing loop_counter, and I was also getting odd behavior (it would freeze the loop). Serial.println("hey"); works in the sense that in the Serial monitor I get plenty of "hey", (i.e. quickly a lot more than 100 "heys", the number of iterations at which the other section of code should trigger)

What could possibly be causing the usage of Serial, with data that is not (as far as I can tell) tied to loop_counter completely prevent it from working properly?

EDIT: Here is the part of the main file that ended up posing the problem (well, contributing the most to it (using too much memory)):



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);
 }
}

Here is "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; short led_matrix[num_rows][num_cols];

const short 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}}; const short letter_c[nrows][ncols] = {{0,1,1,1},{1,0,0,0},{1,0,0,0},{0,1,1,1}}; const short 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 *next; int x; int y; } 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]; #endif

Some more information: - I'm using an Uno (ATMega328)

\$\endgroup\$
  • \$\begingroup\$ WHat is your stack size? Is there a chance that you can paint your stack and see if it is getting corrupted. Does the Serial Print use interrupts, is your code reentrant? \$\endgroup\$ – Ktc Sep 25 '12 at 15:03
  • \$\begingroup\$ The Serial print isn't triggered by any interrupts, I'm using it only in the loop() function. How should I paint my stack if the only method of output I have (Serial.print()) is failing me? \$\endgroup\$ – eqzx Sep 25 '12 at 15:42
  • 2
    \$\begingroup\$ To eliminate possible mistakes and misunderstood side effects of seemingly trivial changes, please replace the code in your question with a literal, character-exact copy of a sketch cut down to the minimum needed to trigger the problem. Not "this is my program which fails if I.." but exactly the minimum program which fails in this way. \$\endgroup\$ – Chris Stratton Sep 25 '12 at 21:33
2
\$\begingroup\$

I also had a similar problem to this, and am very sure that yours is also out of stack space related. Try shrinking the code as much as possible.

In my case code would sometimes run when I had a serial message in it, but then it would seem to not run when I did not. I also had a case where sending serial messages would cause the arduino to reset endlessly.

I was also using an arduino328. Likely you should reduce the size of your array if you have any to the smallest size that is acceptable.

\$\endgroup\$
  • \$\begingroup\$ thank you, you and Dave Tweed got it. I refactored the display_state() function to not need that extra allocation. I rarely do embedded processing, I suppose we all have to hit the memory wall at some point! \$\endgroup\$ – eqzx Sep 27 '12 at 1:41
  • \$\begingroup\$ Hello, I have the similar situation. I change the size of the array from 128 to 96 and my program works fine. But I think this problem is really out of trace to debug, because the size of my array is smaller of the declare stack size. Do you know where I can find info to deal with this kind of problem? \$\endgroup\$ – Lion Lai Aug 17 '18 at 19:06
4
\$\begingroup\$

Does your code initialise the serial port? Eg.

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

Failing to do this could result in a crash on first use of the serial.

\$\endgroup\$
  • \$\begingroup\$ Yes, I have that. \$\endgroup\$ – eqzx Sep 25 '12 at 14:06
3
\$\begingroup\$

Maybe you're running out of memory? All strings you print with Serial.print("something") take place in SRAM, equal to the number of characters of that string + 1 for the \0 terminator. It is possible to run out of memory even if your sketch's compiled size is much smaller than the Arduino flash memory, because SRAM is only 2048 bytes for Atmega328 and 1024 bytes for Atmega 168. I had a similar problem, which I solved by shortening all texts and removing unnecessary debug messages.

\$\endgroup\$
  • \$\begingroup\$ Hmm. I have several multidimensional arrays declared in my header, maybe that's the problem? Are they stored in SRAM? \$\endgroup\$ – eqzx Sep 25 '12 at 14:34
  • 1
    \$\begingroup\$ @nrhine1: In that case, you should probably show us your entire sketch, not just the parts where you think the problem lies. \$\endgroup\$ – Dave Tweed Sep 25 '12 at 15:47
  • \$\begingroup\$ @DaveTweed Yes, will do. \$\endgroup\$ – eqzx Sep 25 '12 at 16:44
  • 1
    \$\begingroup\$ I notice you're defining a lot of storage in your header file, rather than simply declaring it there (if you don't understand the distinction see this page). This would be unusual in a C program; is it the normal practice on Arduino? You might be ending up with multiple copies of these structures. Also, you are defining some very large automatic variables, such as the "alive" array in display_state(), which needs over 1024 bytes of stack space. I'm pretty sure you're simply running out of memory. \$\endgroup\$ – Dave Tweed Sep 26 '12 at 3:47
  • \$\begingroup\$ @DaveTweed thank you, you and Reza got it. I refactored the display_state() function to not need that extra allocation. I rarely do embedded processing, I suppose we all have to hit the memory wall at some point! \$\endgroup\$ – eqzx Sep 27 '12 at 1:41
1
\$\begingroup\$

You have not shown the code that initializes the variable "loop_counter". Is that outside the loop() routine?

Do you possibly have that declared in a way that it is adjacent to another memory storage area that is operating outside its declared size and this tromping on the loop_counter variable?

\$\endgroup\$
  • \$\begingroup\$ I've tried declaring it in many different ways, in many different places. In the header, right above loop(), etc. Are you saying that the Serial.print() method might be overwriting it somehow? \$\endgroup\$ – eqzx Sep 25 '12 at 4:14
  • \$\begingroup\$ What I meant by previous comment is that I'm almost positive that I've isolated the 'bad' behavior to the existence of the Serial.print(). When it's not there, things work fine. \$\endgroup\$ – eqzx Sep 25 '12 at 4:19
  • \$\begingroup\$ @nrbine1 - It seems to me that your global variable variable "loop_counter" is getting stepped on by the Serial.print() method like I suggested in my answer. In the answer by posipiet you've been asked if the Serial object has been properly initialized. If that has not been done it may explain the "tromping" on your counter as it Serial.print() attempts to use a buffer that has not been properly allocated and setup. \$\endgroup\$ – Michael Karas Sep 25 '12 at 11:09
  • \$\begingroup\$ I've added all of my source. \$\endgroup\$ – eqzx Sep 25 '12 at 17:58
1
\$\begingroup\$

I don't see in your code where you're calling loop(). It also doesn't look like you're using loop_counter outside that function. Is there a reason you're declaring it global? I'm assuming it's because you want it to retain it's value in between calls. You could do this with a static local variable instead.

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();
    }      
}

That should make sure that no other external functions can stomp on it. You should always declare your variables in the smallest scope possible to avoid unwanted behavior.

If that doesn't work, you will need to really analyze your memory usage. Check this EE.SE Q&A for various sample code to do this within an Arduino.

\$\endgroup\$
  • \$\begingroup\$ I tried making it static already. It did not help. This is a different iteration. setup() and loop() are functions that arduino runs by default, setup() first, loop() second. loop() is essentially like main(), except it is called repeatedly. reference: arduino.cc/en/Reference/loop I will check out that link. \$\endgroup\$ – eqzx Sep 25 '12 at 18:48
  • \$\begingroup\$ again, as I've mentioned in other comments, I cannot debug with Serial.print(). It looks like I'll have to outside the normal processing IDE if I want to be able to use GDB \$\endgroup\$ – eqzx Sep 25 '12 at 18:55
  • \$\begingroup\$ @nrhine1 You said that Serial.print() was working fine in that it was printing out "hey" a lot. It's loop_counter that is giving you a problem. Try removing the if(loop_counter == 0) code and putting in the get_free_memory() code (leave the loop_counter increment) and running it. This will at least tell you if you have any major problems with your memory allocation. \$\endgroup\$ – embedded.kyle Sep 25 '12 at 19:10
1
\$\begingroup\$

The Arduino software serial library uses interrupts. (see "softwareSerial.cpp, .h"). You may have an issue where the ISR is "stepping" on the main code (or vice- versa). Try using interlock flags, so that the code waits while the print operations complete.

\$\endgroup\$
0
\$\begingroup\$

At one point some time ago I had the impression of having the same problem. Back then, I solved it by adding a delay (1) in front or after the serial.println. That was with Arduino 0022 on Linux. Not sure which board it was, probably a Boarduino serial. Cant reproduce it either.

Currently, it works for me on a boarduino USB with Arduino 1.01 on Windows:

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!");
    }      
}
\$\endgroup\$
  • \$\begingroup\$ Thanks for the suggestion. It unfortunately did not solve the problem. \$\endgroup\$ – eqzx Sep 25 '12 at 14:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.