Как уменьшить объём занимаемой динамической памяти?

serega374
Offline
Зарегистрирован: 10.08.2015

Пишу скетч для оранжереи. Управление  светом, помпой. И индикация для начала. Пишу для UNO/NANO. 

В общем компилятор пишет 

Скетч использует 17298 байт (53%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 1638 байт (79%) динамической памяти, оставляя 410 байт для локальных переменных. Максимум: 2048 байт.
Недостаточно памяти, программа может работать нестабильно.
 
Скетч работает но зависает на второй третий цикл LOOP

Это после того как я добавил LCD OLED 128X64 I2C стало не хватать памяти. В начале использовал русифицированую библиотеку LCD вообще 99%. Перешол на #include <Adafruit_SSD1306.h> стало 79%.

Вот скетч туда ещё не вставил код для управления помпой и светом отдельно без LCD всё работает памяти хватает. 

#include <stdio.h>
#include <DS1302.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include "DHT.h" //DHT_sensor_library DHT_U
#define OLED_RESET 3
Adafruit_SSD1306 display(OLED_RESET);
#define DHTPIN 4
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
#if (SSD1306_LCDHEIGHT != 64)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif
namespace {
const int kCePin   = 2;  // Chip Enable
const int kIoPin   = 10;  // Input/Output
const int kSclkPin = 7;  // Serial Clock
// Create a DS1302 object.
DS1302 rtc(kCePin, kIoPin, kSclkPin);
String dayAsString(const Time::Day day) {
  switch (day) {
    case Time::kSunday: return "Sunday";
    case Time::kMonday: return "Monday";
    case Time::kTuesday: return "Tuesday";
    case Time::kWednesday: return "Wednesday";
    case Time::kThursday: return "Thursday";
    case Time::kFriday: return "Friday";
    case Time::kSaturday: return "Saturday";
  }
  return "(unknown day)";
}
void printTime() {
  // Get the current time and date from the chip.
  Time t = rtc.time();
  // Name the day of the week.
  const String day = dayAsString(t.day);

  // Format the time and date and insert into the temporary buffer.
  char buf[50];
  snprintf(buf, sizeof(buf), "%s %04d-%02d-%02d %02d:%02d:%02d",
           day.c_str(),
           t.yr, t.mon, t.date,
           t.hr, t.min, t.sec);
  // Print the formatted string to serial so we can see the time.
  Serial.println(buf);
  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.println(buf);
  display.display();
  delay(2000);
  display.clearDisplay();
}
}
void setup()
{
  Serial.begin(9600);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  dht.begin();
  display.clearDisplay();
}
void loop()
{
  indTempHum ();
  delay(300);
  printTime();
  delay(300);
  testdrawline();
  }

void indTempHum (void) { //функция индикации температуры и влажности
  float h = dht.readHumidity();
  float t = dht.readTemperature();

  if (isnan(h) || isnan(t)) {
    display.clearDisplay();
    display.setTextSize(3);
    display.setTextColor(WHITE);
    display.setCursor(0, 20);
    display.println("SENSOR ERROR!");
    display.display();
    display.clearDisplay();
    return;
  }
  else {
    display.setTextSize(3);
    display.setTextColor(WHITE);
    display.setCursor(0, 0);
    display.println("t");
    display.setCursor(30, 0);
    display.println(t);
    display.setCursor(0, 30);
    display.println("h");
    display.setCursor(30, 30);
    display.println(h);
    display.display();
    delay(300);
    display.clearDisplay();
    return;
  }
}
void testdrawline() {  //функция для украшательств не доработана
  display.drawLine(0, 0, 0, 64, WHITE);
  display.display();
  display.drawLine(0, 0, 128, 0, WHITE);
  display.display();
  display.drawLine(0, 0, 128, 1, WHITE);
  display.display();
  delay(1);
}
хватает. Вот библиотека для DHT, которую я использую, включает три датчика DHT11 DHT21 и DHT22. 

Нашёл библиотек только под DHT11, думаю с ней бужет меньше занимать дин памяти, но я не понимаю как по файлам *.cpp и *.h понять что писать в скетче. Сопостовлял пытался не понял. Подскажите.

Вот dht11.cpp

//
//    FILE: dht11.cpp
// VERSION: 0.4.1
// PURPOSE: DHT11 Temperature & Humidity Sensor library for Arduino
// LICENSE: GPL v3 (http://www.gnu.org/licenses/gpl.html)
//
// DATASHEET: http://www.micro4you.com/files/sensor/DHT11.pdf
//
// HISTORY:
// George Hadjikyriacou - Original version (??)
// Mod by SimKard - Version 0.2 (24/11/2010)
// Mod by Rob Tillaart - Version 0.3 (28/03/2011)
// + added comments
// + removed all non DHT11 specific code
// + added references
// Mod by Rob Tillaart - Version 0.4 (17/03/2012)
// + added 1.0 support
// Mod by Rob Tillaart - Version 0.4.1 (19/05/2012)
// + added error codes
//

#include "dht11.h"

// Return values:
// DHTLIB_OK
// DHTLIB_ERROR_CHECKSUM
// DHTLIB_ERROR_TIMEOUT
int dht11::read(int pin)
{
	// BUFFER TO RECEIVE
	uint8_t bits[5];
	uint8_t cnt = 7;
	uint8_t idx = 0;

	// EMPTY BUFFER
	for (int i=0; i< 5; i++) bits[i] = 0;

	// REQUEST SAMPLE
	pinMode(pin, OUTPUT);
	digitalWrite(pin, LOW);
	delay(18);
	digitalWrite(pin, HIGH);
	delayMicroseconds(40);
	pinMode(pin, INPUT);

	// ACKNOWLEDGE or TIMEOUT
	unsigned int loopCnt = 10000;
	while(digitalRead(pin) == LOW)
		if (loopCnt-- == 0) return DHTLIB_ERROR_TIMEOUT;

	loopCnt = 10000;
	while(digitalRead(pin) == HIGH)
		if (loopCnt-- == 0) return DHTLIB_ERROR_TIMEOUT;

	// READ OUTPUT - 40 BITS => 5 BYTES or TIMEOUT
	for (int i=0; i<40; i++)
	{
		loopCnt = 10000;
		while(digitalRead(pin) == LOW)
			if (loopCnt-- == 0) return DHTLIB_ERROR_TIMEOUT;

		unsigned long t = micros();

		loopCnt = 10000;
		while(digitalRead(pin) == HIGH)
			if (loopCnt-- == 0) return DHTLIB_ERROR_TIMEOUT;

		if ((micros() - t) > 40) bits[idx] |= (1 << cnt);
		if (cnt == 0)   // next byte?
		{
			cnt = 7;    // restart at MSB
			idx++;      // next byte!
		}
		else cnt--;
	}

	// WRITE TO RIGHT VARS
        // as bits[1] and bits[3] are allways zero they are omitted in formulas.
	humidity    = bits[0]; 
	temperature = bits[2]; 

	uint8_t sum = bits[0] + bits[2];  

	if (bits[4] != sum) return DHTLIB_ERROR_CHECKSUM;
	return DHTLIB_OK;
}
//
// END OF FILE
//

И вот dht11.h

// 
//    FILE: dht11.h
// VERSION: 0.4.1
// PURPOSE: DHT11 Temperature & Humidity Sensor library for Arduino
// LICENSE: GPL v3 (http://www.gnu.org/licenses/gpl.html)
//
// DATASHEET: http://www.micro4you.com/files/sensor/DHT11.pdf
//
//     URL: http://playground.arduino.cc/Main/DHT11Lib
//
// HISTORY:
// George Hadjikyriacou - Original version
// see dht.cpp file
// 

#ifndef dht11_h
#define dht11_h

#if defined(ARDUINO) && (ARDUINO >= 100)
#include <Arduino.h>
#else
#include <WProgram.h>
#endif

#define DHT11LIB_VERSION "0.4.1"

#define DHTLIB_OK				0
#define DHTLIB_ERROR_CHECKSUM	-1
#define DHTLIB_ERROR_TIMEOUT	-2

class dht11
{
public:
    int read(int pin);
	int humidity;
	int temperature;
};
#endif
//
// END OF FILE
//

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Первое, что бросается в глаза - обилие текстовых строк.  В том виде как Вы их используете - они жрут ОЗУ как маманегарюй.  Судя по тому, что выдал компилятор - место в памяти программ еще есть, и предостаточно.  Уберите в память программ все константные текстовые строки.  Это навскидку, подробнее не разбирался. 

Я имею в виду вот это и тому подобное

    case Time::kSunday: return "Sunday";
024     case Time::kMonday: return "Monday";
025     case Time::kTuesday: return "Tuesday";
026     case Time::kWednesday: return "Wednesday";
027     case Time::kThursday: return "Thursday";
028     case Time::kFriday: return "Friday";
029     case Time::kSaturday: return "Saturday";

030

 

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

serega374, дисплей 128х64 - коварная штука: для пиксельной адресации необходим экранный буфер, а для контроллеров на Атмере 328 этот буфер отжирает сразу половину всей доступной памяти.

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