LCD1602 большие цифры

Суть в файле hpp. Автор усложнил написание своего шедевра больших цифр слишком, в итоге где то у него косяк и весьма своеобразный, я не могу понять где из-за сложности его кода.

Спойлер
/*
 *  LCDBigNumbers.hpp
 *
 *  Arduino library to write big numbers on a 1602 or 2004 LCD.
 *
 *  Copyright (C) 2022-2025  Armin Joachimsmeyer
 *  armin.joachimsmeyer@gmail.com
 *
 *  This file is part of LCDBigNumbers https://github.com/ArminJo/LCDBigNumbers.
 *
 *  LCDBigNumbers is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *  See the GNU General Public License for more details.

 *  You should have received a copy of the GNU General Public License
 *  along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
 *
 */

#ifndef _LCD_BIG_NUMBERS_HPP
#define _LCD_BIG_NUMBERS_HPP

#include <Arduino.h>

#define ONE_COLUMN_SPACE_CHARACTER      '|' // This input character is printed as a one column space. Normal spaces are printed as a space with the width of the number.
#define ONE_COLUMN_SPACE_STRING         "|" // This input string is printed as a one column space. Normal spaces are printed as a space with the width of the number.

#define ONE_COLUMN_HYPHEN_CHARACTER      '_' // This input character is printed as a one column hyphen. Normal hyphen / minus are printed as a hyphen with the width of the number - 1.
#define ONE_COLUMN_HYPHEN_STRING         "_" // This input string is printed as a one column hyphen. Normal hyphen / minus are printed as a hyphen with the width of the number - 1.

#define VERSION_LCD_BIG_NUMBERS "1.2.3"
#define VERSION_LCD_BIG_NUMBERS_MAJOR 1
#define VERSION_LCD_BIG_NUMBERS_MINOR 2
#define VERSION_LCD_BIG_NUMBERS_PATCH 3

/////////////////////////////////////////////////////////////////////////////////////////////////////////
//#define  0x8E   0x8E
/////////////////////////////////////////////////////////////////////////////////////////////////////////


// The change log is at the README.md

/*
 * Macro to convert 3 version parts into an integer
 * To be used in preprocessor comparisons, such as #if VERSION_LCD_BIG_NUMBERS_HEX >= VERSION_HEX_VALUE(3, 0, 0)
 */
#define VERSION_HEX_VALUE(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
#define VERSION_LCD_BIG_NUMBERS_HEX  VERSION_HEX_VALUE(VERSION_LCD_BIG_NUMBERS_MAJOR, VERSION_LCD_BIG_NUMBERS_MINOR, VERSION_LCD_BIG_NUMBERS_PATCH)

//#define USE_PARALLEL_2004_LCD // Is default
//#define USE_PARALLEL_1602_LCD
#define USE_SERIAL_2004_LCD
//#define USE_SERIAL_1602_LCD

#if !defined(USE_PARALLEL_2004_LCD) && !defined(USE_PARALLEL_1602_LCD) && !defined(USE_SERIAL_2004_LCD) && !defined(USE_SERIAL_1602_LCD)
#warning "No LCD type like USE_SERIAL_2004_LCD specified, therefore using the default USE_PARALLEL_2004_LCD"
#define USE_PARALLEL_2004_LCD    // Use parallel 2004 LCD as default
#endif

#if defined(USE_PARALLEL_2004_LCD) || defined(USE_PARALLEL_1602_LCD)
#  if defined(USE_PARALLEL_2004_LCD)
#define LCD_COLUMNS     20
#define LCD_ROWS        4
#  else
#define LCD_COLUMNS     16
#define LCD_ROWS        2
#  endif
#define USE_PARALLEL_LCD
#include <LiquidCrystal.h>
#else
#  if defined(USE_SERIAL_2004_LCD)
#define LCD_COLUMNS     20
#define LCD_ROWS        4
#  else
#define LCD_COLUMNS     16
#define LCD_ROWS        2
#  endif
#include "LiquidCrystal_I2C.h"  // Use an up to date library version which has the init method
#endif

#define DEFAULT_TEST_DELAY  3000
#define NUMBER_OF_SPECIAL_CHARACTERS_IN_FONT_ARRAY  3

#define COLUMN_MASK     0x0C // Number of columns = shifted masked value + 1
#define ROW_MASK        0x03 // Number of rows = masked value + 1
#define VARIANT_MASK    0x30
// Numbers are created by using the above masks
#define BIG_NUMBERS_FONT_1_COLUMN_2_ROWS_VARIANT_1  0x01
#define BIG_NUMBERS_FONT_2_COLUMN_2_ROWS_VARIANT_1  0x05
#define BIG_NUMBERS_FONT_3_COLUMN_2_ROWS_VARIANT_1  0x09
#define BIG_NUMBERS_FONT_3_COLUMN_2_ROWS_VARIANT_2  0x19
#define BIG_NUMBERS_FONT_3_COLUMN_2_ROWS_VARIANT_3  0x29
#define BIG_NUMBERS_FONT_2_COLUMN_3_ROWS_VARIANT_1  0x06
#define BIG_NUMBERS_FONT_2_COLUMN_3_ROWS_VARIANT_2  0x16
#define BIG_NUMBERS_FONT_3_COLUMN_3_ROWS_VARIANT_1  0x0A
#define BIG_NUMBERS_FONT_3_COLUMN_4_ROWS_VARIANT_1  0x0B
#define BIG_NUMBERS_FONT_3_COLUMN_4_ROWS_VARIANT_2  0x1B

#if defined(DEBUG)
#define LOCAL_DEBUG
#else
//#define LOCAL_DEBUG // To debug/understand the writeBigNumber() function - only for development
#endif

// !!! Must be without comment and closed by @formatter:on
// @formatter:off

// http://www.picbasic.co.uk/forum/showthread.php?t=13376
// 8 custom characters for 1 column font
const uint8_t bigNumbers1x2CustomPatterns_1[][8] PROGMEM = {
 { B11110, B10010, B10010, B10010, B10010, B10010, B10010, B11110 }, // 0 Closed rectangle - 8
 { B11110, B10010, B10010, B10010, B10010, B10010, B10010, B10010 }, // 1 Rectangle - open at bottom - 0
 { B10010, B10010, B10010, B10010, B10010, B10010, B10010, B11110 }, // 2 Rectangle - open at top - 0
 { B11110, B00010, B00010, B00010, B00010, B00010, B00010, B11110 }, // 3 Rectangle - open at left
 { B11110, B10000, B10000, B10000, B10000, B10000, B10000, B11110 }, // 4 Rectangle - open at right
 { B00010, B00010, B00010, B00010, B00010, B00010, B00010, B00010 }, // 5 Right bar - 1
 { B11110, B00010, B00010, B00010, B00010, B00010, B00010, B00010 }, // 6 Top right - 7
 { B00010, B00010, B00010, B00010, B00010, B00010, B00010, B11110 }  // 7 Right bottom - 3,5,9
};
const uint8_t bigNumbers1x2_1[2][13] PROGMEM = {                   // 2-line numbers
//    "-"   "."   ":"    0     1     2     3     4     5     6     7     8     9
    { 0x5F, 0x8E, 0xA5, 0x01, 0x05, 0x06, 0x03, 0x02, 0x04, 0x04, 0x06, 0x00, 0x00 },
    { 0x8E, 0x2E, 0xA5, 0x02, 0x05, 0x04, 0x07, 0x05, 0x07, 0x02, 0x05, 0x02, 0x07 }
};

// https://www.alpenglowindustries.com/blog/the-big-numbers-go-marching-2x2#/
// https://github.com/AlpenglowIndustries/Alpenglow_BigNums2x2
// 8 custom characters for Trek font
// Requires 1 0xFF Block for the special "0"
const uint8_t bigNumbers2x2CustomPatterns_1[][8] PROGMEM = {
 { B11111, B11111, B00000, B00000, B00000, B00000, B00000, B00000 }, // 0
 { B11000, B11000, B11000, B11000, B11000, B11000, B11000, B11000 }, // 1
 { B00000, B00000, B00000, B00000, B00000, B00000, B11111, B11111 }, // 2
 { B11111, B11111, B00011, B00011, B00011, B00011, B11111, B11111 }, // 3
 { B11111, B11111, B11000, B11000, B11000, B11000, B11111, B11111 }, // 4
 { B11111, B11111, B11000, B11000, B11000, B11000, B11000, B11000 }, // 5
 { B00011, B00011, B00011, B00011, B00011, B00011, B11111, B11111 }, // 6
 { B11000, B11000, B11000, B11000, B11000, B11000, B11111, B11111 } // 7
};
const uint8_t bigNumbers2x2_1[2][23] PROGMEM = {                   // 2-line numbers
//    "-"   "."   ":"       0          1          2          3          4          5          6          7          8          9
    { 0x8E, 0x8E, 0xA5, 0x05,0xFF, 0x00,0x01, 0x00,0x03, 0x00,0x03, 0x01,0x01, 0x04,0x00, 0x05,0x00, 0x00,0x03, 0x04,0x03, 0x04,0x03},
    { 0x00, 0x2E, 0xA5, 0x07,0x06, 0x02,0x07, 0x04,0x02, 0x02,0x03, 0x00,0x05, 0x02,0x03, 0x04,0x03, 0x8E,0x01, 0x04,0x03, 0x02,0x06}
};


