Как лучше оптимизировать скетч для работы с majordomo по MQTT?

zztop1967
Offline
Зарегистрирован: 02.01.2017

Уважаемые форумчане, конечно тема оптимизации кода всплывает на поверхность с завидным постоянством, написано множество статей, переломано куча копий, сломано масса судЕп... и все же, не пинайте сильно ногами :)

На этом форуме в трех ветках "Этюды для начинающих: Память" очень подробно разобраны методы программирования. Разумеется их читал, но, пока что в голове не все устаканилось. Но я работаю над собой!

Суть в следующем:

Arduino Uno.

За основу был взят пример из библиотеки "Adafruit MQTT Library Ethernet Example", в который добавлялись, так же из примеров по работе с датчиками участки кода. Все было прекрасно и безоблачно, пока память под переменные не закончилась :(

Разумеется код не оптимален. От слова "абсолютно". Возможно нужно подобрать менее прожорливую библиотеку MQTT. Возможно опрос однотипных датчиков засунуть в цикл, сократив таким образом число переменных. Возможно лучше будет если в некоторых местах работать напрямую а не через переменные. Само собой нужно выкинуть апендикс оставшийся от "Adafruit MQTT Library Ethernet Example" с выводом счетчика циклов, но я намеренно его пока держу. Суть то не в нем, а в принципе.

В общем, посмотрите пожалуста код и просто посоветуйте в каком направлении лучше копать и насколько реально можно оптимизировать код? А то ног у Ардуинки задействовано мало, еще куча свободных а вся память кончилась :(

Понятное дело, что на голом С++ все получится в разы компактней, но я еще к сему подвигу не готов. Не все сразу...

Кхм... Не нашел как код засунуть под спойлер... :( Извините...

/***************************************************
  Adafruit MQTT Library Ethernet Example

  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Alec Moore
  Derived from the code written by Limor Fried/Ladyada for Adafruit Industries.
  MIT license, all text above must be included in any redistribution
 ****************************************************/
#include <SPI.h>
#include <Wire.h>
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"

#include <Ethernet.h>
#include <EthernetClient.h>
#include <Dns.h>
#include <Dhcp.h>
#include "DHT.h" //Датчик температуры и влажности
//#include <BMP085.h> // Датчик давления и температуры
#include <Adafruit_BMP085.h> // Датчик давления и температуры
#include <BH1750-HD.h> // Датчик освещённости в Люксах
/************************* Ethernet Client Setup *****************************/
// Мажардомо Контроллер №1 установлен в комнате
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};

//Uncomment the following, and set to a valid ip if you don't have dhcp available.
//IPAddress iotIP (192, 168, 0, 42);
//Uncomment the following, and set to your preference if you don't have automatic dns.
//IPAddress dnsIP (8, 8, 8, 8);
//If you uncommented either of the above lines, make sure to change "Ethernet.begin(mac)" to "Ethernet.begin(mac, iotIP)" or "Ethernet.begin(mac, iotIP, dnsIP)"


/************************* Описание параметров брокера *********************************/
#define AIO_SERVER      "192.168.1.15" //Адресс брокера
#define AIO_SERVERPORT  1883              //Порт брокера
#define AIO_USERNAME    "user"            //Пользователь брокера
#define AIO_KEY         "12345"      //Пароль пользователя брокера
/************ Global State (you don't need to change this!) ******************/
// Датчики температуры и влажности начало
//#define DHTTYPE DHT11   // DHT 11 
#define DHTTYPE DHT22   // DHT 22  (AM2302)
//#define DHTTYPE DHT21   // DHT 21 (AM2301)
#define DHTPIN1 6        // Пин подключения датчика температуры и влажности 1
#define DHTPIN2 7        // Пин подключения датчика температуры и влажности 2
#define DHTPIN3 8        // Пин подключения датчика температуры и влажности 3

// Датчики температуры и влажности конец
// Датчики газа и дыма начало
int GazPin1 = A0;         //Добавим MQ-2 к аналоговому пину A0
// Датчики газа и дыма конец

// Датчики напряжения начало
int VoltPin1 = A1;         //Добавим датчик напряжения к аналоговому пину A1
// Датчики Напряжения конец
//Датчики Давления и температуры начало
//BMP085 dps = BMP085();
Adafruit_BMP085 dps = Adafruit_BMP085();
//Датчики Давления и температуры конец
//Датчики Освещённости Люкс начало
BH1750 lightMeter;
//Датчики Освещённости Люкс конец

//Set up the ethernet client
EthernetClient client;

Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY); //Соединение с брокером

// You don't need to change anything below this line!
#define halt(s) { Serial.println(F( s )); while(1);  }


/****************************** Feeds ***************************************/
//Создаем топики датчиков влажности и температуры
// Setup a feed called 'photocell' for publishing.
// Notice MQTT paths for AIO follow the form: <username>/feeds/<feedname>
Adafruit_MQTT_Publish photocell = Adafruit_MQTT_Publish(&mqtt,  AIO_USERNAME "/feeds/photocell");

// Setup a feed called 'onoff' for subscribing to changes.
Adafruit_MQTT_Subscribe onoffbutton = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/onoff");
/*
Adafruit_MQTT_Publish Toph1 = Adafruit_MQTT_Publish(&mqtt,  "/Sensor_humidity01/ "); // Создаем топик датчика влажности №1
Adafruit_MQTT_Publish Topt1 = Adafruit_MQTT_Publish(&mqtt,  "/Sensor_temp01/ ");     // Создаем топик датчика температуры №1

Adafruit_MQTT_Publish Toph2 = Adafruit_MQTT_Publish(&mqtt,  "/Sensor_humidity02/ "); // Создаем топик датчика влажности №2
Adafruit_MQTT_Publish Topt2 = Adafruit_MQTT_Publish(&mqtt,  "/Sensor_temp02/ ");     // Создаем топик датчика температуры №2

Adafruit_MQTT_Publish Toph3 = Adafruit_MQTT_Publish(&mqtt,  "/Sensor_humidity03/ "); // Создаем топик датчика влажности №3
Adafruit_MQTT_Publish Topt3 = Adafruit_MQTT_Publish(&mqtt,  "/Sensor_temp03/ ");     // Создаем топик датчика температуры №3

Adafruit_MQTT_Publish Topg1 = Adafruit_MQTT_Publish(&mqtt,  "/Sensor_Smoke01/ ");    // Создаем топик датчика газа/дыма №1

Adafruit_MQTT_Publish Topdps1 = Adafruit_MQTT_Publish(&mqtt,  "/Sensor_pressure01/ ");    // Создаем топик датчика давления и температуры №1
*/
Adafruit_MQTT_Publish Toph1 = Adafruit_MQTT_Publish(&mqtt,  "/SH01/"); // Создаем топик датчика влажности №1
Adafruit_MQTT_Publish Topt1 = Adafruit_MQTT_Publish(&mqtt,  "/ST01/");     // Создаем топик датчика температуры №1

Adafruit_MQTT_Publish Toph2 = Adafruit_MQTT_Publish(&mqtt,  "/SH02/"); // Создаем топик датчика влажности №2
Adafruit_MQTT_Publish Topt2 = Adafruit_MQTT_Publish(&mqtt,  "/ST02/");     // Создаем топик датчика температуры №2

Adafruit_MQTT_Publish Toph3 = Adafruit_MQTT_Publish(&mqtt,  "/SH03/"); // Создаем топик датчика влажности №3
Adafruit_MQTT_Publish Topt3 = Adafruit_MQTT_Publish(&mqtt,  "/ST03/");     // Создаем топик датчика температуры №3

Adafruit_MQTT_Publish Topg1 = Adafruit_MQTT_Publish(&mqtt,  "/SS01/");    // Создаем топик датчика газа/дыма №1

Adafruit_MQTT_Publish Topdps1 = Adafruit_MQTT_Publish(&mqtt,  "/SP01/");    // Создаем топик давления  датчика BMP085  №1

Adafruit_MQTT_Publish Topbmpt1 = Adafruit_MQTT_Publish(&mqtt,  "/STb01/");    // Создаем топик температуры датчика BMP085 №1

Adafruit_MQTT_Publish Toplux1 = Adafruit_MQTT_Publish(&mqtt,  "/SL01/");    // Создаем топик освещённости датчика BH1750 №1

//Adafruit_MQTT_Publish TopVolt1 = Adafruit_MQTT_Publish(&mqtt,  "/SV01/");    // Создаем топик освещённости датчика BH1750 №1

/*************************** Sketch Code ************************************/
// Объявляем глобальные переменные
float dhtx ; //Для датчика темпервтуры и влажности DHT
//float t ; // Температура Для датчика темпервтуры и влажности DHT
char temp[8];
long p_100;
//int SignBit, Whole, Fract;
int  Whole, Fract;
int Pressure = 0;  
 
// 

void setup() {
  Serial.begin(115200);

  Serial.println(F("Adafruit MQTT demo"));

  // Initialise the Client
  Serial.print(F("\nInit the Client..."));
  Ethernet.begin(mac);
  delay(1000); //give the ethernet a second to initialize
  

  mqtt.subscribe(&onoffbutton); Подписываемся на топик

}

uint32_t x=0;

void loop() {     // Начало главного цикла программы
  // Ensure the connection to the MQTT server is alive (this will make the first
  // connection and automatically reconnect when disconnected).  See the MQTT_connect
  // function definition further below.
  delay(1000); // Пауза отправки данных в брокер
  MQTT_connect();

  // this is our 'wait for incoming subscription packets' busy subloop
  Adafruit_MQTT_Subscribe *subscription;
  while ((subscription = mqtt.readSubscription(1000))) {
    if (subscription == &onoffbutton) {
      Serial.print(F("Got: "));
      Serial.println((char *)onoffbutton.lastread);
    }
  }

  // Now we can publish stuff!
  Serial.print(F("\nSending photocell val "));
  Serial.print(x);
  Serial.print("...");
  if (! photocell.publish(x++)) {
    Serial.println(F("Failed"));
  } else {
    Serial.println(F("OK!"));
  }

  // ping the server to keep the mqtt connection alive
  if(! mqtt.ping()) {
    mqtt.disconnect();
  }
//------------- Датчик температуры и влажности 1 начало процедуры
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  // MQTT_connect();
  
DHT dht1(DHTPIN1, DHTTYPE);                        // Присваиваем датчику №1 пин и тип
  dht1.begin();                                    // Инициализируем

  // check if returns are valid, if they are NaN (not a number) then something went wrong!
//  if (isnan(t1) || isnan(h1)) {
//    Serial.println("Failed to read from DHT");
//  } else {
    {
    dhtx = dht1.readHumidity();                    // Счмтываем значения влаги с датчика в переменную
    Serial.print("Humidity №1: ");                // Печатаем надпись в порт
    Serial.print(dhtx);                            // Печатаем в порт значения с датчика влажности №1 
    Toph1.publish (dhtx);                          // Отправляем значения с датчика влажности №1  в брокер
    dhtx = dht1.readTemperature();                 // Счмтываем значения температуры с датчика в переменную 
    Serial.print("  Temperature №1: ");           // Печатаем надпись в порт
    Serial.print(dhtx);                            // Печатаем в порт значения с датчика температуры №1
    Serial.println(" *C");
    Topt1.publish(dhtx);                           // Отправляем значения с датчика температуры №1 в брокер
  }

//------------- Датчик температуры и влажности 1 конец процедуры
//------------- Датчик температуры и влажности 2 начало процедуры
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  // MQTT_connect();
  
DHT dht2(DHTPIN2, DHTTYPE);                        // Присваиваем датчику №1 пин и тип
  dht2.begin();                                    // Инициализируем

  // check if returns are valid, if they are NaN (not a number) then something went wrong!
//  if (isnan(t1) || isnan(h1)) {
//    Serial.println("Failed to read from DHT");
//  } else {
    {
    dhtx = dht2.readHumidity();                    // Счмтываем значения влаги с датчика в переменную
    Serial.print("Humidity №2: ");                // Печатаем надпись в порт
    Serial.print(dhtx);                            // Печатаем в порт значения с датчика влажности №2 
    Toph2.publish (dhtx);                          // Отправляем значения с датчика влажности №2  в брокер
    dhtx = dht2.readTemperature();                 // Счмтываем значения температуры с датчика в переменную 
    Serial.print("  Temperature №2: ");           // Печатаем надпись в порт
    Serial.print(dhtx);                            // Печатаем в порт значения с датчика температуры №2
    Serial.println(" *C");
    Topt2.publish(dhtx);                           // Отправляем значения с датчика температуры №2  в брокер
  }

//------------- Датчик температуры и влажности 2 конец процедуры
//------------- Датчик температуры и влажности 3 начало процедуры
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  // MQTT_connect();
  
DHT dht3(DHTPIN3, DHTTYPE);                        // Присваиваем датчику №1 пин и тип
  dht3.begin();                                    // Инициализируем

  // check if returns are valid, if they are NaN (not a number) then something went wrong!
//  if (isnan(t1) || isnan(h1)) {
//    Serial.println("Failed to read from DHT");
//  } else {
    {
    dhtx = dht3.readHumidity();                    // Счмтываем значения влаги с датчика в переменную
    Serial.print("Humidity №3: ");                // Печатаем надпись в порт
    Serial.print(dhtx);                            // Печатаем в порт значения с датчика влажности №3 
    Toph3.publish (dhtx);                          // Отправляем значения с датчика влажности №3  в брокер
    dhtx = dht3.readTemperature();                 // Счмтываем значения температуры с датчика в переменную 
    Serial.print("  Temperature №3: ");           // Печатаем надпись в порт
    Serial.print(dhtx);                            // Печатаем в порт значения с датчика температуры №3
    Serial.println(" *C");
    Topt3.publish(dhtx);                           // Отправляем значения с датчика температуры №3  в брокер
  }

//------------- Датчик температуры и влажности 3 конец процедуры

//------------- Датчик Газа и дыма 1 начало процедуры

  int GazLevel = analogRead(GazPin1);
      itoa(GazLevel, temp, 10);
      Serial.print("  Газ/Дым №1: ");
      Serial.println (temp);
      Topg1.publish(temp);                           // Отправляем значения с датчика Газ/Дым №1  в брокер
//      Adafruit_MQTT_Publish(&mqtt,  "/Sensor_Smoke01/ ").publish(temp); // Создаем топик датчика газа/дыма №1 и тправляем данные
//      Adafruit_MQTT_Publish(&mqtt,  "/Sensor_Smoke01/ ".publish(temp)); // Создаем топик датчика газа/дыма №1 и тправляем данные
  
//------------- Датчик Газа и дыма 1 конец процедуры

//------------- Датчик Давления и температуры BMP085 1 начало процедуры
    Wire.begin();
    dps.begin();
    dhtx = (dps.readTemperature()); // Получаем значение температуры с датчика давления и температуры bmp80
    Serial.print("Temperature = ");
    Serial.print(dhtx);    
    Serial.println(" *C");
    itoa(dhtx, temp, 10);
    Topbmpt1.publish(temp);                           // Отправляем значения температуры с датчика атмосферного давления bmp80  в брокер   

    Pressure = dps.readPressure()/133.1;     //получаем значение атмосферного давления в паскалях и переводим в мм ртутного столба    
    Serial.print(Pressure);
    Serial.println(" mm  "); 
    itoa(Pressure, temp, 10);
    Topdps1.publish(temp);                           // Отправляем значения с датчика атмосферного давления bmp80     в брокер

//------------- Датчик Давления и температуры BMP085 1 конец процедуры
//------------- Датчик Освещённости 1 начало процедуры
//Adafruit_MQTT_Publish Toplux1 = Adafruit_MQTT_Publish(&mqtt,  "/SL01/");    // Создаем топик освещённости датчика BH1750 №1

      lightMeter.begin(BH1750_CONTINUOUS_HIGH_RES_MODE);
      uint16_t lux = lightMeter.readLightLevel();
//      Serial.print("Light: ");
//      Serial.print(lux);
//      Serial.println(" lx");

      itoa(lux, temp, 10);
      Toplux1.publish(temp);                           // Отправляем значения с датчиа освещённости №1  в брокер

//------------- Датчик Освещённости 1 конец процедуры


} // Конец главного цикла программы

// Function to connect and reconnect as necessary to the MQTT server.
// Should be called in the loop function and it will take care if connecting.
void MQTT_connect() {
  int8_t ret;

  // Stop if already connected.
  if (mqtt.connected()) {
    return;
  }

  Serial.print("Connecting to MQTT... ");

  while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
       Serial.println(mqtt.connectErrorString(ret));
       Serial.println("Retrying MQTT connection in 5 seconds...");
       mqtt.disconnect();
       delay(5000);  // wait 5 seconds
  }
  Serial.println("MQTT Connected!");
}

 

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

