Можно ли оптимизировать скетч

Тема в разделе "Arduino & Shields", создана пользователем РоманИ, 23 фев 2016.

  1. РоманИ

    РоманИ Нерд

    Здравствуйте! подскажите пожалуйста возможно ли уменьшить объем памяти данного скетча? есть необходимость подсоединения SD карты, добавляю немного кода из примера SD read-write, а ИДЕ выдает, слишком мало памяти для работы с переменными программа может работать нестабильно. Сам скетч с блоком SD не совсем работает, и я не знаю, то ли от нехватки памяти, то ли по другой причине. В принципе скетч с пояснениями, а по сути идет считывание с пяти датчиковDS18b сравнение их температур и командованеие двумя сервомашинками. добавлены часы и индикация на лсд по I2C/
    Буду очень признателен за помощь. С уважением Роман.
    Код (C++):
    #include <OneWire.h>
    #include <DallasTemperature.h>
    #include <Wire.h>
    #include <LiquidCrystal_I2C.h>
    #include <Servo.h>
    #include <DS1302.h>
    #include <SPI.h>
    #include <SD.h>
    File myFile;
    // Init the DS1302
    DS1302 rtc(5, 6, 7);// подключение часов
    Servo myservo; //заборник комнаты
    Servo myservo2; //заборник веранды
    OneWire oneWire(10); // вход датчиков 18b20
    DallasTemperature ds(&oneWire); // активируем датчики
    // устанавливаем адрес  и параметры дисплея 0х27 , 16х2
    LiquidCrystal_I2C lcd(0x27, 16, 2);
    DeviceAddress sensor1 = {0x28, 0xFF, 0xC, 0xB, 0x93, 0x15, 0x1, 0x7C};// температура солнечного коллектора
    DeviceAddress sensor2 = {0x28, 0xFF, 0xE3, 0x1B, 0x93, 0x15, 0x1, 0xF1};// температура чердачного заборника
    DeviceAddress sensor3 = {0x28, 0xFF, 0xD8, 0x39, 0x93, 0x15, 0x1, 0x72};//температура веранды
    DeviceAddress sensor4 = {0x28, 0xFF, 0xEE, 0x41, 0x93, 0x15, 0x1, 0xDE};// температура воздуха на улице
    DeviceAddress sensor5 = {0x28, 0xFF, 0xB4, 0x1D, 0x93, 0x15, 0x3, 0x80}; //температура в комнате
    int motor = 3;
    int knopka = 2;
    boolean lastButton = LOW;
    boolean currentButton = LOW;
    boolean chasy = true;
    void setup() {
        // устанавлмваем часы в режим старта и отключаем защиту от записи
      rtc.halt(false);
      rtc.writeProtect(false);
      ds.begin(); //запускаем датчики
      lcd.begin();// запускаем монитор
        lcd.backlight();// включаем подсветку
    // далее устанавливаем время
      //rtc.setDOW(SUNDAY);        // Set Day-of-Week to FRIDAY
      //rtc.setTime(20, 25, 0);     // Set the time to 12:00:00 (24hr format)
      //rtc.setDate(21, 2, 2016);   // Set the date to Augu
      pinMode (motor,OUTPUT);// устанавливаем пин мотора вентилятора
      // временно отключаем pinMode (13,OUTPUT);
      // временно отключаем pinMode (12,OUTPUT);
      pinMode (1,OUTPUT);//выход светодиода
      pinMode (0,OUTPUT);// выход светодиода
      pinMode(knopka,INPUT);
    }
    boolean debounce(boolean last)
    {
    boolean current = digitalRead(knopka);
    if (last != current)
    {
      delay(5);
      current= digitalRead(knopka); delay(50);
    }
    return current;
    }
    void loop() {
      // устанавливаем время по центру дисплея
    //lcd.clear();
      ds.requestTemperatures(); // считываем температуру с датчиков
        /* далее идет блок сраввнения температур и установки положения клапанов
         *
         */

         //присваеваем переменным temps данные датчиков температуры
    float temps1 = ds.getTempC(sensor1);//коллектор
    float temps2 = ds.getTempC(sensor2);// веранда
    float temps3 = ds.getTempC(sensor3);// чердак
    float temps4 = ds.getTempC(sensor4);//улица
    float temps5 = ds.getTempC(sensor5);// помещение
    //далее сравниваем температуры и устанавливаем положение клапанов
    if ( temps1 >18)//если в коллекторе температура больше  18 градусов, тогда запускаем цикл сравнения температур
    {
    analogWrite(motor,254);
    if (temps2>temps3) // если на веранде больше чем под крышей, открываем заборник веранды
    {int MSV=myservo2.read();
    if (MSV!=80){
      myservo.attach(9);
      myservo2.attach(8);
      myservo.write(170);//закрыта заслонка на заборнике с комнаты
      myservo2.write(80);//открыта заслонка на заборнике с веранды
      //Serial.print("Street gate");// забор воздуха с веранды
      // временно отключаем digitalWrite (13,HIGH);// горит зеленый веранды
      // временно отключаем digitalWrite (12,LOW);
      digitalWrite (1,HIGH);// горит красный комнаты
      digitalWrite (0,LOW);
      delay (1000);
      myservo.detach();// отключаем серву
      myservo2.detach();// отключаем серву
      }
    }
    if (temps3>temps2)// если на чердаке больше чем на верандей, открываем заборник крыши
    {
      int MSH=myservo.read();
    if (MSH!=80)
    {
      myservo.attach(9);
      myservo2.attach(8);
      myservo.write(80);//открыта заслонка комнаты
      myservo2.write(180);//закрыта заслонка веранды
     
      //digitalWrite (13,LOW);
      //digitalWrite (12,HIGH);// горит красный веранды
      digitalWrite (0,HIGH);// горит зеленый комнаты
      digitalWrite (1,LOW);
      delay (1000);
      myservo.detach();
      myservo2.detach();
    }
    }
    }
    else // когда температура в коллекторе меньше 18 градусов Закрываем все клапаны и останавливаем вентилятор
    {
      analogWrite(motor,0);
      int MSV=myservo2.read();
      int MSH=myservo.read();

      if (MSV!=170)
      {
        myservo2.attach(8);
        myservo2.write(170);
      //Serial.print("the gate is close");
      digitalWrite (13,LOW);
      digitalWrite (12,HIGH);
      delay (1000);
      myservo2.detach();
    }
    if (MSH!=170) {myservo.attach(9); myservo.write(170); delay (1000); myservo.detach(); digitalWrite (0,LOW);
      digitalWrite (1,HIGH);}
    }
    // код влючения кнопки
      currentButton = debounce(lastButton);
      if (lastButton ==LOW&&currentButton==HIGH)
      {
        if(chasy) chasy=false;
        else (chasy)=true;
        lcd.clear();
        // печатать lcd.print(
        }
        lastButton = currentButton;
        lcd.setCursor(0,1);
        if (chasy)
        {
          lcd.setCursor(4, 0);
      lcd.print(rtc.getTimeStr());
     
      // устанавливаем день недели в нижнем ленвом углу
      lcd.setCursor(0, 1);
      lcd.print(rtc.getDOWStr(FORMAT_SHORT));
      lcd.setCursor(4, 1);
      lcd.print("   ");
     
      // Display date in the lower right corner
      lcd.setCursor(6, 1);
      lcd.print(rtc.getDateStr());

      // Wait one second before repeating :)
      delay (1000);
          }
          else
          {
            lcd.setCursor(0, 0);
        lcd.print("T sun kol:");
        lcd.print(ds.getTempC(sensor1)); // отправляем температуру
        lcd.print("C");      
    delay (2000);
    // далее печатаем на дисплее температуру заборников воздуха и 2,5 сек задержки
      lcd.setCursor(0, 0);
        lcd.print("T roof   :");
        lcd.print(ds.getTempC(sensor3));
        lcd.print("C");
        lcd.setCursor(0, 1);
        lcd.print("Tveranda :");
        lcd.print(ds.getTempC(sensor2));
        lcd.print("C");
      delay (2500);
      //далее печатаем температуру в кккомнате и на улице и 2,5 сек задержки
      lcd.setCursor(0, 0);
        lcd.print("T home   :");
        lcd.print(ds.getTempC(sensor5));
        lcd.print("C");
    lcd.setCursor(0, 1);
        lcd.print("T air    :");
        lcd.print(ds.getTempC(sensor4));
        lcd.print("C");
        delay (2500);
          }  
    }
     
     
  2. Onkel

    Onkel Гуру

    у вас проблема не в объеме памяти, а в объеме озу - маловато оперативной памяти. Рецепт тут прост и однозначен (кстати, пару дней назад аналогичный вопрос рассматривали, можете поискать и посмотреть)
    1 все переменные сделать минимально необходимыми - например, у вас вот
    int motor = 3;
    int knopka = 2;
    4 байта коту под хвост, замените на
    #define motor 3
    #define knopka 2
    ну и там где достаточно int - не нужно float и где достаточно char не нужно Int, особенно это важно если данные в массивах
    2 обратите внимание- не дублируются ли где массивы и особенно строки (это тоже массивы)
     
  3. noevile

    noevile Гик

    вот пример не использования библиотеки 1-wire http://sheepdogguides.com/arduino/ar3ne1tt2.htm
    помни что при использовании delay() твой контроллер просто стоит в стопе. в примере для температурных датчиков есть способ как не использовать delay()
     
  4. AlexU

    AlexU Гуру

    Строки, которые используются в 'lcd.print()' необходимо "отправить" во Flash (копайте тему использования функций из avr/pgmspace.h).
    То же самое необходимо сделать и с переменными типа 'DeviceAddress sensor*', но там немного посложней может оказаться. Наверно придётся залезть в код 'DeviceAddress'.
    Но это позволит сэкономить чуть больше 100 Байт.
    Библиотеки, которые используете, посмотрите повнимательней. Все константы массивы и строки нужно перенести во Flash, числа и символы объявить через define.
     
  5. Unixon

    Unixon Оракул Модератор

    lcd.print("...") => lcd.print(F("..."))
     
  6. Limoney

    Limoney Гик

    eeprom
     
  7. Unixon

    Unixon Оракул Модератор

    Зачем? Его тоже мало и он не для того.
     
  8. Limoney

    Limoney Гик

    маловато конечно, но сохранить можно, почему нет?
     
  9. Максимус-Бог

    Максимус-Бог Убийца матрёшек

    новые переменные, а у человека памяти не хватает.
     
  10. Onkel

    Onkel Гуру

    тут аккуратненько надо. Время записи в eeprom 10 мс. Чтение конечно быстро, но тем не менее запись медленная. И если каждый раз в loop записывать - eeprom кончится, там то ли десятки, то ли сотни тысяч циклов записи на ячейку (блок ячеек).
     
  11. Максимус-Бог

    Максимус-Бог Убийца матрёшек

    А чтение бесконечно раз?
     
  12. Onkel

    Onkel Гуру

    да вроде. но надо даташит смотреть, чтобы уточнить.
     
  13. Limoney

    Limoney Гик

    Не поняли друг друга

    Зачем записывать память eeprom в loop(), конечно такого делать нельзя.
    Раз записать номера датчиков и считывать когда нужно.
     
  14. Onkel

    Onkel Гуру

    Ну вот и я написал, что нельзя. Где ж тут не поняли?
     
  15. РоманИ

    РоманИ Нерд

    Хотел eprom оставить для кнопок переключения и настройки часов. а про Flash подробнее посмотреть где можно?