RGB сосулька

Обсуждаем контроллеры компании Atmel.
Аватара пользователя
ment-bu2
Встал на лапы
Сообщения: 109
Зарегистрирован: Ср дек 09, 2009 00:22:27
Откуда: г. Бендеры Приднестровье.

Re: RGB сосулька

Сообщение ment-bu2 »

Изображение
это желтеньким чего такое?


Если я правильно понял - то это кажись резюки...?

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

Re: RGB сосулька

Сообщение Serzh2000 »

сопротивления 200 Ом их там 20 штук
Аватара пользователя
ment-bu2
Встал на лапы
Сообщения: 109
Зарегистрирован: Ср дек 09, 2009 00:22:27
Откуда: г. Бендеры Приднестровье.

Re: RGB сосулька

Сообщение ment-bu2 »

сопротивления 200 Ом их там 20 штук

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

Re: RGB сосулька

Сообщение Serzh2000 »

программатор
Вложения
avrdude_prog-v.3.3.zip
(813.53 КБ) 201 скачивание
Аватара пользователя
ment-bu2
Встал на лапы
Сообщения: 109
Зарегистрирован: Ср дек 09, 2009 00:22:27
Откуда: г. Бендеры Приднестровье.

Re: RGB сосулька

Сообщение ment-bu2 »

программатор

Принял. Спасибо! Буду делать звёздочку. Удачи Вам!!
Аватара пользователя
Bullet
Вымогатель припоя
Сообщения: 557
Зарегистрирован: Пт июл 04, 2008 19:29:15
Откуда: Мурманск

Re: RGB сосулька

Сообщение Bullet »

https://radiokot.ru/circuit/light/run/78/
Есть эффект капли, читай, изучай, делай.
Аватара пользователя
GoldenAndy
Поставщик валерьянки для Кота
Сообщения: 1925
Зарегистрирован: Чт июл 28, 2016 07:58:37
Откуда: Kyiv, UA
Контактная информация:

Re: RGB сосулька

Сообщение GoldenAndy »

Давайте тогда попробуем разложить все по полочкам.

есть фрагмент схемы:
Изображение
Это фрагмент реальной схемы часов с подсветкой, там реализовано 32 уровня яркости индивидуально для каждого светодиода (я когда то выкладывал описание этих часов - вот. Там и видосик есть свечения этих РГБ светодиодов.)

На схеме - 12 РГБ-светодиодов, подключенных к двум портам Меги 32.
По факту это 36 отдельных светодиодов, включенных матрицей 6х6.
(на самом деле не важно, какая мега, тут подойдет даже тинька 2313 - у нее тоже найдется 12 линий ввода/вывода)

Т.е. реализована динамическая индикация (почти как в звездочке, сделанной на базе часов - только в часах матрица - 4х8).

Здесь к 6 битам порта А подключено по 6 анодов светодиодов, к 6 линиям порта В - по 6 катодов, через резисторы.
Вот что бы зажечь один светодиод - нужно подать 1 на вывод порта А и 0 на вывод порта В.
На пересечении линий от портов А и В загорится светодиод.

Можно вывести 1 на линию порта А и нужное количество 0 на линии порта В - тогда загорится нужное число светодиодов, подключенных к этой линии от порта А.
Потом мы на эту линию порта А можем вывести 0, а 1 - на следующую линию порта А, тогда , подавая нолики и единички на порт В, можно зажечь следующие 6 светодиодов.

Если переключать линии порта быстро-быстро (условно - 1000 раз в секунду), то можно на эту матрицу выводить нужное изображение.

А теперь немножко магии.

Мы выводим на линию РА0 единичку на период 1 мс.
А на линии РВ0 и РВ1 - выводим нолик.
Но через 0,5мс мы выводим на линию РВ1 единичку.

И что у нас получается ? Светодиод, подключенный к линии РВ0 горел 1 миллисекунду, а тот, что на РВ1 - пол миллисекунды.
Визуально - светодиоды будут светиться с разной яркостью.

Ниже я опишу алгоритм для 4 уровней яркости.

Внимательно смотрим за руками.
у атмеловских контроллеров есть таймеры. Их целых два даже в 2313 тине.
А в Меге 8 - целых три. Нам хватит одного.

Открываете даташит на ваш контроллер. Смотрите, как настроить таймер, что бы он переполнялся 4-5 тысяч раз за секунду.
Навскидку - тактовая 8 МГц, таймер 8 бит, итого, при предделителе =1 он переполнится 8000000/256=31250 раз в секунду. Многовато.
Ставим делитель 8. 8000000/(8*256) = 3906 раз в секунду. Почти то , что надо. На этом и остановимся.

Теперь заводим себе массивчик двумерный по размеру нашей матрички светодиодов. В этот массив в основной программе будем писать состояния нужные наших светодиодов - яркость кажого светодиода - от 0 до 4. 0 - не горит, 4 - горит с максимальной яркочтью.

Заводим 2 глобальных счетчика - один - это счетчик наших линий, подключенных к катодам , он будет считать от 0 до 5, второй - счетчик фаз яркости для каждой линии.
Изначально, при старте счетчики обнулены.

