GyverTM1637, вопросы по библиотеке

dorogoy

✩✩✩✩✩✩✩
7 Июн 2020
28
3
Здравствуйте. Есть библиотека для TM1637 GyverTM1637. Все в ней хорошо но не умеет она получать данные от нажатия кнопок на этой микросхеме. Сама микросхема поддерживает аж 16 кнопок с защитой от дребезга. Это отлично реализованно в библиотеке ErriezTM1637. Может есть у кого нибудь опыт переноса функций из одной библиотеки в другую. Сейчас приходится подключать 2 библиотеки одна показывает, вторая кнопки читает. https://github.com/Erriez/ErriezTM1637

от себя могу добавить куда подпаиваться и какие значения получаем функцией tm1637.getKeys();


K2 (20 pin 1637)
индикатор (pin) знач
1------------------------------12
2------------------------------11
3------------------------------15
4------------------------------10
5------------------------------14
6----
7------------------------------9
8----
9----
10------------------------------13
11------------------------------8
12---

K1 (19 pin 1637)
индикатор (pin ) знач
1------------------------------4
2------------------------------3
3------------------------------7
4------------------------------2
5------------------------------6
6----
7------------------------------1
8----
9----
10------------------------------5
11------------------------------0
12---
 
Изменено:

dorogoy

✩✩✩✩✩✩✩
7 Июн 2020
28
3
Есть где нить доки почитать как это делается. Или может это вообще делов на 30 секунд закопипастить.. getKeys из ErriezTM1637 в GyverTM1637
 

Эдуард Анисимов

★★★★★★✩
23 Сен 2019
2,407
976
58
Марий-Эл
 

Вложения

dorogoy

✩✩✩✩✩✩✩
7 Июн 2020
28
3
писать библиотеки сложно для меня пока, там уже объекты идут. буду 2 использовать.
 

kalobyte

★★★✩✩✩✩
1 Янв 2020
724
148
объект это на 95% просто набор тех же функций, просто организован в удобный пакет-обертку
это если так просто объяснить суть класса и объекта
к тому же у тебя класс уже готовый, тебе и надо скопипастить готовые функции
 

dorogoy

✩✩✩✩✩✩✩
7 Июн 2020
28
3
Сделал я модификацию библиотеки теперь работает функция getKeys(); возвращает нажатые кнопки
Куда подпаиватся нарисованно на схеме. Потдерживается 16 кнопок. Можно освободить пины контроллера для чего нибудь более нужного.


#define CLK 2
#define DIO 3

#include "GyverTM1637.h"
GyverTM1637 disp(CLK, DIO);

static uint8_t keysLast = 0;


void setup()
{
Serial.begin(19200);
// while (!Serial) {
;
// }
// Serial.println(F("TM1637 example"));

// Initialize TM1637
disp.clear();
disp.brightness(7); // яркость, 0 - 7 (минимум - максимум)

}

void loop()
{
uint8_t keys;

// Read 8-bit keys
keys = disp.getKeys();

// Check key down
if (keys != 255) {


Serial.print(F("Keys: "));
Serial.println(keys);

}
}
 

Вложения

Изменено:

Mix_man

✩✩✩✩✩✩✩
21 Янв 2020
91
9
@dorogoy, Отлично сработано 🤜🤛
Только я не понял кнопки по какому принципу подключены?
Впервом посте это что за цифры?
 

dorogoy

✩✩✩✩✩✩✩
7 Июн 2020
28
3
Лучше и понятнее нарисовано в daеsheet в 4 сообщении, а в таблице вот что. На микросхеме есть контакты K1,K2 они на плату не выведены поэтому придется подпаиваться прямо к микросхеме. А вот контакты SG1...SG8 выведенные на ноги индикатора . Ноги подписанны 1-12. Тоесть припаиваем 1 провод K1, второй к ноге индикатора 1 и ставим кнопку. К контактам индикатора 6,8,9,12 подпаиваться нельзя. При вызове getKeys(); ; получаем 4(значение из таблицы) . Если 1 провод К2 второй к ноге индикатора 1 getKeys(); вернет 12(значение из таблицы). И так можно подпаять 16 кнопок .Надеюсь понятно написал. Если есть вопросы пишите. Конструкция if (keys != 255) в примере применяется потому что если ни одна кнопка не нажата всегда аозвращается значение 255схема.jpg
 
Изменено:
  • Лойс +1
Реакции: Mix_man и MrBob

Gallis

✩✩✩✩✩✩✩
17 Сен 2020
5
0
Вывожу время на дисплей с анимацией
Но на часах если число одно то перед цифрой он 0 не ставит
1600721360339.png

