E-Ink дисплей 4.2" 3 цвета, проблемы с отображением при разном расположении объектов на экране
- Войдите на сайт для отправки комментариев
Приветствую всех!
Я в самом начале изучения С++, да и программирования вообще, можно сказать что пилю самый первый свой проект.
Изучаю вот такой дисплей: 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() {
}
Заранее благодарю за помощь


Написал производителю, он исправил ошибку в своих библиотеках. Теперь все отображается верно.
Может кому пригодится информация
Написал производителю, он исправил ошибку в своих библиотеках. Теперь все отображается верно.
Может кому пригодится информация
Спасибо! Более чем пригодилась!!!. С Вашим кодом заработала
А вы показания с датчиков не выводили E-ink?
Это не мой код, это производитель. ))
Показания выводил, конечно.
Коли не сложно, поделитесь примером вывода показаний датчиков, а то всю голову сломал
Я могу только вывод на экран показать. Съем данных с датчиков - это от датчиков зависит.
Вывод в два этапа,
на первом при инициализации в 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(); // засыпаем }