И начинаем шаманить в обработчике прерывания переполнения таймера (не забыть разрешить прерывания от таймера и глобальные):
Проверяем состояние счетчика фаз. Если нулевое:
  • выдаем единички на все светодиодные линии порта В - светодиоды погаснут.
  • Выдаем нолик на линию порта А , соответствующую значению счетчика линий.
  • Увеличиваем счетчик линий. Если он стал больше 5 (у нас же матрица 6х6 - счетчик считает от 0 до 5) - пишем в него 0.
  • Пишем в счетчик фаз четверку.
  • выводим 1 на линию порта А, соответствующую счетчику линий.
теперь перебираем значения в нашем массиве яркостей для выбранной линии.
И сравниваем значение в массиве со значением счетчика фаз. Если они равны = выводим на соответствующую линию потра В нолик. Остальные биты порта В не трогаем!
Теперь уменьшаем счетчик фаз на 1 - и выходим из прерывания.

Все, автомат управления светодиодами - готов.
Он тикает почти 4000 раз в секунду.
каждые 4 тика переключает линию матрицы светодиодов, в течении 4 тактов управляет длительностью свечения светодиодов в выбранной линии. Т.е. по сути у нас получилось программное управление яркостью для 36 независимых светодиодов.
Линии переключаются со скоростью 3906/4 - 976 раз в секунду. Цикл перебора всех 6 линий будет выполняться 976/6 = 162 раза в секунду.
И при этом мы можем управлять яркостью каждого светодиода независимо.

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

Если вдруг есть сложности с англоязычным даташитом - можно посмотреть книжки Евстифеева - по сути это вольный перевод даташитов.
Так же поищите книжицу Белова - Самоучитель разработчика устройств на МК AVR - в ней, кроме описания контроллера тини 2313, есть еще разработка нескольких схем, в т.ч. и бегущих огней (надо если - я куда то выложу Белова и Евстифеева).

Вобщем, дерзайте, если что то не будет получаться - выкладыывайте код, будем смотреть.

И да, не у всех есть установленный протеус, посему лучше выкладывать схему в виде картинки в пост с вопросом и прикладывать прямо в текст поста фрагмент листинга. (для листинга в редакторе даже кнопочка есть - Code)
ИзображениеИзображение
Изображение
 
Telegram               Лучшая благодарность ->
[+]
Аватара пользователя
Serzh2000
Опытный кот
Сообщения: 867
Зарегистрирован: Пт фев 27, 2015 12:00:53
Откуда: Рязанская область

Re: RGB сосулька

Сообщение Serzh2000 »

с новым годом!

все каникулы провозился все равно не пойму.
теперь перебираем значения в нашем массиве яркостей

как их перебрать весь интернет просмотрел все пишут в авр студио и используют библиотеки....

пофигу эта динамика пока хоть 10 светиков засветить с разной яркостью.
Изображение

Навскидку - тактовая 8 МГц, таймер 8 бит, итого, при предделителе =1 он переполнится 8000000/256=31250 раз в секунду. Многовато.
Ставим делитель 8. 8000000/(8*256) = 3906 раз в секунду. Почти то , что надо. На этом и остановимся.


сделано

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

TCNT0=0b00000000;
TCCR0=0b00000100;



Теперь заводим себе массивчик двумерный по размеру нашей матрички светодиодов. В этот массив в основной программе будем писать состояния нужные наших светодиодов - яркость кажого светодиода - от 0 до 4. 0 - не горит, 4 - горит с максимальной яркочтью.


с двумерными массивами не знаю как пока давайте без динамики попробуем

счетчик фаз яркости

сделано

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

 interrupt [TIM0_OVF] void timer0_ovf_isr(void) {
 
    faza++; if (faza > 10) {
      faza = 0;
        }
         
 
 }


теперь перебираем значения в нашем массиве яркостей для выбранной линии.
И сравниваем значение в массиве со значением счетчика фаз. Если они равны = выводим на соответствующую линию потра В нолик. Остальные биты порта В не трогаем!
Теперь уменьшаем счетчик фаз на 1 - и выходим из прерывания.


тут я застрял. в принципе понятно, что Вы объяснили, но на практике как это сделать не получается у меня :solder:
Вложения
sosulka.zip
(60.2 КБ) 202 скачивания
сосулька.png
(63.97 КБ) 374 скачивания
Аватара пользователя
GoldenAndy
Поставщик валерьянки для Кота
Сообщения: 1925
Зарегистрирован: Чт июл 28, 2016 07:58:37
Откуда: Kyiv, UA
Контактная информация:

Re: RGB сосулька

Сообщение GoldenAndy »

Так. Язык Си. это уже проще.

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

есть фрагмент схемы:
Изображение
Теперь заводим себе массивчик двумерный по размеру нашей матрички светодиодов. В этот массив в основной программе будем писать состояния нужные наших светодиодов - яркость кажого светодиода - от 0 до 4. 0 - не горит, 4 - горит с максимальной яркочтью.