Вот прошивка 1600721431813.png
Как это исправить?
 

Вложения

Старик Похабыч

★★★★★★★
14 Авг 2019
4,263
1,301
Москва
На сколько я понимаю, автором библиотеки не предусмотрен вывод лидирующего нуля.
Но что мешает это сделать самому ?
disp.display(0, 0);
 

AlexGyver

★★★★★★✩
Команда форума
30 Июл 2018
359
573
@Gallis, часы лучше выглядят без нуля слева, так задумано) в принципе можно залезть в библу и исправить, там вроде бы всё очень просто сделано
 
  • Лойс +1
Реакции: Старик Похабыч

Эдуард Анисимов

★★★★★★✩
23 Сен 2019
2,407
976
58
Марий-Эл
Если часы меньше 10, то выводим дополнительно-принудительно лидирующий 0
Если у минут лидирующий ноль не пропадает смотри как там это сделано и повтори для часов.
 

EREME1

✩✩✩✩✩✩✩
18 Май 2022
8
0
Решил сделать приблуду из видео "Рисую светом! Голограмма своими руками"
Собрал схему, прошил, но вышла проблема. При подключенном дисплее TM1637 схема не работает, как только отключаю - все нормально. Компилируется и прошивается без проблем, кроме одной, пишет:


C:\Users\serge\Documents\Arduino\libraries\TM1637_Gyver\TM1637.cpp: In member function 'void TM1637::displayByte(uint8_t, int8_t, int8_t, int8_t)':
C:\Users\serge\Documents\Arduino\libraries\TM1637_Gyver\TM1637.cpp:132:46: warning: narrowing conversion of 'bit1' from 'uint8_t {aka unsigned char}' to 'int8_t {aka signed char}' inside { } [-Wnarrowing]
int8_t SegData[4] = {bit1, bit2, bit3, bit4};
^
C:\Users\serge\Documents\Arduino\libraries\TM1637_Gyver\TM1637.cpp: In member function 'void TM1637::displayIntZero(int)':
C:\Users\serge\Documents\Arduino\libraries\TM1637_Gyver\TM1637.cpp:156:39: warning: narrowing conversion of 'n4' from 'int' to 'int8_t {aka signed char}' inside { } [-Wnarrowing]
int8_t DispData[4] = {n4, n3, n2, n1};
^
C:\Users\serge\Documents\Arduino\libraries\TM1637_Gyver\TM1637.cpp:156:39: warning: narrowing conversion of 'n3' from 'int' to 'int8_t {aka signed char}' inside { } [-Wnarrowing]
C:\Users\serge\Documents\Arduino\libraries\TM1637_Gyver\TM1637.cpp:156:39: warning: narrowing conversion of 'n2' from 'int' to 'int8_t {aka signed char}' inside { } [-Wnarrowing]
C:\Users\serge\Documents\Arduino\libraries\TM1637_Gyver\TM1637.cpp:156:39: warning: narrowing conversion of 'n1' from 'int' to 'int8_t {aka signed char}' inside { } [-Wnarrowing]
Скетч использует 18878 байт (61%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 1435 байт (70%) динамической памяти, оставляя 613 байт для локальных переменных. Максимум: 2048 байт.


Все файлы брал со страницы проекта
 

PiratFox

★★★★★✩✩
13 Фев 2020
1,706
474
@EREME1, объявите переменные n1, n2, n3 как однобайтовые, с типом uint8_t или byte. Это не ошибка библиотеки, как Вы думаете, это ошибка в Вашем коде при объявлении переменных.
P.S. Не нужно создавать на форуме 2 темы в разных ветках по одному и тому же вопросу. Такое наказуемо.
 
Изменено:
  • Лойс +1
Реакции: EREME1

EREME1

✩✩✩✩✩✩✩
18 Май 2022
8
0
Было объявлено подобным образом:

uint8_t b, startupTrigger, minBrightness;
char infile[13], outfile[13];
boolean found;
uint16_t i, n;
SdFile tmp;
uint32_t lastBlock;

Я перенес n из uint_16 в uint_8, а так же в byte, т.е.:

uint8_t n, b, startupTrigger, minBrightness;
или
byte n;

но не помогло. Компиляция теперь без ошибки, но схема не работает
 
Изменено:

PiratFox

★★★★★✩✩
13 Фев 2020
1,706
474
Компиляция теперь без ошибки, но схема не работает
Значит, накосячили при монтаже или какие-то модули битые. Опять же, не исключены ошибки в скетче. Например, логические. Компиллер на такие материться не будет. Телепатов и ясновидцев тут нету, выложите скетч. Гадать никто не будет.
 
  • Лойс +1
Реакции: EREME1

EREME1

✩✩✩✩✩✩✩
18 Май 2022
8
0
@PiratFox,
C++:
/*
   РАСШИФРОВКА НАДПИСЕЙ НА ДИСПЛЕЕ:
   Strt - (Start) начало работы, инициализация SD карты. Эту надпись можно успеть
   прочитать только при запуске в режиме загрузки
   PreP - (Perparing) подготовка к преобразованию изображений
   LOAd - (Loading) преобразование и загрузка изображений
   read - (Reading) чтение преобразованных изображений с карты
   rdy  - (Ready) готов к работе
   Proc - (Processing) показываем анимацию

   НАСТРОЙКИ:
   Br** - (Brightness) настройка яркости (в процентах, 10-95)
   Fr** - (Frame) номер изображения, которое будет показано при нажатии на кнопку
   SP** - (Speed) скорость анимации (в процентах, 0-95)

   ОШИБКИ:
   Sder - (SD error) ошибка подключения SD карты (карта не подключена, карта сломана, карта не подходит)
   FrEr - (Frame Error) ошибка при чтении картинки. Возникает на разных стадиях, подробнее видно с компьютера
   Ferr - (Fatal error) критическая ошибка, работа остановлена. Возникает на разных стадиях, подробнее видно с компьютера
*/

// ------------------------------ НАСТРОЙКИ ------------------------------
#define N_LEDS       144    // количество светодиодов (максимум 170 !!!)
#define FLIP_H 0            // зеркально отражать изображения по горизонтали
#define CURRENT_MAX 2000    // максимальный ток (авто-ограничение по расчёту яркости)
#define DEBUG 0             // отправка информации в порт, 1-вкл, 0-выкл
#define ENC_TYPE 1            // тип энкодера (1 и 0) если двоит/мельчит, смени тип
// ПРИ ВЫКЛЮЧЕННОМ DEBUG СИСТЕМА РАБОТАЕТ ГОРАЗДО БЫСТРЕЕ!!
// ------------------------------ НАСТРОЙКИ ------------------------------

// ----------------------- ПОДКЛЮЧЕНИЕ -----------------------
#define TRIGGER 2  // кнопка запуска анимации

#define CLK_ENC 3  // ПИН CLK ЭНКОДЕРА
#define DT_ENC 4   // ПИН DT ЭНКОДЕРА
// CLK и DT можно менять местами, чтобы инвертировать направление

#define SW_ENC 5   // ПИН SW ЭНКОДЕРА

#define DIO 6      // ДИСПЛЕЙ
#define CLK 7      // ДИСПЛЕЙ

#define LED_PIN 8  // пин DIN ленты

// SD card module: CLK (SCK) -> D13, MOSI -> D11, MISO -> D12, CS -> D10
#define CARD_SELECT   10    // CS пин карты
// ----------------------- ПОДКЛЮЧЕНИЕ -----------------------

// ---- БИБЛИОТЕКИ ----
#include <SdFat.h>
#include <avr/pgmspace.h>
#include "./gamma.h"
#include "TM1637.h"
#include "EEPROMex.h"
TM1637 tm1637(CLK, DIO);
// ---- БИБЛИОТЕКИ ----

// ----------------------- ДЛЯ РАЗРАБОТЧИКОВ ----------------------
byte NORM_STEP = 1;   // шаг изменения переменной norm_counter при вращении
#define HOLD_STEP 5   // шаг изменения переменной hold_counter при нажатии, удерживании и вращении

#define OVERHEAD 150 // Extra microseconds for loop processing, etc.
uint8_t           sdBuf[512],  // One SD block (also for NeoPixel color data)
                  pinMask;     // NeoPixel pin bitmask
uint16_t          maxLPS,      // Max playback lines/sec
                  nFrames = 0, // Total # of image files
                  frame   = 0; // Current image # being painted
uint32_t          firstBlock,  // First block # in temp working file
                  nBlocks;     // Number of blocks in file
SdFat             sd;          // SD filesystem
volatile uint8_t *port;        // NeoPixel PORT register
boolean bmpProcess(char *inName, char *outName, uint8_t *brightness);

uint32_t block    = 0;     // Current block # within file
boolean  stopFlag = false; // If set, stop playback loop
uint32_t lastBlock;
char     infile[13];
SdFile   tmp;

char norm_counter, hold_counter;
boolean DT_now, DT_last, SW_state, turn_flag, SWstate, SWlast;
byte anim_speed;
// ----------------------- ДЛЯ РАЗРАБОТЧИКОВ -----------------------

void setup() {
  Serial.begin(57600);
  if (EEPROM.read(0) != 1) {  // если это САМЫЙ ПЕРВЫЙ запуск
    EEPROM.write(0, 1);       // запомнить, что первый запуск был
    EEPROM.writeByte(1, 50);      // ячейка 1 - яркость (по умолчанию)
    EEPROM.writeByte(3, 50);      // ячейка 3 - скорость (по умолчанию)
    if (DEBUG) Serial.println("first");
    norm_counter = 50;
    anim_speed = 50;
  } else {
    norm_counter = EEPROM.readByte(1);  // читаем яркость
    anim_speed = EEPROM.readByte(3);    // читаем скорость
  }

  tm1637.init();  // инициализация
  tm1637.set(BRIGHT_TYPICAL);  // яркость, 0 - 7 (минимум - максимум)
  tm1637.displayByte(_S, _t, _r, _t);

  pinMode(CLK_ENC, INPUT);
  pinMode(DT_ENC, INPUT);
  pinMode(SW_ENC, INPUT_PULLUP);
  DT_last = digitalRead(CLK);

  uint8_t  n, b, startupTrigger, minBrightness;
  char     infile[13], outfile[13];
  boolean  found;
  uint16_t i;
  SdFile   tmp;
  uint32_t lastBlock;

  pinMode(TRIGGER, INPUT_PULLUP);        // Enable pullup on trigger button
  startupTrigger = digitalRead(SW_ENC);      // Poll startup trigger ASAP

  pinMode(LED_PIN, OUTPUT);              // Enable NeoPixel output
  digitalWrite(LED_PIN, LOW);            // Default logic state = low
  port    = portOutputRegister(digitalPinToPort(LED_PIN));
  pinMask = digitalPinToBitMask(LED_PIN);
  memset(sdBuf, 0, N_LEDS * 3);          // Clear LED buffer
  show();                                // Init LEDs to 'off' state

  if (DEBUG) Serial.print(F("Initializing SD card..."));
  if (!sd.begin(CARD_SELECT, SPI_FULL_SPEED)) {
    tm1637.displayByte(_S, _d, _e, _r);  // надпись Sder
    error(F("failed. Things to check:\n"
            "* is a card is inserted?\n"
            "* Is your wiring correct?\n"
            "* did you edit CARD_SELECT to match the SD shield or module?"));
  }
  if (DEBUG) Serial.println(F("OK"));

#if 0
  if (!volume.init(&card)) {
    tm1637.displayByte(_S, _d, _e, _r);  // надпись Sder
    error(F("Could not find FAT16/FAT32 partition.\n"
            "Make sure the card is formatted."));
  }
  root.openRoot(&volume);
#endif
  if (startupTrigger == LOW) { // если при запуске кнопка НАЖАТА
    while (digitalRead(SW_ENC) == LOW); // ждём отпускания кнопки
    tm1637.displayByte(_P, _r, _e, _P);

    minBrightness = 255;
    do {
      sprintf(infile, "frame%03d.bmp", nFrames);
      b = 255; // Assume frame at full brightness to start...
      // ...it's then modified by the bmpProcess() function here to the
      // actual brightness limit the UBEC can sustain for *this image*.
      if (found = bmpProcess(infile, NULL, &b)) {
        nFrames++;
        if (b < minBrightness) minBrightness = b;
      }
    } while (found && (nFrames < 1000));

    if (DEBUG) Serial.print(nFrames);
    if (DEBUG) Serial.print(" frames\nbrightness = ");
    if (DEBUG) Serial.println(minBrightness);

    tm1637.displayByte(0, _b);
    tm1637.displayByte(1, _r);
    NORM_STEP = 5;
    tm1637.displayInt(norm_counter);
    for (;;) {
      encoderTick();
      if (turn_flag) {
        norm_counter = constrain(norm_counter, 10, 95);
        tm1637.displayInt(norm_counter);
        turn_flag = false;
      }
      if (digitalRead(SW_ENC) == LOW) break;
    }
    NORM_STEP = 1;
    minBrightness = map(norm_counter, 0, 95, 1, minBrightness);
    EEPROM.updateByte(1, norm_counter);      // записываем новую яркость в память
    norm_counter = 0;
    tm1637.displayByte(_L, _O, _A, _d);

    for (i = 0; i < nFrames; i++) {
      sprintf(infile , "frame%03d.bmp", i);
      sprintf(outfile, "frame%03d.tmp", i);
      b = minBrightness; // Reset b to safe limit on each loop iteration
      bmpProcess(infile, outfile, &b);
    }

  } else {  // если кнопка НЕ НАЖАТА при старте - используем преобразованные картинки!
    tm1637.displayByte(_r, _e, _a, _d);
    do { // Scan for files to get nFrames
      sprintf(infile, "frame%03d.tmp", nFrames);
      if (found = tmp.open(infile, O_RDONLY)) {
        if (tmp.contiguousRange(&firstBlock, &lastBlock)) {
          nFrames++;
        }
        tmp.close();
      }
    } while (found);

  } // end startupTrigger test

  for (i = 0; i < nFrames; i++) { // Scan all files
    sprintf(infile, "frame%03d.tmp", i);
    tmp.open(infile, O_RDONLY);
    tmp.contiguousRange(&firstBlock, &lastBlock);
    nBlocks = tmp.fileSize() / 512;
    tmp.close();
    n = (uint16_t)(1000000L /                         // 1 uSec /
                   (((benchmark(firstBlock, nBlocks) * 21) / 20) + // time + 5% +
                    (N_LEDS * 30L) + OVERHEAD));                   // 30 uSec/pixel
    if (n > maxLPS) maxLPS = n;
  }
  if (maxLPS > 400) maxLPS = 400; // NeoPixel PWM rate is ~400 Hz
  if (DEBUG) Serial.print(F("Max lines/sec: "));
  if (DEBUG) Serial.println(maxLPS);

  // Set up Timer1 for 64:1 prescale (250 KHz clock source),
  // fast PWM mode, no PWM out.
  TCCR1A = _BV(WGM11) | _BV(WGM10);
  TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS11) | _BV(CS10);
  // Timer0 interrupt is disabled for smoother playback.
  // This means delay(), millis(), etc. won't work after this.
  TIMSK0 = 0;

  if (DEBUG) Serial.println(F("Setup done"));

  tm1637.displayByte(_r, _d, _y, _empty);
  delay(500);
  hold_counter = anim_speed;
  norm_counter = 0;
}

