Go Down

Topic: Problem with modulo (%) and reset (Read 14380 times) previous topic - next topic

vesal

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

robtillaart

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: [Select]

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;
 }
}
Rob Tillaart

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

vesal

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.

;)

robtillaart

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.
Rob Tillaart

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

vesal

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???

:-[

robtillaart

just observed this statement in your code

#undef int

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

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

vesal

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.

Mike Murdock

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

Regards,

-Mike

retrolefty

#8
Dec 30, 2010, 12:25 am Last Edit: Dec 30, 2010, 12:33 am by retrolefty Reason: 1
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.  ;)

Lefty

vesal

.. +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.

robtillaart

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: [Select]
n1000 = millis() % 1000;

with

Code: [Select]

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.

Rob Tillaart

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

vesal

#11
Dec 30, 2010, 01:08 pm Last Edit: Dec 30, 2010, 01:41 pm by vesal Reason: 1
Now I have a code:

Code: [Select]

#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: [Select]

#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)?

vesal

Actually changing
Code: [Select]
n1000 = micros() % 1000000;
 
to
Code: [Select]

 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  / ???

 

James C4S

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

retrolefty

In your failing code example:

Code: [Select]
// 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: [Select]
// 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

Go Up