AVR и светодиодный индикатор

Обсуждаем контроллеры компании Atmel.
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: AVR и светодиодный индикатор

Сообщение Аlex »

Посмотрел повнимательнее код. Что там можно вообще соптимизировать, не понятно ?
В условиях встречается совершенно разный код. Где-то работа с еепром, где-то её нет, где-то какие-то условия дополнительные, в других - нет, ...
О каких одинаковых кодах ТС говорил ?
Реклама
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: AVR и светодиодный индикатор

Сообщение ARV »

Аlex писал(а):Что там можно вообще соптимизировать, не понятно ?
опыт подсказывает, что как-раз в подобном коде и можно очень здорово все оптимизировать. только начинать придется не с этого места :)
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Реклама
melandr
Вымогатель припоя
Сообщения: 580
Зарегистрирован: Пт ноя 08, 2013 01:01:18

Re: AVR и светодиодный индикатор

Сообщение melandr »

[uquote="ARV",url="/forum/viewtopic.php?p=3606220#p3606220"]Описали структуру с параметрами таймера.
Создали массив таких структур.
Создали функцию, которая получает на входе указатель на структуру таймера (или номер этой структуры в массиве), и изменяет эту структуру.
Вызываете эту функцию из пунктов меню с нужным указателем (или номером).
В чем проблема?[/uquote]
1.
Спойлер//Структура для хранения переменных таймеров
typedef struct {
unsigned char work; //состояние таймера 1 - включен, 0 - выключен
unsigned char on_hour; //часы включения
unsigned char on_min; //минуты включения
unsigned char off_hour; //часы выключения
unsigned char off_min; //минуты выключения
} timer;
2.
Спойлер//Переменные таймеров, которые сохраняются в оперативной памяти
timer time[4];
3. А вот с функцией завтык. void Function(timer *t)
а вот дальше не могу сообразить, что в функции делать и как ее вызывать из пунктов меню.
Аlex писал(а):Сколько условий, кошмар ... :facepalm:
Сделайте лучше через switch-case, быстрее код будет выполняться.

По поводу таймеров и оптимизации кода - не понятно. Что Вы хотите соптимизировать ?
Хоть и код в условиях примерно одинаковый, условия то разные. Единственное, что напрашивается, - таблица с перебором в цикле. Но, время выполнение такого кода будет даже больше текущего варианта.
Код в условиях примерно одинаков, отличаются пункты меню. Один из вариантов, мне коллега предлагал хранить параметры таймеров в многомерном массиве, в соответствии с пунктами меню и считывать либо записывать настройки с помощью цикла.
ARV писал(а):да, кстати... проверку eeprom_is_ready() перед вызовом функций работы с EEPROM делать не надо - она там уже встроена. эта проверка требуется только в случаях работы с EEPROM в обработчиках прерываний и/или перед тем, как перевести МК в режим SLEEP_POWER_DOWN.
Спасибо, не знал, подкорректирую код
Аlex писал(а):Посмотрел повнимательнее код. Что там можно вообще соптимизировать, не понятно ?
В условиях встречается совершенно разный код. Где-то работа с еепром, где-то её нет, где-то какие-то условия дополнительные, в других - нет, ...
О каких одинаковых кодах ТС говорил ?
Вот этот фрагмент
Спойлер//Настройка таймера t1
if (menu == 11000) {
time[0].on_hour = EditHour(time[0].on_hour, button);
if (eeprom_is_ready())
eeprom_update_byte(&t[0].on_hour, time[0].on_hour);
}
if (menu == 11001) {
time[0].on_min = EditMinute(time[0].on_min, button);
if (eeprom_is_ready())
eeprom_update_byte(&t[0].on_min, time[0].on_min);
}
if (menu == 11010) {
time[0].off_hour = EditHour(time[0].off_hour, button);
if (eeprom_is_ready())
eeprom_update_byte(&t[0].off_hour, time[0].off_hour);
}
if (menu == 11011) {
time[0].off_min = EditMinute(time[0].off_min, button);
if (eeprom_is_ready())
eeprom_update_byte(&t[0].off_min, time[0].off_min);
}
if (menu == 1102) {
if (button == BTN_SHRT_RIGHT) {
if (time[0].work == 0) time[0].work = 1;
}

if (button == BTN_SHRT_LEFT) {
if (time[0].work == 1) time[0].work = 0;
}
if (eeprom_is_ready())
eeprom_update_byte(&t[0].work, time[0].work);
}
//Настройка таймера t2
if (menu == 11100) {
time[1].on_hour = EditHour(time[1].on_hour, button);
if (eeprom_is_ready())
eeprom_update_byte(&t[1].on_hour, time[1].on_hour);
}
if (menu == 11101) {
time[1].on_min = EditMinute(time[1].on_min, button);
if (eeprom_is_ready())
eeprom_update_byte(&t[1].on_min, time[1].on_min);
}
if (menu == 11110) {
time[1].off_hour = EditHour(time[1].off_hour, button);
if (eeprom_is_ready())
eeprom_update_byte(&t[1].off_hour, time[1].off_hour);
}
if (menu == 11111) {
time[1].off_min = EditMinute(time[1].off_min, button);
if (eeprom_is_ready())
eeprom_update_byte(&t[1].off_min, time[1].off_min);
}
if (menu == 1112) {
if (button == BTN_SHRT_RIGHT) {
if (time[1].work == 0) time[1].work = 1;
}

if (button == BTN_SHRT_LEFT) {
if (time[1].work == 1) time[1].work = 0;
}
if (eeprom_is_ready())
eeprom_update_byte(&t[1].work, time[1].work);
}
//Настройка таймера t3
if (menu == 11200) {
time[2].on_hour = EditHour(time[2].on_hour, button);
if (eeprom_is_ready())
eeprom_update_byte(&t[2].on_hour, time[2].on_hour);
}
if (menu == 11201) {
time[2].on_min = EditMinute(time[2].on_min, button);
if (eeprom_is_ready())
eeprom_update_byte(&t[2].on_min, time[2].on_min);
}
if (menu == 11210) {
time[2].off_hour = EditHour(time[2].off_hour, button);
if (eeprom_is_ready())
eeprom_update_byte(&t[2].off_hour, time[2].off_hour);
}
if (menu == 11211) {
time[2].off_min = EditMinute(time[2].off_min, button);
if (eeprom_is_ready())
eeprom_update_byte(&t[2].off_min, time[2].off_min);
}
if (menu == 1122) {
if (button == BTN_SHRT_RIGHT) {
if (time[2].work == 0) time[2].work = 1;
}

if (button == BTN_SHRT_LEFT) {
if (time[2].work == 1) time[2].work = 0;
}
if (eeprom_is_ready())
eeprom_update_byte(&t[2].work, time[2].work);
}
//Настройка таймера t4
if (menu == 11300) {
time[3].on_hour = EditHour(time[3].on_hour, button);
if (eeprom_is_ready())
eeprom_update_byte(&t[3].on_hour, time[3].on_hour);
}
if (menu == 11301) {
time[3].on_min = EditMinute(time[3].on_min, button);
if (eeprom_is_ready())
eeprom_update_byte(&t[3].on_min, time[3].on_min);
}
if (menu == 11310) {
time[3].off_hour = EditHour(time[3].off_hour, button);
if (eeprom_is_ready())
eeprom_update_byte(&t[3].off_hour, time[3].off_hour);
}
if (menu == 11311) {
time[3].off_min = EditMinute(time[3].off_min, button);
if (eeprom_is_ready())
eeprom_update_byte(&t[3].off_min, time[3].off_min);
}
if (menu == 1132) {
if (button == BTN_SHRT_RIGHT) {
if (time[3].work == 0) time[3].work = 1;
}

if (button == BTN_SHRT_LEFT) {
if (time[3].work == 1) time[3].work = 0;
}
if (eeprom_is_ready())
eeprom_update_byte(&t[3].work, time[3].work);
}
ARV писал(а):[опыт подсказывает, что как-раз в подобном коде и можно очень здорово все оптимизировать. только начинать придется не с этого места :)
Если Вам не сложно немного подсказать, был бы рад услышать замечания и критику.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: AVR и светодиодный индикатор

Сообщение ARV »

melandr писал(а):не могу сообразить, что в функции делать и как ее вызывать из пунктов меню
что в ней делать - это вам виднее. например, если пункт меню служит для изменения настроек ЧАСОВ ВКЛЮЧЕНИЯ таймера, то функция будет какой-то такой

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