// 3x2 https://liudr.wordpress.com/2011/03/21/big-font/
// 3x2 http://www.netzmafia.de/skripten/hardware/Arduino/LCD/index.html
// Requires 0xFF Blocks, but character 6 could be used for it
const uint8_t bigNumbers3x2CustomPatterns_1[6][8] PROGMEM = {
  { B11111,B11111,B00000,B00000,B00000,B00000,B00000,B00000 }, // 0 Upper bar
  { B00000,B00000,B00000,B00000,B00000,B00000,B11111,B11111 }, // 1 Lower bar
  { B11111,B11111,B00000,B00000,B00000,B00000,B11111,B11111 }, // 2 Upper and lower bar
  { B00000,B00000,B00000,B11111,B11111,B00000,B00000,B00000 }, // 3 Minus sign
  { B00000,B00000,B00000,B00000,B00000,B01110,B01110,B01110 }, // 4 Decimal point
  { B00000,B00000,B01110,B01110,B01110,B00000,B00000,B00000 }  // 5 Colon
};
const uint8_t bigNumbers3x2_1[2][33] PROGMEM = {               // 2-line numbers
//    "-"   "."   ":"         0               1               2               3               4               5               6               7               8               9
    { 0x01, 0x8E, 0x05, 0xFF,0x00,0xFF, 0x00,0xFF,0x8E, 0x02,0x02,0xFF, 0x00,0x02,0xFF, 0xFF,0x01,0xFF, 0xFF,0x02,0x02, 0xFF,0x02,0x02, 0x00,0x00,0xFF, 0xFF,0x02,0xFF, 0xFF,0x02,0xFF},
    { 0x8E, 0x04, 0x05, 0xFF,0x01,0xFF, 0x01,0xFF,0x01, 0xFF,0x01,0x01, 0x01,0x01,0xFF, 0x8E,0x8E,0xFF, 0x01,0x01,0xFF, 0xFF,0x01,0xFF, 0x8E,0x8E,0xFF, 0xFF,0x01,0xFF, 0x01,0x01,0xFF}
};

// 3x2 https://forum.arduino.cc/t/display-3-character-wide-big-digits-on-16x2-lcd/905360 bottom of page
// Requires 0xFF Blocks
const uint8_t bigNumbers3x2CustomPatterns_2[8][8] PROGMEM = {
  { B11111,B11111,B11111,B00000,B00000,B00000,B00000,B00000 }, // 0 Upper bar
  { B00000,B00000,B00000,B00000,B00000,B11111,B11111,B11111 }, // 1 Lower bar
  { B11111,B11111,B11111,B00000,B00000,B00000,B11111,B11111 }, // 2 Upper and lower bar for 5,6
  { B11100,B11100,B11100,B11100,B11100,B11100,B11100,B11100 }, // 3 Left bar
  { B00000,B00000,B00000,B00000,B00000,B11100,B11100,B11100 }, // 4 Left lower bar for 2
  { B11100,B11100,B11100,B00000,B00000,B00000,B11100,B11100 }, // 5 Left upper and lower bar for 5,6
  { B00000,B00000,B00000,B00000,B00000,B01110,B01110,B01110 }, // 6 Decimal point
  { B00000,B00000,B01110,B01110,B01110,B00000,B00000,B00000 }  // 7 Colon
};
const uint8_t bigNumbers3x2_2[2][33] PROGMEM = {               // 2-line numbers
//    "-"   "."   ":"         0               1               2               3               4               5               6               7               8               9
    { 0x01, 0x8E, 0x07, 0xFF,0x00,0x03, 0x00,0x03,0x8E, 0x02,0x02,0x03, 0x02,0x02,0x03, 0xFF,0x01,0x03, 0xFF,0x02,0x05, 0xFF,0x02,0x05, 0x00,0x00,0x03, 0xFF,0x02,0x03, 0xFF,0x02,0x03},
    { 0x8E, 0x06, 0x07, 0xFF,0x01,0x03, 0x8E,0x03,0x8E, 0xFF,0x01,0x04, 0x01,0x01,0x03, 0x8E,0x8E,0x03, 0x01,0x01,0x03, 0xFF,0x01,0x03, 0x8E,0x8E,0x03, 0xFF,0x01,0x03, 0x8E,0x8E,0x03}
};

//3x2 https://exploreembedded.com/wiki/Distance_Meter_with_Big_Fonts
const uint8_t bigNumbers3x2CustomPatterns_3[8][8] PROGMEM = {
{ B11100, B11110, B11110, B11110, B11110, B11110, B11110, B11100}, // 0 left bar
{ B00111, B01111, B01111, B01111, B01111, B01111, B01111, B00111}, // 1 right bar
{ B11111, B11111, B00000, B00000, B00000, B00000, B11111, B11111}, // 2 upper and lower bar
{ B11110, B11100, B00000, B00000, B00000, B00000, B11000, B11100}, // 3 left upper and lower rounded
{ B01111, B00111, B00000, B00000, B00000, B00000, B00011, B00111}, // 4 right upper and lower rounded
{ B00000, B00000, B00000, B00000, B00000, B00000, B11111, B11111}, // 5 right lower
{ B00000, B00000, B00000, B00000, B00000, B00000, B00111, B01111}, // 6 right lower rounded
{ B11111, B11111, B00000, B00000, B00000, B00000, B00000, B00000}  // 7 upper bar
};
const uint8_t bigNumbers3x2_3[2][33] PROGMEM = {                   // 2-line numbers
//    "-"   "."   ":"         0               1               2               3               4               5               6               7               8               9
    { 0x8E, 0x8E, 0xA5, 0x01,0x07,0x00, 0x8E,0x00,0x8E, 0x04,0x02,0x00, 0x04,0x02,0x00, 0x01,0x05,0x00, 0x01,0x02,0x03, 0x01,0x02,0x03, 0x01,0x07,0x00, 0x01,0x02,0x00, 0x01,0x02,0x00},
    { 0x07, 0x06, 0xA5, 0x01,0x05,0x00, 0x8E,0x00,0x8E, 0x01,0x05,0x05, 0x06,0x05,0x00, 0x8E,0x8E,0x00, 0x06,0x05,0x00, 0x01,0x05,0x00, 0x8E,0x8E,0x00, 0x01,0x05,0x00, 0x06,0x05,0x00}
};

// http://woodsgood.ca/projects/2015/01/16/large-numbers-on-small-displays/
// 2x3 - Version 1 with space above
const uint8_t bigNumbers2x3CustomPatterns_1[8][8] PROGMEM = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07 }, // char 0: bottom right
        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x1C },     // char 1: bottom left
        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F },     // char 2: bottom block
        { 0x07, 0x07, 0x07, 0x07, 0x07, 0x1F, 0x1F, 0x1F },     // char 3: right bottom block
        { 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1F, 0x1F, 0x1F },     // char 4: left bottom block
        { 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C },     // char 5: left bar
        { 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07 },     // char 6: right bar
        { 0x00, 0x00, 0x0E, 0x0E, 0x0E, 0x00, 0x00, 0x00 }      // char 7: 3x3 block for colon
};
const uint8_t bigNumbers2x3_1[3][23] PROGMEM = {                   // 3-line numbers
//    "-"   "."   ":"       0          1          2          3          4          5          6          7          8          9
    { 0x8E, 0x8E, 0x8E, 0x02,0x02, 0x00,0x01, 0x02,0x02, 0x02,0x02, 0x01,0x00, 0x02,0x02, 0x01,0x8E, 0x02,0x02, 0x02,0x02, 0x02,0x02},
    { 0x02, 0x8E, 0x07, 0x05,0x06, 0x8E,0x05, 0x02,0x03, 0x00,0x03, 0x04,0x03, 0x04,0x02, 0x04,0x02, 0x8E,0x06, 0x04,0x03, 0x04,0x03},
    { 0x8E, 0x01, 0x07, 0x04,0x03, 0x00,0x04, 0x04,0x02, 0x02,0x03, 0x8E,0x06, 0x02,0x03, 0x04,0x03, 0x8E,0x06, 0x04,0x03, 0x8E,0x06}
};

// 2x3 - Version 2 with space below
const uint8_t bigNumbers2x3CustomPatterns_2[][8] PROGMEM = { { 0x07, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00  }, // char 0: top right
        { 0x1C, 0x1C, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00 },     // char 1: top left
        { 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00 },     // char 2: top block
        { 0x1F, 0x1F, 0x1F, 0x07, 0x07, 0x07, 0x07, 0x07 },     // char 3: right top block
        { 0x1F, 0x1F, 0x1F, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C },     // char 4: left top block
        { 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C },     // char 5: left bar
        { 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07 },     // char 6: right bar
        { 0x00, 0x00, 0x0E, 0x0E, 0x0E, 0x00, 0x00, 0x00 }      // char 7: 3x3 block for colon
};

const uint8_t bigNumbers2x3_2[][23] PROGMEM = {                   // 3-line numbers
//    "-"   "."   ":"       0          1          2          3          4          5          6          7          8          9
    { 0x8E, 0x8E, 0x07, 0x04,0x03, 0x00,0x05, 0x02,0x03, 0x02,0x03, 0x05,0x06, 0x04,0x02, 0x05,0x8E, 0x02,0x03, 0x04,0x03, 0x04,0x03},
    { 0x02, 0x8E, 0x07, 0x05,0x06, 0x8E,0x05, 0x04,0x02, 0x00,0x03, 0x02,0x03, 0x02,0x03, 0x04,0x03, 0x8E,0x06, 0x04,0x03, 0x02,0x03},
    { 0x8E, 0x01, 0x8E, 0x02,0x02, 0x00,0x02, 0x02,0x02, 0x02,0x02, 0x8E,0x00, 0x02,0x02, 0x02,0x02, 0x8E,0x00, 0x02,0x02, 0x8E,0x00}
};

// 3x4 Font custom patterns http://woodsgood.ca/projects/2015/03/06/3-4-line-big-font-numerals/
// Requires 0xFF Blocks
const uint8_t bigNumbers3x3And3x4CustomPatterns_1[][8] PROGMEM = { { 0x01, 0x07, 0x0F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }, // char 0: bottom right triangle
        { 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x1F },     // char 1: bottom block
        { 0x10, 0x1C, 0x1E, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F },     // char 2: bottom left triangle
        { 0x1F, 0x0F, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00 },     // char 3: top right triangle
        { 0x1F, 0x1E, 0x1C, 0x10, 0x00, 0x00, 0x00, 0x00 },     // char 4: top left triangle
        { 0x1F, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00 },     // char 5: upper block
        { 0x10, 0x1C, 0x1E, 0x1F, 0x00, 0x00, 0x00, 0x00 },     // char 6: full top left triangle Used only once in 7
//        { 0x1F, 0x1F, 0x1E, 0x1C, 0x18, 0x10, 0x00, 0x00 },     // char 6: full top left triangle Used only once in 7
        { 0x01, 0x07, 0x0F, 0x1F, 0x00, 0x00, 0x00, 0x00 }      // char 7: top right triangle
};