// Обработчик ошибки. Полностью вешает систему
static void error(const __FlashStringHelper *ptr) {
  if (DEBUG) Serial.println(ptr); // Show message
  tm1637.displayByte(_F, _e, _r, _r);
  for (;;);            // and hang
}

boolean _new_step;
void encoderTick() {
  SWstate = digitalRead(SW_ENC);
  if (SWstate != SWlast) {
    SWlast = SWstate;
    turn_flag = true;                    // флаг что был поворот ручки энкодера
  }
  DT_now = digitalRead(CLK_ENC);          // читаем текущее положение CLK
  if (DT_now != DT_last) {            // если предыдущее и текущее положение CLK разные, значит был поворот
    if (ENC_TYPE) _new_step = !_new_step;
    if (_new_step) {
      if (digitalRead(DT_ENC) != DT_now) {  // если состояние DT отличается от CLK, значит крутим по часовой стрелке
        if (SWstate) norm_counter += NORM_STEP;
        else hold_counter += HOLD_STEP;
      } else {                          // если совпадают, значит против часовой
        if (SWstate) norm_counter -= NORM_STEP;
        else hold_counter -= HOLD_STEP;
      }
    }
    turn_flag = true;                    // флаг что был поворот ручки энкодера
  }
  DT_last = DT_now;                   // обновить значение
}

