Issue with Pow() function

Hi!
Im getting crazy with this processor… Im a experienced programmer (not yet on arduinos :frowning: so im really wondering what kind of bug this is.
Im using a Pro Mini running on 3V3 and 8mhz.
The software uses 10% Programm Memory and 9 Bytes dynamical memory.
I have no debugging possibilities at the moment.

What the software should do is basically blink out the digits of any decimal numbers.
There are workarounds, but i want to hunt down this obviously bug in the compiler.

With the 321 Parameter it should:

Blink 3 times with 500ms
wait 1000ms
Blink 2 times with 500ms
wait 1000ms
Blink 1 times with 500ms
wait 1000ms
and so on…

what it does:
Blink 3 times with 500ms
wait 1000ms
Blink 2 times with 500ms
wait 1000ms
Blink 4 times with 500ms BUG! BUG! BUG!
wait 1000ms
and so on…

If i activate one of the two outcommented lines in function BlinkDec() the software works as expected. But the number I write in this lines are for sure already in this variable.
If i put the content from BlinkDec() to the main loop it also works!
So the Problem is exactly with the setup of subfunctions i use.

Can anyone tell me whats going on ?!? AAAAAAHHHHHH i Jump out of the window…
Maybe someone with a debugger?
Or is it a Pro Mini issue?

Thanks in advance!
Stefan

const int LedPin = 13;

// the setup function runs once when you press reset or power the board
void setup() {
  pinMode     (LedPin   ,   OUTPUT);

}

//
//
void loop()
{
  unsigned int BlinkNumber = 321; //The decimal Number which i want to print out.
  BlinkDec(BlinkNumber);         //Call a sub functtion
  delay(3000);
}

//Blink the digits of a big decimal number.
//The digits are blinking fast with 500ms
//between every digit is a long sleep with 1000ms
void BlinkDec(unsigned int Number)
{
  unsigned int DigitCount;
  unsigned int Divider;

  //Number = 321; //Activate this line to workaround the bug

  if (Number > 999)
  {
    DigitCount = 4;
  }
  else if (Number > 99)
  {
    DigitCount = 3;
  }
  else if (Number > 9)
  {
    DigitCount = 2;
  }
  else if (Number > 0)
  {
    DigitCount = 1;
  }

  //DigitCount=3; //Activate this line to workaround the bug

  Divider = pow(10, (DigitCount - 1)); //pow(10,2)=100
  Blink(Number / Divider );
  Number = Number % Divider;
  DigitCount = DigitCount - 1;
  delay(1000);

  Divider = pow(10, (DigitCount - 1)); //pow(10,1)=10
  Blink(Number / Divider );
  Number = Number % Divider;
  DigitCount = DigitCount - 1;
  delay(1000);

  Divider = pow(10, (DigitCount - 1)); //pow(10,0)=1
  Blink(Number / Divider );
  Number = Number % Divider;
  DigitCount = DigitCount - 1;
  delay(1000);

}

void Blink(int HowOften)
{
  int Runner2;
  for (int Runner2 = 0; Runner2 < HowOften; Runner2++)
  {
    digitalWrite(LedPin, HIGH);   // turn the LED on (HIGH is the voltage level)
    delay(5);
    digitalWrite(LedPin, LOW);    // turn the LED off by making the voltage LOW
    delay(500);
  }
}

put some serial.print() statements in there so it will output on serial what values it’s calculating for key variables. That’ll point the way to the solution.

I can’t see what the issue is looking at the code, but it’s almost certainly a bug in your code, not a compiler bug. Compiler bugs are rare - not non-existent, but most of us will never encounter one that produces unexpected output.

I currently have no infrastructure for getting serial data on a screen. Sorry. i probalby need a serial to usb adapter ?!? I will read the internet what i need...

stefanb123: I currently have no infrastructure for getting serial data on a screen. Sorry. i probalby need a serial to usb adapter ?!? I will read the internet what i need...

Yeah, you need a USB-serial adapter.

How are you loading code onto the pro mini without one?

stefanb123: Im a experienced programmer...

In which case you should already understand the caveats of floating point arithmetic. Such as using pow to calculate an integer...

  Divider = pow(10, (DigitCount - 1)); //pow(10,2)=100
...
  Divider = pow(10, (DigitCount - 1)); //pow(10,1)=10
...
  Divider = pow(10, (DigitCount - 1)); //pow(10,0)=1

https://drive.google.com/file/d/0B80Hh3Ka3Ob_Wm9mOU9BRzU5RWM/view?usp=sharing

This is what it does on my Uno. Unless I'm mistaken it appears to be doing exactly what you described you wanted. The only change I made was to flash the LED for 50 ms instead of 5 to make it more visible.

I didn't film it, but my 16 MHz Pro Mini does the same thing.

So...I've no idea what you think is wrong. Is yours behaving differently than what's in my video?

Im a experienced programmer

void Blink(int HowOften)
{
  int Runner2;
  for (int Runner2 = 0;

this obviously bug in the compiler.

Right.

@DrAzzy: you are right. Obviously its a serial adpater. I currently try to get someting out of it.

@CodingBadly @Awol If you are SO MORE experienced, then present a solution, instead of blocking this thread with useless comments. If you feel better i withdraw "my exprience".

@Jiggy-Ninja: Thanks a lot! Yes my board behaves differently! My Pro Mini does blink 3,2,4. Yours 3,2,1 Your board does work as i expected!!! So it looks like an issue on my board. I need my serial interface running...

Do you understand floating-point numbers? Do you understand the difference between integers and floating-point numbers? Do you understand loops?

If you are SO MORE experienced, then present a solution, instead of blocking this thread with useless comments.

I'm trying to get you to refer back to your experience to get you to fix your problem yourself.

@stefan Before having a tanty, go read about the Serial Monitor. Then you can insert debugging code to understand what your tightly woven code is doing. The time required to send the serial chars will have no perceptible effect on the execution of your code, unless you accidentally use/write over some important variables.

I have the serial running. It is the pow function. The results are more or less randon and do depend on what was done before.

This does result 99 with DigitCount==3 Divider = (unsigned int)pow(10, (DigitCount - 1)); //pow(10,2)=100

This does result 100 Divider = (unsigned int)pow(10, (3 - 1)); //pow(10,2)=100

@Awol: You are really my hero! Because you knows loops, pow functions and all all all the programming stuff. And i understand only nothing :-(

Thanks to the rest!

The results are more or less randon

We need to see proof of this.

Hint: Integer arithmetic is much more precise than floating-point arithmetic. (that means "don't use "pow", which is a floating-point function". Sorry to labour the point.)

Please change the title of this thread - it's NOT a compiler bug, irrespective of the amount of punctuation you add.

OK, you've changed the thread title. I'll make things a little clearer:

[u]Integer arithmetic is much more precise than floating-point arithmetic. (that means "don't use "pow", which is a floating-point function".[/u]

void BlinkDec(unsigned int Number) {
  while(Number >=100) {
    Blink(1);
    Number-=100;
  }
  delay(INTER_DIGIT_DELAY);
  while(Number >=10) {
    Blink(1);
    Number-=10;
  }
  delay(INTER_DIGIT_DELAY);
  while(Number >=1) {
    Blink(1);
    Number-=1;
  }
}

Of course this has 'leading zeros' and it can't handle anything larger than 999 but I think it meets the spec. Notice that I don't ever use division as the places that I'm using this sort of code (TFT displays) a division operation is much too slow for good visual performance. Floating-point is even slower.

unsigned int    theBlinkingNum = 321;

const  size_t   NUM_DIGITS = log10(theBlinkingNum) + 1;
uint8_t         theBlinkingDigits[NUM_DIGITS];
for ( size_t i = sizeof(theBlinkingDigits); i--; theBlinkingNum /= 10 )
{
    theBlinkingDigits[i] = theBlinkingNum % 10;
}

// ... NO LEADING ZEROS ...
for ( size_t i = 0; i < sizeof(theBlinkingDigits);  i++ )
{
    Blink(theBlinkingDigits[i]);
}

EDIT: Chamged array allocation size calculation

You forgot the 1-second gap between digits.

That is also going to fall apart when the number becomes variable instead of constant. But a pretty good concept anyway.

MorganS: You forgot the 1-second gap between digits.

That is also going to fall apart when the number becomes variable instead of constant. But a pretty good concept anyway.

Not meant to be finished usable code.

How do you see it falling apart?

If the value changes, then the size of the digits array must change.

As it already does!

To be fair I did correct an issue with the array allocation as you posted your comment.