Problem with modulo (%) and 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

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)

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

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.

:wink:

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.

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

:-[

just observed this statement in your code

#undef int

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

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.

I don't know about the reset problem, but your code may not work correctly unless you change some of your constants:
1000000should be1000000Land50000should be50000L

Regards,

-Mike

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.

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. :wink:

Lefty

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

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:

n1000 = millis() % 1000;

with

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.

Now I have a 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:

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

Actually changing

n1000 = micros() % 1000000;

to

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

Why is stdio.h included?

In your failing code example:

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

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

Why is stdio.h included?

It was just from the bigger program I tried to split to smallest one where the error still exists and I forgot include there. If I remove all includes, it still works same way wrong.

Software isn't my strong suit, but shouldn't it be:
if ( (!dOn && n1000) >= 500 ) {

Does not matter, because && has stronger precedence than >=.
In case of clarity this would of course be better.

Still none of the above is the problem. The problem is that something weird is with division.

Pardon me for coming late to the party.

Vesal: Are you by any chance using Linux? There are some known problems with the UNO Boot loader and /dev/ttyACM0 on Linux systems. (If you are not using Linux, then: Never Mind.)

Here's what I did:
I took your original program without the superfluous and confusing (to us mere humans) stuff:

I added a delay of 1 millisecond in the loop. Here's the code:

const int dummyPort = 13; // I use pin 13 since it already has an LED

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

When I do this, I see the three-blink bootloader sequence and then the LED blinks on and off with a period of about a second, which, I perceive, was your intent. I can reset by opening a terminal and I can reset by pressing button. All is Good on my Centos 5.5 system with Arduino version 0022 , avr-gcc version 4.3.4 built from source and with the latest version of the Optiboot boot loader from Google Code Archive - Long-term storage for Google Code Project Hosting.

However, if I delete the delay() statement, it repeatedly does the bootloader three-blink thing on the LED on pin 13 whenever I hit the button or when I open a terminal, and never gets to the code in the sketch.

If you are using Windows, then never mind (but I already said that). Maybe some of the other helpers can come up with something.

The code itself works just swell on Duemilanove boards as well as the UNO with my Linux system, although I might have written it a little differently. With the Duemilanove boards it doesn't need the delay() statement.

The problem is that something weird is with division.

I can state unequivocally (and I am unanimous in that) that it has nothing do do with division.

Regards,

Dave

I can state unequivocally (and I am unanimous in that) that it has nothing do do with division.

But that's what he is saying, division is do do. :wink:

Lefty

Hmmm... I was just testing whether the forum's swear filter would let me say "do do" on the Internet. (That's my story and I'm sticking with it.)

I mean, it does its damndest to keep us from saying "damn," right? Really.

Regards,

Dave

Footnote:
If you hadn't been so fast on the trigger, I might have caught it and done a sneaky, silent edit to change it. I really wish I hadn't had to lay off my proofreader and editor. Oh, well...

Footnote:
If you hadn't been so fast on the trigger, I might have caught it and done a sneaky, silent edit to change it. I really wish I hadn't had to lay off my proofreader and editor. Oh, well...

Somehow I think you will get over it. :wink:

Lefty