const uint8_t bigNumbers3x3_1[3][33] PROGMEM = {   // 3-line numbers
//    "-"   "."   ":"         0               1               2               3               4              5               6                7               8               9
    { 0x8E, 0x8E, 0x01, 0x00,0x05,0x02, 0x07,0xFF,0x8E, 0x07,0x05,0x02, 0x07,0x05,0x02, 0xFF,0x8E,0xFF, 0xFF,0x05,0x05, 0x00,0x05,0x06, 0x05,0x05,0xFF, 0x00,0x05,0x02, 0x00,0x05,0x02},
    { 0x05, 0x8E, 0x01, 0xFF,0x8E,0xFF, 0x8E,0xFF,0x8E, 0x00,0x05,0x05, 0x8E,0x05,0xFF, 0x05,0x05,0xFF, 0x05,0x05,0xFF, 0xFF,0x05,0x02, 0x8E,0x00,0x04, 0xFF,0x05,0xFF, 0x03,0x05,0xFF},
    { 0x8E, 0x05, 0x8E, 0x03,0x05,0x04, 0x8E,0x05,0x8E, 0x05,0x05,0x05, 0x03,0x05,0x04, 0x8E,0x8E,0x05, 0x03,0x05,0x04, 0x03,0x05,0x04, 0x8E,0x05,0x8E, 0x03,0x05,0x04, 0x03,0x05,0x04}
};

// 3x4 Font variant 1
const uint8_t bigNumbers3x4_1[4][33] PROGMEM = {                   // 4-line numbers
//    "-"   "."   ":"         0               1               2               3               4              5               6                7               8               9
    { 0x8E, 0x8E, 0x8E, 0x00,0x05,0x02, 0x07,0xFF,0x8E, 0x07,0x05,0x02, 0x07,0x05,0x02, 0xFF,0x8E,0xFF, 0xFF,0x05,0x05, 0x00,0x05,0x02, 0x05,0x05,0xFF, 0x00,0x05,0x02, 0x00,0x05,0x02},
    { 0x01, 0x8E, 0x05, 0xFF,0x8E,0xFF, 0x8E,0xFF,0x8E, 0x01,0x01,0xFF, 0x8E,0x01,0xFF, 0xFF,0x01,0xFF, 0xFF,0x01,0x01, 0xFF,0x01,0x01, 0x8E,0x00,0x04, 0xFF,0x01,0xFF, 0xFF,0x01,0xFF},
    { 0x8E, 0x8E, 0x01, 0xFF,0x8E,0xFF, 0x8E,0xFF,0x8E, 0xFF,0x8E,0x8E, 0x8E,0x8E,0xFF, 0x8E,0x8E,0xFF, 0x8E,0x8E,0xFF, 0xFF,0x8E,0xFF, 0x8E,0xFF,0x8E, 0xFF,0x8E,0xFF, 0x8E,0x8E,0xFF},
    { 0x8E, 0x05, 0x8E, 0x03,0x05,0x04, 0x8E,0x05,0x8E, 0x05,0x05,0x05, 0x03,0x05,0x04, 0x8E,0x8E,0x05, 0x03,0x05,0x04, 0x03,0x05,0x04, 0x8E,0x05,0x8E, 0x03,0x05,0x04, 0x03,0x05,0x04}
};

// 3x4 Font variant 2
// https://forum.arduino.cc/t/wie-bekommt-man-solch-grosse-zahlen-hin/986148/12
// Requires 0xFF Blocks
const uint8_t bigNumbers3x4CustomPatterns_2[][8] PROGMEM = {
{ B00000, B00000, B00000, B00000, B00001, B00111, B01111, B11111 }, // char 0: bottom right triangle
{ B00000, B00000, B00000, B00000, B11111, B11111, B11111, B11111 }, // char 1: bottom block
{ B00000, B00000, B00000, B00000, B10000, B11100, B11110, B11111 }, // char 2: bottom left triangle
{ B11111, B01111, B00111, B00001, B00000, B00000, B00000, B00000 }, // char 3: top right triangle
{ B11111, B11111, B11111, B11111, B00000, B00000, B00000, B00000 }, // char 4: upper block
{ B11111, B11110, B11100, B10000, B00000, B00000, B00000, B00000 }, // char 5: top left triangle
{ B11111, B11111, B11111, B11111, B11111, B01111, B00111, B00001 }, // char 6: full top right triangle
{ B11111, B11111, B11111, B11111, B11111, B11110, B11100, B10000 }  // char 7: full top left triangle
};

const uint8_t bigNumbers3x4_2[4][33] PROGMEM = {                         // 4-line numbers
//    "-"   "."   ":"         0               1               2               3               4              5               6                7               8               9
    { 0x8E, 0x8E, 0x8E, 0x00,0x01,0x02, 0x00,0x01,0x8E, 0x00,0x01,0x02, 0x00,0x01,0x02, 0x00,0x8E,0x01, 0x01,0x01,0x01, 0x00,0x01,0x02, 0x01,0x01,0x01, 0x00,0x01,0x02, 0x00,0x01,0x02},
    { 0x01, 0x8E, 0x04, 0xFF,0x00,0xFF, 0x05,0xFF,0x8E, 0x04,0x00,0x07, 0x04,0x00,0x07, 0xFF,0x8E,0xFF, 0x06,0x01,0x02, 0xFF,0x01,0x02, 0x8E,0x00,0x07, 0x06,0x01,0x07, 0x06,0x01,0xFF},
    { 0x8E, 0x8E, 0x01, 0xFF,0x05,0xFF, 0x8E,0xFF,0x8E, 0xFF,0x05,0x8E, 0x01,0x03,0xFF, 0x04,0x04,0xFF, 0x01,0x8E,0xFF, 0xFF,0x8E,0xFF, 0xFF,0x05,0x8E, 0xFF,0x8E,0xFF, 0x8E,0x8E,0xFF},
    { 0x8E, 0x04, 0x8E, 0x03,0x04,0x05, 0x8E,0x04,0x8E, 0x04,0x04,0x04, 0x03,0x04,0x05, 0x8E,0x8E,0x04, 0x03,0x04,0x05, 0x03,0x04,0x05, 0x04,0x8E,0x8E, 0x03,0x04,0x05, 0x03,0x04,0x05}
};

// 4x4: https://github.com/wa1hco/BigFont
// @formatter:on
class LCDBigNumbers: public Print { // @suppress("Class has a virtual method and non-virtual destructor")

public:
// If activated gives linker error: undefined reference to `operator delete(void*, unsigned int)'
// If disabled I get a Eclipse warning: Class 'LCDBigNumbers' has virtual method 'flush' but non-virtual destructor
//    virtual ~LCDBigNumbers() {}
#if defined(USE_PARALLEL_LCD)
    LiquidCrystal *LCD;
#else
    LiquidCrystal_I2C *LCD;
#endif
    uint8_t NumberWidth; // Width of the rendered number not including the optional blank gap
    uint8_t NumberHeight;
    uint8_t FontVariant;
    const uint8_t (*bigNumbersCustomPatterns)[8];
    uint8_t NumberOfCustomPatterns;
    const uint8_t *bigNumbersFont;
    bool forceGapBetweenNumbers;    // The default depends on the font used
    uint8_t upperLeftColumnIndex;   // Start of the next character
    uint8_t maximumColumns; // Auto detected maximum of columns which can be written (e.g. 16 or 20). To avoid clearing the gap after a number which ends at the last column. (44 bytes program space)
    uint8_t upperLeftRowIndex;      // Start of the next character

    /*
     *
     */
    void setBigNumberCursor(uint8_t aUpperLeftColumnIndex, uint8_t aUpperLeftRowIndex = 0) {
        upperLeftColumnIndex = aUpperLeftColumnIndex;
        upperLeftRowIndex = aUpperLeftRowIndex;
    }

    size_t write(uint8_t aBigNumberValue) {
        return writeBigNumber(aBigNumberValue);
    }

    /*
     * Creates custom character used for generating big numbers
     * This also sets cursor to 0.0 by call to _createChar()
     */
    void begin() {
        maximumColumns = 0;
        // create maximum 8 custom characters
        for (uint_fast8_t i = 0; i < NumberOfCustomPatterns; i++) {
            _createChar(i, bigNumbersCustomPatterns[i]);
        }
    }

    void enableGapBetweenNumbers() {
        forceGapBetweenNumbers = true;
    }
    void disableGapBetweenNumbers() {
        forceGapBetweenNumbers = false;
    }
    void setGapBetweenNumbers(bool aForceGapBetweenNumbers) {
        forceGapBetweenNumbers = aForceGapBetweenNumbers;
    }

