7-сегментный светодиодный индикатор с матричной адресацией

Есть в наличии индикатор от сгоревшего китайского вольтметра DSN-DVM-368. Хотел бы сделать на нем вольтметр на ардуинке. Беда в том, что распиновка у него не обычная по сегментам, а матричная.
Индикатор от DSN-DVM-368(5631-2А)

Расписал его сегменты матрицей 5*5


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

[code]
byte c[5] = {12,11,10,9,8}; // пины столбцов-катоды 
byte r[5] = {2,3,4,5,6};    // пины строк - аноды

//               пин 12     пин 11     пин 10     пин 9      пин 8
//               ---65432   ---65432   ---65432   ---65432   ---65432
byte d31[5] = {0b00000110,0b00000000,0b00000000,0b00000000,0b00000000};
byte d32[5] = {0b00011010,0b00000011,0b00000000,0b00000000,0b00000000};
byte d33[5] = {0b00011110,0b00000001,0b00000000,0b00000000,0b00000000};
byte d34[5] = {0b00010111,0b00000000,0b00000000,0b00000000,0b00000000};
byte d35[5] = {0b00011101,0b00000001,0b00000000,0b00000000,0b00000000};
byte d36[5] = {0b00011101,0b00000011,0b00000000,0b00000000,0b00000000};
byte d37[5] = {0b00001110,0b00000000,0b00000000,0b00000000,0b00000000};
byte d38[5] = {0b00011111,0b00000011,0b00000000,0b00000000,0b00000000};
byte d39[5] = {0b00011111,0b00000001,0b00000000,0b00000000,0b00000000};
byte d30[5] = {0b00001111,0b00000011,0b00000000,0b00000000,0b00000000};
//               пин 12     пин 11     пин 10     пин 9      пин 8
//               ---65432   ---65432   ---65432   ---65432   ---65432
byte d21[5] = {0b00000000,0b00000000,0b00000011,0b00000000,0b00000000};
byte d22[5] = {0b00000000,0b00011000,0b00000101,0b00000001,0b00000000};
byte d23[5] = {0b00000000,0b00010000,0b00000111,0b00000001,0b00000000};
byte d24[5] = {0b00000000,0b00000000,0b00010111,0b00000000,0b00000000};
byte d25[5] = {0b00000000,0b00010000,0b00010110,0b00000001,0b00000000};
byte d26[5] = {0b00000000,0b00011000,0b00010110,0b00000001,0b00000000};
byte d27[5] = {0b00000000,0b00000000,0b00000011,0b00000001,0b00000000};
byte d28[5] = {0b00000000,0b00011000,0b00010111,0b00000001,0b00000000};
byte d29[5] = {0b00000000,0b00010000,0b00010111,0b00000001,0b00000000};
byte d20[5] = {0b00000000,0b00011000,0b00010011,0b00000001,0b00000000};
//               пин 12     пин 11     пин 10     пин 9      пин 8
//               ---65432   ---65432   ---65432   ---65432   ---65432
byte d11[5] = {0b00000000,0b00000000,0b00000000,0b00000000,0b00000110};
byte d12[5] = {0b00000000,0b00000000,0b00000000,0b00001110,0b00001100};
byte d13[5] = {0b00000000,0b00000000,0b00000000,0b00001100,0b00001110};
byte d14[5] = {0b00000000,0b00000000,0b00000000,0b00001000,0b00000111};
byte d15[5] = {0b00000000,0b00000000,0b00000000,0b00001100,0b00001011};
byte d16[5] = {0b00000000,0b00000000,0b00000000,0b00001110,0b00001011};
byte d17[5] = {0b00000000,0b00000000,0b00000000,0b00000000,0b00001110};
byte d18[5] = {0b00000000,0b00000000,0b00000000,0b00001110,0b00001111};
byte d19[5] = {0b00000000,0b00000000,0b00000000,0b00001100,0b00001111};
byte d10[5] = {0b00000000,0b00000000,0b00000000,0b00000110,0b00001111};

