Обновление экрана при использовании библиотеки u8glib

Здравствуйте! Для изучения программирования и arduino я пытаюсь сделать “устройство” которое бы совмещало data logger, экран с отображением информации о времени и температуре, а так же веб-сервер. На данный момент я смог собрать код, который выводит на экран информацию, а так же записывает данные на sd карту каждую минуту.
Читая различные инструкции и мнения на форуме я обнаружил, что скорее всего мой код слишком часто считывает показания датчиков ds18b20, а так же отрисовывает экран.
Эту “проблему” я попытался решить с помощью функции millis() и таймеров и это явно не лучшее решение, но таков путь познания. После имплементации заметил. что на экране секунды часов “замерают” каждый 500ms :буквально на момент :smile: Возможно еще есть какие то проблемы, которые я не вижу ввиду отсутствия опыта программирования .

На форуме нашел рекомендации, что необходимо отрисовывать только ту часть экарана, что изменилась, но комментатор не удосужился предоставить пример, либо ссылок на пример, поэтому решил задать вопрос сообществу arduino.ru:

Как правильно отрисовывать экран при использовании библиотеки u8glib, чтобы экономить ресурсы мк

Заодно прошу дать дельные замечания по моему “коду”.
Спасибо!

P.S. Может часты тоже не надо опрашивать со скоростью работы МК ? Если я правильно понял, то все, что в loop() и без таймеров либо условий, “опрашивается” так быстро на сколько это возможно.

#include <U8glib.h>
#include <Wire.h>
#include <TimeLib.h>
#include <DS1307RTC.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <SPI.h>
#include <SD.h>
#define PERIOD 500
#define PERIOD2 250
uint32_t timer = 0;

/*
* SD card attached to SPI bus as follows:
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 4
 */
const int chipSelect = 4;  //SD card pin. CS pin of your data logger shield

File LogFile;  //Name of the file


// Data wire is plugged into pin X on the Arduino
#define ONE_WIRE_BUS 3

// Setup a oneWire instance to communicate with any OneWire devices
// (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

//uint8_t sensor1[8] = { 0x28, 0xED, 0x2E, 0x3C, 0x05, 0x00, 0x00, 0x48 };
//uint8_t sensor2[8] = { 0x28, 0xB7, 0x1B, 0x3D, 0x05, 0x00, 0x00, 0x70 };


U8GLIB_ST7920_128X64 u8g(22, 23, 24, U8G_PIN_NONE);  // настройка пинов
tmElements_t tm;

const char *monthName[12] = {
  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};



void draw() {

  if (millis() - timer >= PERIOD2) {
    // ваше действие
    u8g.setRot180();
    u8g.setFont(u8g_font_unifont);
    // u8g.drawStr(15, 12, "SOMEtEXT");
    //u8g.setPrintPos( 10, 12);  u8g.print(tm.Hour);
    if (tm.Second / 10 == 1) {
      u8g.setPrintPos(10, 12);
      u8g.print(tm.Hour / 10);
    } else {
      u8g.setPrintPos(10, 12);
      u8g.print(tm.Hour / 10);
    }
    if (tm.Second % 10 == 1) {
      u8g.setPrintPos(19, 12);
      u8g.print(tm.Hour % 10);
    } else {
      u8g.setPrintPos(19, 12);
      u8g.print(tm.Hour % 10);
    }
    //u8g.setPrintPos( 30, 12);  u8g.print(tm.Minute);
    if (tm.Second / 10 == 1) {
      u8g.setPrintPos(30, 12);
      u8g.print(tm.Minute / 10);
    } else {
      u8g.setPrintPos(30, 12);
      u8g.print(tm.Minute / 10);
    }
    if (tm.Second % 10 == 1) {
      u8g.setPrintPos(39, 12);
      u8g.print(tm.Minute % 10);
    } else {
      u8g.setPrintPos(39, 12);
      u8g.print(tm.Minute % 10);
    }
    //u8g.setPrintPos( 50, 12);  u8g.print(tm.Second);
    if (tm.Second / 10 == 1) {
      u8g.setPrintPos(50, 12);
      u8g.print(tm.Second / 10);
    } else {
      u8g.setPrintPos(50, 12);
      u8g.print(tm.Second / 10);
    }
    if (tm.Second % 10 == 1) {
      u8g.setPrintPos(59, 12);
      u8g.print(tm.Second % 10);
    } else {
      u8g.setPrintPos(59, 12);
      u8g.print(tm.Second % 10);
    }
    u8g.drawLine(0, 15, 128, 15);
    u8g.setFont(u8g_font_6x12);
    u8g.setPrintPos(10, 25);
    u8g.print(sensors.getTempCByIndex(0));
    u8g.drawStr(1, 25, "C");
    u8g.setPrintPos(50, 25);
    u8g.print(sensors.getTempCByIndex(1));
    u8g.setColorIndex(1);
    u8g.drawBox(0, 35, 128, 20);
    u8g.setFont(u8g_font_unifont);
    u8g.setColorIndex(0);
    u8g.drawStr(35, 50, "ARDUINO");
    u8g.setColorIndex(1);
    u8g.setFont(u8g_font_unifont);
    u8g.drawStr(45, 64, "HELLO");
    do {
      timer += PERIOD;
      if (timer < PERIOD) break;          // переполнение uint32_t
    } while (timer < millis() - PERIOD);  // защита от пропуска шага
  }
}