    /*
     * Internal function to select the appropriate font arrays
     */
    void init(const uint8_t aBigNumberFontIdentifier) {
        setBigNumberCursor(0);
        NumberWidth = ((aBigNumberFontIdentifier & COLUMN_MASK) >> 2) + 1;
        NumberHeight = (aBigNumberFontIdentifier & ROW_MASK) + 1;
        FontVariant = ((aBigNumberFontIdentifier & VARIANT_MASK) >> 4) + 1;
        NumberOfCustomPatterns = 8;
        forceGapBetweenNumbers = true;
        switch (aBigNumberFontIdentifier) {
        case BIG_NUMBERS_FONT_1_COLUMN_2_ROWS_VARIANT_1:
            bigNumbersCustomPatterns = bigNumbers1x2CustomPatterns_1;
            bigNumbersFont = (const uint8_t*) bigNumbers1x2_1;
            forceGapBetweenNumbers = false;
            break;
        case BIG_NUMBERS_FONT_2_COLUMN_2_ROWS_VARIANT_1:
            bigNumbersCustomPatterns = bigNumbers2x2CustomPatterns_1;
            bigNumbersFont = (const uint8_t*) bigNumbers2x2_1;
            break;
        case BIG_NUMBERS_FONT_3_COLUMN_2_ROWS_VARIANT_1:
            bigNumbersCustomPatterns = bigNumbers3x2CustomPatterns_1;
            bigNumbersFont = (const uint8_t*) bigNumbers3x2_1;
            NumberOfCustomPatterns = 6;
            break;
        case BIG_NUMBERS_FONT_3_COLUMN_2_ROWS_VARIANT_2:
            bigNumbersCustomPatterns = bigNumbers3x2CustomPatterns_3;
            bigNumbersFont = (const uint8_t*) bigNumbers3x2_3;
            forceGapBetweenNumbers = false;
            break;
        case BIG_NUMBERS_FONT_3_COLUMN_2_ROWS_VARIANT_3:
            bigNumbersCustomPatterns = bigNumbers3x2CustomPatterns_2;
            bigNumbersFont = (const uint8_t*) bigNumbers3x2_2;
            forceGapBetweenNumbers = false;
            break;
#if LCD_ROWS <= 2
            default:
                // ERROR: NumberHeight is greater than 2 for a 2 line display -> fallback to 2x2 font
                bigNumbersCustomPatterns = bigNumbers2x2CustomPatterns_1;
                bigNumbersFont = (const uint8_t*) bigNumbers2x2_1;
                break;
#else
        case BIG_NUMBERS_FONT_2_COLUMN_3_ROWS_VARIANT_1:
            bigNumbersCustomPatterns = bigNumbers2x3CustomPatterns_1;
            bigNumbersFont = (const uint8_t*) bigNumbers2x3_1;
            break;
        case BIG_NUMBERS_FONT_2_COLUMN_3_ROWS_VARIANT_2:
            bigNumbersCustomPatterns = bigNumbers2x3CustomPatterns_2;
            bigNumbersFont = (const uint8_t*) bigNumbers2x3_2;
            break;
        case BIG_NUMBERS_FONT_3_COLUMN_3_ROWS_VARIANT_1:
            bigNumbersCustomPatterns = bigNumbers3x3And3x4CustomPatterns_1;
            bigNumbersFont = (const uint8_t*) bigNumbers3x3_1;
            break;
        case BIG_NUMBERS_FONT_3_COLUMN_4_ROWS_VARIANT_1:
            bigNumbersCustomPatterns = bigNumbers3x3And3x4CustomPatterns_1;
            bigNumbersFont = (const uint8_t*) bigNumbers3x4_1;
            break;
        case BIG_NUMBERS_FONT_3_COLUMN_4_ROWS_VARIANT_2:
            bigNumbersCustomPatterns = bigNumbers3x4CustomPatterns_2;
            bigNumbersFont = (const uint8_t*) bigNumbers3x4_2;
            break;
#endif

        }
    }

#if defined(USE_PARALLEL_LCD)
    LCDBigNumbers(LiquidCrystal *aLCD, const uint8_t aBigNumberFontIdentifier) :
#else
    LCDBigNumbers(LiquidCrystal_I2C *aLCD, const uint8_t aBigNumberFontIdentifier) :
#endif
                    LCD(aLCD) {
        init(aBigNumberFontIdentifier);
    }

    /*
     * Like LiquidCrystal::createChar(uint8_t location, uint8_t charmap[])
     * but with PROGMEM input
     * This also sets cursor to 0.0
     */
    void _createChar(uint8_t location, const uint8_t *charmap) {
        location &= 0x7; // we only have 8 locations 0-7
        LCD->command(LCD_SETCGRAMADDR | (location << 3));
        for (int i = 0; i < 8; i++) {
            LCD->write(pgm_read_byte(charmap++));
        }
        LCD->command(LCD_SETDDRAMADDR); // set cursor to 0.0, this avoids overwriting CGRAM by next write() command.
    }

    /**
     * Draws a big digit of size aNumberWidth x aNumberHeight at cursor position
     * Special characters always have the width of 1!
     * After each number one column gap is inserted. The gap is cleared, if not at the (last + 1) column!
     * @param aNumber - byte 0x00 to 0x09 or ASCII number or one of these special characters: ' ', '|', '-', '_', '.', ':'
     * @return  The number of columns written (1 to 4 currently)
     */
    size_t writeBigNumber(uint8_t aNumberOrSpecialCharacter) {
        uint_fast8_t tFontArrayOffset = 0;
        uint_fast8_t tCharacterWidth = 1;
        /*
         * First 3 entries are the special characters
         * All non characters not compared with here, are mapped to a space with the width of the number
         */
        if (aNumberOrSpecialCharacter == '-' || aNumberOrSpecialCharacter == ONE_COLUMN_HYPHEN_CHARACTER) {
            // here we have the initial values: tFontArrayOffset = 0; and tCharacterWidth = 1;
        } else if (aNumberOrSpecialCharacter == '.') {
            tFontArrayOffset = 1;
        } else if (aNumberOrSpecialCharacter == ':') {
            tFontArrayOffset = 2;
        } else if (aNumberOrSpecialCharacter == ' ') {
            tCharacterWidth = NumberWidth;
        } else if (aNumberOrSpecialCharacter == ONE_COLUMN_SPACE_CHARACTER) {
            // print a one column space
            aNumberOrSpecialCharacter = ' ';
        } else {
            /*
             * Here we have numbers only
             */
            if (aNumberOrSpecialCharacter > 9) {
                // if not byte 0x00 to 0x09, convert ASCII character to number
                aNumberOrSpecialCharacter -= '0';
            }
            if (aNumberOrSpecialCharacter > 9) {
                // If we do not have a number 0 to 9 now, we convert it to a space with the width of a number
                aNumberOrSpecialCharacter = ' ';
            }
            tCharacterWidth = NumberWidth;
            tFontArrayOffset = NUMBER_OF_SPECIAL_CHARACTERS_IN_FONT_ARRAY + (aNumberOrSpecialCharacter * tCharacterWidth);
        }
#if defined(LOCAL_DEBUG)
        Serial.print(F("Number="));
        Serial.print(aNumberOrSpecialCharacter);
        Serial.print(F(" CharacterWidth="));
        Serial.print(tCharacterWidth);
        Serial.print(F(" FontArrayOffset="));
        Serial.print(tFontArrayOffset);
        Serial.print(F(" ColunmOffset="));
        Serial.println(upperLeftColumnIndex);
#endif
        const uint8_t *tArrayPtr = bigNumbersFont + tFontArrayOffset;
        // Render character row by row
        for (uint_fast8_t tRow = 0; tRow < NumberHeight; tRow++) {
            LCD->setCursor(upperLeftColumnIndex, upperLeftRowIndex + tRow);
            // Render all columns in a row
            for (uint_fast8_t i = 0; i < tCharacterWidth; i++) {
                uint8_t tCharacterIndex;
                if (aNumberOrSpecialCharacter == ' ') {
                    tCharacterIndex = ' '; // Blank
                } else {
                    tCharacterIndex = pgm_read_byte(tArrayPtr);
                }
                LCD->write(tCharacterIndex);
                tArrayPtr++; // Prepare for next column, we do not use i
#if defined(LOCAL_DEBUG)
                Serial.print(F(" 0x"));
                Serial.print(tCharacterIndex, HEX);
                Serial.print(F(" 0x"));
                Serial.print((uint16_t) tArrayPtr, HEX);
#endif
            }
            tArrayPtr += NUMBER_OF_SPECIAL_CHARACTERS_IN_FONT_ARRAY + (NumberWidth - tCharacterWidth) + (9 * NumberWidth); // Next array row
#if defined(LOCAL_DEBUG)
            Serial.print('|');
#endif
        }
        upperLeftColumnIndex += tCharacterWidth; // now we are at the index for the next number or the optional blank gap

        /*
         * Auto detect maximum column count, which can be written.
         * We assume that all characters, which were written, fit on the display.
         * Thus the maximum of the upperLeftColumnIndex after write is the index of the first column after the display and maximum possible column count.
         */
        if (maximumColumns < upperLeftColumnIndex) {
            // find maximum column at runtime
            maximumColumns = upperLeftColumnIndex;
        }

        /*
         * Implement the gap after the number character
         */
        if (forceGapBetweenNumbers && (NumberWidth == 1 || tCharacterWidth > 1 || aNumberOrSpecialCharacter == '-')) {
            if (maximumColumns >= upperLeftColumnIndex) {
                // We are not at the last column, so clear the gap after the number
                for (uint_fast8_t tRow = 0; tRow < NumberHeight; tRow++) {
                    LCD->setCursor(upperLeftColumnIndex, upperLeftRowIndex + tRow);
                    LCD->write(' '); // Blank
                }
                tCharacterWidth++;
            }
            upperLeftColumnIndex++; // This provides one column gap between numbers, but not between special characters.
        }

#if defined(LOCAL_DEBUG)
        Serial.println();
#endif
        return tCharacterWidth;
    }

    /**
     * Draws a big digit of size aNumberWidth x aNumberHeight
     * @param aNumber - Number to display, if > 9 a blank character is drawn
     * @param aUpperLeftColumnIndex - Starts with 0, no check!
     * @param aStartRowIndex - Starts with 0, no check!
     */
    size_t writeAt(uint8_t aNumber, uint8_t aUpperLeftColumnIndex, uint8_t aUpperLeftRowIndex = 0) {
        setBigNumberCursor(aUpperLeftColumnIndex, aUpperLeftRowIndex);
        return writeBigNumber(aNumber);
    }

};