void Function(timer *t){
   unsigned char tmp = t->on_hour; // запоминаем текущее значение часов включения
   if(!edit_hour(t.on_hour)) t->on_hour = tmp; // если редактирование не завершено корректно, восстанавливаем прежнее значение
}
в общем, никто, кроме вас, не знает, что именно вы собираетесь делать в этой функции.

а вот как вызывать эту функцию из пунктов меню - это вопрос совсем другой, и ответ на него зависит от того, как вы систему меню реализовали, что тоже никто, кроме вас, не знает.

Добавлено after 2 minutes 8 seconds:
melandr писал(а):Если Вам не сложно немного подсказать
чтобы подсказывать, надо быть в курсе ваших планов.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Реклама
Эиком - электронные компоненты и радиодетали
melandr
Вымогатель припоя
Сообщения: 580
Зарегистрирован: Пт ноя 08, 2013 01:01:18

Re: AVR и светодиодный индикатор

Сообщение melandr »

Реализацию меню для микроконтроллера использовал вот из этой статьи http://easymcu.ucoz.ru/publ/11-1-0-88
Показалась несложной для повторения. Просто так как необходимо менять по 5 параметров для каждого таймера, таймеров 4. То минимум 20 пунктов меню получаем. Плюс еще вывод текущего времени и настройка текущего времени. Это еще 3 пункта меню. Также есть еще таймер обратного отсчета - это еще 3 пункта меню.
Работает вся система так. При включении микроконтроллера выводится текущее время и в переменную, которая показывает текущее местоположение в меню заносится значение 1. А дальше в зависимости от нажатий кнопок, происходит либо умножение на 10 либо прибавление/вычитание 1. А через конструкцию switch/case вывод необходимых значений в зависимости от того, какое значение в переменной menu.
Реклама
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: AVR и светодиодный индикатор

Сообщение ARV »

20 пунктов меню? серьезно?
я до такой крутости никогда не доходил... обычно хватало 5-6 пунктов на ВСЕ настройки девайса. вот, например: https://radiokot.ru/circuit/digital/home/25/ - до 100 событий срабатывания таймера, меню 6 пунктов... а у вас на 4 аж 20 пунктов.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Реклама
melandr
Вымогатель припоя
Сообщения: 580
Зарегистрирован: Пт ноя 08, 2013 01:01:18

Re: AVR и светодиодный индикатор

Сообщение melandr »

У Вас проще, потому что используется ЖК дисплей. А у меня для таймера используется 4-х разрядный семисегментный светодиодный индикатор. поэтому я не могу одновременно вывести название пункта меню и параметр этого меню Приходится выводить сначала название пункта меню, а потом по нажатию Enter сначала выводить название подменю, а потом параметр. А это естественно увеличивает количество пунктов. Хотя может я что-то не понял в реализации, но до другого не додумался.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: AVR и светодиодный индикатор

Сообщение ARV »

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

Мой уютный бложик... заходите!
melandr
Вымогатель припоя
Сообщения: 580
Зарегистрирован: Пт ноя 08, 2013 01:01:18

Re: AVR и светодиодный индикатор

Сообщение melandr »

Значит какая стоит задача.
Есть внешнее устройство с собственной автоматикой (вентиляционная установка). Так как заказчик (подрядчик) решили сначала сэкономить, то контроллер этой установки включается кнопкой ПУСК (НО) и отключается кнопкой СТОП (НЗ). Режима включения и выключения по расписанию нет. Необходимо было автоматизировать процесс включения и отключения. И достаточно было 4-х интервалов работы в сутки. Было принято решение включиться в схему управления вентиляционной установкой через дополнительные кнопки ПУСК и СТОП, реализуемые в таймере через 2 реле. Ну и чтобы не было жесткой привязки по времени без возможности изменения, необходим интерфейс взаимодействия с пользователем (дисплей и кнопки). Возможно стоило применить ЖКИ, но так как основной контроллер использует 3-х разрядный светодиодный индикатор (http://www.raut-automatic.kiev.ua/snyat ... on-02.html), то решил использовать тоже светодиодный индикатор.
Также заказчик захотел, чтобы если он вручную включит вентиляционную установку, то таймер должен этот момент отследить, и запустить регулируемый таймер обратного отсчета. И после отключить установку. Отслеживание работы вент. установки происходит через нормально открытый контакт пускателя вентилятора. Как-то так. До этого особо много устпройств на МК не делал, так сказать проба сил.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: AVR и светодиодный индикатор

Сообщение ARV »

Стало понятнее, но не сильно. Например, абсолютно не понятен принцип меню. Я ж просил "как если бы вы мне его продавали" :) Сколько кнопок, сколько разрядов, как режимы индицируются - все это где?

