Компиляция прошивки

VladG_NN
Offline
Зарегистрирован: 28.03.2016

Добрый день!

Сразу скажу, что все работает - и железо и прошивка. Вопрос по компиляции, выдает сообщение:

Скетч использует 15 318 байт (49%) памяти устройства. Всего доступно 30 720 байт.

Глобальные переменные используют 1 663 байт (81%) динамической памяти, оставляя 385 байт для локальных переменных. Максимум: 2 048 байт.
Недостаточно памяти, программа может работать нестабильно.
 
Я в шоке, вот эта прошивка "жрет" почти 2 кб ОЗУ? Грузил прошивки из тырнета более ёмкие и с большим количеством библиотек - выдавало там 11%, 17%,  ну, 22% было. Но не 81 % же... Скажите, в чем я не прав? Переменных я вроде не наплодил и до трех десятков байт не дотянет, массивов нет. Библиотека OLED 128х64? Так у меня TFT дисплей 320х240 с тачём как раз и сожрал 22% ОЗУ.
Хотелось бы понять. Прошивка еще не закончена, кнопки прикрутить, график изменения давления сделать ... Получается, что кирдык далекой галактике, прощай график.
Версия IDE 1.6.7, Pro Mini + FTDI 232, OLED 12х64 0,96", DS1307 RTC и BMP-185. 
#include <Wire.h>
#include <OLED_I2C.h>
#include <BMP085.h>

OLED  myOLED(2, 3);               //SDA  - вывод 2, SCL - вывод 3
extern uint8_t SmallFont[];
extern uint8_t RusFont[];
extern uint8_t BigNumbers[];

BMP085 dps = BMP085();    
long Temperature = 0, Pressure = 0;


void setup()
{
  Wire.begin();
  myOLED.begin();
  delay(500);
  dps.init();
  
  byte s=ReadRTC(0x00);
  bitClear(s, 7);                 //установка бита разрешения счета времени
  WriteRTC(0x00, s);
   
  byte h=ReadRTC(0x02);
  bitClear(h, 6);                 //установили 24 часовой формат       
  WriteRTC(0x02, h);

  WriteRTC(0x07, 0);              //отключили выход генератора
  
}


void loop()
{
  for (int i=0; i<=5; i++)
  {
  byte s_dec=ReadRTC(0x00);
  byte m_dec=ReadRTC(0x01);
  byte h_dec=ReadRTC(0x02);
  byte d_dec=ReadRTC(0x03);
  byte dat_dec=ReadRTC(0x04);
  byte mon=ReadRTC(0x05);
  byte yer_dec=ReadRTC(0x06);

//**********Обрабатываем полученное время
//**********Секунды
  byte s_ed=s_dec;
  
  s_dec=s_dec >> 4;
  s_dec=s_dec & 0x07;
  
  s_ed=s_ed & 0x0f;             //выделяем младшие биты

//**********Минуты
  byte m_ed=m_dec;
  
  m_dec=m_dec >> 4;
  m_dec=m_dec & 0x07;
  
  m_ed=m_ed & 0x0f;

//**********Часы
  byte h_ed=h_dec;
  
  h_dec=h_dec >> 4;
  h_dec=h_dec & 0x03;
    
  h_ed=h_ed & 0x0f;

//**********Дата
  byte dat_ed=dat_dec;
  
  dat_dec=dat_dec >> 4;
  dat_dec=dat_dec & 0x03;
    
  dat_ed=dat_ed & 0x0f;

//**********Месяц
  byte mon_dec=0;
  byte mon_ed=mon;

  bitWrite(mon_dec, 0, bitRead(mon, 4));
        
  mon_ed=mon_ed & 0x0f;

  mon=(mon_dec*10)+mon_ed;          //оформляем месяц в виде единого числа


//**********Год
  byte yer_ed=yer_dec;
    
  yer_dec=yer_dec >> 4;
  yer_dec=yer_dec & 0x0f; 
    
  yer_ed=yer_ed & 0x0f;
  
  unsigned int yr=2000+(yer_dec*10)+yer_ed;  //оформляем год в виде единого числа
 
  
//**********Вывод данных на дисплей
//**********Выводим время на дисплей 
  myOLED.clrScr();
  
  myOLED.setFont(BigNumbers);

  myOLED.printNumF(h_dec, 0, 1, 39);
  myOLED.printNumF(h_ed, 0, 17, 39);
  myOLED.print("-", 33, 39);

  myOLED.printNumF(m_dec, 0, 49, 39);
  myOLED.printNumF(m_ed, 0, 65, 39);
  myOLED.print("-", 81, 39);

  myOLED.printNumF(s_dec, 0, 97, 39);
  myOLED.printNumF(s_ed, 0, 113, 39);

//**********Выводим день недели на дисплей 
  myOLED.setFont(RusFont);
  
  switch (d_dec)
  {
    case 1: myOLED.print("GJYTLTKMYBR", CENTER, 0);    break;
    case 2: myOLED.print("DNJHYBR", CENTER, 0);        break;
    case 3: myOLED.print("CHTLF", CENTER, 0);          break;
    case 4: myOLED.print("XTNDTHU", CENTER, 0);        break;
    case 5: myOLED.print("GZNYBWF", CENTER, 0);        break;
    case 6: myOLED.print("CE<<JNF", CENTER, 0);        break;
    case 7: myOLED.print("DJCRHTCTYBT", CENTER, 0);    break;
    case 0: myOLED.print("YJKM", CENTER, 0);           break;
  }

//**********Выводим дату на дисплей
  myOLED.printNumF(dat_dec, 0, 3, 20);
  myOLED.printNumF(dat_ed, 0, 11, 20);

//**********Выводим месяц на дисплей
  switch (mon)
  {
    case 1: myOLED.print("ZYDFHZ", CENTER, 20);    break;
    case 2: myOLED.print("ATDHFKZ", CENTER, 20);    break;
    case 3: myOLED.print("VFHNF", CENTER, 20);    break;
    case 4: myOLED.print("FGHTKZ", CENTER, 20);    break;
    case 5: myOLED.print("VFZ", CENTER, 20);    break;
    case 6: myOLED.print("B>YZ", CENTER, 20);    break;
    case 7: myOLED.print("B>KZ", CENTER, 20);    break;
    case 8: myOLED.print("FDUECNF", CENTER, 20);    break;
    case 9: myOLED.print("CTYNZ<HZ", CENTER, 20);    break;
    case 10: myOLED.print("JRNZ<HZ", CENTER, 20);   break;
    case 11: myOLED.print("YJZ<HZ", CENTER, 20);   break;
    case 12: myOLED.print("LTRF<HZ", CENTER, 20);   break;
  }

//**********Выводим год на дисплей
  myOLED.printNumF(yr, 0, RIGHT, 20);

  myOLED.update();
  delay(250); 
  }

// Модуль давления и температыры
  dps.getPressure(&Pressure); 
  dps.getTemperature(&Temperature);
  
  myOLED.clrScr();
  myOLED.setFont(BigNumbers);
  myOLED.printNumF((Pressure/133.3), 0, 20, 5);
  myOLED.setFont(RusFont);
  myOLED.print(" VV HN CN", 65, 16);
  myOLED.setFont(BigNumbers);
  myOLED.printNumF((Temperature*0.1), 0, 34, 34);
  myOLED.setFont(SmallFont);
  myOLED.print("~C", 70, 45);
  myOLED.update();
  
  delay(2000);


} //**********закрывающая скобка LOOP                         



