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

В этой статье сделаем два новых брелка, проверим оригинальную схему с MAX7219, заменим батарейку и посмотрим на отличия разных светодиодных матриц.

❯ Введение

Если коротко, то в прошлой статье я сделал светодиодный брелок на микросхеме CH32V003F4P6. Как мне кажется, самое интересное в этой затее было то, что он самодельный на односторонней плате и весь процесс я постарался описать. А еще там были заклепки. (Можете ознакомиться с ней, чтобы лучше понимать, о чем я здесь пишу, но все должно быть понятно, если вы понимаете, как работает светодиодная матрица и что в один момент времени могут гореть 8 светодиодов.) Основная проблема, что получившийся брелок светил блекло. Идея этого устройства появилась из роликов с YouTube и там он светит хорошо, даже видно через черный пластик. Поэтому и появилась мысль, что можно сделать лучше.

В комментариях к статье VT100, как мне кажется, точно подсказал симптомы, что разным светодиодам нужен разное напряжение и красные матрицы должны светиться ярче. Там же было подмечено, что CR2032 очень хилые.

В других комментариях и я в конце статьи предположил, что возможно микроконтроллер может быть ограничен по току. И действительно в даташите написано, что максимальный потребляемый ток CH32V003 это 100 мА.

Поэтому план статьи следующий:

  • Посмотрим как светят разные светодиодные матрицы.

  • Заменим CR2032 на LIR2032.

  • Соберем два новых брелка: один на CH32V003 (с другими токоограничивающими резисторами) и один на ATtiny2313A.

  • Сравним с оригинальной схемой на MAX7219 и ATtiny85.

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

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

❯ Светодиодные матрицы

Сначала определимся какая матрица светит ярче. Для тестов я возьму брелок из первой статьи (для упрощения назову его V1) и сделаю фото 3х матриц с ним: синей, зеленой, красной. Напомню, V1 — это брелок со схемой, в которой микроконтроллер CH32V003F4P6 управляет светодиодной матрицей напрямую через токоограничивающие резисторы в 200 Ом.

Но прежде посмотрим на данные из википедии, как должно быть на самом деле. Падение напряжения на светодиодах:

  • Красный — 1,63 < ΔU < 2,03

  • Зеленый — 1,9 < ΔU < 4,0

  • Синий — 2,48 < ΔU < 3,7

Другими словами, если у нас батарейка 3.3В и падение напряжения 1.63В (красный) с токоограничивающим резистором 200 Ом, то ток будет (3.3 - 1.3) / 200 = 9.9 мА. А для падения напряжения 2.48В (синий) получаем ток 4 мА. Этими простыми вычислениями хочу показать, что светодиодные матрицы должны светиться по-разному, красные ярче, затем зеленые, затем синие.

Отличия разных матриц на брелке V1 из прошлой статьи
Отличия разных матриц на брелке V1 из прошлой статьи

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

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

❯ LIR2032

На странице игровой консоли на CH32V003 я увидел сноску про пищалку и что она лучше работает с батарейками LIR2032. Я долгое время искал батарейку по форм фактору CR2032, которая была бы с большим напряжением (3.6В) и к удивлению LIR2032 оказалось ею. Поэтому сразу решил, что надо её проверить на брелке. Тут же заказал и она шла где-то месяц. Одна правда особенность, что она аккумуляторная и нужна зарядка, поэтому заказал с зарядкой.

Отличия разных батареек на V1
Отличия разных батареек на V1

Здесь уже видно невооруженным глазом, с LIR2032 заметно ярче, чем когда сменили синею матрицу на красную.

В последующих тестах будем использовать батарейку LIR2032.

❯ Новые брелки

Теперь проверим новые устройства.

Когда я писал первую статью, то уже сделал плату под следующий брелок и решил на нем проверить, что будет если поставить другие токоограничивающие резисторы. На первой плате они были 200 Ом, а на второй стали 100 Ом.

Но больше всего меня заинтересовал вопрос, возможно можно выбрать другой микроконтроллер у которого лучше характеристики потребления тока. Стал изучать этот вопрос и нашел, что у микроконтроллеров AVR (200 мА) и PIC (300 мА) обычно везде в даташитах потребляемые токи больше, чем у CH32V003 (100 мА), а у STM32 (100 мА) примерно такие же. Другие микроконтроллеры не смотрел, но, забегая вперед, у микросхемы MAX7219 самый большие отдаваемые токи (Sink Current 500мА).

