ATmega328, ошибка кода arduino nano v3, говорящая о недостаточной оперативной памяти
об этом говорится в ошибке кода, и я не уверен, что делать, пожалуйста, мне нужна срочная помощь :(`
// Простая прокрутка текста, управляемая через Bluetooth
// автор: Йорук для Instructable
// 26 02 15: первый код
// 03 03 15: обновление буфера
// 04 03 15: более быстрая версия, оба буфера
// 05 03 15 : уборка и помощь
/*
WIRING :
pin 12 - DataIn of the first led matrix module
pin 11 - CLK of the first led matrix module
pin 10 - CS of the first led matrix module
pin 9 : RX pin of the bluetooth module
pin 8 : TX pin of the bluetooth module
5V : 5v of the matrix module, 5v of the bluetooth module
GND : the two GND signals of the matrix modules and the bluetooth module
WARNING : Use a 3v3 arduino card (nano...) or a level converter !!!
Wire the matrix modules in serie. See the Instructable steps.
*/
//Библиотека для матрицы светодиодов
#include "LedControl.h"
// виртуальная последовательная библиотека, используемая с Bluetooth
#include <SoftwareSerial.h>
//Сколько у нас матриц?
int MatrixNumber =5;
//конфигурация Bluetooth виртуального последовательного порта
SoftwareSerial BT(8, 9); //контакт 8: виртуальный прием; контакт 9: виртуальный TX.
// задержка между каждым отображением экрана (мс)
int SpeedDelay = 12;
//общая длина строки. Первое сообщение имеет длину 25 символов (включая пробелы).
int LongueurChaine=25;
char incomingByte; //входящие данные из канала BT
// два массива пикселей
char Buffer[200]; //содержание пикселей TOUTE LA PHRASE
char Buffer_inverse[200]; //содержимое всех пикселей TOUTE LA PHRASE, но больше всего симметрично для инверсии экрана
// массив сообщений
char Phrase[50];
//здесь мы настраиваем светодиодную матрицу
LedControl lc=LedControl(12,11,10,MatrixNumber);
// библиотека символов
int fontDefinitions[480] = {
0x00,0x00,0x00,0x00,0x00,/*space*/ // равно 32 в ASCII
0x00,0xF6,0xF6,0x00,0x00,/*!*/
0x00,0xE0,0x00,0xE0,0x00,/*"*/
0x28,0xFE,0x28,0xFE,0x28,/*#*/
0x00,0x64,0xD6,0x54,0x08,/*$*/
0xC2,0xCC,0x10,0x26,0xC6,/*%*/
0x4C,0xB2,0x92,0x6C,0x0A,/*&*/
0x00,0x00,0xE0,0x00,0x00,/*'*/
0x00,0x38,0x44,0x82,0x00,/*(*/
0x00,0x82,0x44,0x38,0x00,/*)*/
0x88,0x50,0xF8,0x50,0x88,/***/
0x08,0x08,0x3E,0x08,0x08,/*+*/
0x00,0x00,0x05,0x06,0x00,/*,*/
0x08,0x08,0x08,0x08,0x08,/*-*/
0x00,0x00,0x06,0x06,0x00,/*.*/
0x02,0x0C,0x10,0x60,0x80,/*/*/
0x7C,0x8A,0x92,0xA2,0x7C,/*0*/
0x00,0x42,0xFE,0x02,0x00,/*1*/
0x42,0x86,0x8A,0x92,0x62,/*2*/
0x44,0x82,0x92,0x92,0x6C,/*3*/
0x10,0x30,0x50,0xFE,0x10,/*4*/
0xE4,0xA2,0xA2,0xA2,0x9C,/*5*/
0x3C,0x52,0x92,0x92,0x0C,/*6*/
0x80,0x86,0x98,0xE0,0x80,/*7*/
0x6C,0x92,0x92,0x92,0x6C,/*8*/
0x60,0x92,0x92,0x94,0x78,/*9*/
0x00,0x00,0x36,0x36,0x00,/*:*/
0x00,0x00,0x35,0x36,0x00,/*;*/
0x10,0x28,0x44,0x82,0x00,/*<*/
0x28,0x28,0x28,0x28,0x28,/*=*/
0x00,0x82,0x44,0x28,0x10,/*>*/
0x40,0x80,0x8A,0x90,0x60,/*?*/
0x7C,0x82,0xBA,0xBA,0x62,/*@*/
0x3E,0x48,0x88,0x48,0x3E,/*A*/
0xFE,0x92,0x92,0x92,0x6C,/*B*/
0x7C,0x82,0x82,0x82,0x44,/*C*/
0xFE,0x82,0x82,0x82,0x7C,/*D*/
0xFE,0x92,0x92,0x92,0x82,/*E*/
0xFE,0x90,0x90,0x90,0x80,/*F*/
0x7C,0x82,0x82,0x8A,0x4E,/*G*/
0xFE,0x10,0x10,0x10,0xFE,/*H*/
0x82,0x82,0xFE,0x82,0x82,/*I*/
0x84,0x82,0xFC,0x80,0x80,/*J*/
0xFE,0x10,0x28,0x44,0x82,/*K*/
0xFE,0x02,0x02,0x02,0x02,/*L*/
0xFE,0x40,0x20,0x40,0xFE,/*M*/
0xFE,0x60,0x10,0x0C,0xFE,/*N*/
0x7C,0x82,0x82,0x82,0x7C,/*O*/
0xFE,0x90,0x90,0x90,0x60,/*P*/
0x7C,0x82,0x82,0x86,0x7E,/*Q*/
0xFE,0x90,0x98,0x94,0x62,/*R*/
0x64,0x92,0x92,0x92,0x4C,/*S*/
0x80,0x80,0xFE,0x80,0x80,/*T*/
0xFC,0x02,0x02,0x02,0xFC,/*U*/
0xF8,0x04,0x02,0x04,0xF8,/*V*/
0xFC,0x02,0x0C,0x02,0xFC,/*W*/
0xC6,0x28,0x10,0x28,0xC6,/*X*/
0xC0,0x20,0x1E,0x20,0xC0,/*Y*/
0x86,0x8A,0x92,0xA2,0xC2,/*Z*/
0x00,0x00,0xFE,0x82,0x00,/*[*/
0x00,0x00,0x00,0x00,0x00,/*this should be / */
0x80,0x60,0x10,0x0C,0x02,/*]*/
0x20,0x40,0x80,0x40,0x20,/*^*/
0x01,0x01,0x01,0x01,0x01,/*_*/
0x80,0x40,0x20,0x00,0x00,/*`*/
0x04,0x2A,0x2A,0x2A,0x1E,/*a*/
0xFE,0x12,0x22,0x22,0x1C,/*b*/
0x1C,0x22,0x22,0x22,0x14,/*c*/
0x1C,0x22,0x22,0x12,0xFE,/*d*/
0x1C,0x2A,0x2A,0x2A,0x18,/*e*/
0x10,0x7E,0x90,0x80,0x40,/*f*/
0x18,0x25,0x25,0x25,0x1E,/*g*/
0xFE,0x10,0x10,0x10,0x0E,/*h*/
0x00,0x12,0x5E,0x02,0x00,/*i*/
0x02,0x01,0x01,0x11,0x5E,/*j*/
0xFE,0x08,0x08,0x14,0x22,/*k*/
0x00,0x82,0xFE,0x02,0x00,/*l*/
0x3E,0x20,0x1C,0x20,0x1E,/*m*/
0x3E,0x20,0x20,0x20,0x1E,/*n*/
0x1C,0x22,0x22,0x22,0x1C,/*o*/
0x3F,0x24,0x24,0x24,0x18,/*p*/
0x18,0x24,0x24,0x3F,0x01,/*q*/
0x3E,0x10,0x20,0x20,0x10,/*r*/
0x12,0x2A,0x2A,0x2A,0x04,/*s*/
0x00,0x10,0x3C,0x12,0x04,/*t*/
0x3C,0x02,0x02,0x02,0x3E,/*u*/
0x30,0x0C,0x02,0x0C,0x30,/*v*/
0x38,0x06,0x18,0x06,0x38,/*w*/
0x22,0x14,0x08,0x14,0x22,/*x*/
0x38,0x05,0x05,0x05,0x3E,/*y*/
0x22,0x26,0x2A,0x32,0x22,/*z*/
0x00,0x10,0x6C,0x82,0x82,/*{*/
0x00,0x00,0xFF,0x00,0x00,/*|*/
0x04,0x02,0xFF,0x02,0x04,/*|, arrow*/
0x82,0x82,0x6C,0x10,0x00,/*}*/
0x08,0x10,0x18,0x08,0x10/*~*/
};
void setup() {
//модули матрицы инициализируются
for(int adresse=0;adresse<MatrixNumber;adresse++) {
/*The MAX72XX is in power-saving mode on startup*/
lc.shutdown(adresse,false);
/* Set the brightness to a medium values */
lc.setIntensity(adresse,4);
/* and clear the display */
lc.clearDisplay(adresse);
}
// BufferBuilding("Привет! Отправил мне сообщение...", 25); //первое сообщение на светодиодном экране
BufferBuilding("text", 4); //первое сообщение на светодиодном экране
Serial.begin(9600); //также устанавливаем обычный последовательный канал для отладки
BT.begin(9600); // инициализация Bluetooth
//мы отправили сообщение на телефон, чтобы сообщить пользователю, что он может что-то сделать...
BT.println("Hi ! I'm waiting for a message. Type it and press SEND.");
}
void loop() {
DrawText( LongueurChaine); //рисуем сообщение в цикле
//или, если мы получим что-то на виртуальном порту Bluetooth...
if (BT.available() > 0) {
LongueurChaine = BT.available(); //длина входящей строки
for (int i = 0; i < LongueurChaine; i++) {
// читаем входящий байт:
incomingByte = BT.read();
Phrase[i] = incomingByte; ///сохраняем символ в массив строк
}
//отладка функций, чтобы проверить:
Serial.print("Display: ");
Serial.println(Phrase);
Serial.print("Length : ");
Serial.println(LongueurChaine);
//очистка буфера для сохранения нового сообщения
for(int k = 0; k < 200; k++) {
Buffer[k]=0;
Buffer_inverse[k]=0;
}
//мы создаем новые буферы, поэтому новое сообщение будет отображаться при выходе из подпрограммы
BufferBuilding(Phrase, LongueurChaine);
}
}
void BufferBuilding(char * stringToDisplay, byte stringLength)
{
int i =0;
//цикл по каждому символу (в строке)
for(int k = 0; k < stringLength; k++) {
//здесь мы вызываем библиотеку символов
int caract= k;
Buffer[i+0] = fontDefinitions[((stringToDisplay[caract] - 32) * 5) + 0];
Buffer[i+1] = fontDefinitions[((stringToDisplay[caract] - 32) * 5) + 1];
Buffer[i+2] = fontDefinitions[((stringToDisplay[caract] - 32) * 5) + 2];
Buffer[i+3] = fontDefinitions[((stringToDisplay[caract] - 32) * 5) + 3];
Buffer[i+4] = fontDefinitions[((stringToDisplay[caract] - 32) * 5) + 4];
Buffer[i+5] = B00000000; //один пустой столбец светодиодов между двумя символами
i=i+6;
}
// здесь мы создаем второй буфер для отображения сообщения на переключенных матрицах
for(int k = 0; k < stringLength*6; k++) {
for(int i = 0; i < 8; i++) {
bitWrite( Buffer_inverse[k] ,i, bitRead(Buffer[k] ,7-i) ) ;
}
}
}
void DrawText( byte stringLength) {
for(int k = 0; k < stringLength*6; k++) {
delay(SpeedDelay);
//задержка(10000);
//k — столбец
//буферное рисование
for (int m = 0; m < MatrixNumber; m++) { //цикл по матрице
if (m % 2 == 0) //проверяем, перевернут ли модуль или нет...
{
//здесь матрица перевернута вверх ногами
for (int i = 0; i < 8; i++) { //цикл по столбцам
lc.setRow(m,7-i,Buffer[i+k+8*m]);
}
}
else
{
//классический
for (int i = 0; i < 8; i++) { //цикл по столбцам
lc.setRow(m,i,Buffer_inverse[i+k+8*m]);
}
}
}
}
}
@Sam, 👍0
Обсуждение2 ответа
Вы можете освободить оперативную память, переместив большие массивы и строки во Flash. По умолчанию все строки и массивы помещаются в оперативную память. Недостаток помещения данных во Flash заключается в том, что вы не сможете изменять их во время выполнения.
Чтобы разместить массив во Flash, используйте директиву компилятора PROGMEM:
static const unsigned char PROGMEM my_array[] = { 0x00, 0x01, 0x02 ... };
При этом вы, скорее всего, заметите, что помимо большего количества доступной оперативной памяти многие библиотечные функции могут больше иметь доступ к массиву, который вы поместили во FLASH. Микроконтроллерам AVR приходится использовать специальные инструкции для чтения данных из флэш-памяти. Некоторые библиотечные функции обрабатывают это автоматически, но многие этого не делают. Чтобы получить доступ к данным, вам придется реализовать функцию, которая копирует данные из Flash в ОЗУ.
Вот пример функции для копирования данных Flash в ОЗУ:
char *Get_Flash_String(const char *FlashString)
{
static char buff[MAX_FLASH_STRING_LENGTH+1];
int i, len;
len = strlen_P(FlashString);
for (i = 0; i <= len; i++)
buff[i] = pgm_read_byte_near(FlashString + i);
return(buff);
}
Обратите внимание, что приведенная выше функция предполагает, что вы читаете из флэш-памяти строку, завершающуюся NULL. Если вы читаете массив, вам не нужно использовать strlen() для определения длины.
этот ответ слишком общий, но не общий. сбивает с толку. покажите ему, как использовать это в своем деле., @Juraj
Может быть, лучше научить голодного человека ловить рыбу, чем вручить ему рыбу?, @Jeff Wahaus
из этого ответа он ничего не узнает. ссылка в ответе Дж.Роберта полезна. сначала добавил как комментарий, но потом удалил, чтобы не путать ОП. изменение типа элемента массива на данный момент дает ему память, @Juraj
И вам разрешили говорить от имени другого человека?, @Jeff Wahaus
нет. Я всегда комментирую, почему я голосую против, @Juraj
Таблица определения шрифтов занимает 960 байт ОЗУ — почти 1/2 от общего объема использования. Вы можете восстановить 480 байт, просто объявив этот массив как uint8_t
; 1 байт на каждую запись вместо 2 байтов для int
. Если вам все еще нужно, вы можете восстановить оставшиеся 480, переместив эту таблицу в память программы. На сайте Arduino.cc есть хорошее обсуждение с примерами. Если вы это делаете, просто обратите внимание на типы данных, которые вы используете; каждая функция чтения данных из программной памяти возвращает один конкретный тип.
- Пространство, занимаемое глобальными переменными
- Проблема с памятью Arduino со старыми чипами дисплея HP HDSP-2000
- Как функция/метод может определить, является ли передаваемый массив const PROGMEM (flash) или нет (RAM)?
- Считывание байтов из массива PROGMEM
- Помогите уменьшить размер скетча!
- Чтение элемента вложенного массива из PROGMEM.
- Как долго программа будет оставаться в памяти без питания?
- Можно ли во время выполнения определить, объявлен ли указатель PROGMEM?
Это означает, что вы используете слишком много оперативной памяти микроконтроллера. Следуйте предложению Юрая., @MichaelT
«я не уверен, что делать»: вам необходимо уменьшить объем оперативной памяти (переменные, строки, константы, большие или многочисленные массивы), переместив константы, особенно большие, такие как строки, в программную память. Но не видя вашего кода, мы можем только догадываться. Имея всего 5 КБ кода и почти 2 КБ глобальных переменных, вполне вероятно, что вы использовали много места для строк, и их часто легко переместить в память программы. Покажите нам код, если он не слишком велик, или, по крайней мере, дайте нам некоторые подсказки, которые помогут вам лучше., @JRobert
Если вам нужна помощь, предоставьте исходный код., @Andre Courchesne
как разместить здесь код? это слишком долго, чтобы писать в комментариях, @Sam
Отредактируйте свой вопрос и отформатируйте его правильно, выделив часть кода и нажав кнопку
{}
или нажав Ctrl+k., @chrislспасибо, и я отредактировал код в вопросе, @Sam
сначала попробуйте изменить
int fontDefinitions[480]
наconst byte fontDefinitions[480]
, @Juraj