двумерный массив - он как одномерный. но только двумерный.
unsigned char LedsLevels[6][6]; - вот как раз массивчик 6*6 байтиков. Все просто.
Обращаемся к нему так : LedsLevels[3][5] = 4; - вот мы в ячейку по адресу 3:5 записали четверку.

Заводим 2 глобальных счетчика - один - это счетчик наших линий, подключенных к катодам , он будет считать от 0 до 5, второй - счетчик фаз яркости для каждой линии.
Изначально, при старте счетчики обнулены.

unsigned char Lines = 0, Phase = 0;

И начинаем шаманить в обработчике прерывания переполнения таймера (не забыть разрешить прерывания от таймера и глобальные):
Проверяем состояние счетчика фаз. Если нулевое:
  • выдаем единички на все светодиодные линии порта В - светодиоды погаснут.
  • Выдаем нолик на линию порта А , соответствующую значению счетчика линий.
  • Увеличиваем счетчик линий. Если он стал больше 5 (у нас же матрица 6х6 - счетчик считает от 0 до 5) - пишем в него 0.
  • Пишем в счетчик фаз четверку.
  • выводим 1 на линию порта А, соответствующую счетчику линий.

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

    if (Phase==0) {
        PORTB = 0x3F;
        PORTA = 0;
        Lines++;
        if (Lines>5) Lines = 0;
        Phase = 4;
        PORTA = 1 << Lines;  //выводим 1 на линию порта А, соответствующую счетчику линий.
    }


теперь перебираем значения в нашем массиве яркостей для выбранной линии.
И сравниваем значение в массиве со значением счетчика фаз. Если они равны = выводим на соответствующую линию потра В нолик. Остальные биты порта В не трогаем!
Теперь уменьшаем счетчик фаз на 1 - и выходим из прерывания.


перебираем:

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

unsigned char i;
for (i=0; i<6; i++) {
   if (LedsLevels[Lines][i]==Phase) PORTB &= ~(1<<i);//выводим на соответствующую линию потра В нолик
}
Phase--;



_____

TCNT0=0b00000000;
TCCR0=0b00000100;

Не пишите так. Это 1.Нечитаемо, 2. зависит от контроллера.
Правильно как то вот так:

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

   TCCR1A = ( 0 << WGM11 ) | ( 0 << WGM10 );
   TCCR1B = ( 0 << WGM13 ) | ( 1 << WGM12 ) | ( 0 << CS12 ) | ( 0 << CS11 ) | ( 1 << CS10 );
   OCR1A = F_CPU/1000 - 1;
   TIMSK |= ( 1 << OCIE1A );

Да, тут придется больше писать, но это,блин, читаемый код!
И вероятность ошибок гораздо ниже.

_____
У меня светодиоды спецом были подключены анодами к одному порту, а катодами к другому, причем не в разнобой, а последовательно, к битам от 0 до 5.
Это позволяет перебирать все эти биты портов в циклах.
У вас просто 11 статически подключенных диодов.

Тут придется каждый светик включать и выключать индивидуально.

заводим массив яркостей для 11 светодиодов
volatile unsigned char Leds[11];
и счетчик фаз
volatile unsigned char Phase = 0;

обработчик прерывания:

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

if (Phase == 0 ){
  Phase = 4; // 4 уровня яркости
  // гасим все 10 светодиодов
  PORTC=0;
  PORTD=0;
}
// а теперь перебираем ваши яркости в массиве.
// я тут напишу линейный код, если у вас будет желание обернуть это хозяйство в цикл или еще как сократить/алгоритмизировать - не буду возражать
if (Leds[0] == Phase) PORTD |= (1 << 0);
if (Leds[1] == Phase) PORTD |= (1 << 1);
if (Leds[2] == Phase) PORTD |= (1 << 2);
if (Leds[3] == Phase) PORTD |= (1 << 3);
if (Leds[4] == Phase) PORTD |= (1 << 4);
if (Leds[5] == Phase) PORTD |= (1 << 5);
if (Leds[6] == Phase) PORTD |= (1 << 6);
if (Leds[7] == Phase) PORTD |= (1 << 7);
if (Leds[8] == Phase) PORTC |= (1 << 1);
if (Leds[9] == Phase) PORTC |= (1 << 0);
if (Leds[10] == Phase) PORTC |= (1 << 5);
Phase --;



вот как то так оно будет.

Модификатор volatile говорит компилятору, что обращение к массиву и к счетчику фазы не нужно оптимизировать....


все пишут в авр студио и используют библиотеки....

Нуууу... давайте не будем путать язык программирования и среду разработки.
Авр Студия удобна для написания кода.
Но с тем же успехом можно писать в NotePad++ - там тоже есть подсветка синтаксиса и куча вкусностей...

А библиотеки? Ну так удобнее - большинство простых операций уже описаны в виде библиотек. Так проще.
ИзображениеИзображение
Изображение
 
Telegram               Лучшая благодарность ->
[+]
Аватара пользователя
Serzh2000
Опытный кот
Сообщения: 867
Зарегистрирован: Пт фев 27, 2015 12:00:53
Откуда: Рязанская область

Re: RGB сосулька

Сообщение Serzh2000 »

