Pages: [1]   Go Down
Author Topic: Serial freeze Arduino and MaxMSP - simple?  (Read 1988 times)
0 Members and 1 Guest are viewing this topic.
NL
Offline Offline
Newbie
*
Karma: 0
Posts: 11
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello community,

Can anyone help me? Serial between Arduino and Max always bothers me.
Is there a doc or something that explains the serial comm. process? About buffering,
and smooth datastreams of a sensorreadings with minimal delay, and... to to analyse
this problem I am dealing with now.
Should read such a thing, but could not find it until now...

The problem:
The Arduino scans one pin with an interrupt to detect a simple
motion switch. Then sends one single notification through serial to MaxMsp.
If a detection occurs, the Arduino waits 1 sec to allow sending a new notification...

This works fine.
The problem is that after about a minute the Arduino refuses to send a
notification and looks as if frozen.
When I change the DTR state of the serial-object in Max (send a 1 or 0),
the serial starts running again for about a minute, and freezes again...

Can anybody point me to what I am doing wrong, or lead me to
documentation so I get a better understanding of the basics of
Serial communication between Arduino and Max?

ThanX!

the code, (quite simple):

/* problem: freeze of serial communication after about a minute.
Changing the DTR state in MaxMSP Serial object
from low to high or high to low makes
it work for another minute...
*/

int pbIn = 0;                   // Interrupt 0 is on DIGITAL PIN 2!
int ledOut = 13;               // The output LED pin
volatile int state = LOW;    // The input state toggle
int Time = 0;                   // moment of interrupt
int PrintSer = 0;               // 1 = allow print serial

void setup()
{
    Serial.begin(9600);
  // Set up the digital pin 2 to an Interrupt and Pin 13 to an Output
  pinMode(ledOut, OUTPUT);

  //Attach the interrupt to the input pin and monitor for ANY Change
  attachInterrupt(pbIn, stateChange, RISING);
}

void loop()
{
  digitalWrite(ledOut, state);
  
  
  // Put led to 'on' for 1 second and send a single message out through serial
  if (millis() < (Time + 1000))
      {
        if (PrintSer == 1)   {
                            Serial.println(33, DEC);
                            PrintSer = 0;
                            }
      state = 1;
      }
  else {
       state = 0;
       PrintSer = 1;
       }
// do nothing but waste some time
delay(100);
}

void stateChange()
{
  Time = millis();
}


Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
When I change the DTR state of the serial-object in Max (send a 1 or 0),
the serial starts running again for about a minute, and freezes again...
This causes a reset of the Arduino. This is a clue that there is something wrong with the Arduino code that is related to time. One minute is 60 seconds or 60000 microseconds.

Code:
void stateChange()
{
 Time = millis();
}
Here, we do something that is related to time.

Code:
int Time = 0;                   // moment of interrupt
But, the millis function does not return an int, so storing the value in an int is going to cause problems. When? After 32.767 seconds.

Code:
if (millis() < (Time + 1000))
After 32,767 microseconds (32+ seconds), Time will contain a negative number. Adding 1000 to that will make it positive again until 33,767 milliseconds have elapsed. After that, Time + 1000 will be negative, and millis() never returns a negative number, so this condition will never be true.

So, it isn't that the Arduino freezes when an interrupt occurs after the Arduino has been running for about 34 seconds. It is that it simply can never do what you want it to do.

There are three things that need to be fixed. The first, obviously, is that the type of Time needs to be changed to match what millis() returns. That is unsigned long.

The second thing that needs to change is that both the main code and the ISR access Time. If Time is read to use in the if test, and an interrupt occurs before millis() is called, Time will have changed when millis() is called, and the if test will then be performed using the old Time. Time needs to be declared volatile to prevent this from happening.

state is currently declared volatile, but I can't see any reason for it to be.

The third thing that needs to be changed is the it test itself. You should never perform addition on variables that can overflow. Reorganize the statement to use subtraction, instead:
Code:
if(millis() - Time > 1000)
The reason for this is that if Time contains a very large value (just shy of rolling over) and millis() is called after rollover, millis() - Time will still return the correct interval. Your code relies on millis() being strictly larger than Time.
Logged

NL
Offline Offline
Newbie
*
Karma: 0
Posts: 11
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Autsch Paul,

Thanks.
You are absolutely right...
I didn't expect the problem in this field at all.   :-?
And nice analysis. Learned a lot of your comments. Getting into Arduino by copy and paste from examples can lead to these terrible wrong assumptions (millis = int) ..makes debugging hard...

volatile...? okay, I need to study that too.

Thanks alot.

Pieter


 
Logged

Pages: [1]   Go Up
Jump to: