Оптимизация кода для уменьшения размера используемой ОЗУ

Mariev
Offline
Зарегистрирован: 17.08.2016

День добрый.

Взываю к помощи. В программировании на Си - новичок, поэтому выдержу любые кидания помидорами.

Столкнулся с нехваткой ОЗУ для выполнения необходимых функций на arduino UNO:

Глобальные переменные используют 1 902 байт (92%) динамической памяти, оставляя 146 байт для локальных переменных. Максимум: 2 048 байт.

// Датчик DHT11 подключен к цифровому пину номер 2
// Реле модуль подключен к цифровому выводу 4
// ИК диод подключается на 3 пин
//Часы подключены на 7,8,9 пины
// DS1302:  CE RST pin    -> Arduino Digital 7
//          I/O DATA pin   -> Arduino Digital 8
//          SCLK CLK pin  -> Arduino Digital 9


//Подключение Blynk
#define BLYNK_PRINT Serial
#include <SPI.h>
#include <Ethernet.h>
#include <BlynkSimpleEthernet.h>
#include <SimpleTimer.h>
char auth[] = "1c69d3a8cb2446229cc900e7a7df6fa8";
SimpleTimer timer;

//Подключение бибилиотеки DHT11
#include <dht11.h>      // Добавляем библиотеку DHT11
dht11 DHT;              // Объявление переменной класса dht11
#define DHT11_PIN 2     
// Подключение библиотеки для работы с IR-светодиодом
#include <IRremote.h> 
IRsend irsend;
//Модуль реального времени
#include <DS1302.h>
// Часы
DS1302 rtc(7, 8, 9);
//Контакт реле
int Relay = 4;
//Контакт диода
int LED_PIN = 6;

//Переменные для управления кондиционером
  byte ConditionerON[349] = {5,180,30,90,5,5,5,15,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,15,5,5,5,5,5,15,5,5,5,5,5,15,5,15,5,15,5,15,5,15,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,15,5,15,5,15,5,15,5,30,30,90,5,15,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,15,5,5,5,5,5,15,5,5,5,15,5,15,5,15,5,15,5,15,5,15,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,30,30,90,5,15,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,15,5,5,5,5,5,5,5,5,5,15,5,15,5,5,5,15,5,15,5,15,5,15,5,15,5,15,5,15,5,15,5,5,5,5,5,5,5,15,5,15,5,15,5,5,5,5,5,5,5,5,5,5,5,15,5,15,5,15,5,5,5,15,5,5,5,5,5,5,5,15,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,15,5,15,5,15,5,15,5
}; 
  byte ConditionerOff[349] = {5,180,30,90,5,5,5,15,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,15,5,5,5,5,5,15,5,15,5,5,5,15,5,15,5,15,5,15,5,15,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,15,5,15,5,30,30,90,5,15,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,15,5,5,5,5,5,15,5,5,5,15,5,15,5,15,5,15,5,15,5,15,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,30,30,90,5,15,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,15,5,5,5,5,5,5,5,15,5,15,5,15,5,5,5,15,5,15,5,15,5,15,5,15,5,15,5,15,5,15,5,5,5,5,5,5,5,15,5,15,5,15,5,5,5,5,5,5,5,5,5,5,5,15,5,15,5,15,5,5,5,15,5,5,5,5,5,5,5,15,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,15,5,15,5
}; 
boolean STATE_TEMP;

///////////////////////////////////////////////////////////
//Переменные задания температуры

unsigned int TEMP_MAX;
unsigned int TEMP_MIN;

BLYNK_WRITE(V3)  
{
int widgetValue_MIN = param.asInt(); // Here we create variable to store incoming values from V1.
  Serial.print("MIN TEMP ");
  Serial.println(widgetValue_MIN);
  TEMP_MIN = widgetValue_MIN;
}
BLYNK_WRITE(V4)  
{
int widgetValue_MAX = param.asInt(); // Here we create variable to store incoming values from V1.
  Serial.print("MAX TEMP ");
  Serial.println(widgetValue_MAX);
  TEMP_MAX = widgetValue_MAX;
}
///////////////////////////////////////////////////////////

//Установка интервала считывания данных
long previousMillis = 0;
long interval = 4000;

//Виртуальные переменные
void myTimerEvent(){
  Blynk.virtualWrite(V1, DHT.temperature);
  Blynk.virtualWrite(V2, DHT.humidity);
}

//Для кириллицы в мониторе порта
char* RUS(char* StrIn){char* StrOut=StrIn; uint8_t i[4]={0,0,StrIn[0],StrIn[1]}; while(i[2]>0&&i[0]<255){if(i[2]==0xd0&&i[3]>0x8F&&i[3]<0xC0){StrOut[i[1]]=i[3]+0x30;i[0]++;}else if(i[2]==0xd0&&i[3]==0x81){StrOut[i[1]]=0xA8;i[0]++;}else if(i[2]==0xd1&&i[3]>0x7F&&i[3]<0x90){StrOut[i[1]]=i[3]+0x70;i[0]++;}else if(i[2]==0xd1&&i[3]==0x91){StrOut[i[1]]=0xB8;i[0]++;}else{StrOut[i[1]]=i[2];} i[0]++; i[1]++; i[2]=StrIn[i[0]]; i[3]=StrIn[i[0]+1];} StrOut[i[1]]='\0'; return StrOut;}

////////////////////////////////////////////////////////////////////////////////////////////////////////
void setup(){

  // Set the clock to run-mode, and disable the write protection
  rtc.halt(false);
  rtc.writeProtect(false);
 
  
  //Вывод на монитор порта
  Serial.begin(9600);   // Скорость работы порта
  Blynk.begin(auth);    //Авторизация в Blynk
  
  // Setup a function to be called every second
  timer.setInterval(1000L, myTimerEvent);
  
  pinMode(Relay, OUTPUT); //назначение порта с Реле
  pinMode(LED_PIN, OUTPUT); // назначение порта с диодом
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////
void loop(){
  Blynk.run();  //Запуск Blynk в цикле
  timer.run(); // Initiates SimpleTimer
  
  


  // Выводим показания влажности и температуры датчика/////////////////////////////////
  unsigned long currentMillis = millis();
  if(currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;

    // Мониторинг ошибок датчика температуры
  int chk;
  chk = DHT.read(DHT11_PIN);    // Чтение данных
  switch (chk){
  case DHTLIB_OK:  
  break;
  }
  
  //Часы
  // Send date
  Serial.print(RUS("Дата "));
  Serial.print(rtc.getDateStr());
  // Send time
  Serial.print(RUS("  Время "));
  Serial.print(rtc.getTimeStr());

  //Датчики
  ////int TEMP_MAX = pinValue;
  Serial.print(RUS("  Влажность = "));
  Serial.print(DHT.humidity, 1);
  Serial.print(RUS(",  Температура = "));
  Serial.print(DHT.temperature,1);
  Serial.print(" (");
  Serial.print(TEMP_MIN,1);
  Serial.print(")");
  Serial.print(" - (");
  Serial.print(TEMP_MAX,1);
  Serial.println(")");
  Serial.print("Status ");
  Serial.println(STATE_TEMP,1);
  }
/////////////////////////////////////////////////////////////////////

//Работа диода
  if (DHT.temperature >= TEMP_MAX) digitalWrite(LED_PIN, HIGH);
  else if (DHT.temperature <= TEMP_MIN) digitalWrite(LED_PIN, HIGH);
  else digitalWrite(LED_PIN, LOW);

  
//Работа автоматики по температуре

if (DHT.temperature >= TEMP_MAX && STATE_TEMP == LOW)
{
  irsend.sendRaw(ConditionerON, 349, 38);
  STATE_TEMP = HIGH;
}

if (DHT.temperature <= TEMP_MIN && STATE_TEMP == HIGH)
{
  irsend.sendRaw(ConditionerOff, 349, 38);
  STATE_TEMP = LOW;
}

}

Кириллица занимает 51 байт. Часы реального времени - 47 байт. Это все от чего я могу отказаться, но лучше от этого не становится. Blynk много берет себе, но его функционал мне понравился и отказываться от него в пользу html не хочу.

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

Знаю, что надо еще что-то делать с массивами для передачи ИК-сигнала, но я сделал все что смог: поместил длительности интервалов из int в byte и в библиотеке подправил, чтобы умножалось значение на 100 и отправлялось на ИК передатчик. 

Почитал этюды для начинающих и прочие форумы, но ничего не понял...

Надеюсь на Ваши советы или хотя бы на ссылки на понятные источники. 

 

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

ConditionerOn & ConditionerOff разместить во флеше.

Эти же массивы "сжать". Самое тупое, хранить парами "значение, количество", даже это уже сократит массивы. Пятерок там море.

 

negavoid
Offline
Зарегистрирован: 09.07.2016

kisoft говорит дело :) Начните с разбора вот такого примера:

byte command[349];

#define RLE_LEN 16
byte RLEcmdOff[ RLE_LEN ] = {1, 5, 1, 180, 1, 30, 1, 90, 3, 5, 1, 15, 15, 5, 1, 15};
// original sequence: 5, 180, 30, 90, 5, 5, 5, 15, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 15
// таким вот образом 24 байта сжимаются до 16 байт

void setup()
{
  int ptr = 0;
  for ( int i = 0; i < RLE_LEN; i += 2 )
    for ( byte j = 0; j < RLEcmdOff[ i ]; j++ )
      command[ ptr++ ] = RLEcmdOff[ i + 1 ]; // achtung! possible overflow

  // irsend.sendRaw(command, 349, 38);
}

void loop() { }

 

Mariev
Offline
Зарегистрирован: 17.08.2016

Спасибо огромное за пример и советы!
Буду вечером пробовать!
Отпишусь по количеству увеличенной свободной памяти!

Mariev
Offline
Зарегистрирован: 17.08.2016

Прошу прощения, но я, видимо, где то накосячил.

сделал все так, как в примере, но ОЗУ теперь занимает на 500 байт больше.

В моем коде, видимо, память резервируется и для переменных и для развернутой переменной commandON/OFF. Может если способ очищать ОЗУ после каждого разворачивания переменной command?

// Датчик DHT11 подключен к цифровому пину номер 2
// Реле модуль подключен к цифровому выводу 4
// ИК диод подключается на 3 пин
//Часы подключены на 7,8,9 пины
// DS1302:  CE RST pin    -> Arduino Digital 7
//          I/O DATA pin   -> Arduino Digital 8
//          SCLK CLK pin  -> Arduino Digital 9


//Подключение Blynk
#define BLYNK_PRINT Serial
#include <SPI.h>
#include <Ethernet.h>
#include <BlynkSimpleEthernet.h>
#include <SimpleTimer.h>
char auth[] = "ХХХ";
SimpleTimer timer;

//Подключение бибилиотеки DHT11
#include <dht11.h>      // Добавляем библиотеку DHT11
dht11 DHT;              // Объявление переменной класса dht11
#define DHT11_PIN 2     
// Подключение библиотеки для работы с IR-светодиодом
#include <IRremote.h> 
IRsend irsend;
//Модуль реального времени
#include <DS1302.h>
// Часы
DS1302 rtc(7, 8, 9);
//Контакт реле
int Relay = 4;
//Контакт диода
int LED_PIN = 6;

//Переменные для управления кондиционером
// byte ConditionerON[349] = {5,180,30,90,5,5,5,15,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,15,5,5,5,5,5,15,5,5,5,5,5,15,5,15,5,15,5,15,5,15,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,15,5,15,5,15,5,15,5,30,30,90,5,15,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,15,5,5,5,5,5,15,5,5,5,15,5,15,5,15,5,15,5,15,5,15,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,30,30,90,5,15,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,15,5,5,5,5,5,5,5,5,5,15,5,15,5,5,5,15,5,15,5,15,5,15,5,15,5,15,5,15,5,15,5,5,5,5,5,5,5,15,5,15,5,15,5,5,5,5,5,5,5,5,5,5,5,15,5,15,5,15,5,5,5,15,5,5,5,5,5,5,5,15,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,15,5,15,5,15,5,15,5
//}; 
//  byte ConditionerOff[349] = {5,180,30,90,5,5,5,15,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,15,5,5,5,5,5,15,5,15,5,5,5,15,5,15,5,15,5,15,5,15,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,15,5,15,5,30,30,90,5,15,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,15,5,5,5,5,5,15,5,5,5,15,5,15,5,15,5,15,5,15,5,15,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,30,30,90,5,15,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,15,5,5,5,5,5,5,5,15,5,15,5,15,5,5,5,15,5,15,5,15,5,15,5,15,5,15,5,15,5,15,5,5,5,5,5,5,5,15,5,15,5,15,5,5,5,5,5,5,5,5,5,5,5,15,5,15,5,15,5,5,5,15,5,5,5,5,5,5,5,15,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,15,5,15,5
//}; 
boolean STATE_TEMP;



byte commandON[349];
byte commandOFF[349];
#define RLE_LEN 228
byte RLEcmdON[ RLE_LEN ] = {1,5,1,180,1,30,1,90,3,5,1,15,15,5,1,15,5,5,1,15,5,5,1,15,1,5,1,15,1,5,1,15,1,5,1,15,1,5,1,15,1,5,64,5,1,15,1,5,1,15,1,5,1,15,1,5,1,15,1,5,2,30,1,90,1,5,1,15,1,5,16,5,1,15,1,5,4,5,1,15,1,5,2,5,1,15,1,5,1,15,1,5,1,15,1,5,1,15,1,5,1,15,1,5,1,15,1,5,72,5,2,30,1,90,1,5,1,15,1,5,16,5,1,15,1,5,8,5,1,15,1,5,1,15,1,5,2,5,1,15,1,5,1,15,1,5,1,15,1,5,1,15,1,5,1,15,1,5,1,15,1,5,1,15,1,5,1,15,1,5,6,5,1,15,1,5,1,15,1,5,1,15,1,5,10,5,1,15,1,5,1,15,1,5,1,15,1,5,2,5,1,15,1,5,6,5,1,15,1,5,14,5,1,15,1,5,1,15,1,5,1,15,1,5,1,15,1,5
};
byte RLEcmdOFF[ RLE_LEN ] = {1,5,1,180,1,30,1,90,1,5,2,5,1,15,1,5,14,5,1,15,1,5,4,5,1,15,1,5,1,15,1,5,2,5,1,15,1,5,1,15,1,5,1,15,1,5,1,15,1,5,1,15,1,5,68,5,1,15,1,5,1,15,1,5,2,30,1,90,1,5,1,15,1,5,16,5,1,15,1,5,4,5,1,15,1,5,2,5,1,15,1,5,1,15,1,5,1,15,1,5,1,15,1,5,1,15,1,5,1,15,1,5,72,5,2,30,1,90,1,5,1,15,1,5,16,5,1,15,1,5,6,5,1,15,1,5,1,15,1,5,1,15,1,5,2,5,1,15,1,5,1,15,1,5,1,15,1,5,1,15,1,5,1,15,1,5,1,15,1,5,1,15,1,5,1,15,1,5,6,5,1,15,1,5,1,15,1,5,1,15,1,5,10,5,1,15,1,5,1,15,1,5,1,15,1,5,2,5,1,15,1,5,6,5,1,15,1,5,18,5,1,15,1,5,1,15,1,5
};

///////////////////////////////////////////////////////////
//Переменные задания температуры

unsigned int TEMP_MAX;
unsigned int TEMP_MIN;

BLYNK_WRITE(V3)  
{
int widgetValue_MIN = param.asInt(); // Here we create variable to store incoming values from V1.
  Serial.print("MIN TEMP ");
  Serial.println(widgetValue_MIN);
  TEMP_MIN = widgetValue_MIN;
}
BLYNK_WRITE(V4)  
{
int widgetValue_MAX = param.asInt(); // Here we create variable to store incoming values from V1.
  Serial.print("MAX TEMP ");
  Serial.println(widgetValue_MAX);
  TEMP_MAX = widgetValue_MAX;
}
///////////////////////////////////////////////////////////

//Установка интервала считывания данных
long previousMillis = 0;
long interval = 4000;

//Виртуальные переменные
void myTimerEvent(){
  Blynk.virtualWrite(V1, DHT.temperature);
  Blynk.virtualWrite(V2, DHT.humidity);
}

//Для кириллицы в мониторе порта
char* RUS(char* StrIn){char* StrOut=StrIn; uint8_t i[4]={0,0,StrIn[0],StrIn[1]}; while(i[2]>0&&i[0]<255){if(i[2]==0xd0&&i[3]>0x8F&&i[3]<0xC0){StrOut[i[1]]=i[3]+0x30;i[0]++;}else if(i[2]==0xd0&&i[3]==0x81){StrOut[i[1]]=0xA8;i[0]++;}else if(i[2]==0xd1&&i[3]>0x7F&&i[3]<0x90){StrOut[i[1]]=i[3]+0x70;i[0]++;}else if(i[2]==0xd1&&i[3]==0x91){StrOut[i[1]]=0xB8;i[0]++;}else{StrOut[i[1]]=i[2];} i[0]++; i[1]++; i[2]=StrIn[i[0]]; i[3]=StrIn[i[0]+1];} StrOut[i[1]]='\0'; return StrOut;}

////////////////////////////////////////////////////////////////////////////////////////////////////////
void setup(){

  // Set the clock to run-mode, and disable the write protection
  rtc.halt(false);
  rtc.writeProtect(false);
 
  
  //Вывод на монитор порта
  Serial.begin(9600);   // Скорость работы порта
  Blynk.begin(auth);    //Авторизация в Blynk
  
  // Setup a function to be called every second
  timer.setInterval(1000L, myTimerEvent);
  
  pinMode(Relay, OUTPUT); //назначение порта с Реле
  pinMode(LED_PIN, OUTPUT); // назначение порта с диодом
  
  int ptr1 = 0;
  for ( int i = 0; i < RLE_LEN; i += 2 )
    for ( byte j = 0; j < RLEcmdON[ i ]; j++ )
      commandON[ ptr1++ ] = RLEcmdON[ i + 1 ];

  int ptr2 = 0;
  for ( int i = 0; i < RLE_LEN; i += 2 )
    for ( byte j = 0; j < RLEcmdOFF[ i ]; j++ )
      commandOFF[ ptr2++ ] = RLEcmdOFF[ i + 1 ];
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////
void loop(){
  Blynk.run();  //Запуск Blynk в цикле
  timer.run(); // Initiates SimpleTimer
  
  


  // Выводим показания влажности и температуры датчика/////////////////////////////////
  unsigned long currentMillis = millis();
  if(currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;

    // Мониторинг ошибок датчика температуры
  int chk;
  chk = DHT.read(DHT11_PIN);    // Чтение данных
  switch (chk){
  case DHTLIB_OK:  
  break;
  }
  
  //Часы
  // Send date
  Serial.print(RUS("Дата "));
  Serial.print(rtc.getDateStr());
  // Send time
  Serial.print(RUS("  Время "));
  Serial.print(rtc.getTimeStr());

  //Датчики
  ////int TEMP_MAX = pinValue;
  Serial.print(RUS("  Влажность = "));
  Serial.print(DHT.humidity, 1);
  Serial.print(RUS(",  Температура = "));
  Serial.print(DHT.temperature,1);
  Serial.print(" (");
  Serial.print(TEMP_MIN,1);
  Serial.print(")");
  Serial.print(" - (");
  Serial.print(TEMP_MAX,1);
  Serial.println(")");
  Serial.print("Status ");
  Serial.println(STATE_TEMP,1);
  }
/////////////////////////////////////////////////////////////////////

//Работа диода
  if (DHT.temperature >= TEMP_MAX) digitalWrite(LED_PIN, HIGH);
  else if (DHT.temperature <= TEMP_MIN) digitalWrite(LED_PIN, HIGH);
  else digitalWrite(LED_PIN, LOW);

  
//Работа автоматики по температуре

if (DHT.temperature >= TEMP_MAX && STATE_TEMP == LOW)
{
  //irsend.sendRaw(ConditionerON, 349, 38);
  irsend.sendRaw(commandON, 349, 38);
  STATE_TEMP = HIGH;
}

if (DHT.temperature <= TEMP_MIN && STATE_TEMP == HIGH)
{
 // irsend.sendRaw(ConditionerOff, 349, 38);
  irsend.sendRaw(commandOFF, 349, 38);
  STATE_TEMP = LOW;
}

}

 

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Уже было и не один раз разжовано, например, здесь: http://arduino.ru/forum/programmirovanie/perepolnyaetsya-sram-komandami-dlya-pulta-pomogite-razobratsya

negavoid
Offline
Зарегистрирован: 09.07.2016

Mariev

немножечко накосячили ))