#if defined(USE_PARALLEL_LCD)
void printSpaces(LiquidCrystal *aLCD, uint_fast8_t aNumberOfSpacesToPrint)
#else
void printSpaces(LiquidCrystal_I2C *aLCD, uint_fast8_t aNumberOfSpacesToPrint)
#endif
        {
    for (uint_fast8_t i = 0; i < aNumberOfSpacesToPrint; ++i) {
        aLCD->print(' ');
    }
}

#if defined(USE_PARALLEL_LCD)
void clearLine(LiquidCrystal *aLCD, uint_fast8_t aLineNumber)
#else
void clearLine(LiquidCrystal_I2C *aLCD, uint_fast8_t aLineNumber)
#endif
        {
    aLCD->setCursor(0, aLineNumber);
    printSpaces(aLCD, LCD_COLUMNS);
    aLCD->setCursor(0, aLineNumber);
}

#if defined(USE_PARALLEL_LCD)
size_t printHex(LiquidCrystal *aLCD, uint16_t aHexByteValue)
#else
size_t printHex(LiquidCrystal_I2C *aLCD, uint16_t aHexByteValue)
#endif
        {
    aLCD->print(F("0x"));
    size_t tPrintSize = 2;
    if (aHexByteValue < 0x10 || (aHexByteValue > 0x100 && aHexByteValue < 0x1000)) {
        aLCD->print('0'); // leading 0
        tPrintSize++;
    }
    return aLCD->print(aHexByteValue, HEX) + tPrintSize;
}

/*
 * On my 2004 LCD the custom characters are available under 0 to 7 and mirrored to 8 to 15
 * The characters 0x80 to 0x8F are blanks
 */
#if defined(USE_PARALLEL_LCD)
void showSpecialCharacters(LiquidCrystal *aLCD)
#else
void showSpecialCharacters(LiquidCrystal_I2C *aLCD)
#endif
        {
    aLCD->setCursor(0, 0);
    // 0 to 7 are mirrored to 8 to 15 as described in datasheet
    for (uint_fast8_t i = 0; i < 0x8; ++i) {
        aLCD->write(i);
    }
    // Print some interesting characters
    aLCD->write(0xA1);
    aLCD->write(0xA5);
    aLCD->write(0xB0);
    aLCD->write(0xDB);
    aLCD->write(0xDF);

    aLCD->setCursor(0, 1);
    // The characters 0x10 to 0x1F seem to be all blanks => ROM Code: A00
    for (uint_fast8_t i = 0x10; i < 0x20; ++i) {
        aLCD->write(i);
    }
    aLCD->setCursor(0, 2);
    // The characters 0x80 to 0x8F seem to be all blanks => ROM Code: A00
    for (uint_fast8_t i = 0x80; i < 0x90; ++i) {
        aLCD->write(i);
    }
    aLCD->setCursor(0, 3);
    // The characters 0x90 to 0x9F seem to be all blanks => ROM Code: A00
    for (uint_fast8_t i = 0x90; i < 0xA0; ++i) {
        aLCD->write(i);
    }
    delay(2000);
}

#if defined(USE_PARALLEL_LCD)
void showCustomCharacters(LiquidCrystal *aLCD)
#else
void showCustomCharacters(LiquidCrystal_I2C *aLCD)
#endif
        {
    aLCD->setCursor(0, 0);
    for (uint_fast8_t i = 0; i < 0x08; ++i) {
        aLCD->write(i);
    }
}

#if defined(USE_PARALLEL_LCD)
/*
 * Print all fonts, used in screenshots, using one object
 */
void testBigNumbers(LiquidCrystal *aLCD)
#else
void testBigNumbers(LiquidCrystal_I2C *aLCD)
#endif
        {
    /*
     * 1 X 2
     */
    aLCD->clear(); // Clear display
    // Allocate object
    LCDBigNumbers bigNumberLCD(aLCD, BIG_NUMBERS_FONT_1_COLUMN_2_ROWS_VARIANT_1);
    bigNumberLCD.begin(); // Generate font symbols in LCD controller
    bigNumberLCD.print(F("0123456789 -.:")); // no special space required, we have an 1 column font

    // Print "-42.38 :"
    bigNumberLCD.setBigNumberCursor(0, 2);
    bigNumberLCD.print(F("-42.38"));
    delay(DEFAULT_TEST_DELAY);

    /*
     * 2 X 2
     */
    aLCD->clear(); // Clear display
    // Reconfigure existing object to hold another font
    bigNumberLCD.init(BIG_NUMBERS_FONT_2_COLUMN_2_ROWS_VARIANT_1);
    bigNumberLCD.begin(); // Generate font symbols in LCD controller
    bigNumberLCD.print(F("01234"));
#if LCD_ROWS <= 2
    delay(DEFAULT_TEST_DELAY);
    bigNumberLCD.setBigNumberCursor(0);
    bigNumberLCD.print(F("56789"));
    delay(DEFAULT_TEST_DELAY);
    bigNumberLCD.setBigNumberCursor(0);
    bigNumberLCD.print(F("-.: "));
#else
    bigNumberLCD.setBigNumberCursor(0, 2);
    bigNumberLCD.print(F("56789" ONE_COLUMN_SPACE_STRING "-.:"));
#endif
    delay(DEFAULT_TEST_DELAY);

    aLCD->clear(); // Clear display
    // Print "-42.38 :"
    bigNumberLCD.setBigNumberCursor(0);
    bigNumberLCD.print(F("-42.38"));
    delay(DEFAULT_TEST_DELAY);

    /*
     * 3 X 2 1. variant
     */
    aLCD->clear(); // Clear display
    bigNumberLCD.init(BIG_NUMBERS_FONT_3_COLUMN_2_ROWS_VARIANT_1);
    bigNumberLCD.begin();

#if LCD_ROWS <= 2
    bigNumberLCD.print(F("0123"));
    delay(DEFAULT_TEST_DELAY);
    bigNumberLCD.setBigNumberCursor(0);
    bigNumberLCD.print(F("4567"));
    delay(DEFAULT_TEST_DELAY);
    bigNumberLCD.setBigNumberCursor(0);
    bigNumberLCD.print(F("89" ONE_COLUMN_SPACE_STRING "-.: "));
#else
    bigNumberLCD.print(F("01234"));
    bigNumberLCD.setBigNumberCursor(0, 2);
    bigNumberLCD.print(F("56789"));
    delay(DEFAULT_TEST_DELAY);

    aLCD->clear(); // Clear display
    // Print "-42.38 :"
    bigNumberLCD.setBigNumberCursor(0);
    bigNumberLCD.print(F("-42.38:"));
#endif

    delay(DEFAULT_TEST_DELAY);

    /*
     * 3 X 2 2. variant
     */
    aLCD->clear(); // Clear display
    bigNumberLCD.init( BIG_NUMBERS_FONT_3_COLUMN_2_ROWS_VARIANT_2);
    bigNumberLCD.begin();
    bigNumberLCD.print(F("01234"));
#if LCD_ROWS <= 2
    delay(DEFAULT_TEST_DELAY);
    bigNumberLCD.setBigNumberCursor(0);
    bigNumberLCD.print(F("56789"));
    delay(DEFAULT_TEST_DELAY);
    bigNumberLCD.setBigNumberCursor(0);
    bigNumberLCD.print(F("-.: "));
#else
    bigNumberLCD.setBigNumberCursor(0, 2);
    bigNumberLCD.print(F("56789")); // we have a space between this characters, i.e. forceGapBetweenNumbers is true
#endif
    delay(DEFAULT_TEST_DELAY);

    aLCD->clear(); // Clear display
    // Print "-42.38 :"
    bigNumberLCD.setBigNumberCursor(0);
    bigNumberLCD.print(F("-42.38:"));
    delay(DEFAULT_TEST_DELAY);

    /*
     * 3 X 2 3. variant
     */
    aLCD->clear(); // Clear display
    bigNumberLCD.init( BIG_NUMBERS_FONT_3_COLUMN_2_ROWS_VARIANT_3);
    bigNumberLCD.begin();
    bigNumberLCD.print(F("01234"));
#if LCD_ROWS <= 2
    delay(DEFAULT_TEST_DELAY);
    bigNumberLCD.setBigNumberCursor(0);
    bigNumberLCD.print(F("56789"));
    delay(DEFAULT_TEST_DELAY);
    bigNumberLCD.setBigNumberCursor(0);
    bigNumberLCD.print(F("-.: "));
#else
    bigNumberLCD.setBigNumberCursor(0, 2);
    bigNumberLCD.print(F("56789" ONE_COLUMN_SPACE_STRING "-.:"));
#endif
    delay(DEFAULT_TEST_DELAY);

    aLCD->clear(); // Clear display
    // Print "-42.38 :"
    bigNumberLCD.setBigNumberCursor(0);
    bigNumberLCD.print(F("-42.38"));
    delay(DEFAULT_TEST_DELAY);

#if LCD_ROWS > 2
    /****************
     * 3 line numbers
     ****************/
    /*
     * 2 X 3 Space above
     */
    aLCD->clear(); // Clear display
    bigNumberLCD.init(BIG_NUMBERS_FONT_2_COLUMN_3_ROWS_VARIANT_1);
    bigNumberLCD.begin();
    bigNumberLCD.setBigNumberCursor(0, 1);
    bigNumberLCD.print(F("01234"));
    delay(DEFAULT_TEST_DELAY);
    bigNumberLCD.setBigNumberCursor(0, 1);
    bigNumberLCD.print(F("56789" ONE_COLUMN_SPACE_STRING "-.:"));
    delay(DEFAULT_TEST_DELAY);

    aLCD->clear(); // Clear display
    // Print "-42.38 :"
    bigNumberLCD.setBigNumberCursor(0, 1);
    bigNumberLCD.print(F("-42.38"));
    delay(DEFAULT_TEST_DELAY);

    /*
     * 2 X 3 Space below
     */
    aLCD->clear(); // Clear display
    bigNumberLCD.init( BIG_NUMBERS_FONT_2_COLUMN_3_ROWS_VARIANT_2);
    bigNumberLCD.begin();
    bigNumberLCD.setBigNumberCursor(0, 1);
    bigNumberLCD.print(F("01234"));
    delay(DEFAULT_TEST_DELAY);
    bigNumberLCD.setBigNumberCursor(0, 1);
    bigNumberLCD.print(F("56789" ONE_COLUMN_SPACE_STRING "-.:"));
    delay(DEFAULT_TEST_DELAY);

    aLCD->clear(); // Clear display
    // Print "-42.38 :"
    bigNumberLCD.setBigNumberCursor(0, 1);
    bigNumberLCD.print(F("-42.38"));
    delay(DEFAULT_TEST_DELAY);

    /*
     * 3 X 3 Space below
     */
    aLCD->clear(); // Clear display
    bigNumberLCD.init(BIG_NUMBERS_FONT_3_COLUMN_3_ROWS_VARIANT_1);
    bigNumberLCD.begin();
    bigNumberLCD.setBigNumberCursor(0, 1);
    bigNumberLCD.print(F("01234"));
    delay(DEFAULT_TEST_DELAY);
    bigNumberLCD.setBigNumberCursor(0, 1);
    bigNumberLCD.print(F("56789"));
    delay(DEFAULT_TEST_DELAY);

    aLCD->clear(); // Clear display
    // Print "-42.38 :"
    bigNumberLCD.setBigNumberCursor(0, 1);
    bigNumberLCD.print(F("-42.38:"));
    delay(DEFAULT_TEST_DELAY);

    /****************
     * 4 line numbers
     ****************/
    /*
     * 3 X 4
     */
    aLCD->clear(); // Clear display
    bigNumberLCD.init( BIG_NUMBERS_FONT_3_COLUMN_4_ROWS_VARIANT_1);
    bigNumberLCD.begin();
    bigNumberLCD.print(F("01234"));
    delay(DEFAULT_TEST_DELAY);
    bigNumberLCD.setBigNumberCursor(0);
    bigNumberLCD.print(F("56789"));
    delay(DEFAULT_TEST_DELAY);

    aLCD->clear(); // Clear display
    // Print "-42.38 :"
    bigNumberLCD.setBigNumberCursor(0);
    bigNumberLCD.print(F("-42.38:"));
    delay(DEFAULT_TEST_DELAY);

    /*
     * Variant 2
     */
    aLCD->clear(); // Clear display
    bigNumberLCD.init( BIG_NUMBERS_FONT_3_COLUMN_4_ROWS_VARIANT_2);
    bigNumberLCD.begin();
    bigNumberLCD.print(F("01234"));
    delay(DEFAULT_TEST_DELAY);
    bigNumberLCD.setBigNumberCursor(0);
    bigNumberLCD.print(F("56789"));
    delay(DEFAULT_TEST_DELAY);

    aLCD->clear(); // Clear display
    // Print "-42.38 :"
    bigNumberLCD.setBigNumberCursor(0);
    bigNumberLCD.print(F("-42.38:"));
    delay(DEFAULT_TEST_DELAY);
#endif // LCD_ROWS > 2
}