Добавлено after 9 minutes 48 seconds:
Вот в одном из своих "проектов" я применял три дополнительных светодиода, чтобы как-то разные режимы обозначить без задействования главного 7-сегментного индикатора. У вас как?
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
melandr
Вымогатель припоя
Сообщения: 580
Зарегистрирован: Пт ноя 08, 2013 01:01:18

Re: AVR и светодиодный индикатор

Сообщение melandr »

Для управления используется 4 кнопки - ESC, ENTER, LEFT, RIGHT. Для индикации используется 4-х разрядный семисегментный индикатор. При включении таймера на индикаторе отображается текущее время. При нажатии кнопки RIGHT - отображается время задержки отключения (может быть от 1 до 99 минут). Возврат к текущему времени происходит при нажатии кнопки LEFT. При нажатии кнопки ENTER - на индикаторе отображается cLoc - подменю настройки текущего времени. При нажатии RIGHT - отображается conF - настройка таймеров. Теперь при нажатии ENTER попадаем либо в настройку текущего времени, либо в подменю выбора таймеров. Допусти мы нажали ENTER находясь в меню cloc. Сначала отображаются часы - для редактирования нажимаем ENTER, значение часов начинает мигать. Кнопками LEFT и RIGHT изменяем значение текущих часов. Подтверждаем кнопкой ENTER. Кнопкой RIGHT переходим к минутам текущего времени и по аналогии с текущими часам.
Если нажали ENTER находясь в меню conf. На экране отображается t1 - настройка таймера Т1. Кнопки LEFT, RIGHT - отображается t2, t3, t4. Допустим на экране t1 и нажимаем ENTER, попадаем в меню настройки времени включения - t1on. Еще раз ENTER - отображаются часы включения. Далее по аналогии с текущим временем. И так по всем таймерам.
ЗЫ: ну у Вас там и инструкция конкретная.
Во вложении проект AVR Studio 4.19 и проект Протеус 8.6 Можно запустить пощелкать кнопками будет видна структура меню.
ЗЫ1: спасибо за ссылочку на Ваш проект с исходниками, почитаю.
Вложения
timer.rar
(216.16 КБ) 172 скачивания
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: AVR и светодиодный индикатор

Сообщение ARV »

ну так вы описали все просто шикарно! меню у вас уже "щелкает", каждое меню имеет некий "текст" и соответствующую этому тексту функцию.
функция может быть "подменю" или конкретное действие.
подменю вы тоже, как я понял (протеус недоступен), сделали - осталось пустяк!
меню ваших 4 таймеров отличается друг от друга только номером таймера, поэтому сделайте соответствующий раздел так, чтобы "текст" подменю формировался по НОМЕРУ таймера. то есть стрелками в бок меняйте номер таймера и выводите его "название", а если нажмут Enter - у вас уже есть номер по массиву и останется только "отредактировать" таймер той же самой функцией, как и текущие часы...
по-мому, достаточно просто все.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
melandr
Вымогатель припоя
Сообщения: 580
Зарегистрирован: Пт ноя 08, 2013 01:01:18

Re: AVR и светодиодный индикатор

Сообщение melandr »

