очередная "Лампа настроения" с энкодером

После недели головной боли над неправильно работающим циклом вычисления цвета допилил прошивку к своей лампе настроения.
Микроконтроллер atmega32a (на самодельной макетке)
(почему такой монстр для такой фигни? да потому-что моя самодельная макетка сделана для 16й и 32й атмег, пока что без совместимости с аттинями, в планах сделать переходник с тиней и 8меги на DIP40 установленный на плате.
а код легко переносится на другие платформы
суть разработки заключается в полной разработке девайса, от идеи до реализации в готовом виде.
и да, это мой первый девайс который делается ОТ и ДО)
Светодиод обычный RGB с общим анодом, взят со светодиодной ленты. Катоды подключены к ШИМ выходам микроконтроллера через токоограничительные резисторы.
Энекодер самый обычный, с А В выходами, подключены к 1 и 2 пину порта А (0й пин не работает)
Цвет меняется вращением энкодера, направление учитывается.
765 цветов.

Прошу прощения, но пока я могу писать на микропаскале (в С пока плохо ориентируюсь)
Собственно код:


program main;

var 
    state: byte;
    new:byte;
    r_led,g_led,b_led:byte;

procedure step_up();           
begin                               
if (r_led>0) and (g_led<255) and (b_led=0) then 
                                            begin 
                                            dec(r_led); 
                                            inc(g_led); 
                                            end;
if (g_led>0) and (b_led<255) and (r_led=0) then 
                                            begin 
                                            dec(g_led); 
                                            inc(b_led); 
                                            end;
if (b_led>0) and (r_led<255) and (g_led=0) then 
                                            begin 
                                            dec(b_led); 
                                            inc(r_led); 
                                            end;
end;

procedure step_down();
begin
if (g_led>0) and (r_led<255) and (b_led=0) then 
                                            begin 
                                            dec(g_led); 
                                            inc(r_led); 
                                            end;
if (b_led>0) and (g_led<255) and (r_led=0) then 
                                            begin 
                                            dec(b_led); 
                                            inc(g_led); 
                                            end;
if (r_led>0) and (b_led<255) and (g_led=0) then 
                                            begin 
                                            dec(r_led); 
                                            inc(b_led); 
                                            end;
end;



procedure init_pwm();         //включение таймеров в режим PWM
begin
ddrd:=176;
TCCR1A.COM1A1:=1;
TCCR1A.COM1B1:=1;
TCCR1A.WGM10:=1;
TCCR1B.CS10:=1;
TCCR2.WGM20:=1;
TCCR2.COM21:=1;
TCCR2.CS20:=1;

r_led:=255;                   //красный 100%
g_led:=0;                     //зеленый 0%
b_led:=0;                     //синий   0%

end;


procedure encoder_scan();          //скан енкодера
                                   //пинА и пинВ энкодера подключены к
begin
new:=(pina)and(%00000110);         //пинА1 и пинА2 атмеги  
delay_us(100);                     //достаточно для работы
case state of                      //обработка сигнала с энкодера
     0: begin
        if new=4 then step_up;        //всю эту хрень с обработкой энкодера вывести в отдельный юнит
        if new=2 then step_down;
        end;
     2: begin
        if new=0 then step_up;
        if new=6 then step_down;
        end;
     6: begin
        if new=2 then step_up;
        if new=4 then step_down;
        end;
     4: begin
        if new=6 then step_up;
        if new=0 then step_down;
        end;
     end;
state:=new;

OCR1AL:=255-r_led;               // в компаратор таймера1А
OCR1BL:=255-g_led;               // в компаратор таймера1В
OCR2:=255-b_led;                 // в компаратор таймера2

end;





begin
DDRA:=%00000000;            //портА на вход
init_pwm;

while (1) do
begin
encoder_scan;  //бесконечно сканируем энкодер
end;
                     
end.


а вот и фотки макетки
выкл
вкл

и схема

правда светодиоды я тут в обратную сторону воткнул случайно
  • +1
  • 18 января 2012, 19:40
  • Acinonyx

Комментарии (14)

RSS свернуть / развернуть
Где схема? Где фотки готового дивайса?
+1
  • avatar
  • Aneg
  • 18 января 2012, 21:30
аппаратно все на жуткой макетке. сейчас в поисках подходящего корпуса. затем надо портировать на 8ю атмегу (или вообще в тиню 2313) и собрать все в готовый аппарат.
0
Тут даже для тиньки программка маловата, можт стоит ещё какой-либо функционал добавить?)

Паскаль очень непривычно видеть, это точно. Особенно после долгой «разлуки».)
0
функционал будет добавляться по мере придумывания.
для начала будет вторая версия, у которой регулировка каждого канала цвета и общая яркость (также будет выполнена гамма-коррекция)
третья версия, предварительно, будет иметь светильники-спутники (в количестве 8 штук), будет режим волны, когда цвета будут плыть с выбираемой скоростью по сателитам
0
*у которой будет регулировка…
0
Таки да, где что-то кроме кода?

Паскаль на МК… Прикольно. :) Не то чтобы это сильно плохо, просто непривычно как-то… :)
0
  • avatar
  • _YS_
  • 18 января 2012, 21:35
Код оформлен ужасно. Нечитабелен даже с комментариями.
Во первых, сбитая индентация (а она весьма сильно на восприятие структуры программы влияет).
Во вторых — магические числа. Тем более в mP, где можно было написать DDRA1_bit:=1. Или DDRA.1:=1. Если уж и работать с пинами с помощью битовой математики — стоит их задефайнить в начале как const EncoderPins = $60 и дальше использовать эту константу. В ините таймера и подавно следует использовать константы в духе TCCR2 := (1 shl WGM20) or (1 shl WGM21) or (2 shl COM20) or (1 shl CS20).
В третьих — однострочники в процедурах step_up и step-down. Не надо строчки экономить. Каждому begin'у и end'у следует выделять свою, личную строку.

Ну и бесконечный цикл в паскале записывается как while true do. На while (1) do вообще говоря нормальный паскаль должен ругаться. Ну и операторные скобки (begin..end) здесь не обязательны.

P.S. Сколь скомпиленный код весит?
0
  • avatar
  • Vga
  • 19 января 2012, 05:00
про сложность чтения своего кода знаю
про магические числа я тоже знаю, в следующей версии будут более привычные глазу дефайны пинов с энкодером
в ините тоже рука поднималась сделать все эти 1 shl WGM20, но не дошла.
по поводу степ_ап и даун процедур… ну мне так захотелось в этот момент =)
HEX весит 2 килобайта
0
HEX весит 2 килобайта
Сам файл или объем кода в нем (последний сам mP показывает после компиляции)?
0
0 1144 Used ROM (bytes): 732 (2%) Free ROM (bytes): 32036 (98%) Used ROM (bytes): 732 (2%) Free ROM (bytes): 32036 (98%)
0
Хотим фото макетки)
0
и главное никто не заметил как я энкодер на вход включил…
ddra:=%00000110
0
Дык я ж и говорю — нечитабельно) Только и остается что пробежаться глазами по комментам, не вникая в суть кода)
То ли дело код без единого комментария — пока не разберешь по косточкам — ничего не поймешь :D
0
добавил фотки и схему
как я и говорил, там ничего интересного =)
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.