#if defined(LOCAL_DEBUG)
#undef LOCAL_DEBUG
#endif
#endif // _LCD_BIG_NUMBERS_HPP

Не надо ничего обзывать, автор писал своё произведение под англо-китайский вариант дисплея, а у меня англо-русский. Из-за этого у автора под числом 0хFE пусто место, а у меня кракозябр.

Его косяки: цифры 3х4 на позиции 0 в строке, в столбцах не высвечиваются (точнее, после высвечивания быстро затирается)- цифра полузатёрта, её надо постоянно обновлять :slight_smile:
На свободных местах от цифр данные стираются при обновлении цифр, их тоже нужно обновлять. В итоге картинка пестрит по двоеточиям.

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

1 лайк

Взял у автора только картинки цифр, библиотека его заумная слишком :slight_smile:

Спойлер

#include <Wire.h>
#include "LiquidCrystal_I2C.h"
#include "Adafruit_NeoPixel.h"

#define line_ 66 //число пикселей в ленте
uint8_t dataPin = 6;// вывод для подключения
Adafruit_NeoPixel strip = Adafruit_NeoPixel(line_,dataPin , NEO_GRB + NEO_KHZ800);// Создаем переменную strip для управления нашей лентой.

LiquidCrystal_I2C lcd(0x27,20,4);
const char utf_recode[]=
       { 0x70,0x63,0xbf,0x79,0xe4,0x78,0xe5,0xc0,0xc1,0xe6,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7, //р....я
         0x41,0xa0,0x42,0xa1,0xe0,0x45,0xa3,0xa4,0xa5,0xa6,0x4b,0xa7,0x4d,0x48,0x4f,        //АБВГДЕЖЗИЙКЛМНО
         0xa8,0x50,0x43,0x54,0xa9,0xaa,0x58,0xe1,0xab,0xac,0xe2,0xad,0xae,0x62,0xaf,0xb0,0xb1,//П....Я
         0x61,0xb2,0xb3,0xb4,0xe3,0x65,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0x6f,0xbe, //а......п
         0xa2,0xb5                                                                        //Ёё   
       }; 
byte fragm_1[] = {
B00000, B00000, B00000, B00000, B00001, B00111, B01111, B11111
};
byte fragm_2[] = {
B00000, B00000, B00000, B00000, B11111, B11111, B11111, B11111
};
byte fragm_3[] = {
B00000, B00000, B00000, B00000, B10000, B11100, B11110, B11111
};
byte fragm_4[] = {
B11111, B01111, B00111, B00001, B00000, B00000, B00000, B00000
};
byte fragm_5[] = {
B11111, B11111, B11111, B11111, B00000, B00000, B00000, B00000
};
byte fragm_6[] = {
B11111, B11110, B11100, B10000, B00000, B00000, B00000, B00000
};
byte fragm_7[] = {
B11111, B11111, B11111, B11111, B11111, B01111, B00111, B00001
};
byte fragm_8[] = {
B11111, B11111, B11111, B11111, B11111, B11110, B11100, B10000
};
 struct { 
    byte *bitmap;
  }
 fragm_1_8[]={fragm_1,fragm_2,
              fragm_3,fragm_4,
              fragm_5,fragm_6,
              fragm_7,fragm_8,
              };
  byte perehodnik[]={0x00,0x01,0x02,0xFF,0x00,0xFF,0xFF,0x05,0xFF,0x03,0x04,0x05,    //0
                     0x00,0x01,0x8E,0x05,0xFF,0x8E,0x8E,0xFF,0x8E,0x8E,0x04,0x8E,    //1
                     0x00,0x01,0x02, 0x04,0x00,0x07,0xFF,0x05,0x8E,0x04,0x04,0x04,   //2 
                     0x00,0x01,0x02,0x04,0x00,0x07,0x01,0x03,0xFF,0x03,0x04,0x05,    //3
                     0x00,0x8E,0x01,0xFF,0x8E,0xFF,0x04,0x04,0xFF,0x8E,0x8E,0x04,    //4
                     0x01,0x01,0x01,0x06,0x01,0x02,0x01,0x8E,0xFF,0x03,0x04,0x05,    //5
                     0x00,0x01,0x02,0xFF,0x01,0x02,0xFF,0x8E,0xFF,0x03,0x04,0x05,    //6
                     0x01,0x01,0x01,0x8E,0x00,0x07,0xFF,0x05,0x8E,0x04,0x8E,0x8E,    //7
                     0x00,0x01,0x02,0x06,0x01,0x07,0xFF,0x8E,0xFF,0x03,0x04,0x05,    //8
                     0x00,0x01,0x02,0x06,0x01,0xFF,0x8E,0x8E,0xFF,0x03,0x04,0x05,    //9
                     };             
 int R=50;//
 int G=25;//
 int B=50;//

int tschas=10;//
int minuta=37;//
int sekundi=0;//  
void setup() {
lcd.init();
strip.begin();
for(int i=0;i<20;i++){
      //варианты подсветки
        strip.setPixelColor(18+i,R,G,B);
        strip.setPixelColor(45+i,R,G,B);
        }
       strip.show();
 
 for(byte i=0;i<8;i++){
 lcd.createChar(i,fragm_1_8[i].bitmap );
 
  }
lcd.setCursor(6, 1); lcd.print('.'); lcd.setCursor(6, 2); lcd.print('.'); lcd.setCursor(13, 1); lcd.print('.'); lcd.setCursor(13, 2); lcd.print('.');//двоеточия
}

