Pages: [1] 2 3   Go Down
Author Topic: Problem with modulo (%) and reset  (Read 12752 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 23
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have a problem that after a small piece of code the Arduoino (UNO)
does no reset.  It resets only by uploading a new sketch or by power off.

In the code below I separated the problem to % operation.  My idea
was to give exact 1 second signal compared to last reset.  I can go
around the problem by other ways, but I'm worried about why this peace of code has a problem.  Because I got the same problem in longer code but occasionally (when interrupt happens during %).

My guess is that if reset or interrupt happens during % then the board is somehow  in unknown state and does not reset.

The problem can be repeated by code below and pressing the reset button repeatedly until led in line 13 remains blinking.  Then the Arduiono is possible to reset only by new sketch or power on.


#include <Wire.h>
#include <string.h>

#undef int
#include <stdio.h>

const int dummyPort = 7;


void setup() {
  Serial.begin(115200);
  Serial.println("Start Arduino");
  pinMode(dummyPort, OUTPUT);
  
}


unsigned long n1000 = 0;
int dOn = 0;


void loop() {
  
  n1000 = micros() % 1000000;
  if ( !dOn && n1000 >= 500000 ) {
    digitalWrite(dummyPort, 1);
    dOn = 1;
  }  
  
  if ( dOn && n1000 < 500000 ) {
    digitalWrite(dummyPort, 0);
    dOn = 0;
  }
  

}

 :o
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 212
Posts: 13531
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I have a problem that after a small piece of code the Arduino (UNO) does no reset.

How should this code do a reset? as simple as the code is I do not understand how it should do a reset.

some remarks:

instead of - int dOn - use a boolean variable, is more clear imho

I can imagine that the micros() wraps around quite fast - start with 0 again, maybe you should try millis() instead as it takes 1000 times as long before wrapping around.

(code not tested)
Code:
unsigned long n1000 = 0;
boolean dOn = false;

void loop()
{
  n1000 = millis() % 1000;
  if ( !dOn && n1000 >= 500 )
  {
    digitalWrite(dummyPort, 1);
    dOn = true;
  }  
  if ( dOn && n1000 < 500 )
  {
    digitalWrite(dummyPort, 0);
    dOn = false;
  }
}
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

0
Offline Offline
Newbie
*
Karma: 0
Posts: 23
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This code is not doing the reset.  The problem is that if YOU do reset
somehow during this code, the Aruino hangs and you can not do another
reset.  Why should you do the reset?  When you start serial from PC
it sinks the DTR and resets Arduino. So the problem is that when you have code like my example, you have good change to hang the Arduino
when you connect it thru USB from PC.  And to simulate that it is much faster to just press the reset button and see what happends.

The micros is just OK for me, because millis is not accurate enough in my purpose.  And dOn I admit that boolean is better in this case, but this was just a smallest peace of code from much much bigger case
where a noticed the problem and tried to minimize the problem something that is easy to repeat.  

And the worst thing is that the same problem comes when some interrupt happens.  And that is the main point, but I think Reset is more familiar for most people.

 smiley-wink
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 212
Posts: 13531
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

OK, so when you press the reset button the Arduino locks itself up in a permanent state. Sounds definitely as a hardware problem.
If you have a voltmeter you could check if the reset switch is working correctly or if it blocks.
Also check your board for small pieces that connect (bad soldering a bit of grease whatever).
You could also circumvent the reset switch by resetting using the reset pin.
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

0
Offline Offline
Newbie
*
Karma: 0
Posts: 23
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have 3 Arduino Uno module and all behaves the same way.
And the reset comes also from USB-serial line by DTR low and
it has exactly same effect.  So do external reset.

The difference in reset by reset button, external reset,
serial start reset and uplod is that when upload is done, the
rset signal stays 5 V, goes to 0 V and the over 7 V and then back to
5 V.  All others just pull reset signal to 0 V and returns it 5 V.

The reset is one of my worries.  The biggest is that WHY Arduino
hangs when Reset or Interrupt is done during %-operation???

 :-[
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 212
Posts: 13531
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

just observed this statement in your code

#undef int

What is its purpose?
Does the problem exists when you remove that line?
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

0
Offline Offline
Newbie
*
Karma: 0
Posts: 23
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Actually I do not know why there is #undef int.
I pick the code where I started somewhere and it was there.

But removing it does not help.  Works exactly same way.
Logged

Huntsville, Alabama, USA
Offline Offline
Sr. Member
****
Karma: 2
Posts: 327
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I don't know about the reset problem, but your code may not work correctly unless you change some of your constants:
Code:
1000000
should be
Code:
1000000L
and
Code:
50000
should be
Code:
50000L

Regards,

-Mike
Logged

Left Coast, CA (USA)
Offline Offline
Brattain Member
*****
Karma: 361
Posts: 17263
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
the reset signal stays 5 V, goes to 0 V and the over 7 V and then back to
5 V.


When the reset is being done via the DTR/RTS signal from the serial FTDI chip, by way to the Arduino IDE or any PC application that is opening or closing that comm port, it is capacitance coupled to the reset pin by a .1mfd cap, so the overshoot to +7vdc is just a transent pulse caused by the discharging of the cap and should not be a concern nor have any effect on the chip. The reset pin unlike all the other pins is rated for a much higher voltage, +12vdc I think, because that is the mechanism to allow the chip to utilize a different high voltage programming mode. All the ugly details are in the AVR datasheet for the chip.

Quote
The biggest is that WHY Arduino
hangs when Reset or Interrupt is done during %-operation???

This has nothing to do with the hardware reset circuitry, just some software mistake or error not yet solved by you or us.  smiley-wink

Lefty
« Last Edit: December 29, 2010, 06:33:42 pm by retrolefty » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 23
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

.. +7vdc is just a transent pulse ...

Anyway, after reset button or normal reset from PC it does not reset
correctly like it does when power on or upload program.  And the signal from osciloscope is different between those two cases.

Still the buggest problem is that WHY Arduiono goes on that kind of state.   No I'm not bold enough to use %-operator in my code...

And for Mike:  for some reason it works same way (= correct when reset happens to work) if there is 500000 or 500000L. You are right that it should have L, but seems to be ok without also.  Still this is not the biggest point of the problem.
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 212
Posts: 13531
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
No I'm not bold enough to use %-operator in my code...

It would suprise me if the % operator has anything todo with it.

replace the line:

Code:
n1000 = millis() % 1000;

with

Code:
unsigned long t1 = millis();
unsigned long t2 = t1 / 1000;
n1000 = t1 - (t2 * 1000);

This is what the modulo does so now you can test the code without the % operator to see if it still behaves that way.

Please post your results.

Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

0
Offline Offline
Newbie
*
Karma: 0
Posts: 23
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Now I have a code:

Code:
#include <Wire.h>
#include <string.h>

#include <stdio.h>

const int dummyPort = 7;


void setup() {
  Serial.begin(115200);
  Serial.println("Start Arduino");
  pinMode(dummyPort, OUTPUT);
  
}


unsigned long n1000 = 0;
int dOn = 0;


void loop() {

  unsigned long t1 = millis();
  unsigned long t2 = t1 / 1000;
  n1000 = t1 - (t2 * 1000);

  
  // n1000 = micros() % 1000000;
  if ( !dOn && n1000 >= 500 ) {
    digitalWrite(dummyPort, 1);
    dOn = 1;
  }  
  
  if ( dOn && n1000 < 500 ) {
    digitalWrite(dummyPort, 0);
    dOn = 0;
  }

}



And that woks exactly same way in all 3 Arduino Uno-modules.
Pressing Rest button or starting Terminal hangs the Arduino.
Upulod or Power on resets and led in 7 starts to blink once
a second.

Instead the code:

Code:
#include <Wire.h>
#include <string.h>

#include <stdio.h>

const int dummyPort = 7;


void setup() {
  Serial.begin(115200);
  Serial.println("Start Arduino");
  pinMode(dummyPort, OUTPUT);
  
}


unsigned long n1000 = 0;
boolean dOn = true;
unsigned long ms = 0;
unsigned long msHigh = 0;
unsigned long msgoal = 500000L;
unsigned long msgoalHigh = 0;

void loop() {

  ms = n1000;
  n1000 = micros();
  if ( n1000 < ms ) msHigh++;
  if ( n1000 >= msgoal && msHigh >= msgoalHigh) {
    digitalWrite(dummyPort, dOn);
    dOn = !dOn;
    unsigned long newms = msgoal + 500000L;
    if ( newms < msgoal ) msgoalHigh++;
    msgoal = newms;
  }  
}


works perfect in this form and also by lot of other stuff in
loop or in interrupts.  So what else I could suspect than
division (or modulo)?
« Last Edit: December 30, 2010, 07:41:23 am by vesal » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 23
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Actually changing
Code:
n1000 = micros() % 1000000;
 
to
Code:
 n1000 = micros();
  while ( n1000 > 1000000L) n1000 -= 1000000L;

(where is no sense after few minutes of course)
makes the code work.  So even more proofs against
modulo % or division  / ???

  
Logged

Austin, TX
Offline Offline
Faraday Member
**
Karma: 71
Posts: 6143
Baldengineer
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Why is stdio.h included?
Logged

Capacitor Expert By Day, Enginerd by night.  ||  Personal Blog: www.baldengineer.com  || Electronics Tutorials for Beginners:  www.addohms.com

Left Coast, CA (USA)
Offline Offline
Brattain Member
*****
Karma: 361
Posts: 17263
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

In your failing code example:

Code:
// n1000 = micros() % 1000000;
  if ( !dOn && n1000 >= 500 ) {
    digitalWrite(dummyPort, 1);
    dOn = 1;
  }  
  
  if ( dOn && n1000 < 500 ) {
    digitalWrite(dummyPort, 0);
    dOn = 0;
  }

Software isn't my strong suit, but shouldn't it be:

Code:
// n1000 = micros() % 1000000;
  if ( [glow]([/glow]!dOn && n1000[glow]) [/glow]>= 500 ) {
    digitalWrite(dummyPort, 1);
    dOn = 1;
  }  
  
  if ( [glow]([/glow]dOn && n1000[glow]) [/glow]< 500 ) {
    digitalWrite(dummyPort, 0);
    dOn = 0;
  }

Lefty
Logged

Pages: [1] 2 3   Go Up
Jump to: