Не удалось выделить SSD1306 при добавлении константы
Я пытаюсь заставить этот код работать:
#include <Button.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <RTClib.h>
#define SCREEN_WIDTH 128 // Ширина OLED-дисплея в пикселях
#define SCREEN_HEIGHT 32 // Высота OLED-дисплея в пикселях
// Объявление для дисплея SSD1306, подключенного к I2C (контакты SDA, SCL)
#define OLED_RESET 4 // Номер контакта сброса (или -1, если используется общий контакт сброса Arduino)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
RTC_DS1307 RTC;
// когда я удаляю эту часть, все работает...
int mode = 1;
const String periodicSystem[60] = {
"H", "He", "Li", "Be", "B", "C", "N", "O",
"F", "Ne", "Na", "Mg", "Al", "Si", "P", "S",
"Cl", "Ar", "K", "Ca", "Sc", "Ti", "V", "Cr",
"Mn", "Fe", "Co", "Ni", "Cu", "Zn", "Ga", "Ge",
"As", "Se", "Br", "Kr", "Rb", "Sr", "Y", "Zr", "Nb",
"Mo", "Tc", "Ru", "Rh", "Pd", "Ag", "Cd", "In", "Sn",
"Sb", "Te", "I", "Xe", "Cs", "Ba", "La", "Ce", "Pr", "Nd"
};
/////////////////////////////////////////////////// ////////////////////
Button button1(7);
void setup() {
Serial.begin(9600);
// SSD1306_SWITCHCAPVCC = генерировать напряжение дисплея от 3,3 В внутри
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Адрес 0x3C для 128x32
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Не продолжать, цикл бесконечен
}
RTC.begin();
if (! RTC.isrunning()) {
Serial.println("RTC is NOT running!");
// Это будет отражать время компиляции вашего скетча
RTC.adjust(DateTime(__DATE__, __TIME__));
}
display.display();
}
void loop() {
DateTime now = RTC.now();
if(button1.pressed()) {
display.clearDisplay();
display.setTextSize(1); // Рисуем текст в масштабе 2X
display.setTextColor(WHITE);
display.setCursor(10, 0);
display.print(now.second());
display.display();
}
}
Всякий раз, когда я пытаюсь добавить константу periodicSystem
, я получаю сообщение об ошибке Ошибка выделения SSD1306
через последовательный порт. Ошибка также исчезает, когда я удаляю часть с помощью button1.pressed()
. По сути, я не могу добавить константу periodicSystem
и одновременно считывать цифровой вывод. Мне кажется, это какая-то проблема с памятью (я только добавляю константу и больше ничего с ней не делаю), но моя IDE сообщает мне, что я использую только 52% доступного хранилища. Что я делаю не так?
Вот моя проводка (на самом деле я использую дисплей 128x32, у меня не было подходящей детали для Fritzing; мой дисплей помечен SDA, SCK, VCC, GND вместо SDA, SCK, VDD, GND; Я использую модуль RTC DS1307 AT24C32):
@allinonemovie, 👍1
Обсуждение1 ответ
Лучший ответ:
Вашему дисплею требуется 624 байта ОЗУ для внутреннего буфера (128 * ((32 + 7) / 8)
). Массиву periodicSystem
требуется 360 байт оперативной памяти только для объектов. Это не включает память, используемую для хранения фактических строковых данных, которая, по моим подсчетам, составляет 168 байт.
На данный момент мы достигли 624+360+168 = 1152 байт из максимума в 2048. Пройдена половина пути, и мы не затронули последовательные буферы или другие объекты, которые вы используете.
Массив (const
или другой) объектов String
— это, безусловно, наименее эффективный способ хранения константных строковых данных на Arduino. Вы используете 528 байт ОЗУ для хранения того, что может храниться в 121 байт флэш-памяти.
Лично я бы хранил данные так:
const char periodicSystem[] PROGMEM = "H HeLiBeB C N O F NeNaMgAlSiP S ClArK CaScTiV CrMnFeCoNiCuZnGaGeAsSeBrKrRbSrY ZrNbMoTcRuRhPdAgCdInSnSbTeI XeCsBaLaCePrNd";
Каждый символ состоит ровно из двух байтов, и PROGMEM
заставляет его оставаться во флэш-памяти и никогда не копироваться в ОЗУ.
Вы можете получить два байта каждого символа с помощью:
char b1 = pgm_read_byte(periodicSystem + (i * 2));
char b2 = pgm_read_byte(periodicSystem + (i * 2) + 1);
Затем либо распечатайте их отдельно, либо объедините в строку C:
char symbol[3] = { b1, b2, 0 };
Разумеется, это будет включать в себя пробел. Так что вы можете удалить это, если хотите:
if (symbol[1] == ' ') symbol[1] = 0;
Теоретически вы также можете изменить пробелы в исходных данных на символ 0, если хотите — в зависимости от того, что вы с ним делаете, это не должно вызвать никаких проблем:
const char periodicSystem[] PROGMEM = "H\0HeLiBeB\0C\0N\0O\0F\0NeNaMgAlSiP\0S\0ClArK\0CaScTiV\0CrMnFeCoNiCuZnGaGeAsSeBrKrRbSrY\0ZrNbMoTcRuRhPdAgCdInSnSbTeI\0XeCsBaLaCePrNd";
- SSD1306 распознается сканером I2C, но не может его отобразить
- сканер i2c застрял на сканировании моего 0,96 дюймового OLED экрана с помощью Arduino Nano
- Программа Arduino, использующая i2c, перестает работать после нескольких раз печати на OLED
- Arduino Nano и oled-экран 0.96 i2c не работают
- Помогите в личном проекте будильника, не могу записать время на семисегментный дисплей
- Как отображать переменные на 0,96-дюймовом OLED-дисплее с библиотекой u8glib?
- Путаница между SPI и I2C для SSD1306 OLED
- Как перевести Arduino Nano в спящий режим с низким энергопотреблением (<0,05 мА)
Подсказка: подумайте о более эффективном использовании памяти для таблицы строк. Использовать для этого Arduino String — очень-очень плохая идея. Используйте строки символов и поместите всю таблицу в память программы. Ссылка. https://www.arduino.cc/reference/en/language/variables/utilities/progmem/, @Mikael Patel