Семисегментный LED-индикатор. Эффекты анимации

Обсуждаем контроллеры компании Atmel.
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Demiurg »

Так и я также попался... Казалось бы, а ...
Реклама
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Dimon456 »

Demiurg писал(а):Ну, есть способы. "Заменить на xxxx"
Куда уж проще.
В ексель делается табличка, один раз, на видео все покажу
Спойлер
Далее я использовал код ARV,

Код: Выделить всё

#define A   _BV(0)
#define B   _BV(1)
#define C   _BV(2)
#define D   _BV(3)
#define E   _BV(4)
#define F   _BV(5)
#define G   _BV(6)
#define H   _BV(7)
весь код не привожу.
Реклама
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Demiurg »

Я уже делал. Есть опыт...
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18546
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение ARV »

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

Мой уютный бложик... заходите!
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
Serzh2000
Опытный кот
Сообщения: 867
Зарегистрирован: Пт фев 27, 2015 12:00:53
Откуда: Рязанская область

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Serzh2000 »

как нарисовать анимацию, я понял.
Спойлер//ATMEGA328

//ВЫВОДЫ ATMEGA328 НА СЕГМЕНТЫ
#define A 1
#define B 4
#define C 16
#define D 64
#define E 128
#define F 2
#define G 8

int h1,h0,m1,m0; // h1 - десятки часов, h0 - еденицы часов и так далее
unsigned char digit_out[4], // буфер экрана (нумерация от 0 до 3 плюс четвертый невидимый разряд)
cur_dig; // тек.высвечиваемый символ (позиция)

unsigned char digits[] = {
(A+B+C+D+E+F), // 0
(B+C), // 1
(A+B+D+E+G), // 2
(A+B+C+D+G), // 3
(B+C+F+G), // 4
(A+C+D+F+G), // 5
(A+C+D+E+F+G), // 6
(A+B+C), // 7
(A+B+C+D+E+F+G), // 8
(A+B+C+D+F+G), // 9
(A+B+C+E+F+G), // A - 10
(C+D+E+F+G), // b - 11
(A+D+E+F), // C - 12
(B+C+D+E+G), // d - 13
(A+D+E+F+G), // E - 14
(A+E+F+G), // F - 15
(A+E+F), // Г - 16
(A+B+F+G), // 17 - символ градус цельсия
(0), // 18 - пусто
(C+E+G), // n - 19
(D+E+F+G), // t - 20
(A+B+C+E+F), // П - 21
(B+C+E+F+G), // Н - 22
(A+B+E+F+G), // Р - 23
(A+C+D+E+F+G), // Б - 24
(D+E+F), // L - 25
(E+G), // r - 26
(A+C+D+F+G), // S - 27
(E+F), // I - 28
(A+D+E+F+C), // G - 29
(A), // - - 30
(B), // _ - 31
(C), // - - 32
(D), // _ - 33
(E), // - - 34
(F), // _ - 35
(G), // - - 36
(A+E+F+B), // M - 37
(F+A+B+C) // M - 38
};