void buffering() {
  block    = 0;     // Current block # within file
  stopFlag = false; // If set, stop playback loop

  // Get existing contiguous tempfile info
  sprintf(infile, "frame%03d.tmp", frame);
  if (!tmp.open(infile, O_RDONLY)) {
    error(F("Could not open NeoPixel tempfile for input"));
  }
  if (!tmp.contiguousRange(&firstBlock, &lastBlock)) {
    error(F("NeoPixel tempfile is not contiguous"));
  }

  nBlocks = tmp.fileSize() / 512;
  tmp.close(); // File handle is no longer accessed, just block reads
  sd.card()->readBlock(firstBlock, sdBuf);
}
// PLAYBACK LOOP -------------------------------------------------------------------------------
void loop() {
  buffering();
  tm1637.clearDisplay();
  tm1637.displayByte(0, _F);
  tm1637.displayByte(1, _r);
  tm1637.displayInt(frame);

  while (digitalRead(TRIGGER)) {      // ждём нажатия кнопки !!!
    encoderTick();
    if (turn_flag) {
      if (SWstate) { // если НЕ НАЖАТА кнопка энкодера
        norm_counter = constrain(norm_counter, 0, nFrames - 1);
        frame = norm_counter;
        tm1637.clearDisplay();
        tm1637.displayByte(0, _F);
        tm1637.displayByte(1, _r);
        tm1637.displayInt(frame);
        buffering();
      } else {       // если НАЖАТА кнопка энкодера
        hold_counter = constrain(hold_counter, 0, 95);
        anim_speed = hold_counter;
        tm1637.clearDisplay();
        tm1637.displayByte(0, _S);
        tm1637.displayByte(1, _P);
        tm1637.displayInt(anim_speed);
      }
      turn_flag = false;
    }
  }
  tm1637.displayByte(_P, _r, _o, _c);

  uint32_t linesPerSec = map(anim_speed, 0, 95, 10, maxLPS);  // настройка скорости
  EEPROM.updateByte(3, anim_speed);      // записываем новую скорость в память
  OCR1A = (F_CPU / 64) / linesPerSec;          // Timer1 interval

  // ------------ бесконечный цикл
  for (;;) {                                   // бесконечный цикл
    while (!(TIFR1 & _BV(TOV1)));              // Wait for Timer1 overflow
    TIFR1 |= _BV(TOV1);                        // Clear overflow bit

    show();                                    // отобразить линию
    if (stopFlag) break;                       // выходим из цикла, если stopFlag

    if (++block >= nBlocks) {                  // показали последний блок
      if (digitalRead(TRIGGER) == HIGH) {      // если отпустили кнопку
        memset(sdBuf, 0, N_LEDS * 3);          // прекращаем показывать картинку
        stopFlag = true;                       // флаг на выключение
        continue;
      }                                        // если кнопка всё ещё удерживается
      block = 0;                               // начать сначала!
    }
    sd.card()->readBlock(block + firstBlock, sdBuf); // загрузить следующий блок с карты памяти
  }
  // ------------ бесконечный цикл
}

