Недостаточно памяти

Я делаю простой калькулятор на Arduino Uno R3. Здесь есть только +, -, x и /.

Я использую 3 библиотеки:

  1. Это использование для ЖК-дисплея с модулем I2C. Arduino-LiquidCrystal-I2C-library
  2. Это использование для клавиатуры 4x4. Chris--A/Keypad
  3. А это: jamesgregson/expression_parser

Мой код:

#include "expression_parser.h"
#include <Keypad.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>


LiquidCrystal_I2C lcd(0x3F, 16, 2);

const byte ROWS = 4; 
const byte COLS = 4; 

char keys[ROWS][COLS] = {
  {'1', '2', '3', '+'},
  {'4', '5', '6', '-'},
  {'7', '8', '9', '*'},
  {'.', '0', '=', '/'}
};

byte rowPins[ROWS] = {10, 9, 8, 7}; 
byte colPins[COLS] = {6, 5, 4, 3}; 

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

String s = "";  
char ex[16];

void setup() {
  Serial.begin(9600);
  lcd.init();          
  lcd.backlight();      
  lcd.setCursor(0, 0);  
}

int cur = 0;
bool enter = false;

void loop() 
{
  char key = keypad.getKey();   

  if ((key != '=') && (key != NO_KEY) ) {
    if (!enter) {               
      Serial.println(F("key"));
      if(key=='/')
        lcd.print(F("':'"));
      else 
      if (key=='*')
        lcd.print(F("'x'"));
      else
        lcd.print(F("key"));
      s = s + key;              
      cur++;                    
      lcd.setCursor(cur, 0);    
    } else {                    

      lcd.setCursor(0, 0);      
      lcd.print("");
      enter = false;
      lcd.setCursor(0, 0);
      cur = 0;
      lcd.print(F("key"));
      s = "";
      s = s + key;
      cur++;
      lcd.setCursor(cur, 0);
    }
  } else if (key == '=') {    
    enter = true;

    if ((s[0] == '=') || (s[0] == '/') || (s[0] == '*') || (s[0] == '.')) {
      lcd.setCursor(0, 1);
      lcd.print("Error");
    } else {
      lcd.setCursor(0, 1);
      lcd.print("");
      s.toCharArray(ex, 16);
      Serial.println(F("s"));
      int re = parse_expression(ex); 
      String check = String(re);
      if (check.length() > 15) {
        lcd.setCursor(0, 1);
        lcd.print("Overflow");
      } else {
        Serial.println(re);
        lcd.setCursor(0, 1);
        lcd.print("=");
        lcd.print(F("re"));                
      }
    }
  }
}

Я запустил его и получил ошибку:

Глобальные переменные используют 3302 байта (161%) динамической памяти, а для локальных переменных остается -1254 байта. Максимум — 2048 байт. Недостаточно памяти; см. http://www.arduino.cc/en/Guide/Troubleshooting#size для получения советов по уменьшению твой след. Ошибка компиляции для платы Arduino/Genuino Uno.

И что мне делать?

, 👍3

Обсуждение

анализатор выражений использует много оперативной памяти, избавьтесь от него. Вы выполняете всего 4 основные операции, поэтому все, что вам нужно сделать, это небольшой набор операторов IF и проанализировать сами числа, что Arduino может сделать без большой библиотеки., @dandavis

Самая эффективная система, которую вы можете использовать, называется «[Обратная польская нотация](https://en.wikipedia.org/wiki/Reverse_Polish_notation)» или *RPN*. Это система на основе стека, и она может очень эффективно работать в системах с очень небольшим объемом памяти. Просто надо привыкнуть правильно вводить уравнения..., @Majenko

какую плату Arduino вы используете?, @Rohit Singh


2 ответа


3

Ваши собственные объявленные глобальные переменные не занимают много места.

Остерегайтесь использования строки: ее можно расширять в ходе выполнения программы, таким образом используя больше.

Проблема в библиотеках.

Что вы можете сделать:

  • Оставьте включаемый и связанный код для каждой библиотеки, чтобы увидеть, какая из них занимает много глобального пространства.
  • Когда вы выясните, что вызывает проблемы, попробуйте проследить за внутренним устройством библиотеки, чтобы увидеть, есть ли какая-то буферизованная память, которую вы можете уменьшить.

Если нет, то, боюсь, единственное решение — перейти на Arduino с большим объемом памяти (например, Arduino Mega с 8 КБ).

С помощью PROGMEM вы сможете сэкономить место

char keys[ROWS][COLS] = {
  {'1', '2', '3', '+'},
  {'4', '5', '6', '-'},
  {'7', '8', '9', '*'},
  {'.', '0', '=', '/'}
};

byte rowPins[ROWS] = {10, 9, 8, 7}; 
byte colPins[COLS] = {6, 5, 4, 3}; 

Поскольку он будет размещен во Flash, а не в SRAM, но это сэкономит вам всего 24 байта.

,

При беглом взгляде на эти библиотеки мне кажется, что парсер выражений потребляет _намного_ больше оперативной памяти, чем два других. Он содержит множество сообщений об ошибках и код для работы с трансцендентными функциями: вещи, которые ОП не использует., @Edgar Bonet


-1

Перейдите на плату на базе '1284P. Они имеют 16 КБ SRAM и еще 12 контактов ввода-вывода, что даст вам достаточно места для добавления и расширения дополнительных функций позже.

Я предлагаю платы 1284P в нескольких форм-факторах на сайте www.crossroadsfencing.com/BobuinoRev17/

Его легко добавить в IDE с помощью MegaCore от MCUdude. https://github.com/MCUdude/MegaCore

,