byte command[349]; // в оперативке должен остаться только он один

PROGMEM byte RLEcmdOff[ RLE_LEN ] = { .. } // эти два массива можно объявить так для перемещения их во флеш, см. ссылку kisoft

PROGMEM byte RLEcmdOn[ RLE_LEN2 ] = { .. } // и проверьте, на самом ли деле совпадает у вас размерность сжатых массивов, а то она скорее всего должна быть разной - RLE_LEN1 и RLE_LEN2

и перед отправкой irsend заполняйте буфер command[] уже из флеша как-то так (не проверял):

command[ ptr++ ] = pgm_read_byte_near(& RLEcmdOff[ i + 1 ] );

Mariev
Offline
Зарегистрирован: 17.08.2016

Спасибо.
Про занесение данных во флэш узнал из ссылки kisoft.
Уже сделал - теперь используется 75% памяти. 497 байт свободно. А главное можно внести еще несколько команд управления в память.
Архивирование массива в конечном итоге не делал, т.к. не вижу как это поможет в уменьшении используемой ОЗУ - все равно разворачивается переменная в 349 байт.
Если в чем то ошибаюсь - поправьте пожалуйста.

За советы всем спасибо

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Mariev пишет:
...
Архивирование массива в конечном итоге не делал, т.к. не вижу как это поможет в уменьшении используемой ОЗУ - все равно разворачивается переменная в 349 байт.
...

Это всего лишь твоя фантазия, не нужно ничего разворачивать в ОЗУ, коды из массива считываются в send побайтово и сразу отправляются.

1. Короче говоря, если нужно больше ОЗУ, переносить во флеш и оттуда считывать при отправке.

2. Если нужно больше флеша, то нужно делать "сжатие". При этом не нужно разворачивать сжатый массив в ОЗУ, а считывая по два байта из флеша формировать данные и сразу их отправлять.

3. Если нужно еще больше флеша, то нужно "закодировать" последовательность, хранить её во флеше в бинарном виде, а при отправке считывать из флеша в бинарном виде, после чего отправлять, например, как в sendNEC.

Возможно еще есть варианты, но третий, самый эффективный, в плане того, что можно море команд хранить во флеше. Именно третий я и буду использовать, когда буду свой DAIKIN окучивать :)

 

Logik
Offline
Зарегистрирован: 05.08.2014

Угу. Именно п.3 - единственно верный. Мало того, если на него перейдете то только тогда поймете что ж и как на самом деле передаете в ИК на кондиционер и как установить любую температуру, режим и т.д.  Читайте например http://radiokot.ru/articles/14/http://radiokot.ru/articles/14/ похоже первый описаный и ваш.

Еще для экономии ОЗУ строковые константы тоже в флеш засунуть.

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

Logik пишет:

Еще для экономии ОЗУ строковые константы тоже в флеш засунуть.

Вообще-то, с этого надо начинать.

Только, строго говоря, эти константы УЖЕ засунуты в флеш. А потом оттуда копируются в ОЗУ перед началом выполнения программы.

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

Есть у меня сомение, что такое количество (конкретных) библиотек можно запихнуть в Уно и все это будет стабильно работать.

Mariev
Offline
Зарегистрирован: 17.08.2016

Отбросьте сомнения. Запихнул переменные во флэш и убрал вывод информации в монитор порта. Теперь свободного ОЗУ 600 кб и все стабильно работает

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

Mariev пишет:
Отбросьте сомнения. Запихнул переменные во флэш и убрал вывод информации в монитор порта. Теперь свободного ОЗУ 600 кб и все стабильно работает

Вы хотите сказать, что статические переменные занимают ровно -598 кб?

Mariev
Offline
Зарегистрирован: 17.08.2016

Нет. Некоторый объем был свободен и ранее. Потом при переносе переменных передачи сигнала по ИК освободилось 349 байт. И немного увеличил свободной памяти за счет исключения вывода информации в монитор порта, т.к. теперь это не надо - все выводится в blynk