// BMP->NEOPIXEL FILE CONVERSION ---------------------------------------------

#define BMP_BLUE  0 // BMP and NeoPixels have R/G/B color
#define BMP_GREEN 1 // components in different orders.
#define BMP_RED   2 // (BMP = BGR, Neo = GRB)
#define NEO_GREEN 0
#define NEO_RED   1
#define NEO_BLUE  2

boolean bmpProcess(
  char    *inName,
  char    *outName,
  uint8_t *brightness) {

  SdFile    inFile,              // Windows BMP file for input
            outFile;             // NeoPixel temp file for output
  boolean   ok        = false,   // 'true' on valid BMP & output file
            flip      = FLIP_H;  // 'true' if image stored top-to-bottom
  int       bmpWidth,            // BMP width in pixels
            bmpHeight,           // BMP height in pixels
            bmpStartCol,         // First BMP column to process (crop/center)
            columns,             // Number of columns to process (crop/center)
            row,                 // Current image row (Y)
            column;              // and column (X)
  uint8_t  *ditherRow,           // 16-element dither array for current row
           pixel[3],            // For reordering color data, BGR to GRB
           b = 0,               // 1 + *brightness
           d,                   // Dither value for row/column
           color,               // Color component index (R/G/B)
           raw,                 // 'Raw' R/G/B color value
           corr,                // Gamma-corrected R/G/B
           *ledPtr,              // Pointer into sdBuf (output)
           *ledStartPtr;         // First LED column to process (crop/center)
  uint16_t  b16;                 // 16-bit dup of b
  uint32_t  bmpImageoffset,      // Start of image data in BMP file
            lineMax   = 0L,      // Cumulative brightness of brightest line
            rowSize,             // BMP row size (bytes) w/32-bit alignment
            sum,                 // Sum of pixels in row
            startTime = millis();

  if (brightness)           b = 1 + *brightness; // Wraps around, fun with maths
  else if (NULL == outName) return false; // MUST pass brightness for power est.

  if (DEBUG) Serial.print(F("Reading file '"));
  if (DEBUG) Serial.print(inName);
  if (DEBUG) Serial.print(F("'..."));
  if (!inFile.open(inName, O_RDONLY)) {
    tm1637.displayByte(_F, _r, _E, _r);
    if (DEBUG) Serial.println(F("error"));
    return false;
  }

  if (inFile.read(sdBuf, 34)             &&   // Load header
      (*(uint16_t *)&sdBuf[ 0] == 0x4D42) &&    // BMP signature
      (*(uint16_t *)&sdBuf[26] == 1)      &&    // Planes: must be 1
      (*(uint16_t *)&sdBuf[28] == 24)     &&    // Bits per pixel: must be 24
      (*(uint32_t *)&sdBuf[30] == 0)) {         // Compression: must be 0 (none)
    // Supported BMP format -- proceed!
    bmpImageoffset = *(uint32_t *)&sdBuf[10]; // Start of image data
    bmpWidth       = *(uint32_t *)&sdBuf[18]; // Image dimensions
    bmpHeight      = *(uint32_t *)&sdBuf[22];
    // That's some nonportable, endian-dependent code right there.

    if (DEBUG) Serial.print(bmpWidth);
    Serial.write('x');
    if (DEBUG) Serial.print(bmpHeight);
    if (DEBUG) Serial.println(F(" pixels"));

    if (outName) { // Doing conversion?  Need outFile.
      // Delete existing outFile file (if any)
      (void)sd.remove(outName);
      if (DEBUG) Serial.print(F("Creating contiguous file..."));
      // NeoPixel working file is always 512 bytes (one SD block) per row
      if (outFile.createContiguous(sd.vwd(), outName, 512L * bmpHeight)) {
        uint32_t lastBlock;
        outFile.contiguousRange(&firstBlock, &lastBlock);
        outFile.close();
        nBlocks = bmpHeight; // See note in setup() re: block calcs
        ok      = true;      // outFile is good; proceed
        if (DEBUG) Serial.println(F("OK"));
      } else {
        if (DEBUG) Serial.println(F("error"));
        tm1637.displayByte(_F, _r, _E, _r);
      }
    } else ok = true; // outFile not needed; proceed

    if (ok) { // Valid BMP and contig file (if needed) are ready
      if (DEBUG) Serial.print(F("Processing..."));

      rowSize = ((bmpWidth * 3) + 3) & ~3; // 32-bit line boundary
      b16     = (int)b;

      if (bmpHeight < 0) {      // If bmpHeight is negative,bmpHeight
        bmpHeight = -bmpHeight; // image is in top-down order.
        flip      = true;       // Rare, but happens.
      }

      if (bmpWidth >= N_LEDS) { // BMP matches LED bar width, or crop image
        bmpStartCol = (bmpWidth - N_LEDS) / 2;
        ledStartPtr = sdBuf;
        columns     = N_LEDS;
      } else {                 // Center narrow image within LED bar
        bmpStartCol = 0;
        ledStartPtr = &sdBuf[((N_LEDS - bmpWidth) / 2) * 3];
        columns     = bmpWidth;
        memset(sdBuf, 0, N_LEDS * 3); // Clear left/right pixels
      }

      for (row = 0; row < bmpHeight; row++) { // For each row in image...
        Serial.write('.');
        inFile.seekSet(
          bmpImageoffset + (bmpStartCol * 3) + (rowSize * (flip ?
                                                (bmpHeight - 1 - row) : // Image is stored top-to-bottom
                                                row)));                 // Image stored bottom-to-top
        if (!inFile.read(ledStartPtr, columns * 3)) { // Load row
          if (DEBUG) Serial.println(F("Read error"));
          tm1637.displayByte(_F, _r, _E, _r);
        }

        sum       = 0L;
        ditherRow = (uint8_t *)&dither[row & 0x0F]; // Dither values for row
        ledPtr    = ledStartPtr;
        for (column = 0; column < columns; column++) { // For each column...
          if (b) { // Scale brightness, reorder R/G/B
            pixel[NEO_BLUE]  = (ledPtr[BMP_BLUE]  * b16) >> 8;
            pixel[NEO_GREEN] = (ledPtr[BMP_GREEN] * b16) >> 8;
            pixel[NEO_RED]   = (ledPtr[BMP_RED]   * b16) >> 8;
          } else { // Full brightness, reorder R/G/B
            pixel[NEO_BLUE]  = ledPtr[BMP_BLUE];
            pixel[NEO_GREEN] = ledPtr[BMP_GREEN];
            pixel[NEO_RED]   = ledPtr[BMP_RED];
          }

          d = pgm_read_byte(&ditherRow[column & 0x0F]); // Dither probability
          for (color = 0; color < 3; color++) {         // 3 color bytes...
            raw  = pixel[color];                        // 'Raw' G/R/B
            corr = pgm_read_byte(&gamma[raw]);          // Gamma-corrected
            if (pgm_read_byte(&bump[raw]) > d) corr++;  // Dither up?
            *ledPtr++ = corr;                           // Store back in sdBuf
            sum      += corr;                           // Total brightness
          } // Next color byte
        } // Next column

        if (outName) {
          if (!sd.card()->writeBlock(firstBlock + row, (uint8_t *)sdBuf)) {
            if (DEBUG) Serial.println(F("Write error"));
            tm1637.displayByte(_F, _r, _E, _r);
          }
        }
        if (sum > lineMax) lineMax = sum;

      } // Next row
      if (DEBUG) Serial.println(F("OK"));

      if (brightness) {
        lineMax = (lineMax * 20) / 255; // Est current @ ~20 mA/LED
        if (lineMax > CURRENT_MAX) {
          // Estimate suitable brightness based on CURRENT_MAX
          *brightness = (*brightness * (uint32_t)CURRENT_MAX) / lineMax;
        } // Else no recommended change
      }

      if (DEBUG) Serial.print(F("Processed in "));
      if (DEBUG) Serial.print(millis() - startTime);
      if (DEBUG) Serial.println(F(" ms"));

    } // end 'ok' check
  } else { // end BMP header check
    if (DEBUG) Serial.println(F("BMP format not recognized."));
    tm1637.displayByte(_F, _r, _E, _r);
  }

  inFile.close();
  return ok; // 'false' on various file open/create errors
}