void loop() {
  
sekundi++;
if(sekundi>=60||sekundi<0){sekundi=0;minuta++;}
if(minuta>=60||minuta<0){minuta=0;tschas++;}
if(tschas>=24||tschas<0){tschas=0;}
zifra(tschas/10,0);//
zifra(tschas%10,3);//
zifra(minuta/10,7);//
zifra(minuta%10,10);//
zifra(sekundi/10,14);//
zifra(sekundi%10,17);//
delay(1000);//подбор опытным путём

}
///////////////////////
void zifra(byte zif,byte poz){// функция вывода цифры по позиции
lcd.setCursor(poz, 0);
lcd.write(perehodnik[12*zif]);
lcd.setCursor(poz+1, 0);
lcd.write(perehodnik[12*zif+1]);
lcd.setCursor(poz+2, 0);
lcd.write(perehodnik[12*zif+2]);
//
lcd.setCursor(poz, 1);
lcd.write(perehodnik[12*zif+3]);
lcd.setCursor(poz+1, 1);
lcd.write(perehodnik[12*zif+4]);
lcd.setCursor(poz+2, 1);
lcd.write(perehodnik[12*zif+5]);
// 
lcd.setCursor(poz, 2);
lcd.write(perehodnik[12*zif+6]);
lcd.setCursor(poz+1, 2);
lcd.write(perehodnik[12*zif+7]);
lcd.setCursor(poz+2, 2);
lcd.write(perehodnik[12*zif+8]); 
//
lcd.setCursor(poz, 3);
lcd.write(perehodnik[12*zif+9]);
lcd.setCursor(poz+1, 3);
lcd.write(perehodnik[12*zif+10]);
lcd.setCursor(poz+2, 3);
lcd.write(perehodnik[12*zif+11]); 
}
///////////////////////
void text_rus(String source,int poz,byte str)// текст-строка,позиция,строка
{
  
  int i,k;
 // String target;
  unsigned char n;
  k = source.length(); i = 0;

  while (i < k) {
   
    n = source[i]; i++;
    
     if(n<128){if(poz>=0&&poz<20){lcd.setCursor(poz, str);lcd.write(n);}poz++;}//печатаем английские символы
     
    if (n >= 0xC0) {//192 пошли наши буквы
      switch (n) {
        case 0xD0: {//208
          n = source[i]; i++;
          if (n == 0x81) {if(poz>=0&&poz<20){lcd.setCursor(poz, str);lcd.write(utf_recode[64]);}poz++; break; }//129 Ё
          if (n >= 0x90 && n <= 0xBF) {if(poz>=0&&poz<20){lcd.setCursor(poz, str);lcd.write(utf_recode[n-128]);}poz++; break;}//144-191
          break; 
         }
        case 0xD1: {//209
          n = source[i]; i++;
          if (n == 0x91) {if(poz>=0&&poz<20) {lcd.setCursor(poz, str);lcd.write(utf_recode[65]);}poz++; break; }//145 ё
          if (n >= 0x80 && n <= 0x8F){if(poz>=0&&poz<20){lcd.setCursor(poz, str);lcd.write(utf_recode[n-128]);}poz++; break;}//128-143 
          break;
        }
      }
    
  }
 
  } 
}
////////////////////////////////////////////////////////////
// Вместо 0x8E используйте 0x20 (пробел) или 0x00
// Вместо 0xFF используйте другие значения в диапазоне 0-7 для пользовательских символов
#include <Wire.h>
#include "LiquidCrystal_I2C.h"
#include "Adafruit_NeoPixel.h"

#define line_ 66 //число пикселей в ленте
uint8_t dataPin = 6;// вывод для подключения
Adafruit_NeoPixel strip = Adafruit_NeoPixel(line_,dataPin , NEO_GRB + NEO_KHZ800);// Создаем переменную strip для управления нашей лентой.

LiquidCrystal_I2C lcd(0x27,20,4);
const char utf_recode[]=
       { 0x70,0x63,0xbf,0x79,0xe4,0x78,0xe5,0xc0,0xc1,0xe6,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7, //р....я
         0x41,0xa0,0x42,0xa1,0xe0,0x45,0xa3,0xa4,0xa5,0xa6,0x4b,0xa7,0x4d,0x48,0x4f,        //АБВГДЕЖЗИЙКЛМНО
         0xa8,0x50,0x43,0x54,0xa9,0xaa,0x58,0xe1,0xab,0xac,0xe2,0xad,0xae,0x62,0xaf,0xb0,0xb1,//П....Я
         0x61,0xb2,0xb3,0xb4,0xe3,0x65,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0x6f,0xbe, //а......п
         0xa2,0xb5                                                                        //Ёё   
       }; 
byte fragm_1[] = {
B00000, B00000, B00000, B00000, B00001, B00111, B01111, B11111
};
byte fragm_2[] = {
B00000, B00000, B00000, B00000, B11111, B11111, B11111, B11111
};
byte fragm_3[] = {
B00000, B00000, B00000, B00000, B10000, B11100, B11110, B11111
};
byte fragm_4[] = {
B11111, B01111, B00111, B00001, B00000, B00000, B00000, B00000
};
byte fragm_5[] = {
B11111, B11111, B11111, B11111, B00000, B00000, B00000, B00000
};
byte fragm_6[] = {
B11111, B11110, B11100, B10000, B00000, B00000, B00000, B00000
};
byte fragm_7[] = {
B11111, B11111, B11111, B11111, B11111, B01111, B00111, B00001
};
byte fragm_8[] = {
B11111, B11111, B11111, B11111, B11111, B11110, B11100, B10000
};
 struct { 
    byte *bitmap;
  }
 fragm_1_8[]={fragm_1,fragm_2,
              fragm_3,fragm_4,
              fragm_5,fragm_6,
              fragm_7,fragm_8,
              };
              
// Исправленный массив - заменены 0x8E и 0xFF на 0x20 (пробел)
byte perehodnik[]={
  0x00,0x01,0x02,0x20,0x00,0x20,0x20,0x05,0x20,0x03,0x04,0x05,    //0
  0x00,0x01,0x20,0x05,0x20,0x20,0x20,0x20,0x20,0x20,0x04,0x20,    //1
  0x00,0x01,0x02,0x04,0x00,0x07,0x20,0x05,0x20,0x04,0x04,0x04,   //2
  0x00,0x01,0x02,0x04,0x00,0x07,0x01,0x03,0x20,0x03,0x04,0x05,    //3
  0x00,0x20,0x01,0x20,0x20,0x20,0x04,0x04,0x20,0x20,0x20,0x04,    //4
  0x01,0x01,0x01,0x06,0x01,0x02,0x01,0x20,0x20,0x03,0x04,0x05,    //5
  0x00,0x01,0x02,0x20,0x01,0x02,0x20,0x20,0x20,0x03,0x04,0x05,    //6
  0x01,0x01,0x01,0x20,0x00,0x07,0x20,0x05,0x20,0x04,0x20,0x20,    //7
  0x00,0x01,0x02,0x06,0x01,0x07,0x20,0x20,0x20,0x03,0x04,0x05,    //8
  0x00,0x01,0x02,0x06,0x01,0x20,0x20,0x20,0x20,0x03,0x04,0x05,    //9
};             
 int R=50;//
 int G=25;//
 int B=50;//

int tschas=10;//
int minuta=37;//
int sekundi=0;//  

void setup() {
  lcd.init();
  lcd.backlight();
  
  strip.begin();
  for(int i=0;i<20;i++){
    //варианты подсветки
    strip.setPixelColor(18+i,R,G,B);
    strip.setPixelColor(45+i,R,G,B);
  }
  strip.show();
 
  for(byte i=0;i<8;i++){
    lcd.createChar(i,fragm_1_8[i].bitmap );
  }
  
  lcd.setCursor(6, 1); lcd.print('.'); 
  lcd.setCursor(6, 2); lcd.print('.'); 
  lcd.setCursor(13, 1); lcd.print('.'); 
  lcd.setCursor(13, 2); lcd.print('.');//двоеточия
}

void loop() {
  sekundi++;
  if(sekundi>=60||sekundi<0){sekundi=0;minuta++;}
  if(minuta>=60||minuta<0){minuta=0;tschas++;}
  if(tschas>=24||tschas<0){tschas=0;}
  
  zifra(tschas/10,0);//
  zifra(tschas%10,3);//
  zifra(minuta/10,7);//
  zifra(minuta%10,10);//
  zifra(sekundi/10,14);//
  zifra(sekundi%10,17);//
  
  delay(1000);//подбор опытным путём
}

///////////////////////
void zifra(byte zif,byte poz){// функция вывода цифры по позиции
  lcd.setCursor(poz, 0);
  lcd.write(perehodnik[12*zif]);
  lcd.setCursor(poz+1, 0);
  lcd.write(perehodnik[12*zif+1]);
  lcd.setCursor(poz+2, 0);
  lcd.write(perehodnik[12*zif+2]);
  //
  lcd.setCursor(poz, 1);
  lcd.write(perehodnik[12*zif+3]);
  lcd.setCursor(poz+1, 1);
  lcd.write(perehodnik[12*zif+4]);
  lcd.setCursor(poz+2, 1);
  lcd.write(perehodnik[12*zif+5]);
  // 
  lcd.setCursor(poz, 2);
  lcd.write(perehodnik[12*zif+6]);
  lcd.setCursor(poz+1, 2);
  lcd.write(perehodnik[12*zif+7]);
  lcd.setCursor(poz+2, 2);
  lcd.write(perehodnik[12*zif+8]); 
  //
  lcd.setCursor(poz, 3);
  lcd.write(perehodnik[12*zif+9]);
  lcd.setCursor(poz+1, 3);
  lcd.write(perehodnik[12*zif+10]);
  lcd.setCursor(poz+2, 3);
  lcd.write(perehodnik[12*zif+11]); 
}
///////////////////////
void text_rus(String source,int poz,byte str)// текст-строка,позиция,строка
{
  int i,k;
  unsigned char n;
  k = source.length(); i = 0;

  while (i < k) {
    n = source[i]; i++;
    
    if(n<128){
      if(poz>=0&&poz<20){
        lcd.setCursor(poz, str);
        lcd.write(n);
      }
      poz++;
    }//печатаем английские символы
     
    if (n >= 0xC0) {//192 пошли наши буквы
      switch (n) {
        case 0xD0: {//208
          n = source[i]; i++;
          if (n == 0x81) {
            if(poz>=0&&poz<20){
              lcd.setCursor(poz, str);
              lcd.write(utf_recode[64]);
            }
            poz++; 
            break; 
          }//129 Ё
          if (n >= 0x90 && n <= 0xBF) {
            if(poz>=0&&poz<20){
              lcd.setCursor(poz, str);
              lcd.write(utf_recode[n-128]);
            }
            poz++; 
            break;
          }//144-191
          break; 
        }
        case 0xD1: {//209
          n = source[i]; i++;
          if (n == 0x91) {
            if(poz>=0&&poz<20) {
              lcd.setCursor(poz, str);
              lcd.write(utf_recode[65]);
            }
            poz++; 
            break; 
          }//145 ё
          if (n >= 0x80 && n <= 0x8F){
            if(poz>=0&&poz<20){
              lcd.setCursor(poz, str);
              lcd.write(utf_recode[n-128]);
            }
            poz++; 
            break;
          }//128-143 
          break;
        }
      }
    }
  } 
}