//**********Подпрограммы

byte ReadRTC(byte adress)
{
  Wire.beginTransmission(0x68);  //работа с DS1307
  Wire.write(adress);            //адрес регистра часов
  Wire.endTransmission();        //
  Wire.requestFrom(0x68, 1);     //читаем один байт               
  return Wire.read();            //прочитали значение регистра
}

void WriteRTC(byte adress, byte data)
{
  Wire.beginTransmission(0x68);  //DS1307 запись регистра по адресу
  Wire.write(adress);            //адрес регистра 
  Wire.write(data);              //записываемые данные
  Wire.endTransmission();
}

 

 

 

VladG_NN
Offline
Зарегистрирован: 28.03.2016

Библиотека OLED или тынц На второй ссылке надо поменять расширение gif  на rar. С BMP-185 проблем, думаю, быть не должно.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

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

VladG_NN
Offline
Зарегистрирован: 28.03.2016

Тоже грешил на шрифты, но с другой стороны есть у меня стыренная прошивка с тем же функционалом, только там используется библиотека для работы с RTC - так там расход ОЗУ 59% (выложить смогу только вечером).

Мне казалось, что грузить шрифт в ОЗУ сильно не рационально, я таблицы всегда размещаю в памяти программ. Тогда вопрос - есть ли возможность прямо указать размещение шрифтов в памяти программ?

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

VladG_NN пишет:

Мне казалось, что грузить шрифт в ОЗУ сильно не рационально, я таблицы всегда размещаю в памяти программ. Тогда вопрос - есть ли возможность прямо указать размещение шрифтов в памяти программ?

Это зависит от библиотеки: скажем, в u8glib такая возможность есть. Как в вашей - не знаю, надо доку по ней читать ;)

 

VladG_NN
Offline
Зарегистрирован: 28.03.2016

DIYMan Спасибо!

Да, действительно, шрифты размещаются в памяти программ. А так, в библиотеке организован буфер на килобайт. Его несколько можно убавить без ущерба для данной программы, в случае необходимости. При использовании и графики и шрифтов, возможно, уже не убавить.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

VladG_NN пишет:

...Библиотека OLED 128х64? Так у меня TFT дисплей 320х240 с тачём как раз и сожрал 22% ОЗУ.

Хотелось бы понять...
Объясняю.
Изображение на дисплей можно записать только побайтно. Побитно его передавать на дисплей невозможно.
OLED 128х64 монохромный. У него 8 пикселов хранятся в одном байте. Следовательно, чтобы нарисовать пиксел, нужно взять байт изображения, установить в нем один бит и записать обратно. Для этого нужен экранный буфер (т.к. с самого дисплея прочитать нельзя). Именно он и занимает 1К памяти, т.е. 50% памяти 328. Если Вам не нужна попиксекльная графика, а достаточно только текста (с размером символа кратным 8 пикселям) можно обойтись и без буфера.
TFT 320x240 многоцветный. У него 1 пиксел занимает 2 байта. Поэтому пиксели можно рисовать независимо друг от друга, и пропадает необходимость в экранном буфере.