Роман, что-то сижу, смотрю на код настройки таймера и не понимаю. У меня значение переменной menu, которое указывает на пункт меню, никак не поддается математической логике. Как его можно подвязать к номеру таймера?
Спойлер//Настройка таймера t1
if (menu == 11000) {
time[0].on_hour = EditHour(time[0].on_hour, button);
if (eeprom_is_ready())
eeprom_update_byte(&t[0].on_hour, time[0].on_hour);
}
if (menu == 11001) {
time[0].on_min = EditMinute(time[0].on_min, button);
if (eeprom_is_ready())
eeprom_update_byte(&t[0].on_min, time[0].on_min);
}
if (menu == 11010) {
time[0].off_hour = EditHour(time[0].off_hour, button);
if (eeprom_is_ready())
eeprom_update_byte(&t[0].off_hour, time[0].off_hour);
}
if (menu == 11011) {
time[0].off_min = EditMinute(time[0].off_min, button);
if (eeprom_is_ready())
eeprom_update_byte(&t[0].off_min, time[0].off_min);
}
if (menu == 1102) {
if (button == BTN_SHRT_RIGHT) {
if (time[0].work == 0) time[0].work = 1;
}

if (button == BTN_SHRT_LEFT) {
if (time[0].work == 1) time[0].work = 0;
}
if (eeprom_is_ready())
eeprom_update_byte(&t[0].work, time[0].work);
}
Для второго таймера код меню будет начинаться на 111
Последний раз редактировалось melandr Пн апр 01, 2019 19:17:06, всего редактировалось 1 раз.
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Re: AVR и светодиодный индикатор

Сообщение Dimon456 »

У меня некорректно отображается или может протеус слишком старый
СпойлерИзображение
Еще такой вопросик, всегда думал что динамическая индикация такого рода индикатора должна располагаться в прерывании таймера, а не в основном коде?
А за чем в конце основного кода

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

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

Re: AVR и светодиодный индикатор

Сообщение ARV »

return 0 в конце main - дань традиции, чтобы пендитный компилятор не выдавал предупреждение.
Dimon456 писал(а):динамическая индикация такого рода индикатора должна располагаться в прерывании таймера, а не в основном коде?
по-моему, делать динамическую индикацию в главном цикле разумно только на конкурсе "самый дикий код" :)
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
melandr
Вымогатель припоя
Сообщения: 580
Зарегистрирован: Пт ноя 08, 2013 01:01:18

Re: AVR и светодиодный индикатор

Сообщение melandr »

Добрый вечер.
Вот окно протеуса
Изображение
Индикация располагается в прерывании. Используется библиотека
//***************************************************************************
//
// Description.: Драйвер 7-ми сегментного 4-ех разрядного индикатора
//
//***************************************************************************
Ресурс так сразу не вспомню.
Настраивается таймер с периодом 1 мс. В прерывании в буфер индикатора заносится выводимое значение, а уже в основном цикле функция
Спойлер//Обновляем информацию на индикаторе с частотой 300 Гц
if (updDisplay) {
IND_Update();
updDisplay = 0;
}
В прерывании только выставляется флаг, когда необходимо обновить информацию на индикаторе. Чем библиотека удобна, что можно сконфигурировать вывод на разные индикаторы с произвольным подключением разрядов и сегментов.
Основная функция объявляется как
int main( void )
следовательно, если программа завершилась корректно, то должно быть возвращено значение 0.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: AVR и светодиодный индикатор

Сообщение ARV »

melandr писал(а):следовательно, если программа завершилась корректно, то должно быть возвращено значение 0
формально - это правильно сказано. но для МК это не имеет никакого значения.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
melandr
Вымогатель припоя
Сообщения: 580
Зарегистрирован: Пт ноя 08, 2013 01:01:18

Re: AVR и светодиодный индикатор

Сообщение melandr »

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

Re: AVR и светодиодный индикатор

Сообщение ARV »

melandr писал(а):окончание программы не имеет смысла
окончание, может, смысл и имеет (например, если предусмотрен WDT), но вот возврат значения бессмысленен однозначно :)
melandr писал(а):А то пока ничего не получается
вермя в часах вы задаете какой-то функцией - так? время для таймера чем отличается? только номером таймера.
приведите структуру для настройки часов к точно такому же виду, как и для таймера и пользуйтесь одной и той же функцией для всех слечаев.

или что не получается-то?

Добавлено after 6 minutes 35 seconds:
кстати, что-то ваш проект в протеусе ничего не высвечивает на индикаторе...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Re: AVR и светодиодный индикатор

Сообщение Dimon456 »

[uquote="ARV",url="/forum/viewtopic.php?p=3606681#p3606681"]
melandr писал(а):следовательно, если программа завершилась корректно, то должно быть возвращено значение 0
формально - это правильно сказано. но для МК это не имеет никакого значения.[/uquote]0-FALSE-Ложь
1-TRUE-Истина
следовательно, если программа завершилась корректно, то должно быть возвращено значение 1
Ответить

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