Сначала я хотел попробовать PIC микроконтроллер, нашел что-то вроде PIC16F628A и у него в даташите максимальный потребляемы ток 300 мА, но у меня программатор K150 и он его не поддерживает, находил другие микросхемы и они тоже не поддерживались, поэтому я почти быстро отказался от PIC, т.к. пришлось бы покупать новый программатор и оно того вряд ли бы стоило. (Напишите комментарий, пожалуйста, если вам было это интересно, потому что я подумал, что они сейчас никому не интересны) Потом я искал среди AVR микроконтроллеров и почти у всех было написано максимально потребляемый ток 200 мА и случайно на Озон наткнулся на ATtiny2313A, которые точно подходили под брелок и стоили около 60 рублей за штуку, поэтому я их сразу же заказал и тоже ждал около месяца.

Хочется добавить, что в даташитах AVR или PIC микроконтроллеров везде были одинаковые цифры потребляемого тока: у AVR это 200 мА, у PIC это 300 мА. Т.к. я остановился на AVR, то у некоторых была (не у всех) интересная сноска в даташите, что максимально отдаваемый ток не должен превышать 60 мА и кажется это правдиво для ATtiny2313A, но как проверить не знаю и наверно не нужно, потому что дальше по статье мы поймем что лучше ATtiny2313A или CH32V003F4P6 при потреблении тока.

Приведу получившиеся фото, схему и код проекта на ATtiny2313A, возможно кому-то будет интересно посмотреть.

Печатная платы без компонентов
Печатная платы без компонентов
Финальный вариант, вид сверху. Для сравнения добавил фото из прошлой статьи
Финальный вариант, вид сверху. Для сравнения добавил фото из прошлой статьи
Финальный вариант, вид снизу
Финальный вариант, вид снизу
Принципиальная схема брелка с ATtiny2313A. Конденсатор поставил!
Принципиальная схема брелка с ATtiny2313A. Конденсатор поставил!
Скрытый текст
#include <Arduino.h>

// 0 - PD0
// 1 - PD1
// 2 - PA1
// 3 - PA0
// 4 - PD2
// 5 - PD3
// 6 - PD4
// 7 - PD5
// 8 - PD6
// 9 - PB0
// 10 - PB1
// 11 - PB2
// 12 - PB3
// 13 - PB4
// 14 - PB5
// 15 - PB6
// 16 - PB7
// 17 - PA2

#define COL1 0 // PD0
#define COL2 5 // PD3
#define COL3 15 // PB6
#define COL4 3 // PA0
#define COL5 8 // PD6
#define COL6 14 // PB5
#define COL7 9 // PB0
#define COL8 12 // PB3

#define ROW1 4 // PD2
#define ROW2 10 // PB1
#define ROW3 11 // PB2
#define ROW4 1 // PD1
#define ROW5 13 // PB4
#define ROW6 2 // PA1
#define ROW7 6 // PD4
#define ROW8 7 // PD5

const int row[8] = {
  ROW1, ROW2, ROW3, ROW4, ROW5, ROW6, ROW7, ROW8
};

const int col[8] = {
  COL1, COL2, COL3, COL4, COL5, COL6, COL7, COL8
};

const uint8_t ghost_Frame_1[8] PROGMEM = { 0x1c, 0x3e, 0x6b, 0x49, 0x7f, 0x63, 0x7f, 0x55 };
const uint8_t ghost_Frame_2[8] PROGMEM = { 0x1c, 0x3e, 0x5b, 0x49, 0x7f, 0x63, 0x7f, 0x55 };
const uint8_t ghost_Frame_3[8] PROGMEM = { 0x1c, 0x3e, 0x49, 0x5b, 0x7f, 0x63, 0x7f, 0x55 };
const uint8_t ghost_Frame_4[8] PROGMEM = { 0x1c, 0x3e, 0x49, 0x6d, 0x7f, 0x63, 0x7f, 0x55 };
const uint8_t ghost_Frame_5[8] PROGMEM = { 0x1c, 0x3e, 0x6d, 0x49, 0x7f, 0x63, 0x7f, 0x55 };
const uint8_t ghost_Frame_6[8] PROGMEM = { 0x1c, 0x3e, 0x6b, 0x49, 0x7f, 0x63, 0x7f, 0x55 };
const uint8_t ghost_Frame_7[8] PROGMEM = { 0x1c, 0x3e, 0x6b, 0x49, 0x7f, 0x63, 0x7f, 0x55 };
const uint8_t ghost_Frame_8[8] PROGMEM = { 0x1c, 0x3e, 0x6b, 0x49, 0x7f, 0x63, 0x7f, 0x55 };