void setup() {
DDRD = 0xFF; // порт D на OUTPUT
DDRB = 0xFF; // порт B на OUTPUT
cli();
TCCR1A = 0b00000000; // OC1A Отключен
TCCR1B = 0b00001011; // делитель 64, сброс при совпадении 1A (режим СТС)
OCR1A = 0x041; // 5ms
TIMSK1 = 0b0000010; // запусе прерывания А таймера 1
sei();
}
void loop() {

h1=2; //тут будем читать потом время
h0=3;
m1=1;
m0=4;
/*
(A), // - - 30
(B), // _ - 31
(C), // - - 32
(D), // _ - 33
(E), // - - 34
(F), // _ - 35
(G), // - - 36
*/
for (byte i =0; i<7;++i){ // это сколько кадров

unsigned int AA[] = {30,31,32,33,34,35,h1};
unsigned int BB[] = {35,34,33,32,31,30,h0};
unsigned int CC[] = {30,31,36,35,m1,m1,m1};
unsigned int EE[] = {30,36,33,34,32,35,m0};

digit_out[0] = AA; // первай разряд
digit_out[1] = BB; // второй разряд
digit_out[2] = CC; // третий разряд
digit_out[3] = EE; // четвертый разряд


delay(10);
}
delay(100);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ISR(TIMER1_COMPA_vect) { //обработчик прерывания по совпадению А таймера 1, счетчик сбрасывается в 0

PORTD&=0b11110000; // потушить все (разряды - off)
PORTB=digits[digit_out[cur_dig]]; // символ на экран
PORTD |= (1<<cur_dig); // засветить нужный разряд (бит знакоместа - on)

cur_dig++; if (cur_dig > 3) {
cur_dig = 0;

}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


но как цифру нарисовать на семи сегментном индикаторе :shock: ??? ни как не могу понять :dont_know: как у этого парня получается...


может он выводит цифру на сегмент, а яркость ноль и потом яркость включает на сегменте нужном... :idea:

может кто подкинет идею, совет, предложение любой помощи буду рад. :beer:
Вложения
chasy2.rar
(46.46 КБ) 50 скачиваний
Реклама
Аватара пользователя
MLX90640
Опытный кот
Сообщения: 848
Зарегистрирован: Ср авг 03, 2022 05:22:56

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение MLX90640 »

Надо помедленнее, покадрово бы посмотреть, станет понятнее, что в каком порядке включается/выключается.
А так то в принципе он там сами цифры не трогает, а эффекты сделаны методом наложения посегментной маски по AND для гашения части сегментов. То есть, эффект представляет собой отдельный алгоритм, накладываемый на сегменты в процессе динамической индикации.
Как это реализовать. То есть, нужно иметь карту анимации всех сегментов в виде массива N*7*4 элементов, в котором N - количество кадров анимации, 7 - число сегментов, 4 - число разрядов. В массиве 1 означает пропускание сигнала на сегмент, 0 - запрет включения сегмента. И дальше при запуске эффекта через операцию AND эта маска подмешивается к формирователю выходных состояний индикации.
С анимационными эффектами конечно нужно поработать в плане красивости. Для этого нужно медленно покадрово просмотреть показанное видео и записать всё по порядку в карту анимации.
Реклама
Аватара пользователя
Serzh2000
Опытный кот
Сообщения: 867
Зарегистрирован: Пт фев 27, 2015 12:00:53
Откуда: Рязанская область

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Serzh2000 »

Надо помедленнее, покадрово бы посмотреть, станет понятнее
на ютубе есть шестеренка (в правом нижнем углу ) нажать и уменьшить скорость воспроизведения до 0,25
А так то в принципе он там сами цифры не трогает, а эффекты сделаны методом наложения посегментной маски по AND для гашения части сегментов.
это как? какой-нибудь примерчик или ссылку почитать.
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Demiurg »

2Serzh2000. Самый простой и тупой способ следующий: 7 сегментов. Дискретность времени мультиплексирования делаем кратно 7. Точка живёт сама по себе. Либо подумать.
Маски.
Скажем, нужно вывести по сегментно. Делаем маски:
Seg_A - 0x00000001
Seg_B - 0x00000010
Seg_C - 0x00000100
Seg_D - 0x00001000
Seg_E - 0x00010000
Seg_F - 0x00100000
Seg_G - 0x01000000
Теперь мы делаем так:
Нам нужно вывести 1234. Сами нарисуйте. У нас кратно 7. Первый такт. Маска A. В этот момент будут выводиться только сегменты A. И так далее. Нужна синхронизация. Чтобы первый выводимый символ совпадал с сегментом A.
Как то так. На каждый эффект свой алгоритм и свои маски.
Я создавал графические конструкторы. Есть программы, редакторы 7 сегментных дисплеев. Там тебе сразу и хексы сегментов выдает.
Если что, пиши в личку. Поэкспериментируем.
Аватара пользователя
MLX90640
Опытный кот
Сообщения: 848
Зарегистрирован: Ср авг 03, 2022 05:22:56

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение MLX90640 »

Ух, давно я не занимался семисегментниками.
Как я уже говорил, суть в чем должна быть: ни символы цифр, ни переменные, хранящие активируемые сегменты, не изменяются в процессе анимации. А при выводе каждого разряда в процессе динамическоей индикации происходит наложение маски эффекта по логическому AND на сегменты текущего разряда. Этот метод позволяет не влиять на формирование символов цифр, но независимо добавлять анимированный эффект гашения сегментов в разрядах в любом порядке по карте анимации
.
То есть, функция, реализующая динамическую индикацию, должна выглядеть вот в таком виде:

Код: Выделить всё

/** -------------------------------------------------------
 * @brief	Переключение шагов динамической индикации.
 */
void SegmentLED_DynaScan(void)
{
	static uint8_t digit = 0;
	uint8_t mask;

	mask = SegmentLED_Animation_GetMask(digit);
	SegmentLED_DigitOut(digit, buf[digit] & mask);
	digit++;
	if(digit >= NUM_DIG) digit = 0;
}
через интервал переключения разрядов вызывается эта функция, она для каждого текущего разряда индикатора берет из таблицы анимации значение накладываемой маски и накладывает по AND эту маску на данные для отображения сегментов в текущем разряде. Когда анимация остановлена, маска возвращается 0xFF, пропуская все сегменты. Текущая маска сегментов всего индикатора переключается другой функцией, ответственной за непосредственно воспроизведение анимации.
Аватара пользователя
Serzh2000
Опытный кот
Сообщения: 867
Зарегистрирован: Пт фев 27, 2015 12:00:53
Откуда: Рязанская область

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Serzh2000 »

Логическая операция AND (и)
AND обозначается знаком &.

Оператор AND выполняется с 2-мя битами, возьмём, к примеру, a и b. Результат выполнения операции AND равен 1, если a и b равняются 1. В остальных случаях результат равен 0. Например, с помощью AND мы можем вкл/выкл сегмента по нашему массиву эффектов

вот почти понимаю ... разжуйте еще немного желательно с примерами :shock:
Аватара пользователя
MLX90640
Опытный кот
Сообщения: 848
Зарегистрирован: Ср авг 03, 2022 05:22:56

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение MLX90640 »

Операция побитового AND между двумя числами с удовольствием применяется для наложения так называемой маски на число.
То есть,
0110 1111 - число
&
0001 1110 - маска
=
0000 1110 - результат. Только совпадение 1 в одноименных позициях битов числа и маски пропускает на выход 1 в этой позиции бита, а где нет совпадения - там бит на выход 0. Это свойство и используется для гашения разрядов, не влияя на исходные данные символа.

Щас, допишу до полноценной анимации, соберу на макетке, попробую показать. Давно с семисегментниками не работал уже.
Аватара пользователя
Serzh2000
Опытный кот
Сообщения: 867
Зарегистрирован: Пт фев 27, 2015 12:00:53
Откуда: Рязанская область

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Serzh2000 »

спасибо! покажите ... и код покажите.
Аватара пользователя
MLX90640
Опытный кот
Сообщения: 848
Зарегистрирован: Ср авг 03, 2022 05:22:56

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение MLX90640 »

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



А впрочем, вот демонстрационный набросок как есть:
Собственно, сам "смеситель" по маске:

Код: Выделить всё

/** -------------------------------------------------------
 * @brief	Переключение шагов динамической индикации.
 */
void SegmentLED_DynaScan(void)
{
	static uint8_t digit = 0;
	uint8_t mask;

	mask = SegmentLED_Animation_GetMask(digit);  // получить маску сегментов в текущем разряде
	SegmentLED_DigitOut(digit, buf[digit] & mask);  // смешать отображаемую цифру и маску и вывести в разряд
	digit++;
	if(digit >= NUM_DIG) digit = 0;
}
Анимация:

Код: Выделить всё

/* положение сегментов в байте */
#define SEG_A		(1 << 0)
#define SEG_B		(1 << 1)
#define SEG_C		(1 << 2)
#define SEG_D		(1 << 3)
#define SEG_E		(1 << 4)
#define SEG_F		(1 << 5)
#define SEG_G		(1 << 6)

/* карта анимации сегментов в четырех разрядах, по шагам */
static uint8_t anim1[][4] = {{SEG_A, SEG_D, SEG_A, SEG_D},
		{(SEG_A | SEG_B), (SEG_D | SEG_E), (SEG_A | SEG_B), (SEG_D | SEG_E)},
		 {(SEG_A | SEG_B | SEG_C), (SEG_D | SEG_E | SEG_F), (SEG_A | SEG_B | SEG_C), (SEG_D | SEG_E | SEG_F)},
		 {(SEG_A | SEG_B | SEG_C | SEG_D), (SEG_A | SEG_D | SEG_E | SEG_F), (SEG_A | SEG_B | SEG_C | SEG_D), (SEG_A | SEG_D | SEG_E | SEG_F)},
		 {0xFF, 0xFF, 0xFF, 0xFF}};

uint8_t *ptr = &anim1[0][0]; //указатель на текущую карту анимации и текущий шаг

/** -------------------------------------------------------
 * @brief	Получение маски сегментов в текущем разряде
 * @param digit - текущий активированный разряд
 * @return маска сегментов в текущем разряде
 */
uint8_t SegmentLED_Animation_GetMask(uint8_t digit)
{
	return *(ptr + digit);
}

/** -------------------------------------------------------
 * @brief	Переключение шагов анимации сегментов
 */
void AnimationStep(void)
{
	static uint8_t step = 0;

	ptr = &anim1[step][0];  // указатель ставится на первый разряд текущего шага анимации в карте
	step++;
	if(step > 4) step = 0;
}
Взаимодействие с индикатором (активация разряда, отображение сегментов):

Код: Выделить всё

/** -------------------------------------------------------
 * @brief	Активация сегментов выбранного разряда.
 * @param digit - номер разряда
 * @param seg_data - данные сегментов
 */
void SegmentLED_DigitOut(uint8_t digit, uint8_t seg_data)
{
	ALLSEGs_OFF();   // гашение всех сегментов

	switch(digit){
	case 0:        // разряд 1
		SELECT_DIGIT(DIG1_Pin);  // активация разряда 
		SEGs_OUT(seg_data);   // активация сегментов
		break;

	case 1:   // разряд 2
		SELECT_DIGIT(DIG2_Pin);  // активация разряда 
		SEGs_OUT(seg_data);   // активация сегментов
		break;

	case 2:
		SELECT_DIGIT(DIG3_Pin);
		SEGs_OUT(seg_data);
		break;

	case 3:
		SELECT_DIGIT(DIG4_Pin);
		SEGs_OUT(seg_data);
		break;
	}
}

Последний раз редактировалось MLX90640 Сб авг 13, 2022 22:03:21, всего редактировалось 1 раз.
Аватара пользователя
Serzh2000
Опытный кот
Сообщения: 867
Зарегистрирован: Пт фев 27, 2015 12:00:53
Откуда: Рязанская область

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Serzh2000 »

да!!! есть над чем подумать :shock:
спасибо! :beer:

Добавлено after 24 minutes 9 seconds:
а buf - это что? какую цифру хотим высветить.
Аватара пользователя
MLX90640
Опытный кот
Сообщения: 848
Зарегистрирован: Ср авг 03, 2022 05:22:56

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение MLX90640 »

Это данные для включения сегментов в каждом разряде индикатора. Я просто не дописывал все функции вывода как положено.

Код: Выделить всё

#define NUM_DIG			4

/* кодирование сегментов в байте */
#define SEG_A		(1 << 0)
#define SEG_B		(1 << 1)
#define SEG_C		(1 << 2)
#define SEG_D		(1 << 3)
#define SEG_E		(1 << 4)
#define SEG_F		(1 << 5)
#define SEG_G		(1 << 6)
#define SEG_dp		(1 << 7)

/* символы шрифта */
#define CH_0		(SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F        )
#define CH_1		(        SEG_B | SEG_C                                )
#define CH_2		(SEG_A | SEG_B |         SEG_D | SEG_E         | SEG_G)
#define CH_3		(SEG_A | SEG_B | SEG_C | SEG_D                 | SEG_G)
#define CH_4		(        SEG_B | SEG_C                 | SEG_F | SEG_G)
#define CH_5		(SEG_A         | SEG_C | SEG_D         | SEG_F | SEG_G)
#define CH_6		(SEG_A         | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G)
#define CH_7		(SEG_A | SEG_B | SEG_C                                )
#define CH_8		(SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G)
#define CH_9		(SEG_A | SEG_B | SEG_C | SEG_D         | SEG_F | SEG_G)

#define CH_A		(SEG_A | SEG_B | SEG_C         | SEG_E | SEG_F | SEG_G)
#define CH_B		(                SEG_C | SEG_D | SEG_E | SEG_F | SEG_G)
#define CH_C		(SEG_A                 | SEG_D | SEG_E | SEG_F        )
#define CH_D		(        SEG_B | SEG_C | SEG_D | SEG_E         | SEG_G)
#define CH_E		(SEG_A                 | SEG_D | SEG_E | SEG_F | SEG_G)
#define CH_F		(SEG_A                         | SEG_E | SEG_F | SEG_G)


static uint8_t buf[NUM_DIG] = {CH_0, CH_3, CH_5, CH_6}; // на индикаторе отображается число "0356" 
Аватара пользователя
Serzh2000
Опытный кот
Сообщения: 867
Зарегистрирован: Пт фев 27, 2015 12:00:53
Откуда: Рязанская область

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Serzh2000 »

а это что за функция ALLSEGs_OFF();
блин сложно это для меня :facepalm:
Вы полностью код покажите, пожалуйста

Добавлено after 5 minutes 1 second:
а это потушить все сегменты
Аватара пользователя
MLX90640
Опытный кот
Сообщения: 848
Зарегистрирован: Ср авг 03, 2022 05:22:56

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение MLX90640 »

Ааа, вон чо.. Ну так я пишу только для STM32, на AVR уже давно ничего не делаю. Поэтому полный код будет вам непонятен.
На том видео показан индикатор, работающий в режиме динамической индикации. Сегменты A-G всех четырех разрядов запараллелены, поэтому чтобы отобразить разные цифры в каждом разряде, в один момент времени активируется только один разряд. Индикаторы различаются по направлению светодиодов - с общим анодом (CA) и с общим катодом (CC). У индикатора CC чтобы зажечь сегмент, нужно на вывод разряда подать 0, а на выводы сегментов подавать высокие уровни.
Порядок работы с дин.индикацией будет таков
* Отображение первого разряда:
  • - погасить все сегменты
    - активировать разряд 1 (подав на него низкий уровень) и деактивировать разряды 2,3,4 (подав на них высокие уровни)
    - подать на сегменты нужную комбинацию для первого разряда, и он включится
*Выждать интервал времени, равный 1/4 периода дин.индикации.

* Отображение второго разряда:
  • - погасить все сегменты
    - активировать разряд 2 и деактивировать разряды 1,3,4
    - подать на сегменты нужную комбинацию для второго разряда
...и так далее до последнего разряда, и далее по кругу. Гашение сегментов перед сменой активированных разрядов нужно для исключения паразитной засветки сегментов в соседнем разряде. Интервалы переключения разрядов задаются каким-нибудь таймером и функция переключения разрядов вызывается в прерывании этого таймера. Весь круг индикации проходит например за 1/80 с, таким образом интервал переключения разрядов - 1/(80/4) = 1/20 или 0,05 с.

Такая хитрая посегментная анимация делается, как я показал выше, с помощью наложения маски сегментов. А анимация "бегущая строка" делается просто изменением содержимого переменных, хранящих данные сегментов для каждого разряда. Эти переменные - как раз и есть массив buf[4].
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Demiurg »

2Serzh2000. Развивайте у себя алгоритмическое мышление. Любой проект, даже рукоблудие выходного дня состряпанное на коленке левой пяткой рассматривается как полноценный проект. Это развивает отношение к своему труду.
Мне в свое время тоже это сказали. Берете бумагу, карандаш, стирательную резинку. И начинаете проектировать. Проектирование сверху вниз. Верх - это устройство в целом. Функционал, интерфейс. И начинаем дербанить на кубики. Эти кубики вы тоже дербаните. На каждом этапе анализируете. Представьте себе это устройство и кубики. Взаимодействие кубиков. И рисуйте, рисуйте. Да, лень порой. Переламывайте. Смотрите внутри себя на будущий результат.
Декомпозиция, анализ, синтез.
Аватара пользователя
Serzh2000
Опытный кот
Сообщения: 867
Зарегистрирован: Пт фев 27, 2015 12:00:53
Откуда: Рязанская область

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Serzh2000 »

вот есть, к примеру число h1=2;
из сегментов оно выстраивается так
DDRB = 0b11101101; //2
мне нужно читать биты в произвольном порядке и записывать и в переменную rezultat

DDRB = 0b11101101; // читаем
rezultat = 0b00100000; //записали

DDRB = 0b11101101; // читаем
rezultat = 0b00100001; //записали

DDRB = 0b11101101; // читаем
rezultat = 0b00100001; //записали
.
.
.
DDRB = 0b11101101; // читаем
rezultat = 0b11101101; //записали

как это написать :facepalm:
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Demiurg »

Чё бл@?!
Ответить

Вернуться в «AVR»