спасибо большое подробные разъяснения!!!
попробую дальше повозится прям вдохновение появилось, а то чуть руки не опустились на эту сосульку.

то ка не догнал
OCR1A = F_CPU/1000 - 1;
что это означает
зачем частоту делить 1000 и вычесть 1
Аватара пользователя
GoldenAndy
Поставщик валерьянки для Кота
Сообщения: 1925
Зарегистрирован: Чт июл 28, 2016 07:58:37
Откуда: Kyiv, UA
Контактная информация:

Re: RGB сосулька

Сообщение GoldenAndy »

то ка не догнал

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

OCR1A = F_CPU/1000 - 1;
что это означает
зачем частоту делить 1000 и вычесть 1


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

У меня первый таймер был использован как System Clock, он должен срабатывать 1000 раз в секунду.
WGM1[3:0] = 0100 - это СТС режим таймера.
Считает он от 0 и до OCR1A.

Тактируется напрямую от F_CPU.

Соответственео, что бы получить прерывание от таймера 1000 раз в секунду, таймер должен отсчитать F_CPU/1000 импульсов от источника.

А , поскольку таймер считает от 0 - то F_CPU/1000-1.

При клоке в 8 МГц имеем верх счета 8000000/1000-1 = 7999.
Т.е. таймер каждые 8000 тиков будет мне генерировать прерывание.
ИзображениеИзображение
Изображение
 
Telegram               Лучшая благодарность ->
[+]
Аватара пользователя
Serzh2000
Опытный кот
Сообщения: 867
Зарегистрирован: Пт фев 27, 2015 12:00:53
Откуда: Рязанская область

Re: RGB сосулька

Сообщение Serzh2000 »

ясно.

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

Re: RGB сосулька

Сообщение Serzh2000 »

я с ново в тупик
никак не пойму
заводим массив яркостей для 11 светодиодов
volatile unsigned char Leds[11];

если нет фигурных скобок то там все нолики, так?
теперь перебираем значения в нашем массиве яркостей для выбранной линии.
И сравниваем значение в массиве со значением счетчика фаз. Если они равны = выводим на соответствующую линию потра В нолик. Остальные биты порта В не трогаем!
Теперь уменьшаем счетчик фаз на 1 - и выходим из прерывания.