const uint8_t *ghost_frames[8] = {
    ghost_Frame_1,
    ghost_Frame_2,
    ghost_Frame_3,
    ghost_Frame_4,
    ghost_Frame_5,
    ghost_Frame_6,
    ghost_Frame_7,
    ghost_Frame_8
};

uint8_t _pixels[8];
uint16_t _pwm;
const uint8_t _intensity = 15;

void displayFrame(const uint8_t* frame) {
    for (int y = 0; y < 8; y++) {
        for (int x = 0; x < 8; x++) {
            uint8_t b = pgm_read_byte(frame + y);
            if (b & (1 << x)) {
                _pixels[x] = _pixels[x] | (1 << y);
            } else {
                _pixels[x] = _pixels[x] & ~(1 << y);
            }
        }
    }
}

void refreshScreen() {
    _pwm++;
    if (_pwm > 16) {
        _pwm = 0;
    }

    if (_pwm < _intensity) {
      for (int thisRow = 0; thisRow < 8; thisRow++) {
        digitalWrite(row[thisRow], LOW);

        for (int thisCol = 0; thisCol < 8; thisCol++) {
            int thisPixel;

            if (_pixels[thisCol] & (1 << thisRow)) {
                thisPixel = HIGH;
            } else {
                thisPixel = LOW;
            }

            digitalWrite(col[thisCol], thisPixel);
            if (thisPixel == HIGH) {
                digitalWrite(col[thisCol], LOW);
            }
        }

        digitalWrite(row[thisRow], HIGH);
      }
    }
}

void delayWithRefresh(unsigned long d) {
    unsigned long prevTime = millis();
    unsigned long duration = 0;

    while (true) {
        unsigned long time = millis();
        unsigned long tmp = (time - prevTime);
        prevTime = time;
        duration += tmp;
        if (duration > d) {
            break;
        }

        refreshScreen();
    }
}

void setup() {
  for (int thisPin = 0; thisPin < 8; thisPin++) {
      pinMode(col[thisPin], OUTPUT);
      pinMode(row[thisPin], OUTPUT);
      digitalWrite(col[thisPin], LOW);
      digitalWrite(row[thisPin], HIGH);
  }

  for (int x = 0; x < 8; x++) {
      for (int y = 0; y < 8; y++) {
          _pixels[x] = _pixels[x] | (1 << y);
      }
  }
}

void loop() {
  for (uint8_t i = 0; i < 8; i++) {
    displayFrame(ghost_frames[i]);
    delayWithRefresh(150);
  }
}

Код значительно упростил, он теперь показывает только привидение из Pacman и нажатие кнопки не обрабатывается. На самом деле пришлось небольшую оптимизацию сделать, т.к. ATtiny2313A не обладает большой памятью, поэтому все массивы констант вынесены в ПЗУ. А другие анимации уже не влезают, возможно если написать на ассемблере, то и влезут, но я решил, что пока это не стоит того.

Давайте посмотрим на результаты:

Отличия новых брелков
Отличия новых брелков

V1 — оригинальный брелок из прошлой статьи на CH32V003F4P6, у него 200 Ом токоограничивающие резисторы. V2 — тоже самое, но с 100 Ом токоограничивающими резисторами. Разница небольшая, но она есть. V3 — новый брелок с ATtiny2313A и у него тоже 100 Ом токоограничивающие резисторы.

По фото видно, что действительно ATtiny2313A лучше себя показал. В живую, это конечно не так ярко, а вот на камере появились даже блики. Если посветить им на поверхность, то видно как она освещается. Даже просвечивает через черный пластик! (Эти фото приведу дальше.)

Можно частично сказать, что победа, но давайте посмотрим последний тест.

❯ MAX7219

В роликах на YouTube, которые мне подкинули идею для этого брелка, уже есть готовый код и рассчитан он на ATtiny85. Поэтому я решил собрать их оригинальную схему и посмотреть, что получится.

Получилась очень простая схема на ATtiny85 в SimulIDE
Получилась очень простая схема на ATtiny85 в SimulIDE
Скрытый текст
#include <Arduino.h>
#include <LedControl.h>

#define DIN 0 // PB0
#define CS 1  // PB1
#define CLK 3 // PB3

