RGB-контроллер на Atmega8
Собрал на основе статьи "Управление RGB светодиодом c помощью аппаратной ШИМ ATmega8" и "Работа с прерываниями INT0 и INT1" RGB-контроллер.
Пока только три эффекта:
1. Плавная смена цветов с возможностью регулировки скорости смены цвета.
2. Статичный цвет с возможностью выбора цвета.
3. Режим цветного стробоскопа с регулировкой частоты вспышек.
Выкладываю код. Пока в таком виде, т.к. не получается "подсветить" с помощью code language='c' [код программы] /code. :(
Проблема в следующем: при достижении переменной "m" значения 4, программа "повисает" на 243 строке, а было задумано, что начнётся "Плавное изменение цвета" строка 65.
Хотя, те же самые операции с переменной "s" работают, т.е. идёт настройка параметров каждого эффекта по кругу, т.е. 1->16.
Пробовал использовать оператор "goto" с метками, для выбора режимов, но как-то не получается.
Прошу мне помочь! Это моя первая более-менее серьёзная программа. :)
#include <avr/io.h> #include <avr/interrupt.h> #include <stdint.h> #include <util/delay.h> #define R_channel OCR1AL #define G_channel OCR1BL #define B_channel OCR2 uint8_t volatile s = 1; // начальное значение переменной s volatile int m = 1; //начальное значение переменной m - "mode"(вид эффекта) volatile int a = 1; // начальное значение переменной a(величина задержки) volatile int b = 2500; // начальное значение переменной b(шаг изменения задержки) volatile int c = 2000; // значение задержки после вывода цвета(сколько времени горит цвет) void pause(uint8_t ms) { while(ms--) _delay_ms(1); } ISR(INT1_vect)//обработка прерываний INT1 (кнопка "+"/"mode") { ++m; //увеличиваем переменную m на 1 if (m == 4) m = 1; } ISR(INT0_vect)//обработка прерываний INT0 //(кнопка "-"/настройка праметров режима "mode") { ++s; //увеличиваем переменную s на 1 if (s == 16) s = 1; } void init_pwm (void) { DDRB=0x0e; //Инициализация портов, OC1A,OC1B,OC2 - выходы TCCR1A=(1<<COM1A1)|(1<<COM1B1)|(1<<WGM10); TCCR1B=(1<<CS10); TCCR2=(1<<CS20)|(1<<COM21)|(1<<WGM20); OCR1AL=0xff; //Начальный цвет - красный OCR1BL=0x00; OCR2=0x00; } int main(void) { unsigned char i; DDRD = 0x00; //все порты D вход GIMSK=0b11000000; //разрешаем прерывание int0 и int1 - кнопка MCUCR=0b00001010;// int by falling front - для кнопки 1 и 2(срабатывание при нажатии) //смотрим datasheet "Table 31. Interrupt Sense Control" sei(); //разрешение прерываний init_pwm(); //Инициализация ШИМ каналов //Плавное изменение цвета { while (m == 1) { for(i=0;i<255;i++) //Переход от красного к зеленому { R_channel--; G_channel++; pause(s); } for (i=0;i<255;i++) //Переход от зеленого к синему { G_channel--; B_channel++; pause(s); } for (i=0;i<255;i++) //Переход от синего к красному { B_channel--; R_channel++; pause(s); } } //Смена цвета { while (m == 2) { if (s == 1) { R_channel = 0xff; //красный G_channel = 0x00; B_channel = 0x00; } else if (s == 2) { R_channel = 0x44; G_channel = 0x00; B_channel = 0xff; //фиолетовый } else if (s == 3) { R_channel = 0x00; G_channel = 0xff; //зелёный B_channel = 0x00; } else if (s == 4) { R_channel = 0x00; G_channel = 0x00; B_channel = 0xff; //синий } else if (s == 5) { R_channel = 0xff; //жёлтый G_channel = 0xff; B_channel = 0x00; } else if (s == 6) { R_channel = 0xff; //розовый G_channel = 0x00; B_channel = 0x28; } else if (s == 7) { R_channel = 0xff; //белый G_channel = 0xff; B_channel = 0xff; } else if (s == 8) { R_channel = 0xff; //оранжевый G_channel = 0x5c; B_channel = 0x00; } else if (s == 9) { R_channel = 0x00; //чёрный G_channel = 0x00; B_channel = 0x00; } } } // Режим стробоскопа { while (m == 3) { R_channel = 0xff; G_channel = 0x00; B_channel = 0x00; _delay_us(c); R_channel = 0x00; //чёрный G_channel = 0x00; B_channel = 0x00; _delay_us(s*b); R_channel = 0x00; G_channel = 0xff; B_channel = 0x00; _delay_us(c); R_channel = 0x00; //чёрный G_channel = 0x00; B_channel = 0x00; _delay_us(s*b); R_channel = 0x00; G_channel = 0x00; B_channel = 0xff; _delay_us(c); R_channel = 0x00; //чёрный G_channel = 0x00; B_channel = 0x00; _delay_us(s*b); R_channel = 0xff; G_channel = 0xff; B_channel = 0x00; _delay_us(c); R_channel = 0x00; //чёрный G_channel = 0x00; B_channel = 0x00; _delay_us(s*b); R_channel = 0xff; G_channel = 0x00; B_channel = 0x28; _delay_us(c); R_channel = 0x00; //чёрный G_channel = 0x00; B_channel = 0x00; _delay_us(s*b); R_channel = 0x44; G_channel = 0x00; B_channel = 0xff; _delay_us(c); R_channel = 0x00; //чёрный G_channel = 0x00; B_channel = 0x00; _delay_us(s*b); R_channel = 0xff; G_channel = 0x5c; B_channel = 0x00; _delay_us(c); R_channel = 0x00; //чёрный G_channel = 0x00; B_channel = 0x00; _delay_us(s*b); } } } return 1; }
Всем спасибо! # if (m!=0)
Всем спасибо! #
if (m!=0) return; // проверка на условие помогла, все переключается как нада.
Убрал режим стробоскопа (тк не очень нужен и места много занимал)
Прошу не пинать ногами, я
Прошу не пинать ногами, я только учусь.
Лепил прогу из кусков,
Поправил нумерацию режимов - помогло.
Еще остался вопрос :
Почему когда выполняется цикл плавного изменения цвета прерывание, int1 срабатывает не сразу, а после того как выполнится последнее условие
если скорость маленькая- приходится долго ждать перехода в другой режим.
Делай, как vakula говорит.
Потому что у тебя так
Потому что у тебя так построено переключение режимов.
Рассмотрю подробнее. Когда программа выполняется в функции mode1, ты нажимаешь кнопку на INT1. Вызывается прерывание, в котором меняется переменная m. Далее довыполняется функция mode1. После того, как функция mode1 завершилась, производиться проверка режимов, и вызывается следующая функция - mode2.
Это можно устранить, вставив в mode1 проверку вида
if (m!=0) return;
То есть, если было нажатие кнопки - быстро выскочить из mode1, без довыполнения.
А ногами никто не пинает, все когда-то учились.
Спасибо! Добавил в свой код!
Спасибо! Добавил в свой код! :)
Как то странно, я б сделал
Как то странно, я б сделал все режими от проверки одной переменной а не двух, плюс переключение режимов для простоты в одну сторону, жмешь + и меняется режим по цепочке: 1->2->3->1->2->3.
Подскажите: составил
Подскажите:
составил программу приблизительно по этой модели
Вопрос: почему по прерыванию INT 0 переключается скорость/ цвет сразу же,
а по INT 1 режим переключается не сразу. Прерывание ведь важнее обычных операций?
Например если работает 1-й режим- перелив цвета скорость можно изменить сразу же,
если нажать на кнопку режима то смена режима не осуществится пока не завершится
1-й режим - цвет не дойдет до красного.
Почему может не работать 3-й режим? Первые два работают- при нажатии след раз
на кнопку режима ничего не происходит, при след нажатии происходит переход на
первый режим.
По поводу каши я тоже
По поводу каши я тоже согласен, обычно структура управляющей программы такая:
Библиотеки,
Переменные глобальные,
Прототипы программ,
Обработчик прерываний,
Программы,
.........
Программы,
Основная программа.
Вот так вот не гласно принято оформлять код. Оно читается тогда хорошо, все сразу видно.
Легко проанализировать и разобраться.
У тебя проверка режимов
У тебя проверка режимов начинается с 1-цы
Вот.
А "переключалка" режимов работает от 0 до 2.
То есть, переменная m может принимать значения от 0 до 2 включительно.
А в коде выше, ты сравнивает m с 3.
И еще, оформь покрасивей функции, то я как-то сразу не понял, где main(), а где остальные функции. Каша.
В данном случаи очень помогло
В данном случаи очень помогло бы видео работы устройства! Сними на мобилку хотя бы, выложи на ютубе и мы все вместе посекундно просмотрим и найдем в чем проблема.
Вот видео работы. Качество
Вот видео работы. Качество оставляет желать лучшего... но.
Сомневаюсь что видео сильно поможет...
Третий режим- стробоскоп, код написал San в том исходнике, что он прислал, этот фрагмент кода мигал,
если не секрет, что это за
если не секрет, что это за лента такая? где покупается, и сколько примерно стоит?
ну и марку ее конечно, тоже, если можно.
лента с смд rgb светодиодами.
лента с смд rgb светодиодами. Покупается на ближайшем радиорынке, в случае Киева это Кар-Дачи, цена по разному, в зависимости от плотности забивки светодиодами
Ура! Тема интересна не мне одному. :)
Что подсвечивать собрался? Мебель, машину? :)
А чтобы не останавливаться на достигнутом можно ещё сделать изменение цветов и режимов под музыку.
И ещё ИК пульт приделать неплохо было бы.
А вот исправление, чтобы в режиме "Плавное изменение цвета" можно было сразу менять режим и не ждать до "красного".
Удалось "подсветить" код! :)
Спасибо! Помогло!
Заработало! Только в выражении m=(m+1)%4, четвёрку поменял на 3, и m==0, m==1, m==2.
:)
Вот такой вопросик теперь: как картинки и видео youtube вставлять в форум? Хотелось бы оформить в нормальном виде всё: схему, фотки и видео работы готового устройства выложить хочу. :)
Ага, завтыкал с количеством
Поздравляю :) Ага, завтыкал с количеством режимов.
Статью можно оформить следующим образом. Заходим в Create content->Story.
Картинки вставить так:
"img src="http://avrlab.com/upload_files/rec_front.jpg" alt="фото GPS приемника" width="600" height="400" /"
Вместо первой и последней " надо поставить < и > соответственно.
Картинки и другие файлы можно загрузить на сайт с помощью File attachments. Таже стоит input format поставить как ас.
Видео же с ютуба вставляются таким образом: на запущенном видео клацаем правой клавишей, появится меню, в нем выбираем "Copy embed html" потом этот код вставляем в статью.
Окей. Сделаю фото-
Окей. Сделаю фото- видеоматериалов и будет статья. :)
По программе: пугают такие строчки - Program: 7670 bytes (93.6% Full). А если убрать из программы "режим стробоскопа", то гораздо меньше занимает места.Чего-то я набакланил...
Так же обрати внимание в
Так же обрати внимание в свойстве проэкта в AVR Studio есть пункт "Оптимизация", попробуй поиграться со значением степени оптимизации. Бывали случаи уменьшения кода до 50% :-)
Правда бывали и негативные случаи, начинались сбои в работе библиотеки delay.h
Тип double в функции
Тип double в функции _delay_us(double __us) жрет очень много флеш-памяти, попробуй как-то иначе организовать задержку. Т.е. использовать функцию
Код для умножения и преобразования в double будет всего 1 раз прописан в программе, а не N раз, как у тебя.
Выбери Create Content а потом
Выбери Create Content а потом Story.
Будет страница со статьей как все остальные на сайте.
Пиши побольше описания, читать будут и начинающие тоже, больше подробностей - больше внимания пользователей, больше вопросов :-)
А попробуй ++s; //увеличиваем
А попробуй
в прерываниях по INT0,INT1 заменить на следующее:
Мне встречались глюки с оператором i++, если i - int-товская переменная.
Стоит не забывать о дребезге контактов, может втулить в прерывание код вида:
Вместо конструкции
можно использовать m=(m+1)%4, % - остаток от деления. Переменная m будет принимать значения от 0 до 3. Но это на вкус и цвет :)
Также я бы поменял местами строки,
но это тоже больше для красоты. Т.е. сперва полностью инициализируем все, а потом уже врубаем прерывания.
Дребезг контактов 100% будет
Дребезг контактов 100% будет надо ставить
И по поводу поменть местами согласен потому что это немого не корректно будет разрешить прерывания раньше чем инициализация ШИМ.
Дребезг
Дребезг убрал аппаратными средствами пока. 100 нФ на землю.