1. Просто убило: " А то ног у Ардуинки задействовано мало, еще куча свободных а вся память кончилась". У Вас какая задача: сделать реальный проект или использовать все ноги ардуинки? Если послдеднее - пустите по ним бегущие огни и заканчивайте на этом проект.

2. Одиннадцать !!! подключаемых библиотек. Вы всерьез хотите использовать в таком проекте Уно?

3. Ну и конкретные советы, как исправить Вашу явно неоптимальную работу с памятью: все текстовые константы вынесите в PROGMEM. После этого сразу станет заметно легче. Но, в целом, следует соразмерять свои хотелки с возможностями конкретного контроллера. Т.е. сначла мы формулируем задачу и только протом подбираем для нее подходящий контроллер, а не наоборот, как это сделано у Вас.

 

zztop1967
Offline
Зарегистрирован: 02.01.2017

andriano пишет:

1. У Вас какая задача: сделать реальный проект или использовать все ноги ардуинки? 

Проект реален, просто он "вырос" и другого проекта. Сначала я реализовал погодную станцию описанную в статье 

http://out.arduino.ru/?redirect=http%3A%2F%2Fstudent-proger.ru%2F2014%2F...

Постепенно допиливал скетч, оброс датчиками, которые распихал по всему дому(живу в частном доме и хочется контролировать все и вся). Проект прекрасен своей относительной простотой, но это "вещь в себе", которая только отсылает данные на сайт "народный мониторинг" и только. А хочется не просто смотреть на циферки и строить графики, а еще на их основе и управлять различной автоматикой. А сие реализовывать привязываясь к "народному мониторингу" - не самая удачная, на мой взгляд идея. Поскольку дома есть сервачек на Linux Mint поставил туда Majordomo + Mosquitto. И начал осваивать связку этого хозяйства с тем колхозом, что уже построен. Тут то и выяснилось, что не хватает памяти для подключения всех тех датчиков, которые у меня уже прекрасно работают с другим скетчем.