const uint8_t ghost_Frame_1[8] PROGMEM = {0x1c, 0x3e, 0x6b, 0x49, 0x7f, 0x63, 0x7f, 0x55};
const uint8_t ghost_Frame_2[8] PROGMEM = {0x1c, 0x3e, 0x5b, 0x49, 0x7f, 0x63, 0x7f, 0x55};
const uint8_t ghost_Frame_3[8] PROGMEM = {0x1c, 0x3e, 0x49, 0x5b, 0x7f, 0x63, 0x7f, 0x55};
const uint8_t ghost_Frame_4[8] PROGMEM = {0x1c, 0x3e, 0x49, 0x6d, 0x7f, 0x63, 0x7f, 0x55};
const uint8_t ghost_Frame_5[8] PROGMEM = {0x1c, 0x3e, 0x6d, 0x49, 0x7f, 0x63, 0x7f, 0x55};
const uint8_t ghost_Frame_6[8] PROGMEM = {0x1c, 0x3e, 0x6b, 0x49, 0x7f, 0x63, 0x7f, 0x55};
const uint8_t ghost_Frame_7[8] PROGMEM = {0x1c, 0x3e, 0x6b, 0x49, 0x7f, 0x63, 0x7f, 0x55};
const uint8_t ghost_Frame_8[8] PROGMEM = {0x1c, 0x3e, 0x6b, 0x49, 0x7f, 0x63, 0x7f, 0x55};

const uint8_t *ghost_frames[8] = {
    ghost_Frame_1,
    ghost_Frame_2,
    ghost_Frame_3,
    ghost_Frame_4,
    ghost_Frame_5,
    ghost_Frame_6,
    ghost_Frame_7,
    ghost_Frame_8
};

LedControl lc = LedControl(DIN, CLK, CS, 1);

void displayFrame(const uint8_t *frame)
{
    for (int i = 0; i < 8; i++)
    {
        lc.setRow(0, i, pgm_read_byte(frame + i));
    }
}

void setup()
{
    lc.shutdown(0, false);
    lc.setIntensity(0, 15);
    lc.clearDisplay(0);
}

void loop()
{
    for (uint8_t i = 0; i < 8; i++)
    {
        displayFrame(ghost_frames[i]);
        delay(150);
    }
}

Код очень простой, здесь нет никаких сложностей, т.к. они скрыты в библиотеке LedControl.

Та же схема, но на макетке. Включена лампа на столе
Та же схема, но на макетке. Включена лампа на столе

В схеме на макетке можете заметить батарейку, та же самая, LIR2032.

Сравнение версии ATtiny2313A с MAX7219. Лампа выключена
Сравнение версии ATtiny2313A с MAX7219. Лампа выключена

Фото с макеткой получилось мягче, чем следующее фото, потому что я включил лампу на столе. На фото с сравнением ATtiny2313A с MAX7219 лампа была выключена, поэтому такое отличие. (Думаю надо повториться, но на левой и на правой части фото лампа выключена, т.к. освещение на сравнениях одинаковое, но в рамках одного сравнения.)

В жизни MAX7219 светит действительно ярко, заметно ярче, чем ATtiny2313A, но в то же время не сказать, что ATtiny2313A плохо светит, можно сказать достаточно, чтобы брелком можно пользоваться или хотя бы показывать.

В итоге, столько телодвижений, а можно было взять сразу готовый проект, который показали в YouTube роликах, но правда, как по мне, это было бы менее интересно.

❯ Финальное сравнение

Давайте теперь возьмем самый лучший получившийся вариант (ATtiny2313A + LIR2032 + красная матрица) и сделаем фото как из первой статьи и сравним.

Фото из прошлой статьи и фото с новым брелком
Фото из прошлой статьи и фото с новым брелком

Я специально подставил руку, что было понятно, что теперь брелок заметно освещает поверхность, что никак не получалось у самого первого брелка.

В черном корпусе
В черном корпусе

И даже в черном корпусе что-то видно, плохо, но видно.

В черном корпусе, но MAX7219
В черном корпусе, но MAX7219

А вот MAX7219 выглядит также, как и на фото из YouTube роликов, в черном корпусе все четко и ярко светит, нет никаких проблем.

После написания статьи решил сделать еще тесты.

ATtiny2313A + LIR2032 в разных корпусах и с разными матрицами
ATtiny2313A + LIR2032 в разных корпусах и с разными матрицами
MAX7219 с разными матрицами
MAX7219 с разными матрицами
Фото из прошлой статьи и фото с новым брелком
Фото из прошлой статьи и фото с новым брелком

И теперь можно увидеть, что не обязательно красная матрица будет ярче всех. Видно, что и синяя неплохо светит.