void setup() {
  sensors.begin();
  sensors.setResolution(9);
  bool parse = false;
  bool config = false;

  // get the date and time the compiler was run
  /* if (getDate(__DATE__) && getTime(__TIME__)) {
    parse = true;
    // and configure the RTC with this info
    if (RTC.write(tm)) {
      config = true;
    }
  } */

  Serial.begin(9600);
  while (!Serial)
    ;  // wait for Arduino Serial Monitor
  delay(200);
  if (parse && config) {
    Serial.print("DS1307 configured Time=");
    Serial.print(__TIME__);
    Serial.print(", Date=");
    Serial.println(__DATE__);
  } else if (parse) {
    Serial.println("DS1307 Communication Error :-{");
    Serial.println("Please check your circuitry");
  } else {
    Serial.print("Could not parse info from the compiler, Time=\"");
    Serial.print(__TIME__);
    Serial.print("\", Date=\"");
    Serial.print(__DATE__);
    Serial.println("\"");
  }


  Serial.println("DS1307RTC Read Test");
  Serial.println("-------------------");

  Serial.print("Initializing SD card...");

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  Serial.println("card initialized.");
  LogFile = SD.open("LogFile.csv", FILE_WRITE);  //Open and write once, just for headers
  LogFile.println(" Date/Time;Temp1;Temp2");     //Print headers(not saved yet)
  LogFile.close();                               //Print saved
}


void loop() {
  if (millis() - timer >= PERIOD) {
    // ваше действие
    sensors.requestTemperatures();
    do {
      timer += PERIOD;
      if (timer < PERIOD) break;          // переполнение uint32_t
    } while (timer < millis() - PERIOD);  // защита от пропуска шага
  }

  //tmElements_t tm;
  u8g.firstPage();
  do {
    draw();
  } while (u8g.nextPage());
  // tmElements_t tm;
  // sensors.requestTemperatures();
  RTC.read(tm);
  if (tm.Second == 00) {
    LogFile = SD.open("LogFile.csv", FILE_WRITE);
    Serial.println("open file to write");
    LogFile.print(tmYearToCalendar(tm.Year));
    LogFile.print("/");
    LogFile.print(tm.Month);
    LogFile.print("/");
    LogFile.print(tm.Day);
    LogFile.print(" ");
    LogFile.print(tm.Hour);
    LogFile.print(":");
    LogFile.print(tm.Minute);
    LogFile.print(":");
    LogFile.print(tm.Second);
    LogFile.print(";");
    LogFile.print(sensors.getTempCByIndex(0));
    LogFile.print(";");
    LogFile.print(sensors.getTempCByIndex(1));
    LogFile.println();
    LogFile.close();
    Serial.println("close file to write");
    Serial.println();
  }

  // call sensors.requestTemperatures() to issue a global temperature
  // request to all devices on the bus
  // Serial.print(" Requesting temperatures...");
  // Send the command to get temperatures
  // Serial.println("DONE");

  // Serial.print("Temperature is: ");
  // Serial.print(sensors.getTempCByIndex(0)); // Why "byIndex"?
  // You can have more than one IC on the same bus.
  // 0 refers to the first IC on the wire
  //  Serial.print(" Requesting temperatures...");
  // Send the command to get temperatures
  // Serial.println("DONE");

  //  Serial.print("Temperature is: ");
  //  Serial.print(sensors.getTempCByIndex(1));
}

