E-Ink дисплей 4.2" 3 цвета, проблемы с отображением при разном расположении объектов на экране

Hot Rod
Offline
Зарегистрирован: 27.06.2017

Приветствую всех!

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

Изучаю вот такой дисплей: https://ru.aliexpress.com/item/4-2inch-E-Ink-Display-Module-400x300-E-paper-Module-Red-Black-White-Three-color-SPI/32829541822.html

Есть проблемы при обображении объектов, в координатах которых x > 255. Если x <= 255, то все корректно. Прошу помочь, если не лень разбираться, так как сам не могу справиться. Есть мысль, что величина координаты x ограничена 1 байтом, но найти где это возможное ограничение я не смог. Да и не факт, что мое предположение верно.

На рисунках примеры корректного и некорректного отображения. Рис.1 - вывод символов и строк. Символы и строки не отображаются правильно, если координата x > 255. Черная единичка - координата x <= 255, все правильно. Чуть ниже - та же единичка, но x = 256. Красным сначала должна быть строка "3 -test" с x = 256, а за тем то же самое, но с x = 255

рис.2 - прямоугольники. Прямоугольники рисуются нормально с любыми координатами x, только если ширина рисунка (буфера рисунка) <= 8, как первые два незаполненных прямоугольника. Далее красные заполненные, здесь ширина рисунка (буфера рисунка) задана 16 и координаты у левого x < 255, а у правого x > 255. Прямоугольники изначально одинаковые, шириной 8 и высотой 26, но правый получился растянут через пиксель в вертикали. В самом низу два одинаковых заполненных прямоугольника шириной 16 и высотой 26. Левый при x < 255 - правильно, правый при x > 255 - растянут в вертикали и сужен в горизонтали. Координата "y" ни как не сказывается на корректности отображения, ни до 255, ни после.

Страничка дисплея на сайте производителя  https://www.waveshare.com/wiki/4.2inch_e-Paper_Module_(B)

Скачать библиотеку с сайта производителя https://www.waveshare.com/w/upload/a/af/4.2inch-e-paper-module-b-code.7z

Тут та же библиотека с добавленным мной большим шрифтом и рис.1 и 2 в более высоком качестве, чем позволяет форум  https://cloud.mail.ru/public/AzzQ/wTYustRCK

Скетч с примером и комментариями

#include <SPI.h>
#include <epd4in2b.h>
#include <epdpaint.h>

#define COLORED     0
#define UNCOLORED   1