❯ Заключение

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

Кто давно занимается светодиодами, наверно, мог до всех выводов из статьи догадаться уже заранее, здесь нет ничего нового. Хотя мне некоторые моменты были тоже понятны, но как это на практике может выглядеть, все же до написания стать не представлял.

Практически каждый существенный комментарий к прошлой статье по своему помогал и улучшал общую яркость, но однозначно сказать, что же помогло сложно, да на самом деле проблема осталась, т.к. обычные микроконтроллеры для таких задач конечно подходят, но не лучшим образом. Возможно и PIC бы показал себя лучше, но это на самом деле не важно, потому что очевидно, что ему не превзойти MAX7219.

Еще не стоит забывать, что в получившемся брелке использовался ATtiny2313A, а он в 3 и больше раз дороже, чем CH32V003F4P6, поэтому сложно сказать победа это или нет. Наверно не победа, т.к. изначальная идея была сделать это все на самом дешевом микроконтроллере, а тут суть потеряна. Но все же и небольшая победа, потому что проблема частично решилась и брелок светит приемлемым качеством. А для меня это оказался интересный и полезный проект, возможно и вам было интересно за ним следить.

Все файлы из статьи находятся в репозитории LedKeychain. В том же, что и к первой статье, но в папке V2.

❯ Важный комментарий

Хотя в конце статьи я сделал вывод, что не так важен оказался выбор светодиодной матрицы, но случайно я обнаружил, что в одних случаях он может быть существенным, если не главным.

После того, как написал статью, я взял первый свой брелок с CH32V003 и проверил его на красной и синей матрице, при этом была обычная батарейка CR2032. В результате синяя матрица еле светилась, а красная нормально. Я вставил батарейку LIR2032 и они обе стали светиться нормально, не сказать, что какая-то ярче. Поэтому можно сделать вывод, что если напряжения для каких-то задач может не хватать и тогда в этом случае матрица светит плохо. Я проделал такой же тест с ATtiny2313A и обе матрицы светились нормально при той же CR2032. Получается это может быть банально какая-то особенность CH32V003.

Не понимаю, почему этот случай не произошел в самом первом тесте, возможно батарейка разрядилась. Получается решение взять красную матрицу было правильным.


Новости, обзоры продуктов и конкурсы от команды Timeweb.Cloud — в нашем Telegram-канале 

Перед оплатой в разделе «Бонусы и промокоды» в панели управления активируйте промокод и получите кэшбэк на баланс.

Комментарии (6)


  1. CitizenOfDreams
    10.09.2025 08:35

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

    Просто сейчас китайцы делают очень много хреновых батареек 2032 с высоким внутренним сопротивлением. Напряжение без нагрузки на них нормальное, в часах и на материнских платах работают отлично - но большие токи выдавать не способны даже кратковременно.


    1. m039 Автор
      10.09.2025 08:35

      Согласен, но хочу добавить, что они работают нормально, когда только-только их вставишь, а через время все как вы описали.


    1. KiV66
      10.09.2025 08:35

      Батарейка CR2032 фирмы Panasonic: Continuous drain 0.2mA.

      Это из документации - https://industrial.panasonic.com/cdbs/www-data/pdf2/AAA4000/AAA4000C321.pdf


      1. m039 Автор
        10.09.2025 08:35

        ИИ гугла подсказывает, что при 0.2 мА достигается указанная емкость из даташита, но сама батарейка может испытывать пики по 100 мА и выше. И это верно, т.к. иначе бы брелок вообще не светился, потому что 0.2 мА это совсем как-то мало. Странно, что в даташите от Panasonic про пики и большие токи ничего не написано.


  1. REPISOT
    10.09.2025 08:35

    Но прежде посмотрим на данные из википедии, как должно быть на самом деле. Падение напряжения на светодиодах:

    Смотреть надо данные из даташита производителя матрицы.

    если у нас батарейка 3.3В и падение напряжения 1.63В (красный) с токоограничивающим резистором 200 Ом, то ток будет (3.3 - 1.3) / 200 = 9.9 мА. А для падения напряжения 2.48В (синий) получаем ток 40 мА

    Как это у вас вышло? (3,3 - 2,48) / 200 = 4 mA

    хочу показать, что светодиодные матрицы должны светится по-разному, красные ярче, затем зеленые, затем синие.

    Поэтому обычно на разные цвета ставят разные номиналы резисторов.


    1. m039 Автор
      10.09.2025 08:35

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