ATmega328, ошибка кода arduino nano v3, говорящая о недостаточной оперативной памяти

об этом говорится в ошибке кода, и я не уверен, что делать, пожалуйста, мне нужна срочная помощь :(сообщение об ошибке кода Arduino `

// Простая прокрутка текста, управляемая через 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]);
                }
            }
        }
    }

}

, 👍0

Обсуждение

Это означает, что вы используете слишком много оперативной памяти микроконтроллера. Следуйте предложению Юрая., @MichaelT

«я не уверен, что делать»: вам необходимо уменьшить объем оперативной памяти (переменные, строки, константы, большие или многочисленные массивы), переместив константы, особенно большие, такие как строки, в программную память. Но не видя вашего кода, мы можем только догадываться. Имея всего 5 КБ кода и почти 2 КБ глобальных переменных, вполне вероятно, что вы использовали много места для строк, и их часто легко переместить в память программы. Покажите нам код, если он не слишком велик, или, по крайней мере, дайте нам некоторые подсказки, которые помогут вам лучше., @JRobert

Если вам нужна помощь, предоставьте исходный код., @Andre Courchesne

как разместить здесь код? это слишком долго, чтобы писать в комментариях, @Sam

Отредактируйте свой вопрос и отформатируйте его правильно, выделив часть кода и нажав кнопку {} или нажав Ctrl+k., @chrisl

спасибо, и я отредактировал код в вопросе, @Sam

сначала попробуйте изменить int fontDefinitions[480] на const byte fontDefinitions[480], @Juraj


2 ответа


-1

Вы можете освободить оперативную память, переместив большие массивы и строки во 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


3

Таблица определения шрифтов занимает 960 байт ОЗУ — почти 1/2 от общего объема использования. Вы можете восстановить 480 байт, просто объявив этот массив как uint8_t; 1 байт на каждую запись вместо 2 байтов для int. Если вам все еще нужно, вы можете восстановить оставшиеся 480, переместив эту таблицу в память программы. На сайте Arduino.cc есть хорошее обсуждение с примерами. Если вы это делаете, просто обратите внимание на типы данных, которые вы используете; каждая функция чтения данных из программной памяти возвращает один конкретный тип.

,