byte* bin;        // указатель на массив с кадром
//---------------------------------------------------------
void setup() {
  for(byte i = 0; i < 5; i++){ // инициализация пинов
    pinMode(r[i], OUTPUT);     // строки - аноды
    digitalWrite(r[i], LOW);   // выключаем аноды
    pinMode(c[i], OUTPUT);     // столбцы - катоды
    digitalWrite(c[i], HIGH);  // выключаем катоды
  }
}
//---------------------------------------------------------
void loop(){
    view(bin);      // вывод активного кадра
//    change_d3();     // выводим от 0 до 9  в третьей цифре
//    change_d2();     // выводим от 0 до 9  во второй цифре
    change_d1();    // выводим от 0 до 9  в первой цифре
}
//---------------------------------------------------------
void change_d1(){
    static byte nom = 0;
    static unsigned long timer;
  if(timer > millis()) return;
  switch(nom){               // циклически меняем активный кадр каждую секунду
    case 0:
      bin = &d11[0];
      break;
    case 1:
      bin = &d12[0];
      break;
    case 2:
      bin = &d13[0];
      break;
    case 3:
      bin = &d14[0];
      break; 
    case 4:
      bin = &d15[0];
      break;
    case 5:
      bin = &d16[0];
      break;     
    case 6:
      bin = &d17[0];
      break;
    case 7:
      bin = &d18[0];
      break; 
    case 8:
      bin = &d19[0];
      break;
    case 9:
      bin = &d10[0];
      break;         
  }
    nom++;
  if(nom > 9)nom = 0;
    timer = millis() + 1000;
}
//---------------------------------------------------------
void view(byte* n){
    static unsigned long timer;
    static byte j = 0;
    static byte j_old = 0;
  if(timer > millis()) return;    // не чаще 1 кадра в 1 мс
    digitalWrite(c[j_old], HIGH); // выключаем предыдущий активный столбец-катод
    byte bb = 0b00000001;
  for(byte i = 0; i < 5; i++){    // перебираем биты, выводим в пины
    digitalWrite(r[i], (bb & *(n + j))); // включаем пины-аноды
    bb = bb << 1;
    }
    digitalWrite(c[j], LOW);      // включаем активный столбец-катод
    j_old = j;
  if(j == 4)j = 0; else j = j + 1;
    timer = millis() + 1;
}
//---------------------------------------------------------
[/code]

матричная это как раз обычная

Обычная, это на каждую цифру 8 сегментов и общий катод(анод). Итого 11 ног. А здесь матричная структура и ног 10.

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

2 лайка

Да верно. Я сейчас могу в лупе в каждом разряде выводить только перебором от 0 до 9. Как составить все разряды в месте, чтобы вывести например, число 220? Или для лучшего понимания, сделать на этом скетче для начала секундомер. Пока никак не соображу.

void loop(){
    view(bin);      // вывод активного кадра
//    change_d3();     // выводим от 0 до 9  в третьей цифре
//    change_d2();     // выводим от 0 до 9  во второй цифре
    change_d1();    // выводим от 0 до 9  в первой цифре
}

Есть у Вас, например, функция change_d1(), которая уже умеет рисовать любую цифру. Сделайте свою функцию, которая будет рисовать одну конкретную цифру! (Достаточно выкинуть из change_d1 всё лишнее про циклы, таймеры) Чтобы новая функция знала, какую ей цифру нарисовать, добавьте в неё параметр, через который и будете нужную цифру передавать.
Начните хотя бы с этого. Дальше уже должно быть понятно.

1 лайк

Известная проблема, еще со времен шоу Якубовича: “Угадал все буквы, но не смог произнести слово”.

3 лайка

В самую точку.

Она не умеет рисовать цифры, а только перебирает их. Так я проверяю знакогенератор. А как её заставить рисовать нужную цифру пока не понятно.

void change_d1(const uint8_t nom){
  switch(nom){ 
...
}
...
1 лайк

void change_d1(const uint8_t nom){
switch(nom){

}

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

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

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

1 лайк

Ничего там сложного нет.
Встречали веселее.
6 ног, 3 регистра.
Сплошная светодиодная логика :slight_smile:

Совсем тупой стал. Как я передам в функцию число? Какое число? Откуда его возьму? И почему const uint8_t nom?

А как вы написали вывод вообще? Судя по вопросам - не могли.

1 лайк

…с оказией. Может кто поедет в ту сторону?

1 лайк

@selan61 может ну его нафиг? Какое-нибудь другое занятие для хобби найти? А то в этом без программирования совсем никак! Надо хоть какие-то основы знать.

2 лайка

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

byte num[3];
unsigned int chislo;
void change_d(byte  dig, byte mun);
.
.
.

num[0] = chislo % 10; //получаем младший разряд.
num[1] = chislo / 10 % 10;//получаем средний разряд.
num[2] = chislo / 100; //получаем старший разряд.
.
.
.

for (byte dig = 0; dig < 3; dig++) {
  change_d(dig, num[dig]);    // передаём в функцию вывода параметрами первый байт - разряд и 
}                             // второй байт - число  в этом разряде

P.S.

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

1 лайк

Спасибо всем. Разобрался, сделал. Что то вчера голова не работала. Прошу извинения за глупые вопросы. Очень благодарен всем откликнувшимся за помощь и дельные советы.

1 лайк