andriano пишет:

2. Одиннадцать !!! подключаемых библиотек. Вы всерьез хотите использовать в таком проекте Уно?

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

Ну и прокачать свой скил, разумеется, научившись более рационально работать с имеющимися ресурсами.

andriano пишет:

3. Ну и конкретные советы, как исправить Вашу явно неоптимальную работу с памятью: все текстовые константы вынесите в PROGMEM. После этого сразу станет заметно легче. Но, в целом, следует соразмерять свои хотелки с возможностями конкретного контроллера. Т.е. сначла мы формулируем задачу и только протом подбираем для нее подходящий контроллер, а не наоборот, как это сделано у Вас.

Да, про PROGMEM я тоже думал, начал изучать. Спасибо что подтвердили мои мысли. А почему только текстовые? Из за их "объёма"? Числовые не имеет особого смысла, дабы не усложнять код?

А на счет выбора контроллера под задачу - Вы тут совершенно правы. Но откуда ноги растут я уже повествовал чуть выше.

Спасибо Вам большое!

sadman41
Offline
Зарегистрирован: 19.10.2016

Сначала бы вам нужно рассказать, что подразумевается под "закончилась память под переменные" - RAM, Progspace? 

zztop1967
Offline
Зарегистрирован: 02.01.2017

sadman41 пишет:

Сначала бы вам нужно рассказать, что подразумевается под "закончилась память под переменные" - RAM, Progspace? 

Наверное так будет наглядней?

Скетч использует 25362 байт (78%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 1585 байт (77%) динамической памяти, оставляя 463 байт для локальных переменных. Максимум: 2048 байт.
sadman41
Offline
Зарегистрирован: 19.10.2016

По мне так нормально, раз работает. 

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

zztop1967 пишет:

А дальше расширять функционал буду добавлением контроллеров для локальных задачь.

Для этого, минимум, надо, чтобы было куда расширять. А если по принципу: У меня есть готовый проект, и он помещается в Уно. У меня также есть другой проект, и он также помещается в Уно. Вот я и хочу объединить эти два проекта и добавить к ним следующий функционал... то какого-то из ресурсов (оперативной памяти, флэш-памяти, EEPROM, выводов, таймеров, прерываний...) может и не хватить.

Цитата:

А почему только текстовые? Из за их "объёма"? Числовые не имеет особого смысла, дабы не усложнять код?

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

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

zztop1967 пишет:

Скетч использует 25362 байт (78%) памяти устройства. Всего доступно 32256 байт.

Глобальные переменные используют 1585 байт (77%) динамической памяти, оставляя 463 байт для локальных переменных. Максимум: 2048 байт.

Ну и замечательно.

После того, как Вы уберете строки в PROGMEM, у Вас остантся примерно по 20% обоих видов памяти на дополнение функциональности.

zztop1967
Offline
Зарегистрирован: 02.01.2017

andriano]</p> <p>Для этого, минимум, надо, чтобы было куда расширять. А если по принципу: <em><strong>У меня есть готовый проект, и он помещается в Уно. У меня также есть другой проект, и он также помещается в Уно. Вот я и хочу объединить эти два проекта и добавить к ним следующий функционал...</strong></em> то какого-то из ресурсов (оперативной памяти, флэш-памяти, EEPROM, выводов, таймеров, прерываний...) может и не хватить.</p> <p>[quote пишет:

Не совсем так. Я хочу заменить скетч на свой и отправлять данные в majordomo и уже оттуда, те, что нужно, отсылать на народный мониторинг. Благо что в majordomo есть нужный функционал.

И из majordomo управлять другими контроллерами, которые будут рулить исполнительными устройствами.

Можно конечно перейти на мегу, но тогда придется переделывать то, что уже смонтировано в коробочку и подсоеденино с кучей датчиков. К тому же это лишь отсрочит проблему но не решит ее. На сегодняшний момент мой корявый скетч не позволяет использовать все датчики, которые уже смонтированы и прекрасно работают со старым скетчем.

andriano пишет:

А почему только текстовые? Из за их "объёма"? Числовые не имеет особого смысла, дабы не усложнять код?

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

Правильно ли я понимаю, что начать нужно с засовыванием вот этих переменных в массив строк?

Adafruit_MQTT_Publish Toph1 = Adafruit_MQTT_Publish(&mqtt,  "/SH01/"); // Создаем топик датчика влажности №1
Adafruit_MQTT_Publish Topt1 = Adafruit_MQTT_Publish(&mqtt,  "/ST01/");     // Создаем топик датчика температуры №1

Adafruit_MQTT_Publish Toph2 = Adafruit_MQTT_Publish(&mqtt,  "/SH02/"); // Создаем топик датчика влажности №2
Adafruit_MQTT_Publish Topt2 = Adafruit_MQTT_Publish(&mqtt,  "/ST02/");     // Создаем топик датчика температуры №2

Adafruit_MQTT_Publish Toph3 = Adafruit_MQTT_Publish(&mqtt,  "/SH03/"); // Создаем топик датчика влажности №3
Adafruit_MQTT_Publish Topt3 = Adafruit_MQTT_Publish(&mqtt,  "/ST03/");     // Создаем топик датчика температуры №3

Adafruit_MQTT_Publish Topg1 = Adafruit_MQTT_Publish(&mqtt,  "/SS01/");    // Создаем топик датчика газа/дыма №1

Adafruit_MQTT_Publish Topdps1 = Adafruit_MQTT_Publish(&mqtt,  "/SP01/");    // Создаем топик давления  датчика BMP085  №1

Adafruit_MQTT_Publish Topbmpt1 = Adafruit_MQTT_Publish(&mqtt,  "/STb01/");    // Создаем топик температуры датчика BMP085 №1

Adafruit_MQTT_Publish Toplux1 = Adafruit_MQTT_Publish(&mqtt,  "/SL01/");    // Создаем топик освещённости датчика BH1750 №1

Уж больно много каждая отжирает памяти отведённой для переменных :(

В описании PROGMEM это выглядит следующим образом:

/*
Демонстрация работы со строками при помощи PROGMEM
Как записывать таблицу строк в программную память (flash-память),  а затем доставать их оттуда.
 
Это выжимка отсюда:
http://www.nongnu.org/avr-libc/user-manual/pgmspace.html
 
Размещение таблицы (массива) строк в программную память — не самая простая задача,
но данный скетч, будем надеться, поможет разобраться, как это сделать.
 
Запись строк — это 2-этапный процесс. Для начала определяем строки.
*/
 
#include <avr/pgmspace.h>
const char string_0[] PROGMEM = "String 0";   // "String 0" и т.д. - это содержимое строк; если необходимо меняйте его
const char string_1[] PROGMEM = "String 1";
const char string_2[] PROGMEM = "String 2";
const char string_3[] PROGMEM = "String 3";
const char string_4[] PROGMEM = "String 4";
const char string_5[] PROGMEM = "String 5";
 
 
// Теперь создаем таблицу с отсылками к этим строкам:
const char* const string_table[] PROGMEM = {string_0, string_1, string_2, string_3, string_4, string_5};
 
char buffer[30];    // массив был достаточно велик, чтобы вместить даже самую большую строку
 
void setup()
{
  Serial.begin(9600);
  while(!Serial);
  Serial.println("OK");
}
 
 
void loop()
{
  /*
Теперь, если мы хотим достать данные их программной памяти, нам потребуется специальная функция.
Это strcpy_P — она копирует строку из программной памяти в строку, находящуюся в RAM («буфер»).
Убедитесь, что принимающая строка (т.е. находящаяся в RAM) достаточно велика для того,
чтобы вместить данные из программной памяти.
 */
 
 
  for (int i = 0; i < 6; i++)
  {
    strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); // необходимые функции и расшифровки, просто скопируйте
    Serial.println(buffer);
    delay( 500 );
  }
}

Но, если честно, я, пока что, не очень представляю как это сделать в моем случае... Я ведь только только хоть что то начал понимать что к чему...

sadman41
Offline
Зарегистрирован: 19.10.2016

Экземпляр класса в PROGMEM не засунуть.

Просто продолжите использовать макрос F() в Serial.println(). Или вообще не выводите ничего в Serial, отключив этот функционал.

Далее... когда решите перейти к радикальным мерам, можете начать избавляться от float-переменных, но тогда придется переписывать часть библиотек. Выкиньте DNS, он вам не нужен. DHCP так просто не отключить, необходимо править библиотеку Ethernet. Много оперативки жрет Wire. Переходом на альтернативную библиотечку поэкономите слегонца. Но адафрутовские рутины работают только со стандартным Wire. И вновь - все придется переписать.

 

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

Некоторые функции могут напрямую работать с PROGMEM, некоторые - нет.

Например, println/print - может.

Поэтому начните с того, что все строки вида 

 Serial.println("MQTT Connected!");

замените на 

 Serial.println(F("MQTT Connected!"));

этим Вы уже достигнете некоторого эффекта. А дальше можно попытаться проделать то же самое с другими функциями, принимающими строку - вдруг получится.

zztop1967
Offline
Зарегистрирован: 02.01.2017

sadman41 пишет:

Экземпляр класса в PROGMEM не засунуть.

Adafruit_MQTT_Publish Toph1 = Adafruit_MQTT_Publish(&mqtt,  "/SH01/"); // Создаем топик датчика влажности №1
Adafruit_MQTT_Publish Topt1 = Adafruit_MQTT_Publish(&mqtt,  "/ST01/");     // Создаем топик датчика температуры №1

Я думал засунуть "/SH01/"...  Тоже никак не получится?

sadman41 пишет:

Просто продолжите использовать макрос F() в Serial.println(). Или вообще не выводите ничего в Serial, отключив этот функционал.

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

sadman41 пишет:

Далее... когда решите перейти к радикальным мерам, можете начать избавляться от float-переменных, но тогда придется переписывать часть библиотек. Выкиньте DNS, он вам не нужен. DHCP так просто не отключить, необходимо править библиотеку Ethernet. Много оперативки жрет Wire. Переходом на альтернативную библиотечку поэкономите слегонца. Но адафрутовские рутины работают только со стандартным Wire. И вновь - все придется переписать.

Да, DNS мне тоже не нужен. Я работаю с локальной сеткой. DHCP можно и оставить. Остается найти менее прожорливую MQTT библиотеку.... Их я нашел вагон и маленькую тележку, но, для меня самым понятным оказалась именно адафрутовская. Отказаться от float - на сегодняшний момент непосильная для меня задача. недорос. Не подскажите менее прожорливые библиотеки?

p.s. Что то глюкнуло и предыдущий комментарий запостился невероятное количество раз. Как удалить лишнее - что то не обнаружил :( Не ругайте слишком сильно, сам не рад:(

sadman41
Offline
Зарегистрирован: 19.10.2016

zztop1967 пишет:

Я думал засунуть "/SH01/"...  Тоже никак не получится?

Попробуйте. Но я смысла не вижу, 60 байтов наэкономите может. Я с MQTT не сражался, не смогу посоветовать. Общие рекомендации написал выше.

knack
knack аватар
Offline
Зарегистрирован: 27.03.2012

zztop1967 пишет:

 найти менее прожорливую MQTT библиотеку.... Их я нашел вагон и маленькую тележку, но, для меня самым понятным оказалась именно адафрутовская. 

https://github.com/256dpi/arduino-mqtt лучше будет и попроще.

Пущай тут лежит )

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

интересно девки пляшут...esp8266 для mqtt видимо более правильный выбор