nickgammon / BigNumber

BigNumber library for the Arduino
MIT License
85 stars 22 forks source link

failure on repeated operations. hardware limitations? #21

Closed kilpaff closed 4 months ago

kilpaff commented 4 months ago

hello

I'm creating a calculator with a pro micro (ATMega32U4) I receive char from a keypad. The new keystroke must be the lightest digit:

Serial.print("key presed "); Serial.println(tecla); entrada_num = 10 *entrada_num; int b = String(tecla).toInt(); entrada_num += b; Serial.print("new value: "); Serial.println(entrada_num);

The first 5 presses have a correct result, but...

key preset 1 new value: 1,000 key presed 2 new value: 12,000 key presed 3 new value: 123,000 key presed 4 new value: 1234,000 key presed 5 new value: 12345,000 key preset 6 new value: -7616,000 key presed 7 new value: -10617,000

Thank you!

nickgammon commented 4 months ago

Can you show more of your code please? It depends how entrada_num is declared.

kilpaff commented 4 months ago

is a initial test code:

#include <Arduino.h>
#include "ButtonMatrix.h" /** Include this header in order to work with the button matrix */
#include <TimeLib.h>
#include <Keypad.h>

#include "BigNumber.h"

//#define _Screen_Over_511_ //if using 4.3" high definition screen

#define _Digole_Serial_I2C_
#include <DigoleSerial.h>

//--------I2C setup
#if defined(_Digole_Serial_I2C_)
#include <Wire.h>
DigoleSerialDisp mydisp(&Wire, '\x27');  //I2C:Arduino UNO: SDA (data line) is on analog input pin 4, and SCL (clock line) is on analog input pin 5 on UNO and Duemilanove
#endif

#define LCDCol 16
#define LCDRow 2
#define lcdancho 240  //the pixels width and height of the display
#define lcdalto 320

int x, y;  //posiciones del touchScreen
int i;
String a;
String linea[10];
String entrada;
BigNumber entrada_num;
//BigNumber historico[10];
BigNumber numero[2];
BigNumber resultado;

char operacion;

char tecla;
int decimales = 2;

/** Everything in the ButtonMatrix library is within this namespace */
using namespace RSys;

static const uint32_t c_uiMonitorBaud = 115200;  // USB monitoring baud rate

// -------------
// Button matrix
// -------------

const uint8_t COLS = 6; /** Number of button matrix columns */
const uint8_t ROWS = 4; /** Number of button matrix rows */

//uint8_t colPins[COLS] = { 6, 7, 8, 9, 10, 16 }; /** Button matrix column pins */
//uint8_t rowPins[ROWS] = { 1, 0, 4, 5 };         /** Button matrix row pins */

uint8_t colPins[COLS] = { 6, 7, 8, 9, 10, 16 }; /** Button matrix column pins */
uint8_t rowPins[ROWS] = { 1, 0, 4, 5 };         /** Button matrix row pins */

/** Button matrix button definitons */
RSys::Button buttons[ROWS][COLS] = {
  { '0', 'x', '.', 'A', 'B', 'C' },
  { '1', '2', '3', '/', '%', 'S' },
  { '4', '5', '6', '*', '-', 'F' },
  { '7', '8', '9', '+', '=', 'DEL' }
};

ButtonMatrix matrix((Button*)buttons, rowPins, colPins, ROWS, COLS);

void setup() {

  Serial.begin(c_uiMonitorBaud);

  BigNumber::begin(3);

  matrix.init(); /** Initialize the ButtonMatrix*/

  mydisp.begin();
  mydisp.setRotation(1);

  /*----------for text LCD adapter and graphic LCD adapter ------------*/
  mydisp.clearScreen();  //CLear screen
  //mydisp.displayConfig(1);    //set config display ON, 0=off
  //mydisp.setI2CAddress(0x29);  //this function only working when you connect using I2C, from 1 to 127
  //delay(1000);
  //mydisp.setLCDColRow(16,2);  //set LCD Col and Row, only time set up is OK
  mydisp.disableCursor();  //disable cursor, enable cursore use: enableCursor();
  //mydisp.drawStr(4, 0, "Demo now"); //display string at: x=4, y=0

  mydisp.setFlashFont(600000);

  mydisp.resetDrawWindow();
  mydisp.setBackLight(50);  //hay que apagar/encender para que se cargue la config

  //ponemos el 0 inicial
  mydisp.setFlashFont(600000);
  mydisp.setPrintPos(0, 5);
  mydisp.print(0);
}