void print2digits(int number) {
  if (number >= 0 && number < 10) {
    Serial.write('0');
  }
  Serial.print(number);
}

bool getTime(const char *str) {
  int Hour, Min, Sec;

  if (sscanf(str, "%d:%d:%d", &Hour, &Min, &Sec) != 3) return false;
  tm.Hour = Hour;
  tm.Minute = Min;
  tm.Second = Sec;
  return true;
}

bool getDate(const char *str) {
  char Month[12];
  int Day, Year;
  uint8_t monthIndex;

  if (sscanf(str, "%s %d %d", Month, &Day, &Year) != 3) return false;
  for (monthIndex = 0; monthIndex < 12; monthIndex++) {
    if (strcmp(Month, monthName[monthIndex]) == 0) break;
  }
  if (monthIndex >= 12) return false;
  tm.Day = Day;
  tm.Month = monthIndex + 1;
  tm.Year = CalendarYrToTm(Year);
  return true;
}

Это чего за чупакабра?

do {
      timer += PERIOD;
      if (timer < PERIOD) break;          // переполнение uint32_t
    } while (timer < millis() - PERIOD);  // защита от пропуска шага

период опроса датчика температуры не менее 750мс и вообще отказаться от библиотеки и получать температуру напрямую, тема обсуждалась на старом форуме

Изучаю же программирование
взято вот от сюда → Многозадачность в Arduino
Я попробовал все варианты, если что.

Так для чего эта конструкция предназначена?

Я вас понял, чтобы тема была полезной, ее стоит обогатить информацией, может у вас найдется ссылка? Если найду я сам вставлю.
Касательно периода опроса , то я ориентировался вот на эту статью → Датчик температуры DS18B20. Влияние саморазогрева на точность измерений. — StopTest.ru

Так я пытался задать период опроса датчика, либо отрисовки экрана.

if (millis() - timer >= PERIOD) {
    timer = millis();
    // ваше действие
    sensors.requestTemperatures();
  }

Это уже период. Зачем ему эти do…while?..

1 лайк

А чё так мало фич? А корованы кто грабить будет?

1 лайк

так это только изучение…практика будет потом…

Чтобы не было “Великого переполнения millis()” используйте:
unsigned long Timer;
if(millis() - Timer =>)

Так если к секундам привязываться, то раз в секунду и обновлять. RTC какой?

Читая старый форум русскоязычное сообщество arduino поражает…вечно найдется быдло, которому в падлу ответить по делу, но пройти мимо оно не может, поэтому обязательной зайдет, насрет и будет таков. На старом форуме вас можно выделить как исключительно сказочного персонажа… реальной помощи вы никому не оказываете, но упрекнуть. унизить , либо постебаться это да…в этом вы мастак.

DS1307 . Уже знаю, что это не самые точные часы

Прям как меня описАл. :slight_smile:

1 лайк

Ну, вот такое я говно :frowning:

И, главное, ведь ничего с собой поделать не могу :frowning:

1 лайк

Ты чё ет на мою славу заришься?

1 лайк

Вот как ни новичок, так чудо, считающее себя пупом земли. Не, нуачо, он же тут супер-пупер штуку придумал, а ему никакого уважения. Да же ку не говорят :sweat_smile:

1 лайк

Прям как в кино.

Ну и все просто тогда:

time.gettime();   
cur_seconds = time.seconds;   // Не знаю как у вас в библиотеке это сделано....
if (last_seconds != cur_seconds) {
    draw();
    last_seconds = cur_seconds;
}
1 лайк