Epd epd;          // e-paper дисплей. Подключение: RST 8, DC 9, CS 10, BUSY 7, DIN 11, CLK 13, gnd - gnd, 3.3 - 5v (на 3.3 не работает)


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

  Serial.begin(9600);

  // e-Paper
  if (epd.Init() != 0) {
    Serial.print("e-Paper init failed");
    return;
  }
  epd.ClearFrame();               // This clears the SRAM of the e-paper display
  Serial.println("Started");

  unsigned char image[512];

  // символы и строки не отображаются правильно, если координата x > 255
  // смотри рис. 1
  Paint paint(image, 64, 64);    //ширина должна быть кратна 8
  paint.Clear(COLORED);         // чистим
  paint.DrawCharAt(2, 3, 49, &Font64d, UNCOLORED);  // рисуем символ "1" белым на черном фоне и потом размещаем его в разных координатах
  epd.SetPartialWindowBlack(paint.GetImage(), 255, 0, paint.GetWidth(), paint.GetHeight()); // тут, где координата x <= 255, все правильно
  epd.SetPartialWindowBlack(paint.GetImage(), 256, 70, paint.GetWidth(), paint.GetHeight());   // тут, где координата x > 255, отрисовано не правильно

  Paint paint1(image, 128, 32);
  paint1.Clear(COLORED);
  paint1.DrawStringAt(2, 3, "3 -test", &Font24, UNCOLORED);  // пишем строку "3 -test" белым на красном фоне и потом размещаем ее в разных координатах
  epd.SetPartialWindowRed(paint1.GetImage(), 256, 200, paint1.GetWidth(), paint1.GetHeight());    // тут, где координата x > 255, отрисовано не правильно
  epd.SetPartialWindowRed(paint1.GetImage(), 255, 256, paint1.GetWidth(), paint1.GetHeight());    // тут, где x <= 255, все правильно, хотя y > 255



  // прямоугольники рисуются нормально с любыми координатами x, только если ширина рисунка <= 8,
  // смотри рис. 2
  Paint paint2(image, 8, 64); // здесь ширина рисунка <= 8, все в порядке не зависимо от координаты x
  paint2.Clear(UNCOLORED);
  paint2.DrawRectangle(0, 0, 7, 25, COLORED); // рисуем черный прямоугольник и потом размещаем его в разных координатах
  epd.SetPartialWindowBlack(paint2.GetImage(), 10, 0, paint2.GetWidth(), paint2.GetHeight());
  epd.SetPartialWindowBlack(paint2.GetImage(), 360, 0, paint2.GetWidth(), paint2.GetHeight()); // рисуется правильно, даже если координата x > 255

  Paint paint4(image, 16, 64); // здесь ширина рисунка > 8, и рисует не то, что нужно, если в координатах x > 255
  paint4.Clear(UNCOLORED);
  paint4.DrawFilledRectangle(0, 0, 7, 25, COLORED); // рисуем красный заполненный прямоугольник шириной 8 и потом размещаем его в разных координатах
  epd.SetPartialWindowRed(paint4.GetImage(), 10, 70, paint4.GetWidth(), paint4.GetHeight());  // здесь x <= 255, и все рисуется правильно
  epd.SetPartialWindowRed(paint4.GetImage(), 360, 70, paint4.GetWidth(), paint4.GetHeight()); // здесь x > 255, не корректно, через пиксель растянут по вертикали

  
  paint4.Clear(UNCOLORED);
  paint4.DrawFilledRectangle(0, 0, 15, 25, COLORED); // рисуем черный заполненный прямоугольник шириной 16  и потом размещаем его в разных координатах
  epd.SetPartialWindowBlack(paint4.GetImage(), 10, 130, paint4.GetWidth(), paint4.GetHeight());  // здесь x <= 255, и все рисуется правильно
  epd.SetPartialWindowBlack(paint4.GetImage(), 360, 130, paint4.GetWidth(), paint4.GetHeight()); // здесь x > 255, не корректно, сужен до 8 и вытянут по вертикали


  epd.DisplayFrame();       // This displays the data from the SRAM in e-Paper module
  epd.Sleep();      // Deep sleep
}



// =========================================
void loop() {

}

Заранее благодарю за помощь

Hot Rod
Offline
Зарегистрирован: 27.06.2017

Написал производителю, он исправил ошибку в своих библиотеках. Теперь все отображается верно.

Может кому пригодится информация

Skalolaz
Skalolaz аватар
Offline
Зарегистрирован: 01.05.2018

Hot Rod пишет:

Написал производителю, он исправил ошибку в своих библиотеках. Теперь все отображается верно.

Может кому пригодится информация

Спасибо! Более чем пригодилась!!!. С Вашим кодом заработала

А вы показания с датчиков не выводили E-ink?

Hot Rod
Offline
Зарегистрирован: 27.06.2017

Это не мой код, это производитель. ))

Показания выводил, конечно. 

Skalolaz
Skalolaz аватар
Offline
Зарегистрирован: 01.05.2018

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

Hot Rod
Offline
Зарегистрирован: 27.06.2017

Я могу только вывод на экран показать. Съем данных с датчиков - это от датчиков зависит.

Вывод в два этапа,

на первом при инициализации в setup рисуем один раз таблицы и надписи, которые не меняются