void loop() {
  Button* pButton = NULL;

  const uint16_t numButtons = matrix.getNumButtons();

  if (matrix.update()) {

    for (uint16_t idx = 0; idx < numButtons; idx++) {
      pButton = matrix.getButton(idx);

      if (pButton->rose()) {  //cuando soltemos el boton

        tecla = char(pButton->getNumber());
        //Serial.print(tecla);

        if (isDigit(tecla)) {
          if (entrada == "0" || operacion == "=") {
            mydisp.clearScreen();
            mydisp.setFlashFont(600000);
            mydisp.setPrintPos(0, 5);

            entrada = tecla;
            entrada_num = String(tecla).toInt();
          } else {

            entrada = entrada + tecla;

            Serial.print("key presed ");
            Serial.println(tecla);
            entrada_num = 10 *entrada_num;
            int b = String(tecla).toInt();
            entrada_num += b;
            Serial.print("new value: ");
            Serial.println(entrada_num);

            //

          }

          //sumando[0] = entrada.toFloat();
          //mydisp.setFlashFont(600000);
          //mydisp.setPrintPos(0, 5);
          mydisp.print(tecla);

        } else {  //si no es un digito

          if (tecla == '=') {

            numero[1] = entrada_num;

            switch (operacion) {
              case '+':
                resultado = numero[0] + numero[1];
                break;
              case '-':
                resultado = numero[0] - numero[1];
                break;
              case '*':
                resultado = numero[0] * numero[1];
                break;
              case '/':
                resultado = numero[0] / numero[1];
                break;
            }

            Serial.println(numero[0]);
            Serial.print(operacion);
            Serial.println(numero[1]);
            Serial.println("-----------");
            Serial.println(resultado);

            mydisp.setFlashFont(600000);
            mydisp.setPrintPos(0, 5);
            mydisp.println(resultado);

            numero[0] = 0;
            numero[1] = 0;
            entrada = "0";
            tecla = "";

          } else {
            operacion = tecla;
            numero[0] = entrada_num;
            entrada_num = 0;
            entrada = "0";
            tecla = "";
            Serial.println(numero[0]);
          }

          //Serial.println(linea[0]);
          //historico[0] = entrada.toFloat();
          //historial();
        }
      }
    }
  }
}
nickgammon commented 4 months ago

Try changing

            entrada_num = 10 *entrada_num;

to:

            entrada_num = entrada_num * 10;

or:

            entrada_num = entrada_num * BigNumber(10);
kilpaff commented 4 months ago

Try changing

            entrada_num = 10 *entrada_num;

to:

            entrada_num = entrada_num * 10;

exit status 1

Compilation error: ambiguous overload for 'operator*' (operand types are 'BigNumber' and 'int')

or:

            entrada_num = entrada_num * BigNumber(10);

exit status 1

Compilation error: expected primary-expression before ')' token

nickgammon commented 4 months ago

I made a minimal example, which is what you should do when debugging this sort of stuff:


#include "BigNumber.h"

String entrada;
BigNumber entrada_num;

void SimulateKeypress (char tecla)
  {

  entrada = entrada + tecla;

  Serial.print("key presed ");
  Serial.println(tecla);
  entrada_num = 10 *entrada_num;
  int b = String(tecla).toInt();
  entrada_num += b;
  Serial.print("new value: ");
  Serial.println(entrada_num);
  }

void setup() {
  Serial.begin(115200);
  BigNumber::begin(3);
  SimulateKeypress ('1');
  SimulateKeypress ('2');
  SimulateKeypress ('3');
  SimulateKeypress ('4');
  SimulateKeypress ('5');
  SimulateKeypress ('6');
  SimulateKeypress ('7');
}

void loop() { }

output was indeed:

key presed 1
new value: 1.000
key presed 2
new value: 12.000
key presed 3
new value: 123.000
key presed 4
new value: 1234.000
key presed 5
new value: 12345.000
key presed 6
new value: -7616.000
key presed 7
new value: -10617.000

This works:

#include "BigNumber.h"

BigNumber entrada_num;

void SimulateKeypress (char tecla)
  {
  Serial.print("key presed ");
  Serial.println(tecla);
  entrada_num = entrada_num * BigNumber(10);
  entrada_num = entrada_num + BigNumber (tecla - '0');
  Serial.print("new value: ");
  Serial.println(entrada_num);
  }

void setup() {
  Serial.begin(115200);
  BigNumber::begin(3);
  entrada_num = BigNumber (0);
  SimulateKeypress ('1');
  SimulateKeypress ('2');
  SimulateKeypress ('3');
  SimulateKeypress ('4');
  SimulateKeypress ('5');
  SimulateKeypress ('6');
  SimulateKeypress ('7');
  SimulateKeypress ('8');
  SimulateKeypress ('9');
}

void loop() { }

Output:

key presed 1
new value: 1.000
key presed 2
new value: 12.000
key presed 3
new value: 123.000
key presed 4
new value: 1234.000
key presed 5
new value: 12345.000
key presed 6
new value: 123456.000
key presed 7
new value: 1234567.000
key presed 8
new value: 12345678.000
key presed 9
new value: 123456789.000
kilpaff commented 4 months ago

Perfect!!!

This solution works perfectly.

Thank you so much!