там одни ноли и есть
if ([color=#FF0040]ноль [/color]== Phase) PORTD |= (1 << порт);

то есть когда Phase равна нулю светики все загорятся по очереди, но Leds никогда не станет 1,2,3,4 так?

как же яркость меняется?

и еще в протеусе смотрю постоянно Phase выходит за пределы ноля и четверки
Изображение
я не так настроил таймер0 ?

Спойлер#include <mega8.h>
#include <delay.h>

unsigned char Leds[10];
volatile unsigned char Phase = 4;// счетчик фаз


// ----------
interrupt [TIM0_OVF] void timer0_ovf_isr(void) {
if (Phase == 0 ){
Phase = 4; // 4 уровня яркости

PORTC=0; // гасим все 10 светодиодов
PORTD=0;
}
}//=================== main ==========


//основаня функция
void main(void){


//настройка портов

PORTB=0b00000000;
DDRB=0b00000000;
PORTC=0b00000000; //порт С 4 первые по умолчанию 1
DDRC=0b00000011; //порт С 4 первые ноги на вывод
PORTD=0b00000000; //порт D по умолчанию все ноги на 0
DDRD=0b11111111; //порт D все ноги на вывод


TCCR0 = 0;
TIMSK |= 0b00000001;
TCCR0 |= (0<<CS02)|(1<<CS01)|(0<<CS00);

#asm("sei") // Глобальные прерывания включения

// ---------- рабочая часть ----------
while (1) {

// а теперь перебираем ваши яркости в массиве.
// я тут напишу линейный код, если у вас будет желание обернуть это хозяйство в цикл или еще как сократить/алгоритмизировать - не буду возражать
if (Leds[0] == Phase) PORTD |= (1 << 0);
if (Leds[1] == Phase) PORTD |= (1 << 1);
if (Leds[2] == Phase) PORTD |= (1 << 2);
if (Leds[3] == Phase) PORTD |= (1 << 3);
if (Leds[4] == Phase) PORTD |= (1 << 4);
if (Leds[5] == Phase) PORTD |= (1 << 5);
if (Leds[6] == Phase) PORTD |= (1 << 6);
if (Leds[7] == Phase) PORTD |= (1 << 7);
if (Leds[8] == Phase) PORTC |= (1 << 1);
if (Leds[9] == Phase) PORTC |= (1 << 0);
Phase --;

}; // ---------- рабочая часть (end) ----------

} // ================= end main ======

//
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- The End -=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
//

может что не так понял не сочтите за наглость объясните, пожалуйста.
Вложения
sosulka.zip
(62.71 КБ) 182 скачивания
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Re: RGB сосулька

Сообщение Dimon456 »

Где-то так
Спойлер

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

/*******************************************************
This program was created by the
CodeWizardAVR V3.10 Advanced
Automatic Program Generator
© Copyright 1998-2014 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project :
Version :
Date    : 16.12.2018
Author  :
Company :
Comments:


Chip type               : ATmega168P
Program type            : Application
AVR Core Clock frequency: 16,000000 MHz
Memory model            : Small
External RAM size       : 0
Data Stack size         : 256
*******************************************************/

#include <mega168.h>

#include <delay.h>


volatile unsigned int f=400,    // время кадра
             h=5,      // число повторов эффекта
             z=1000;   // ms для паузы после эффекта
                         
volatile unsigned char Phase=0, Lines = 0;

// Declare your global variables here
     //unsigned char A[5][4] = {{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}};
     //unsigned char B[5][4] = {{0,0,0,1},{0,0,0,1},{0,0,0,1},{0,0,0,1},{0,0,0,1}};
    // unsigned char C[5][4] = {{2,0,2,0},{2,0,2,0},{2,0,2,0},{2,0,2,0},{2,0,2,0}};
    // unsigned char D[5][4] = {{3,0,3,0},{3,0,3,0},{3,0,3,0},{3,0,3,0},{3,0,3,0}};
    // unsigned char E[5][4] = {{0,4,0,0},{0,4,0,0},{0,4,0,0},{0,4,0,0},{0,4,0,0}};
    // unsigned char F[5][4] = {{0,4,0,0},{0,4,0,0},{0,4,0,0},{0,4,0,0},{0,4,0,0}};
    // unsigned char G[5][4] = {{3,0,3,0},{3,0,3,0},{3,0,3,0},{3,0,3,0},{3,0,3,0}};
    // unsigned char H[5][4] = {{2,0,2,0},{2,0,2,0},{2,0,2,0},{2,0,2,0},{2,0,2,0}}; 
    // unsigned char I[5][4] = {{0,0,0,1},{0,0,0,1},{0,0,0,1},{0,0,0,1},{0,0,0,1}};
    // unsigned char J[5][4] = {{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}};



flash char flasher_0[200] =
   { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
      0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,
      2,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,
      3,0,3,0,3,0,3,0,3,0,3,0,3,0,3,0,3,0,3,0,
      0,4,0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,4,0,0,
      0,4,0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,4,0,0,
      3,0,3,0,3,0,3,0,3,0,3,0,3,0,3,0,3,0,3,0,
      2,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,
      0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,
      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
    };   
   

flash char flasher_1[200] =
   { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
      0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,
      0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,
      0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,
      0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,
      0,0,0,3,0,0,0,3,0,0,0,3,0,0,0,3,0,0,0,3,
      0,0,0,3,0,0,0,3,0,0,0,3,0,0,0,3,0,0,0,3,
      0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,4,
      0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,4
    };

flash char flasher_2[200] =
   { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
      1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
      1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
      2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
      2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
      3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
      3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
      4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
      4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
    };
           
   volatile flash char *u;
   volatile char a;   
   
// Timer2 overflow interrupt service routine
interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{
unsigned char i;

    if (Phase==0) {
        PORTD = 0x3F;
        PORTC = 0;
        Lines++;
        if (Lines>5) Lines = 0;
        Phase = 4;
        PORTC = 1 << Lines;  //выводим 1 на линию порта А, соответствующую счетчику линий.
    }

for (i=0; i<4; i++) {
   //if (LedsLevels[Lines][i]==Phase) PORTD &= ~(1<<i);//выводим на соответствующую линию потра В нолик
   a = *(u+Lines*4+i);
   if (a==Phase) PORTD &= ~(1<<i);//выводим на соответствующую линию потра В нолик
}
Phase--;
}


void view_pauza(void) {
       delay_ms(z);

         
void view_flasher_0(void) {
     int i,j;             
   
   for (j =0; j<h;++j){
   
   for (i =0; i<9;++i){
     
      u = &(flasher_0[i*20]);
        delay_ms(f);
     }
     
  }
  view_pauza();
}


void view_flasher_1(void) {
     int i,j;             
   
   for (j =0; j<h;++j){
   
   for (i =0; i<9;++i){
     
      u = &(flasher_1[i*20]);
        delay_ms(f);
     }
     
  }
  view_pauza();
}

void view_flasher_2(void) {
     int i,j;             
   
   for (j =0; j<h;++j){
   
   for (i =0; i<9;++i){
     
      u = &(flasher_2[i*20]);
        delay_ms(f);
     }
     
  }
  view_pauza();
}

void main(void)
{
// Declare your local variables here

// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=(1<<CLKPCE);
CLKPR=(0<<CLKPCE) | (0<<CLKPS3) | (0<<CLKPS2) | (0<<CLKPS1) | (0<<CLKPS0);
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

// Input/Output Ports initialization
// Port B initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
DDRB=(0<<DDB7) | (0<<DDB6) | (0<<DDB5) | (0<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (0<<DDB0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);

// Port C initialization
// Function: Bit6=In Bit5=In Bit4=Out Bit3=Out Bit2=Out Bit1=Out Bit0=Out
DDRC=(0<<DDC6) | (0<<DDC5) | (1<<DDC4) | (1<<DDC3) | (1<<DDC2) | (1<<DDC1) | (1<<DDC0);
// State: Bit6=T Bit5=T Bit4=0 Bit3=0 Bit2=0 Bit1=0 Bit0=0
PORTC=(0<<PORTC6) | (0<<PORTC5) | (0<<PORTC4) | (0<<PORTC3) | (0<<PORTC2) | (0<<PORTC1) | (0<<PORTC0);

// Port D initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=Out Bit2=Out Bit1=Out Bit0=Out
DDRD=(0<<DDD7) | (0<<DDD6) | (0<<DDD5) | (0<<DDD4) | (1<<DDD3) | (1<<DDD2) | (1<<DDD1) | (1<<DDD0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=0 Bit2=0 Bit1=0 Bit0=0
PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=0xFF
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=(0<<COM0A1) | (0<<COM0A0) | (0<<COM0B1) | (0<<COM0B0) | (0<<WGM01) | (0<<WGM00);
TCCR0B=(0<<WGM02) | (0<<CS02) | (0<<CS01) | (0<<CS00);
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer1 Stopped
// Mode: Normal top=0xFFFF
// OC1A output: Disconnected
// OC1B output: Disconnected
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (0<<CS11) | (0<<CS10);
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: 500,000 kHz
// Mode: Normal top=0xFF
// OC2A output: Disconnected
// OC2B output: Disconnected
// Timer Period: 0,512 ms
ASSR=(0<<EXCLK) | (0<<AS2);
TCCR2A=(0<<COM2A1) | (0<<COM2A0) | (0<<COM2B1) | (0<<COM2B0) | (0<<WGM21) | (0<<WGM20);
TCCR2B=(0<<WGM22) | (0<<CS22) | (1<<CS21) | (1<<CS20);
TCNT2=0x00;
OCR2A=0x00;
OCR2B=0x00;

// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=(0<<OCIE0B) | (0<<OCIE0A) | (0<<TOIE0);

// Timer/Counter 1 Interrupt(s) initialization
TIMSK1=(0<<ICIE1) | (0<<OCIE1B) | (0<<OCIE1A) | (0<<TOIE1);

// Timer/Counter 2 Interrupt(s) initialization
TIMSK2=(0<<OCIE2B) | (0<<OCIE2A) | (1<<TOIE2);

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// Interrupt on any change on pins PCINT0-7: Off
// Interrupt on any change on pins PCINT8-14: Off
// Interrupt on any change on pins PCINT16-23: Off
EICRA=(0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00);
EIMSK=(0<<INT1) | (0<<INT0);
PCICR=(0<<PCIE2) | (0<<PCIE1) | (0<<PCIE0);

// USART initialization
// USART disabled
UCSR0B=(0<<RXCIE0) | (0<<TXCIE0) | (0<<UDRIE0) | (0<<RXEN0) | (0<<TXEN0) | (0<<UCSZ02) | (0<<RXB80) | (0<<TXB80);

// Analog Comparator initialization
// Analog Comparator: Off
// The Analog Comparator's positive input is
// connected to the AIN0 pin
// The Analog Comparator's negative input is
// connected to the AIN1 pin
ACSR=(1<<ACD) | (0<<ACBG) | (0<<ACO) | (0<<ACI) | (0<<ACIE) | (0<<ACIC) | (0<<ACIS1) | (0<<ACIS0);
ADCSRB=(0<<ACME);
// Digital input buffer on AIN0: On
// Digital input buffer on AIN1: On
DIDR1=(0<<AIN0D) | (0<<AIN1D);

// ADC initialization
// ADC disabled
ADCSRA=(0<<ADEN) | (0<<ADSC) | (0<<ADATE) | (0<<ADIF) | (0<<ADIE) | (0<<ADPS2) | (0<<ADPS1) | (0<<ADPS0);

// SPI initialization
// SPI disabled
SPCR=(0<<SPIE) | (0<<SPE) | (0<<DORD) | (0<<MSTR) | (0<<CPOL) | (0<<CPHA) | (0<<SPR1) | (0<<SPR0);

// TWI initialization
// TWI disabled
TWCR=(0<<TWEA) | (0<<TWSTA) | (0<<TWSTO) | (0<<TWEN) | (0<<TWIE);

// Global enable interrupts
#asm("sei")

while (1)
      {
      // Place your code here
         view_flasher_0();   
         view_flasher_1();
         view_flasher_2();
         
         
      } 
}
Пусть тебе таймер помогут настроить, а то у меня под 168мегу и 16МГц.
Аватара пользователя
GoldenAndy
Поставщик валерьянки для Кота
Сообщения: 1925
Зарегистрирован: Чт июл 28, 2016 07:58:37
Откуда: Kyiv, UA
Контактная информация:

Re: RGB сосулька

Сообщение GoldenAndy »

я с ново в тупик
никак не пойму
заводим массив яркостей для 11 светодиодов
volatile unsigned char Leds[11];

если нет фигурных скобок то там все нолики, так?

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


По коду - вы немножко напутали.

У вас есть 8-битный таймер. Вы его должны настроить на счет с предделителем 8. Для меги 8 - это таймеры 0 и 2, для тиньки 2313 - только таймер 0.
Можно настроить и таймер 1 в 8-битном режиме.

Вам нужно разрешить в настройках таймера прерывание по переполнению OVF0 (или OVF2, если заюзаете Т2 меги8)
в основной программе после настройки периферии и инициализации своих переменных разрешить глобальные прерывания.

теперь выписываем обработчик прерывания таймера.
В него попадает ВСЯ секция
Спойлер

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

if (Phase == 0 ){
  Phase = 4; // 4 уровня яркости
  // гасим все 10 светодиодов
  PORTC=0;
  PORTD=0;
}
// а теперь перебираем ваши яркости в массиве.
// я тут напишу линейный код, если у вас будет желание обернуть это хозяйство в цикл или еще как сократить/алгоритмизировать - не буду возражать
if (Leds[0] == Phase) PORTD |= (1 << 0);
if (Leds[1] == Phase) PORTD |= (1 << 1);
if (Leds[2] == Phase) PORTD |= (1 << 2);
if (Leds[3] == Phase) PORTD |= (1 << 3);
if (Leds[4] == Phase) PORTD |= (1 << 4);
if (Leds[5] == Phase) PORTD |= (1 << 5);
if (Leds[6] == Phase) PORTD |= (1 << 6);
if (Leds[7] == Phase) PORTD |= (1 << 7);
if (Leds[8] == Phase) PORTC |= (1 << 1);
if (Leds[9] == Phase) PORTC |= (1 << 0);
if (Leds[10] == Phase) PORTC |= (1 << 5);
Phase --;

По сути - это весь обработчик прерывания.

Всё. Переменную Phase в основной программе мы не трогаем. И никак больше светодиодами не управляем.
Этим займется прерывание. Ему будет совершенно фиолетово, что вы делаете в основной программе. Оно будет молотить свои 3906 раз в секунду.

Вам в основной программе нужно будет только заполнять с определенной периодичностью массив Leds.


Т.е. будет как то так:
Спойлер

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

#include <mega8.h>
#include <delay.h>

unsigned char Leds[10];
volatile unsigned char Phase = 0;// счетчик фаз  <---------- должен стартовать с 0


// _______
interrupt [TIM0_OVF] void timer0_ovf_isr(void) {
if (Phase == 0 ){
   Phase = 4; // 4 уровня яркости
   PORTC=0; // гасим все 10 светодиодов
   PORTD=0;
   }
if (Leds[0] == Phase) PORTD |= (1 << 0);
if (Leds[1] == Phase) PORTD |= (1 << 1);
if (Leds[2] == Phase) PORTD |= (1 << 2);
if (Leds[3] == Phase) PORTD |= (1 << 3);
if (Leds[4] == Phase) PORTD |= (1 << 4);
if (Leds[5] == Phase) PORTD |= (1 << 5);
if (Leds[6] == Phase) PORTD |= (1 << 6);
if (Leds[7] == Phase) PORTD |= (1 << 7);
if (Leds[8] == Phase) PORTC |= (1 << 1);
if (Leds[9] == Phase) PORTC |= (1 << 0);
Phase --;
}


//=================== main ==========
//основаня функция
void main(void){
//настройка портов
PORTB=0b00000000;
DDRB=0b00000000;
PORTC=0b00000000; //порт С 4 первые по умолчанию 1
DDRC=0b00000011; //порт С 4 первые ноги на вывод
PORTD=0b00000000; //порт D по умолчанию все ноги на 0
DDRD=0b11111111; //порт D все ноги на вывод


TCCR0 = 0;
TIMSK |= 0b00000001;
TCCR0 |= (0<<CS02)|(1<<CS01)|(0<<CS00);

#asm("sei") // Глобальные прерывания включения

// заполним Ледс значениями стартовыми
unsigned char i;
for (i=0; i<10; i++) Leds[i] = i % 5; // массив заполнится значениями 0,1,2,3,4,0,1,2,3,4

// ---------- рабочая часть ----------
while (1) {
   // а теперь будем двигать массив по кругу с какой то задержкой
   unsigned char buf = Leds[9];
   for (i=9; i>0; i--) Leds[i] = Leds[i-1];
   Leds[0] = buf;

   // и задержка
   delay_ms(200);
   }; // ---------- рабочая часть (end) ----------

} // ================= end main ======

//
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- The End -=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
//


И да, delay_ms делает задержку тупым пустым циклом. Но у нас есть прерывание, которое тикает приблизительно 4000 раз в секунду. И пока МК в прерывании - задержка не считается.

Тут 2 варианта:
1. Забить на то, что 200 мс будут длиться чуть дольше - каждое прерывание будет сжирать пару-тройку десятков микросекунд... Навскидку - 5-10% добавится.
2. использовать тот факт, что прерывание таймера срабатывает 8МГц/(8*256) = 3906,25 раз в сек..... И завести либо глобальный счетчик, который будет меняться в таймере, а в основном цикле отслеживать изменение счетчика, либо завести какой то флажок срабатывания прерывания, который поднимать в прерывании, а в основной программе сбрасывать его и считать число поднятий флажка уже в основной программе.....
ИзображениеИзображение
Изображение
 
Telegram               Лучшая благодарность ->
[+]
Аватара пользователя
Serzh2000
Опытный кот
Сообщения: 867
Зарегистрирован: Пт фев 27, 2015 12:00:53
Откуда: Рязанская область

Re: RGB сосулька

Сообщение Serzh2000 »

:shock: МЯУУУУУУУУУууууу!!!!!!!!!!!!

спасибо добрые люди!
теперь есть где когти поточить! :))
Аватара пользователя
GoldenAndy
Поставщик валерьянки для Кота
Сообщения: 1925
Зарегистрирован: Чт июл 28, 2016 07:58:37
Откуда: Kyiv, UA
Контактная информация:

Re: RGB сосулька

Сообщение GoldenAndy »

Serzh2000, как когти наточите - результатом заточки поделитесь, пожалуйста. (Аж самому интересно, как оно выглядеть будет)
ИзображениеИзображение
Изображение
 
Telegram               Лучшая благодарность ->
[+]
Аватара пользователя
Serzh2000
Опытный кот
Сообщения: 867
Зарегистрирован: Пт фев 27, 2015 12:00:53
Откуда: Рязанская область

Re: RGB сосулька

Сообщение Serzh2000 »

ЕС И ЧИЗ !
Аватара пользователя
Serzh2000
Опытный кот
Сообщения: 867
Зарегистрирован: Пт фев 27, 2015 12:00:53
Откуда: Рязанская область

Re: RGB сосулька

Сообщение Serzh2000 »

собрал я наконец сосульку RGB правда на макетки
Спойлер#include <mega8.h>

#include <delay.h>


volatile unsigned int f=200, // время кадра

z=1000; // ms для паузы после эффекта

volatile unsigned char Lines, Phase=0;

flash char flasher_0[200] =
{ 4,0,0,0,0,0,0,0,
3,4,0,0,0,0,0,0,
2,3,4,0,0,0,0,0,
1,2,3,4,0,0,0,0,
0,1,2,3,4,0,0,0,
0,0,1,2,3,4,0,0,
0,0,0,1,2,3,4,0,
0,0,0,0,1,2,3,4,
0,0,0,0,0,1,2,3,
0,0,0,0,0,0,1,2,
0,0,0,0,0,0,0,1,
0,0,0,0,0,0,0,0


};


volatile flash char *u;
volatile char a;

// Timer2 overflow interrupt service routine
interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{
unsigned char i;


if (Phase==0) {
PORTD = 0xFF;
PORTC = 0;

Phase = 4;
PORTC = (1 << Lines ); //выводим 1 на линию порта А, соответствующую счетчику линий.
}



for (i=0; i<8; i++) {

a = *(u+0*8+i);
if (a==Phase) PORTD &= ~(1<<i);//выводим на соответствующую линию потра В нолик
}
Phase--;
}


void view_pauza(void) {
delay_ms(z);
}

void view_flasher_0(void) {
int i;
Lines=0 ;



for (i =0; i<13;++i){

u = &(flasher_0[i*8]);
delay_ms(f);
}

view_pauza();
}


void view_flasher_1(void) {
int i;
Lines=1 ;



for (i =0; i<13;++i){

u = &(flasher_0[i*8]);
delay_ms(f);
}

view_pauza();
}

void view_flasher_2(void) {
int i;
Lines=2 ;


for (i =0; i<13;++i){

u = &(flasher_0[i*8]);
delay_ms(f);
}



view_pauza();
}
//=================== main ==========
void main(void)
{

//настройка портов
PORTB=0b00000000;
DDRB=0b00000000;
PORTC=0b00000000; //порт С 4 первые по умолчанию 1
DDRC=0b00000111; //порт С 4 первые ноги на вывод
PORTD=0b00000000; //порт D по умолчанию все ноги на 0
DDRD=0b11111111; //порт D все ноги на вывод



TCCR2 |= (0<<CS02)|(1<<CS01)|(0<<CS00);
TIMSK=0b01000000;
// 0b11000001
// || | |
// || | Timer0
// || Timer1
// |Timer2
//

#asm("sei") // Глобальные прерывания включения
//====================

while (1)
{
// Place your code here
view_flasher_0(); //красный
view_flasher_1(); //синий
view_flasher_2(); //зеленый


}
}


хотя может этот проект в железе и не будет существовать, но за то благодаря Вашей помощи
получился отличный движок
добавь лучи будет снежинка,
убавь один будет звезда
или скажем елочка на окно по четыре веточки и на каждой по восемь светиков

на следующий год обязательно что нибуть замучу.
Всем кто помогал, советовал большое спасибо!
Вложения
sosulk.zip
(96.21 КБ) 183 скачивания
Аватара пользователя
GoldenAndy
Поставщик валерьянки для Кота
Сообщения: 1925
Зарегистрирован: Чт июл 28, 2016 07:58:37
Откуда: Kyiv, UA
Контактная информация:

Re: RGB сосулька

Сообщение GoldenAndy »

А видосик, снятый на тапок?
ИзображениеИзображение
Изображение
 
Telegram               Лучшая благодарность ->
[+]
Ответить

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