// ====================================== рисуем начальные линии и надписи
// =======================================================================
void  drawInit () {
  epd.ClearFrame();           // очищаем SRAM e-paper display
  unsigned char image[512];   // буфер рисунка

  Paint paint(image, 152, 16);    // рисунок, ширина должна быть кратна 8

  //------------------// заголовки каналов термометра
  paint.Clear(COLORED);                                                                     // очищаем цветом
  paint.DrawStringAt(2, 3, "ch-1 outdoor:", &Font16, UNCOLORED);                            // пишем строку
  epd.SetPartialWindowBlack(paint.GetImage(), 248, 0, paint.GetWidth(), paint.GetHeight()); // отправляем в SRAM e-paper
  paint.Clear(COLORED);
  paint.DrawStringAt(2, 3, "ch-2 indoor:", &Font16, UNCOLORED);
  epd.SetPartialWindowBlack(paint.GetImage(), 248, 75, paint.GetWidth(), paint.GetHeight());
  paint.Clear(COLORED);
  paint.DrawStringAt(2, 3, "ch-3 refrig:", &Font16, UNCOLORED);
  epd.SetPartialWindowBlack(paint.GetImage(), 248, 150, paint.GetWidth(), paint.GetHeight());
  paint.Clear(COLORED);
  paint.DrawStringAt(2, 3, "ch-4 pool:", &Font16, UNCOLORED);
  epd.SetPartialWindowBlack(paint.GetImage(), 248, 225, paint.GetWidth(), paint.GetHeight());

  //------------------// линии общие и термометра вертикальные
  Paint paint1(image, 8, 300);
  paint1.Clear(UNCOLORED);
  paint1.DrawFilledRectangle(0, 0, 2, 300, COLORED);
  paint1.DrawFilledRectangle(4, 0, 6, 300, COLORED);
  epd.SetPartialWindowBlack(paint1.GetImage(), 0, 0, paint1.GetWidth(), paint1.GetHeight());
  epd.SetPartialWindowBlack(paint1.GetImage(), 240, 0, paint1.GetWidth(), paint1.GetHeight());
  epd.SetPartialWindowBlack(paint1.GetImage(), 392, 0, paint1.GetWidth(), paint1.GetHeight());

  //------------------// линии термометра горизонтальные
  Paint paint2(image, 208, 3);
  paint2.Clear(UNCOLORED);
  paint2.DrawFilledRectangle(0, 0, 158, 2, COLORED);
  epd.SetPartialWindowBlack(paint2.GetImage(), 240, 0, paint2.GetWidth(), paint2.GetHeight());
  epd.SetPartialWindowBlack(paint2.GetImage(), 240, 71, paint2.GetWidth(), paint2.GetHeight());
  epd.SetPartialWindowBlack(paint2.GetImage(), 240, 146, paint2.GetWidth(), paint2.GetHeight());
  epd.SetPartialWindowBlack(paint2.GetImage(), 240, 221, paint2.GetWidth(), paint2.GetHeight());

  //------------------// линии общие внешние горизонтальные
  Paint paint3(image, 400, 3);
  paint3.Clear(UNCOLORED);
  paint3.DrawFilledRectangle(0, 0, 398, 2, COLORED);
  epd.SetPartialWindowBlack(paint3.GetImage(), 0, 0, paint3.GetWidth(), paint3.GetHeight());
  epd.SetPartialWindowBlack(paint3.GetImage(), 0, 297, paint3.GetWidth(), paint3.GetHeight());

  //    epd.DisplayFrame();  // отображаем данные из SRAM на дисплей
  //  epd.Sleep();        // засыпаем
}

На втором в loop - выводим данные из переменных на экран