// MISC UTILITY FUNCTIONS ----------------------------------------------------

// Estimate maximum block-read time for card (microseconds)
static uint32_t benchmark(uint32_t block, uint32_t n) {
  uint32_t t, maxTime = 0L;

  do {
    t = micros();
    sd.card()->readBlock(block++, sdBuf);
    if ((t = (micros() - t)) > maxTime) maxTime = t;
  } while (--n);

  return maxTime;
}

// NEOPIXEL FUNCTIONS --------------------------------------------------------

static void show(void) {
  volatile uint16_t
  i   = N_LEDS * 3; // Loop counter
  volatile uint8_t
  *ptr = sdBuf,      // Pointer to next byte
   b   = *ptr++,     // Current byte value
   hi,               // PORT w/output bit set high
   lo,               // PORT w/output bit set low
   next,
   bit = 8;

  noInterrupts();
  hi   = *port |  pinMask;
  lo   = *port & ~pinMask;
  next = lo;

  asm volatile(
    "head20_%=:"                "\n\t"
    "st   %a[port],  %[hi]"    "\n\t"
    "sbrc %[byte],  7"         "\n\t"
    "mov  %[next], %[hi]"     "\n\t"
    "dec  %[bit]"              "\n\t"
    "st   %a[port],  %[next]"  "\n\t"
    "mov  %[next] ,  %[lo]"    "\n\t"
    "breq nextbyte20_%="       "\n\t"
    "rol  %[byte]"             "\n\t"
    "rjmp .+0"                 "\n\t"
    "nop"                      "\n\t"
    "st   %a[port],  %[lo]"    "\n\t"
    "nop"                      "\n\t"
    "rjmp .+0"                 "\n\t"
    "rjmp head20_%="           "\n\t"
    "nextbyte20_%=:"            "\n\t"
    "ldi  %[bit]  ,  8"        "\n\t"
    "ld   %[byte] ,  %a[ptr]+" "\n\t"
    "st   %a[port], %[lo]"     "\n\t"
    "nop"                      "\n\t"
    "sbiw %[count], 1"         "\n\t"
    "brne head20_%="          "\n"
    : [port]  "+e" (port),
    [byte]  "+r" (b),
    [bit]   "+r" (bit),
    [next]  "+r" (next),
    [count] "+w" (i)
    : [ptr]    "e" (ptr),
    [hi]     "r" (hi),
    [lo]     "r" (lo));

  interrupts();
  // There's no explicit 50 uS delay here as with most NeoPixel code;
  // SD card block read provides ample time for latch!
}
 

EREME1

✩✩✩✩✩✩✩
18 Май 2022
8
0
Я проверил ардуано скетчем, на пинах нет коротышей и все читается нормально, дисплей новый, на вид косяков в нем нет. Единственное - не проверил работу самого дисплея, а сразу припаял и прошил этим скетчем

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

PiratFox

★★★★★✩✩
13 Фев 2020
1,706
474
@EREME1, пока не надо ничего отпаивать. Просто в тестовом скетче укажите пины для ТМ1637 согласно физического подключения.
 
  • Лойс +1
Реакции: EREME1

EREME1

✩✩✩✩✩✩✩
18 Май 2022
8
0
@PiratFox,
Дисплей исправно работает с библиотекой Grove 4-Digit Display и скетчем из папки с примерами
 

PiratFox

★★★★★✩✩
13 Фев 2020
1,706
474
@EREME1, это та библиотека, которую Вы используете в загружаемом скетче?
 
  • Лойс +1
Реакции: EREME1