сомневаюсь что ии справился, но вот по быстрому, может поможет
Основные изменения:

  1. Заменены все 0x8E и 0xFF на 0x20 (пробел) в массиве perehodnik

  2. Сохранил пользовательские символы 0x00-0x07 без изменений

  3. Добавил lcd.backlight() в setup для включения подсветки

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

Эх, если б вы с ИИ ещё и понимали, что делаете, цены б вам не было :slight_smile:

Не поможет ИИ, тут явно аксиома, я уже писал - ИИ может ровно столько, сколько может вопрошающий :slight_smile:

А с чем он справиться должен был?

ну естественно, ии могут пользоваться только те кто обучился, хотя иногда он выдает решения некоторым и без знаний, но это редкость, скоро наверное он заменит программистов, но это скоро будет не скоро)))
я просил его заменить 1 адрес и 1 символ на пробел… не в том файле, а в коде сделать замену
кстати встречаю все больше таких вакансий https://hh.ru/vacancy/126794177 правда там написано не понятно как, то ли они воротят нос от сеньоров, толи им нужны сеньоры, которые будут писать через ии, и получать оплату едой))) я так и не понял их)))

Необязательно работать по профессии. У нас в выпуске примерно больше половины так и не стали учителями :slight_smile: Здесь как в известном анекдоте , попал - гордись, не попал-радуйся. Я не понимаю маниакальное стремление быть программистом. Это не самодостаточная профессия, она зыбкая как песок во времени и обстоятельствах, а учитель как могильщик - это навсегда :slight_smile:

Ну тогда ладно.

видимо это, капитализм же

а что он там ? совсем совсем накосячил ?)))) я просто не вник в ваш код… возможно не смог описать проблему…

в жизни и так мало смысла, а тут можно что то творить, меня вроде это радует, а вот учить других не осилю чисто психологически))) еще есть врачи, которые могут оказаться не нужны и пойдут продавцами в аптеку, все 3 профессии такие же затратные и не окупаемые хобби))) разница только в том что программистов надо больше…

Так нет уже проблемы. А ИИ не понимает по коду ничего. Вот спросите у него, что означают массивы в данном скетче :slight_smile:

…или проще попросить дать комментарии к каждой строке.

в том смысле что ИИ можно бить ногой ниже пояса )

  1. Проблемные значения 0x8E и 0xFF в массиве perehodnik

  2. Отсутствует очистка экрана перед обновлением цифр

  3. Двоеточия рисуются каждый раз в loop, что вызывает мерцание
    вот просьба вникнуть в код повнимательнее, без указания причин, и того что надо исправить

#include <Wire.h>
#include "LiquidCrystal_I2C.h"
#include "Adafruit_NeoPixel.h"

#define line_ 66 //число пикселей в ленте
uint8_t dataPin = 6;// вывод для подключения
Adafruit_NeoPixel strip = Adafruit_NeoPixel(line_,dataPin , NEO_GRB + NEO_KHZ800);// Создаем переменную strip для управления нашей лентой.

LiquidCrystal_I2C lcd(0x27,20,4);

// Графические элементы для больших цифр 3x4
byte fragm_1[] = {B00000, B00000, B00000, B00000, B00001, B00111, B01111, B11111};
byte fragm_2[] = {B00000, B00000, B00000, B00000, B11111, B11111, B11111, B11111};
byte fragm_3[] = {B00000, B00000, B00000, B00000, B10000, B11100, B11110, B11111};
byte fragm_4[] = {B11111, B01111, B00111, B00001, B00000, B00000, B00000, B00000};
byte fragm_5[] = {B11111, B11111, B11111, B11111, B00000, B00000, B00000, B00000};
byte fragm_6[] = {B11111, B11110, B11100, B10000, B00000, B00000, B00000, B00000};
byte fragm_7[] = {B11111, B11111, B11111, B11111, B11111, B01111, B00111, B00001};
byte fragm_8[] = {B11111, B11111, B11111, B11111, B11111, B11110, B11100, B10000};

struct { 
    byte *bitmap;
} fragm_1_8[] = {
    fragm_1, fragm_2, fragm_3, fragm_4, 
    fragm_5, fragm_6, fragm_7, fragm_8
};

// ИСПРАВЛЕННЫЙ массив - заменены 0x8E и 0xFF на 0x20 (пробел)
byte perehodnik[] = {
    // Цифра 0
    0x00,0x01,0x02,0x20,0x00,0x20,0x20,0x05,0x20,0x03,0x04,0x05,
    // Цифра 1  
    0x00,0x01,0x20,0x05,0x20,0x20,0x20,0x20,0x20,0x20,0x04,0x20,
    // Цифра 2
    0x00,0x01,0x02,0x04,0x00,0x07,0x20,0x05,0x20,0x04,0x04,0x04,
    // Цифра 3
    0x00,0x01,0x02,0x04,0x00,0x07,0x01,0x03,0x20,0x03,0x04,0x05,
    // Цифра 4
    0x00,0x20,0x01,0x20,0x20,0x20,0x04,0x04,0x20,0x20,0x20,0x04,
    // Цифра 5
    0x01,0x01,0x01,0x06,0x01,0x02,0x01,0x20,0x20,0x03,0x04,0x05,
    // Цифра 6
    0x00,0x01,0x02,0x20,0x01,0x02,0x20,0x20,0x20,0x03,0x04,0x05,
    // Цифра 7
    0x01,0x01,0x01,0x20,0x00,0x07,0x20,0x05,0x20,0x04,0x20,0x20,
    // Цифра 8
    0x00,0x01,0x02,0x06,0x01,0x07,0x20,0x20,0x20,0x03,0x04,0x05,
    // Цифра 9
    0x00,0x01,0x02,0x06,0x01,0x20,0x20,0x20,0x20,0x03,0x04,0x05
};

int R=50, G=25, B=50;
int tschas=10, minuta=37, sekundi=0;

void setup() {
    lcd.init();
    lcd.backlight();
    lcd.clear(); // ОЧИСТКА ЭКРАНА при запуске
    
    // Инициализация подсветки
    strip.begin();
    for(int i=0; i<20; i++){
        strip.setPixelColor(18+i, R, G, B);
        strip.setPixelColor(45+i, R, G, B);
    }
    strip.show();
    
    // Создание пользовательских символов
    for(byte i=0; i<8; i++){
        lcd.createChar(i, fragm_1_8[i].bitmap);
    }
    
    // Отрисовка статических элементов (двоеточия) ОДИН РАЗ в setup
    lcd.setCursor(6, 1); lcd.print('.');
    lcd.setCursor(6, 2); lcd.print('.');
    lcd.setCursor(13, 1); lcd.print('.');
    lcd.setCursor(13, 2); lcd.print('.');
}

void loop() {
    // Обновление времени
    sekundi++;
    if(sekundi >= 60) { sekundi = 0; minuta++; }
    if(minuta >= 60) { minuta = 0; tschas++; }
    if(tschas >= 24) { tschas = 0; }
    
    // Отрисовка ВСЕХ цифр каждый раз
    zifra(tschas/10, 0);
    zifra(tschas%10, 3);
    zifra(minuta/10, 7);
    zifra(minuta%10, 10);
    zifra(sekundi/10, 14);
    zifra(sekundi%10, 17);
    
    delay(1000);
}

// Функция вывода цифры
void zifra(byte zif, byte poz) {
    // Верхняя строка
    lcd.setCursor(poz, 0); lcd.write(perehodnik[12*zif]);
    lcd.setCursor(poz+1, 0); lcd.write(perehodnik[12*zif+1]);
    lcd.setCursor(poz+2, 0); lcd.write(perehodnik[12*zif+2]);
    
    // Вторая строка
    lcd.setCursor(poz, 1); lcd.write(perehodnik[12*zif+3]);
    lcd.setCursor(poz+1, 1); lcd.write(perehodnik[12*zif+4]);
    lcd.setCursor(poz+2, 1); lcd.write(perehodnik[12*zif+5]);
    
    // Третья строка
    lcd.setCursor(poz, 2); lcd.write(perehodnik[12*zif+6]);
    lcd.setCursor(poz+1, 2); lcd.write(perehodnik[12*zif+7]);
    lcd.setCursor(poz+2, 2); lcd.write(perehodnik[12*zif+8]);
    
    // Нижняя строка
    lcd.setCursor(poz, 3); lcd.write(perehodnik[12*zif+9]);
    lcd.setCursor(poz+1, 3); lcd.write(perehodnik[12*zif+10]);
    lcd.setCursor(poz+2, 3); lcd.write(perehodnik[12*zif+11]);
}

иначе надо много времени тратить))) объясняя каждый пункт что не так… не исключенно что каждый раз надо напоминать что всего символов своих можно сделать 8 штук… и за 10-20 обращений можно получить ответ, но надо вникать в суть, а я пытаюсь быстро получить ответ, почти нечего не делая)))

Похвально, а если ещё и делать, ну хотя бы проверять на практике, то ах, как здорово.

…вот тоже у ИИ выклянчил функцию перевода времени из чисел в текст и добавил к бегущей строке.

…с 3 раза получилось вроде правильно, с падежами и т.д.

Вариант цифр по ассоциации, а не по числу углов.

:slight_smile:

Очень удобный вариант часов, посмотрел…и забыл, что хотел.

может просто в двоичном виде получать время ?))) такие часы даже видел в продаже, наручные

Лилик, коль тема про часы (как я понял) и разные варианты их отображения, не задумывался ли ты…
Тут сразу извиняюсь, если не в тему!
Какой вариант отображения часов лучше бы подошел для «электронной бумаги»? Чтобы на по дольше хватило, ведь (на сколько я знаю) число перезаписи элементов там ограничено сильно…