void outputDisplay () {

//  epd.Init();                 // пробуждаем e-paper
  unsigned char image[512];   // буфер рисунка
  char strbuf[20];            // буфер строки

  //-----------------// вывод значений температуры и влажности
  Paint paint(image, 144, 24);    // рисунок, ширина должна быть кратна 8
  //  paint.SetRotate(1);             // поворот рисунка

  //  sprintf(strbuf, "%2d,%d %02d%%", temp1 / 10, abs(temp1 % 10), humm1);
  sprintf(strbuf, "%c%2d,%d %02d%%", temp1 < 0 ? '-' : ' ', abs(temp1 / 10), abs(temp1 % 10), humm1);   // формируем строку1 канала 1
  paint.Clear(UNCOLORED);                                                                       // очищаем
  paint.DrawStringAt(0, 3, (strbuf), &Font24ariald, COLORED);                                   // пишем строку
  epd.SetPartialWindowBlack(paint.GetImage(), 248, 21, paint.GetWidth(), paint.GetHeight());    // выводим строку1 в SRAM e-paper

  if (timeoutStDykie1 == 0) {                                                                       // если timeoutStDykie1 == 0
    paint.Clear(UNCOLORED);                                                                     // очищаем буфер Red
    epd.SetPartialWindowRed(paint.GetImage(), 248, 45, paint.GetWidth(), paint.GetHeight());    // выводим буфер Red в SRAM e-paper
    paint.Clear(UNCOLORED);
    paint.DrawStringAt(32, 6, "OK data", &Font16, COLORED);                                       // пишем 2 строку
    epd.SetPartialWindowBlack(paint.GetImage(), 248, 45, paint.GetWidth(), paint.GetHeight());    // выводим строку2 в SRAM e-paper
  }
  else if (timeoutStDykie1 == 1) {
    paint.Clear(UNCOLORED);
    epd.SetPartialWindowBlack(paint.GetImage(), 248, 45, paint.GetWidth(), paint.GetHeight());
    paint.Clear(UNCOLORED);
    paint.DrawStringAt(16, 6, "DELAY data", &Font16, COLORED);
    epd.SetPartialWindowRed(paint.GetImage(), 248, 45, paint.GetWidth(), paint.GetHeight());
  }
  else if (timeoutStDykie1 == 2) {
    paint.Clear(UNCOLORED);
    epd.SetPartialWindowBlack(paint.GetImage(), 248, 45, paint.GetWidth(), paint.GetHeight());
    paint.Clear(UNCOLORED);
    paint.DrawStringAt(24, 6, "LOST data", &Font16, COLORED);
    epd.SetPartialWindowRed(paint.GetImage(), 248, 45, paint.GetWidth(), paint.GetHeight());
  }

  sprintf(strbuf, "%c%2d,%d %02d%%", temp2 < 0 ? '-' : ' ', abs(temp2 / 10), abs(temp2 % 10), humm2);   // формируем строку1 канала 2
  paint.Clear(UNCOLORED);
  paint.DrawStringAt(0, 3, (strbuf), &Font24ariald, COLORED);
  epd.SetPartialWindowBlack(paint.GetImage(), 248, 96, paint.GetWidth(), paint.GetHeight());

  if (timeoutStDykie2 == 0) {
    paint.Clear(UNCOLORED);
    epd.SetPartialWindowRed(paint.GetImage(), 248, 120, paint.GetWidth(), paint.GetHeight());
    paint.Clear(UNCOLORED);
    paint.DrawStringAt(32, 6, "OK data", &Font16, COLORED);
    epd.SetPartialWindowBlack(paint.GetImage(), 248, 120, paint.GetWidth(), paint.GetHeight());
  }
  else if (timeoutStDykie2 == 1) {
    paint.Clear(UNCOLORED);
    epd.SetPartialWindowBlack(paint.GetImage(), 248, 120, paint.GetWidth(), paint.GetHeight());
    paint.Clear(UNCOLORED);
    paint.DrawStringAt(16, 6, "DELAY data", &Font16, COLORED);
    epd.SetPartialWindowRed(paint.GetImage(), 248, 120, paint.GetWidth(), paint.GetHeight());
  }
  else if (timeoutStDykie2 == 2) {
    paint.Clear(UNCOLORED);
    epd.SetPartialWindowBlack(paint.GetImage(), 248, 120, paint.GetWidth(), paint.GetHeight());
    paint.Clear(UNCOLORED);
    paint.DrawStringAt(24, 6, "LOST data", &Font16, COLORED);
    epd.SetPartialWindowRed(paint.GetImage(), 248, 120, paint.GetWidth(), paint.GetHeight());
  }

  sprintf(strbuf, "%c%2d,%d %02d%%", temp3 < 0 ? '-' : ' ', abs(temp3 / 10), abs(temp3 % 10), humm3);   // формируем строку канала 3
  paint.Clear(UNCOLORED);
  paint.DrawStringAt(0, 3, (strbuf), &Font24ariald, COLORED);
  epd.SetPartialWindowBlack(paint.GetImage(), 248, 171, paint.GetWidth(), paint.GetHeight());

  if (timeoutStDykie3 == 0) {
    paint.Clear(UNCOLORED);
    epd.SetPartialWindowRed(paint.GetImage(), 248, 195, paint.GetWidth(), paint.GetHeight());
    paint.Clear(UNCOLORED);
    paint.DrawStringAt(32, 6, "OK data", &Font16, COLORED);
    epd.SetPartialWindowBlack(paint.GetImage(), 248, 195, paint.GetWidth(), paint.GetHeight());
  }
  else if (timeoutStDykie3 == 1) {
    paint.Clear(UNCOLORED);
    epd.SetPartialWindowBlack(paint.GetImage(), 248, 195, paint.GetWidth(), paint.GetHeight());
    paint.Clear(UNCOLORED);
    paint.DrawStringAt(16, 6, "DELAY data", &Font16, COLORED);
    epd.SetPartialWindowRed(paint.GetImage(), 248, 195, paint.GetWidth(), paint.GetHeight());
  }
  else if (timeoutStDykie3 == 2) {
    paint.Clear(UNCOLORED);
    epd.SetPartialWindowBlack(paint.GetImage(), 248, 195, paint.GetWidth(), paint.GetHeight());
    paint.Clear(UNCOLORED);
    paint.DrawStringAt(24, 6, "LOST data", &Font16, COLORED);
    epd.SetPartialWindowRed(paint.GetImage(), 248, 195, paint.GetWidth(), paint.GetHeight());
  }

  //  sprintf(strbuf, "  %2d,%d ", temp4 / 10, abs(temp4 % 10));
  sprintf(strbuf, " %c%2d,%d ", temp4 < 0 ? '-' : ' ', abs(temp4 / 10), abs(temp4 % 10));          // формируем строку канала 4
  paint.Clear(UNCOLORED);
  paint.DrawStringAt(2, 3, (strbuf), &Font24ariald, COLORED);
  epd.SetPartialWindowBlack(paint.GetImage(), 248, 246, paint.GetWidth(), paint.GetHeight());

  if (timeoutStDykie4 == 0) {
    paint.Clear(UNCOLORED);
    epd.SetPartialWindowRed(paint.GetImage(), 248, 270, paint.GetWidth(), paint.GetHeight());
    paint.Clear(UNCOLORED);
    paint.DrawStringAt(32, 6, "OK data", &Font16, COLORED);
    epd.SetPartialWindowBlack(paint.GetImage(), 248, 270, paint.GetWidth(), paint.GetHeight());
  }
  else if (timeoutStDykie4 == 1) {
    paint.Clear(UNCOLORED);
    epd.SetPartialWindowBlack(paint.GetImage(), 248, 270, paint.GetWidth(), paint.GetHeight());
    paint.Clear(UNCOLORED);
    paint.DrawStringAt(16, 6, "DELAY data", &Font16, COLORED);
    epd.SetPartialWindowRed(paint.GetImage(), 248, 270, paint.GetWidth(), paint.GetHeight());
  }
  else if (timeoutStDykie4 == 2) {
    paint.Clear(UNCOLORED);
    epd.SetPartialWindowBlack(paint.GetImage(), 248, 270, paint.GetWidth(), paint.GetHeight());
    paint.Clear(UNCOLORED);
    paint.DrawStringAt(24, 6, "LOST data", &Font16, COLORED);
    epd.SetPartialWindowRed(paint.GetImage(), 248, 270, paint.GetWidth(), paint.GetHeight());
  }

  //-----------------// вывод часов и даты
  Paint paint2(image, 64, 64);

  //-----------------// выводим символ ":"
  paint2.Clear(UNCOLORED);
  paint2.DrawCharAt(0, 0, 58, &Font64bd, COLORED);
  epd.SetPartialWindowBlack(paint2.GetImage(), 108, 8, paint2.GetWidth(), paint2.GetHeight());
  //-----------------// выводим часы
  paint2.Clear(UNCOLORED);
  paint2.DrawStringAt(0, 0, (time.gettime("H")), &Font64bd, COLORED);
  epd.SetPartialWindowBlack(paint2.GetImage(), 48, 8, paint2.GetWidth(), paint2.GetHeight());
  //-----------------// выводим минуты
  paint2.Clear(UNCOLORED);
  paint2.DrawStringAt(0, 0, (time.gettime("i")), &Font64bd, COLORED);
  epd.SetPartialWindowBlack(paint2.GetImage(), 128, 8, paint2.GetWidth(), paint2.GetHeight());

  //-----------------// выводим день недели
  Paint paint4(image, 40, 16);
  paint4.Clear(UNCOLORED);
  paint4.DrawStringAt(3, 2, (time.gettime("D")), &Font16, COLORED);
  epd.SetPartialWindowBlack(paint4.GetImage(), 32, 80, paint4.GetWidth(), paint4.GetHeight());
  //-----------------// выводим дату
  Paint paint3(image, 128, 24);
  paint3.Clear(UNCOLORED);
  paint3.DrawStringAt(0, 3, (time.gettime("d.m.y")), &Font24ariald, COLORED);
  epd.SetPartialWindowBlack(paint3.GetImage(), 84, 72, paint3.GetWidth(), paint3.GetHeight());

  //-----------------// Вывод большого рисунка тревоги
  Paint paint5(image, 32, 128);
  if (alarm != 0) {        // если тревога == true
    paint5.Clear(COLORED);
    paint5.DrawFilledRectangle(3, 3, 28, 124, UNCOLORED);
    paint5.DrawFilledRectangle(11, 13, 20, 90, COLORED);
    paint5.DrawFilledRectangle(11, 106, 20, 115, COLORED);
  }
  else {
    paint5.Clear(UNCOLORED);
  }
  epd.SetPartialWindowRed(paint5.GetImage(), 108, 140, paint5.GetWidth(), paint5.GetHeight());



  //-----------------// вывод таймаута приема по nRF24

  sprintf(strbuf, "delay data: %2d min.", timeoutReceive);                         // формируем строку таймаута приема
  Paint paint6(image, 216, 16);
  if (timeoutReceive > 10) {    // таймаут в минутах
    paint.Clear(UNCOLORED);                                                                             // очищаем
    epd.SetPartialWindowBlack(paint6.GetImage(), 16, 280, paint6.GetWidth(), paint6.GetHeight());       // отправляем в буфер пустоту
    paint6.Clear(COLORED);
    paint6.DrawStringAt(0, 3, (strbuf), &Font16, UNCOLORED);                                            // рисуем строку
    epd.SetPartialWindowRed(paint6.GetImage(), 16, 280, paint6.GetWidth(), paint6.GetHeight());         // отправляем в буфер строку
  }
  else if (timeoutReceive >= 1) {
    paint.Clear(UNCOLORED);
    epd.SetPartialWindowRed(paint6.GetImage(), 16, 280, paint6.GetWidth(), paint6.GetHeight());
    paint6.Clear(UNCOLORED);
    paint6.DrawStringAt(0, 3, (strbuf), &Font16, COLORED);
    epd.SetPartialWindowBlack(paint6.GetImage(), 16, 280, paint6.GetWidth(), paint6.GetHeight());
  }
  else {
    paint.Clear(UNCOLORED);
    epd.SetPartialWindowRed(paint6.GetImage(), 16, 280, paint6.GetWidth(), paint6.GetHeight());
    paint6.Clear(UNCOLORED);
    epd.SetPartialWindowBlack(paint6.GetImage(), 16, 280, paint6.GetWidth(), paint6.GetHeight());
  }

  //-----------------// Вывод направления изменения температуры

  Paint paint7(image, 24, 24);

  if (timeoutStDykie1 == 0) {                                 // если данные от датчиков DYKIE актуальны
    if (directChange1 < 0) {                                  // если направление изменения t отрицательное
      paint7.Clear(UNCOLORED);
      paint7.DrawCharAt(4, 4, 'P', &Font16sym, COLORED);      //знак "стрелка вверх"
    }
    else if (directChange1 > 0) {                             // если направление изменения t положительное
      paint7.Clear(UNCOLORED);
      paint7.DrawCharAt(4, 4, 'O', &Font16sym, COLORED);      //знак "стрелка вниз"
    }
    else {                                                    // иначе
      paint7.Clear(UNCOLORED);
      paint7.DrawCharAt(4, 4, 'R', &Font16sym, COLORED);      // знак "стрелка вправо"
    }
    epd.SetPartialWindowBlack(paint7.GetImage(), 248, 45, paint7.GetWidth(), paint7.GetHeight());
  }

  if (timeoutStDykie2 == 0) {
    if (directChange2 < 0) {
      paint7.Clear(UNCOLORED);
      paint7.DrawCharAt(4, 4, 'P', &Font16sym, COLORED);
    }
    else if (directChange2 > 0) {
      paint7.Clear(UNCOLORED);
      paint7.DrawCharAt(4, 4, 'O', &Font16sym, COLORED);
    }
    else {
      paint7.Clear(UNCOLORED);
      paint7.DrawCharAt(4, 4, 'R', &Font16sym, COLORED);
    }
    epd.SetPartialWindowBlack(paint7.GetImage(), 248, 120, paint7.GetWidth(), paint7.GetHeight());
  }

  if (timeoutStDykie3 == 0) {
    if (directChange3 < 0) {
      paint7.Clear(UNCOLORED);
      paint7.DrawCharAt(4, 4, 'P', &Font16sym, COLORED);
    }
    else if (directChange3 > 0) {
      paint7.Clear(UNCOLORED);
      paint7.DrawCharAt(4, 4, 'O', &Font16sym, COLORED);
    }
    else {
      paint7.Clear(UNCOLORED);
      paint7.DrawCharAt(4, 4, 'R', &Font16sym, COLORED);
    }
    epd.SetPartialWindowBlack(paint7.GetImage(), 248, 195, paint7.GetWidth(), paint7.GetHeight());
  }

  if (timeoutStDykie4 == 0) {
    if (directChange4 < 0) {
      paint7.Clear(UNCOLORED);
      paint7.DrawCharAt(4, 4, 'P', &Font16sym, COLORED);
    }
    else if (directChange4 > 0) {
      paint7.Clear(UNCOLORED);
      paint7.DrawCharAt(4, 4, 'O', &Font16sym, COLORED);
    }
    else {
      paint7.Clear(UNCOLORED);
      paint7.DrawCharAt(4, 4, 'R', &Font16sym, COLORED);
    }
    epd.SetPartialWindowBlack(paint7.GetImage(), 248, 270, paint7.GetWidth(), paint7.GetHeight());
  }



  //-----------------// Команда дисплею отобразить
  epd.DisplayFrame();   // отображаем данные из SRAM на дисплей
//  epd.Sleep();          // засыпаем
}