Страница 1 из 2
Светодиодная матрица. Первые шаги
Добавлено: Сб июл 09, 2022 09:51:46
Николай1961.
Здравствуйте. Вот на пенсии решил заняться саморазвитием. Но как оказалось с возрастом тяжко впитывать новые знания. Буду весьма благодарен за любую оказанную помощь в изучении программирования микроконтроллеров на AVR.
Собрал не большую схему светодиодной матрицы. Пока ничего сложного, просто перебор светодиодов по порядку. Но хотелось бы узнать Вашего мнения по коду. И если можно укажите на ошибки своими примерами.
Спойлер
Код: Выделить всё
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>
int k =0;
int i;
int main()
{
DDRA=0xFF;
DDRB=0xFF;
PORTA=0x00;
PORTB=0x00;
int a[9]= {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
int b[9]={0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F};
// Write your code here
while (1){
_delay_ms(100);
k++;
switch(k){
case 1: PORTA=a[0];PORTB=b[0]; break;
case 2: PORTA=a[0];PORTB=b[1]; break;
case 3: PORTA=a[0];PORTB=b[2]; break;
case 4: PORTA=a[0];PORTB=b[3]; break;
case 5: PORTA=a[0];PORTB=b[4]; break;
case 6: PORTA=a[0];PORTB=b[5]; break;
case 7: PORTA=a[0];PORTB=b[6]; break;
case 8: PORTA=a[0];PORTB=b[7]; break;
case 9: PORTA=a[1];PORTB=b[0]; break;
case 10: PORTA=a[1];PORTB=b[1]; break;
case 11: PORTA=a[1];PORTB=b[2]; break;
case 12: PORTA=a[1];PORTB=b[3]; break;
case 13: PORTA=a[1];PORTB=b[4]; break;
case 14: PORTA=a[1];PORTB=b[5]; break;
case 15: PORTA=a[1];PORTB=b[6]; break;
case 16: PORTA=a[1];PORTB=b[7]; break;
case 17: PORTA=a[2];PORTB=b[0]; break;
case 18: PORTA=a[2];PORTB=b[1]; break;
case 19: PORTA=a[2];PORTB=b[2]; break;
case 20: PORTA=a[2];PORTB=b[3]; break;
case 21: PORTA=a[2];PORTB=b[4]; break;
case 22: PORTA=a[2];PORTB=b[5]; break;
case 23: PORTA=a[2];PORTB=b[6]; break;
case 24: PORTA=a[2];PORTB=b[7]; break;
case 25: PORTA=a[3];PORTB=b[0]; break;
case 26: PORTA=a[3];PORTB=b[1]; break;
case 27: PORTA=a[3];PORTB=b[2]; break;
case 28: PORTA=a[3];PORTB=b[3]; break;
case 29: PORTA=a[3];PORTB=b[4]; break;
case 30: PORTA=a[3];PORTB=b[5]; break;
case 31: PORTA=a[3];PORTB=b[6]; break;
case 32: PORTA=a[3];PORTB=b[7]; break;
case 33: PORTA=a[4];PORTB=b[0]; break;
case 34: PORTA=a[4];PORTB=b[1]; break;
case 35: PORTA=a[4];PORTB=b[2]; break;
case 36: PORTA=a[4];PORTB=b[3]; break;
case 37: PORTA=a[4];PORTB=b[4]; break;
case 38: PORTA=a[4];PORTB=b[5]; break;
case 39: PORTA=a[4];PORTB=b[6]; break;
case 40: PORTA=a[4];PORTB=b[7]; break;
case 41: PORTA=a[5];PORTB=b[0]; break;
case 42: PORTA=a[5];PORTB=b[1]; break;
case 43: PORTA=a[5];PORTB=b[2]; break;
case 44: PORTA=a[5];PORTB=b[3]; break;
case 45: PORTA=a[5];PORTB=b[4]; break;
case 46: PORTA=a[5];PORTB=b[5]; break;
case 47: PORTA=a[5];PORTB=b[6]; break;
case 48: PORTA=a[5];PORTB=b[7]; break;
case 49: PORTA=a[6];PORTB=b[0]; break;
case 50: PORTA=a[6];PORTB=b[1]; break;
case 51: PORTA=a[6];PORTB=b[2]; break;
case 52: PORTA=a[6];PORTB=b[3]; break;
case 53: PORTA=a[6];PORTB=b[4]; break;
case 54: PORTA=a[6];PORTB=b[5]; break;
case 55: PORTA=a[6];PORTB=b[6]; break;
case 56: PORTA=a[6];PORTB=b[7]; break;
case 57: PORTA=a[7];PORTB=b[0]; break;
case 58: PORTA=a[7];PORTB=b[1]; break;
case 59: PORTA=a[7];PORTB=b[2]; break;
case 60: PORTA=a[7];PORTB=b[3]; break;
case 61: PORTA=a[7];PORTB=b[4]; break;
case 62: PORTA=a[7];PORTB=b[5]; break;
case 63: PORTA=a[7];PORTB=b[6]; break;
case 64: PORTA=a[7];PORTB=b[7]; break;
default: PORTA=0x00; PORTB=0x00;
}
}
}

Re: Светодиодная матрица. Первые шаги
Добавлено: Сб июл 09, 2022 18:17:09
mickbell
С кодом потом, пока давайте посмотрим на схему. Вы знаете, что такое светодиод? Это полупроводниковый прибор, который полагается питать определённым током, а не напряжением. Если подавать напряжение, значит, надо его "преобразовать" в ток добавочным резистором или генератором тока. Можно, конечно, последовательно с каждым светодиодом включить токозадающий резистор, но так не делают - слишком монстроидально это выглядит. Здесь достаточно восьми резисторов: ведь в каждый момент времени активен только один ряд светодиодов, а остальные прохлаждаются, зачем им резисторы? А вот куда их поставить - этот вопрос требует обсуждения. В случае, если развёртка делается строчками (скажем, на порт PB выдаётся бегущий ноль, а на порт PA - данные, зависящие от выводимого изображения), то именно в порт PA и надо ставить резисторы. Если сделать наоборот, то яркость свечения будет зависеть от количества одновременно горящих светодиодов, а это не есть хорошо. Ну а если столбцами (то есть на порт PA выдаётся бегущая единица, а на порт PB - данные в инверсном виде) - то резисторы надо ставить в порт PB.
И ещё имейте в виду: разряды порта, который делает развёртку, получатся перегруженными: каждый разряд питает максимум восемь светодиодов одновременно. (Неее, ну если управлять только одним, то ничего страшного, но ведь так неинтересно, не правда ли?) Учитывая, что каждый светодиод в таком устройстве горит 1/8 времени, ток его должен быть приблизительно в восемь раз больше того, при котором постоянном он нормально светится. То есть даже сверхъяркому светодиоду, которому нормально надо дать 2 мА, придётся выдать 16 мА, а их восемь штук... Нога 128 мА не выдаст, МК имеет полное право издохнуть. Проблема решается внешними ключами.
Ну а теперь посмотрим на код. Что там? Просто беготня одиночного огонька по строчкам, начиная с верхней, в каждый момент времени горит один светодиод. Так-то, конечно, ничего не погорит. Но результат и не очень интересен. Как этот код оформить - по-моему, этот разговор лучше отложить на потом. Пока подумайте над тем, что тут сказано.
Re: Светодиодная матрица. Первые шаги
Добавлено: Сб июл 09, 2022 18:26:13
Николай1961.
[uquote="mickbell",url="/forum/viewtopic.php?p=4257028#p4257028"]С кодом потом, пока давайте посмотрим на схему......... Пока подумайте над тем, что тут сказано.[/uquote]
Здравствуйте. Спасибо что откликнулись. Вы правы, здесь я подключил светодиоды на прямую, в реальной схеме конечно же будут транзисторные ключи и подтягивающие резисторы. Я пока моделирую в Proteus.
В действительности вместо светодиодов будут реле. Светодиоды для контроля работы программы.
Re: Светодиодная матрица. Первые шаги
Добавлено: Сб июл 09, 2022 18:36:51
mickbell
А практическая польза от этого монстра просматривается?
Re: Светодиодная матрица. Первые шаги
Добавлено: Сб июл 09, 2022 19:30:01
Николай1961.
[uquote="mickbell",url="/forum/viewtopic.php?p=4257038#p4257038"]А практическая польза от этого монстра просматривается?[/uquote]
Да, конечно. в будущем планирую подключить вместо светодиодов реле. Они будут управляться через матричную клавиатуру. Алгоритм такой, чрез клавиатуру задаётся номер реле и после ввода ENTER она срабатывает. Но это в будущем. А нагрузкой может быть любая эл.техника.
Re: Светодиодная матрица. Первые шаги
Добавлено: Сб июл 09, 2022 19:32:41
B@R5uk
[uquote="Николай1961.",url="/forum/viewtopic.php?p=4257032#p4257032"]Вы правы, здесь я подключил светодиоды на прямую, в реальной схеме конечно же будут транзисторные ключи и подтягивающие резисторы.[/uquote]Только не подтягивающие резисторы, а токоограничивающие. Ещё, транзисторные усилители тока понадобятся как по каналам выбора, так и по каналам данных. Всё потому, что когда МК тягает матричную нагрузку, то суммарный тягающий ток будет идти через пин питания МК и допустимая величина тока именно по этому пину будет ограничивать нагрузку без усиливающих транзисторов. Смотрите даташит на МК обычно по питанию можно пустить чуть больший ток, чем по пинам ввода-вывода, но совсем не на много больший.
[uquote="Николай1961.",url="/forum/viewtopic.php?p=4257032#p4257032"]В действительности вместо светодиодов будут реле.[/uquote]Если только вы будете держать включенными не более 8 реле, то работать должно без проблем. В противном случае придётся ставить параллельно реле довольно ёмкие конденсаторы, чтобы поддерживать реле включенным, когда обрабатываются другие строки/столбцы. Если такое вообще будет возможно на практике.
По коду всё совсем плохо. Это называется "индусский код", когда без всякой на то причины программист копи-пастит участки кода неимоверно его увеличивая (индусам-программистам платят за объём написанного кода). В вашем случае надо было воспользоваться операциями "деление нацело" и "взятие остатка". Последняя операция в си обозначается значком "%" (процент).
Re: Светодиодная матрица. Первые шаги
Добавлено: Сб июл 09, 2022 20:03:08
Николай1961.
[uquote="B@R5uk",url="/forum/viewtopic.php?p=4257077#p4257077"][/uquote]
В данное время изменил матрицу на более простую
Так же ввел изменения в код. Временно вместо кнопок переменная "k". В нее я ввожу "код кнопок". Так же файл программы разбил на два. Основная и вспомогательная.
Файл main.c
Спойлер
Код: Выделить всё
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>
#include "keyboard.h"
int main()
{
DDRA=0xFF;
DDRB=0xFF;
PORTA=0x00;
PORTB=0x00;
int k=4;
switch(k)
{
case 1: call(); c100(); break;
case 2: call(); c200(); break;
case 3: call(); c300(); break;
case 4: call(); c400(); break;
case 5: call(); c500(); break;
case 6: call(); c600(); break;
case 7: call(); c700(); break;
case 8: call(); c800(); break;
case 9: call(); c900(); break;
case 0: call(); c000(); break;
default: PORTA=0x00; PORTB=0x00;
}
while (1){
;
}
}
Вспомогательный файл keyboard.h
Спойлер
Код: Выделить всё
#define A PORTA
#define B PORTB
#define C _delay_ms(3000);
int a[9]= {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x00};
int b[9]={0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x00};
int i;
int call(void){
A=a[4];B=b[0];
C;
A=a[3];B=b[0];
C;
A=a[0];B=b[0];
C;
A=a[1];B=b[0];
C;
for(i=0;i<4;i++)
{
A=a[4];B=b[2];
C;
A=a[7];B=b[7];
C;
}
A=a[4];B=b[3];
C;
}
int c100(){ //100
A=a[1];B=b[1];
C;
A=a[4];B=b[2];
C;
A=a[1];B=b[1];
C;
A=a[4];B=b[2];
C;
A=a[3];B=b[0];
C;
A=a[4];B=b[0];
C;
A=a[7];B=b[7];
return 0;
}
int c200(){ //200
A=a[1];B=b[1];
C;
A=a[4];B=b[2];
C;
A=a[1];B=b[2];
C;
A=a[4];B=b[2];
C;
A=a[3];B=b[0];
C;
A=a[4];B=b[0];
C;
A=a[7];B=b[7];
return 0;
}
int c300(){ //300
A=a[1];B=b[1];
C;
A=a[4];B=b[2];
C;
A=a[1];B=b[3];
C;
A=a[4];B=b[2];
C;
A=a[3];B=b[0];
C;
A=a[4];B=b[0];
C;
A=a[7];B=b[7];
return 0;
}
int c400(){ //400
A=a[1];B=b[1];
C;
A=a[4];B=b[2];
C;
A=a[2];B=b[1];
C;
A=a[4];B=b[2];
C;
A=a[3];B=b[0];
C;
A=a[4];B=b[0];
C;
A=a[7];B=b[7];
return 0;
}
int c500(){ //500
A=a[1];B=b[1];
C;
A=a[4];B=b[2];
C;
A=a[2];B=b[2];
C;
A=a[4];B=b[2];
C;
A=a[3];B=b[0];
C;
A=a[4];B=b[0];
C;
A=a[7];B=b[7];
return 0;
}
int c600(){ //600
A=a[1];B=b[1];
C;
A=a[4];B=b[2];
C;
A=a[2];B=b[3];
C;
A=a[4];B=b[2];
C;
A=a[3];B=b[0];
C;
A=a[4];B=b[0];
C;
A=a[7];B=b[7];
return 0;
}
int c700(){ //700
A=a[1];B=b[1];
C;
A=a[4];B=b[2];
C;
A=a[3];B=b[1];
C;
A=a[4];B=b[2];
C;
A=a[3];B=b[0];
C;
A=a[4];B=b[0];
C;
A=a[7];B=b[7];
return 0;
}
int c800(){ //800
A=a[1];B=b[1];
C;
A=a[4];B=b[2];
C;
A=a[3];B=b[2];
C;
A=a[4];B=b[2];
C;
A=a[3];B=b[0];
C;
A=a[4];B=b[0];
C;
A=a[7];B=b[7];
return 0;
}
int c900(){ //900
A=a[1];B=b[1];
C;
A=a[4];B=b[2];
C;
A=a[3];B=b[3];
C;
A=a[4];B=b[2];
C;
A=a[3];B=b[0];
C;
A=a[4];B=b[0];
C;
A=a[7];B=b[7];
return 0;
}
int c000(){ //000
A=a[1];B=b[1];
C;
for(i=0;i<3;i++)
{
A=a[4];B=b[2];
C;
A=a[7];B=b[7];
C;
}
C;
A=a[3];B=b[0];
C;
A=a[4];B=b[0];
C;
A=a[7];B=b[7];
return 0;
}
Re: Светодиодная матрица. Первые шаги
Добавлено: Сб июл 09, 2022 21:01:12
mickbell
[uquote="B@R5uk",url="/forum/viewtopic.php?p=4257077#p4257077"]Если только вы будете держать включенными не более 8 реле, то работать должно без проблем. В противном случае придётся ставить параллельно реле довольно ёмкие конденсаторы, чтобы поддерживать реле включенным, когда обрабатываются другие строки/столбцы. Если такое вообще будет возможно на практике.[/uquote]Я так понимаю, релюшки будут включаться по одной, то есть тут не идёт речь про динамическую индикацию со скважностью 8. Ну а в этом случае, скажем, если взять реле IM03xx, ток обмотки которой всего-то 28 мА, то можно... эээ... попробовать прямое управление с МК. И ШИМить выход, дабы снизить ток удержания до разумного - тоже, наверно, можно попробовать.
PS. Неее, я тут неправ, реле могут включаться все. Не знаю, зачем такая масса релюшек, но если действительно надо, то я порекомендую I2C-расширитель портов, например, много раз мной применённый PCF8574 на восемь GPIO. На одну I2C-шину таких можно включить до восьми штук, ещё восемь - если взять восемь других микросхем с буквой A в типе (у них другой I2C-адрес). ТСу рекомендую рассмотреть этот вариант: шины МК неплохо бы знать и освоить. Чем смогу, помогу, да и многие помогут. Что касается [uquote="Николай1961.",url="/forum/viewtopic.php?p=4256855#p4256855"]Но как оказалось с возрастом тяжко впитывать новые знания.[/uquote] - ну, знаете, если ваш ник не врёт, то вы со мной одного возраста, то есть молодой ышшо.

Дорогу осилит идущий.
Re: Светодиодная матрица. Первые шаги
Добавлено: Вс июл 10, 2022 05:05:11
Николай1961.
[uquote="B@R5uk",url="/forum/viewtopic.php?p=4257077#p4257077"]Если только вы будете держать включенными не более 8 реле, то работать должно без проблем. В противном случае придётся ставить параллельно реле довольно ёмкие конденсаторы, чтобы поддерживать реле включенным, когда обрабатываются другие строки/столбцы. Если такое вообще будет возможно на практике.[/uquote]
На практике единовременно будет включено одно реле. Но не в этом суть. В данное время для меня практическое применение схемы не так важна. Меня больше интересует сам код.
[uquote="B@R5uk",url="/forum/viewtopic.php?p=4257077#p4257077"]По коду всё совсем плохо. Это называется "индусский код", когда без всякой на то причины программист копи-пастит участки кода неимоверно его увеличивая (индусам-программистам платят за объём написанного кода). В вашем случае надо было воспользоваться операциями "деление нацело" и "взятие остатка". Последняя операция в си обозначается значком "%" (процент).[/uquote]Вот я и пытаюсь научиться писать не "индусский код"

. Но пока видать не получается.
А с операциями "деление нацело" и "взятие остатка" пока не разобрался.
Добавлено after 1 minute 45 seconds:
[uquote="mickbell",url="/forum/viewtopic.php?p=4257127#p4257127"]- ну, знаете, если ваш ник не врёт, то вы со мной одного возраста, то есть молодой ышшо.

Дорогу осилит идущий.[/uquote]

Стараюсь
Re: Светодиодная матрица. Первые шаги
Добавлено: Вс июл 10, 2022 07:30:52
uldemir
Не всё так просто. Если включаете реле, то так и пишите, что реле. Реле в отличии от светодиодов устройство изотропное, т.е. срабатывает от тока в любом направлении. И из-за этого эффекта, у вас могут быть проблемы. При подаче одного потенциала на линию, а другого на строку у вас будет под током не одно реле, что находится на пересечении, но и куча цепочек из 2-3-4 итд реле. И если этого напряжения будет достаточно, чтобы сработало два последовательных = они стаботают. Потому как реле хоть и пороговое устройство, оно не ограничивает на себе напряжение как светодиод. Так что схема управления должна быть гораздо сложнее.
Так что код, хоть он и ужасный, пока не самое главное.
p.s. Вот добавлю картинку, что уже рисовал, в теме про включение лампочек накаливания в матрицу:

Тут похожие проблемы, на которые еще накладывается гистерезис характерный для реле и выброс индуктивности при обесточивании.
Re: Светодиодная матрица. Первые шаги
Добавлено: Вс июл 10, 2022 07:43:39
musor
с реле матрица в статике не прокатит в динамике МБ (ноэто не точно) но в динамике на каждое релей надо +2диота и время сканирования строк должно быть мене времи ни отьпуска релей так что частота сканирования ДР матрицы не мене 2-3кгц
Re: Светодиодная матрица. Первые шаги
Добавлено: Вс июл 10, 2022 09:12:05
B@R5uk
[uquote="Николай1961.",url="/forum/viewtopic.php?p=4257262#p4257262"]А с операциями "деление нацело" и "взятие остатка" пока не разобрался.[/uquote] Вместо
Код: Выделить всё
switch(k){
case 1: PORTA=a[0];PORTB=b[0]; break;
case 2: PORTA=a[0];PORTB=b[1]; break;
// Бла-бла-бла
case 63: PORTA=a[7];PORTB=b[6]; break;
case 64: PORTA=a[7];PORTB=b[7]; break;
}
Надо
Re: Светодиодная матрица. Первые шаги
Добавлено: Вс июл 10, 2022 09:51:40
Николай1961.
Для того что б был полее понятен мой замысел нарисовал предварительную схему.
Добавлено after 2 minutes 2 seconds:
[uquote="B@R5uk",url="/forum/viewtopic.php?p=4257326#p4257326"][uquote="Николай1961.",url="/forum/viewtopic.php?p=4257262#p4257262"]А с операциями "деление нацело" и "взятие остатка" пока не разобрался.[/uquote] Вместо
Код: Выделить всё
switch(k){
case 1: PORTA=a[0];PORTB=b[0]; break;
case 2: PORTA=a[0];PORTB=b[1]; break;
// Бла-бла-бла
case 63: PORTA=a[7];PORTB=b[6]; break;
case 64: PORTA=a[7];PORTB=b[7]; break;
}
Надо
[/uquote]
Спасибо, сегодня поэкспериментирую..

Re: Светодиодная матрица. Первые шаги
Добавлено: Вс июл 10, 2022 09:59:52
uldemir
А.... понятно почему светодиоды, но не понятно, почему так сложно? Копыт у МК не хватает? Есть сдвиговые регистры, расширители портов, дешифраторы. Если за раз нужно только одно сработавшее реле, есть еще чарлиплексинг - еще ног можно сэкономить. И нужна ли "оптронная развязка" между МК и реле? Ок, дальше тогда придумывайте сами.
Re: Светодиодная матрица. Первые шаги
Добавлено: Вс июл 10, 2022 10:11:32
Martian
оптроны ненужны.
Re: Светодиодная матрица. Первые шаги
Добавлено: Вс июл 10, 2022 10:14:51
КРАМ
Реле в матрицу без диодов ставить нельзя. При выключении защелкнется выход МК.
Re: Светодиодная матрица. Первые шаги
Добавлено: Вс июл 10, 2022 10:33:26
Martian
там же ULN2000. в ней, вроде бы, есть диод
Re: Светодиодная матрица. Первые шаги
Добавлено: Вс июл 10, 2022 15:04:59
mickbell
[uquote="КРАМ",url="/forum/viewtopic.php?p=4257356#p4257356"]Реле в матрицу без диодов ставить нельзя. При выключении защелкнется выход МК.[/uquote]Да и в матрицу их ставить как-то... эээ... Я предложил I2C-расширитель портов, предложение, однако, было проигнорировано. А зря. Платку на восемь релюшек с минимальным количеством лап в разъёме к МК (всего четыре, не считая питания обмоток релюшек) можно сделать отдельным конструктивом и количеством этих плат наращивать систему по потребности. Ну да дело вкуса ТС, настаивать не буду.
Добавлено after 2 minutes 21 second:
[uquote="Martian",url="/forum/viewtopic.php?p=4257363#p4257363"]там же ULN2000. в ней, вроде бы, есть диод[/uquote]Есть. Но как вам удалось разглядеть, что там именно ULN? Я, видимо, совсем слепой стал.
ТСу. По управлению могу предложить сделать по-другому: вводите с цифровой клавиатуры номер канала, затем * или # - чтобы соответственно включить или выключить нагрузку. Это позволит произвольно коммутировать любое число нагрузок. Клавиатур с таким набором кнопок - кругом и везде. Номер канала 0 - широковещательный, последовательность 0# выключит все нагрузки сразу.
Re: Светодиодная матрица. Первые шаги
Добавлено: Вс июл 10, 2022 15:15:04
uldemir
Удаляете в URL слово "medium" и наслаждаетесь полной картинкой:
https://img.radiokot.ru/files/149969/2ui82slyod.jpg
Re: Светодиодная матрица. Первые шаги
Добавлено: Вс июл 10, 2022 15:16:42
mickbell
Понятно, спасибо. Кстати, на схеме диоды ULN не задействованы, надо общий диодов подключать на питание релюшек... блииин, там же матрица, етить её...