“Аналитическое тупление” дало результаты, код изменился, хотя результат работы тот же – плавная смена цветов по кругу:
1: #include <;;avr/io.h>
2: #include <;;avr/interrupt.h>
3: #include <;;avr/pgmspace.h>
4: #include "avrlibtypes.h"
5: #include "delay.h"
6:
7: #define F_OSC F_CPU
8:
9: volatile u08 r, g, b, counter = 0;
10:
11: // таблица нелинейности для яркости
12: // хотя как лучше – с ней или без – я пока не решил
13: // если без нее – тогда можно не включать pgmspace.h и выкинуть 2 строки из
14: // след. функции (v = pgm_…)
15: u08 gamma[256] PROGMEM = {
16: 0, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3,
17: 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4,
18: 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6,
19: 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8,
20: 8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11,
21: 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15,
22: 15, 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 20,
23: 20, 20, 21, 21, 22, 22, 22, 23, 23, 24, 24, 25, 25, 25, 26, 26,
24: 27, 27, 28, 28, 29, 29, 30, 30, 31, 32, 32, 33, 33, 34, 35, 35,
25: 36, 36, 37, 38, 38, 39, 40, 40, 41, 42, 43, 43, 44, 45, 46, 47,
26: 48, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
27: 63, 64, 65, 66, 68, 69, 70, 71, 73, 74, 75, 76, 78, 79, 81, 82,
28: 83, 85, 86, 88, 90, 91, 93, 94, 96, 98, 99, 101, 103, 105, 107, 109,
29: 110, 112, 114, 116, 118, 121, 123, 125, 127, 129, 132, 134, 136, 139, 141, 144,
30: 146, 149, 151, 154, 157, 159, 162, 165, 168, 171, 174, 177, 180, 183, 186, 190,
31: 193, 196, 200, 203, 207, 211, 214, 218, 222, 226, 230, 234, 238, 242, 248, 255
32: };
33:
34: void getRGB (u16 h, u08 s, u08 v)
35: {
36: u16 base;
37:
38: v = pgm_read_byte(&gamma[v]);
39: s = 255 - pgm_read_byte(&;;gamma[255 - s]);
40:
41: if (s == 0)
42: {
43: r = v;
44: g = v;
45: b = v;
46: } else {
47: base = ((255 - s) * v) >;;> 8;
48:
49: switch (h / 60) {
50: case 0:
51: r = v;
52: g = (((v - base) * h) / 60) + base;
53: b = base;
54: break;
55: case 1:
56: r = (((v - base) * (60 - (h % 60))) / 60) + base;
57: g = v;
58: b = base;
59: break;
60: case 2:
61: r = base;
62: g = v;
63: b = (((v - base) * (h % 60)) / 60) + base;
64: break;
65: case 3:
66: r = base;
67: g = (((v - base) * (60 - (h % 60))) / 60) + base;
68: b = v;
69: break;
70: case 4:
71: r = (((v - base) * (h % 60)) / 60) + base;
72: g = base;
73: b = v;
74: break;
75: case 5:
76: r = v;
77: g = base;
78: b = (((v - base) * (60 - (h % 60))) / 60) + base;
79: break;
80: }
81: }
82: }
83:
84: void init(void)
85: {
86: //{{AVR_IO_DESIGNER_INIT
87: // Project Options - ambi-lamp
88: //
89: // Device Name = ATtiny2313
90: // CPU Frequency (F_CPU) = 11,059 MHz
91: // IC Package = DIP
92: // Sort Pins by = Pin Number
93: // Output Code File = ..\main.c
94: // Output Header File = ..\hardware.h
95: // Assume Default State = True
96: // Write Unmodified Bits = True
97: // Set Unused PORT Pins = Input
98:
99: //
100: // PORTD variable initializations
101: //
102: // PORTD3 for 1: led_red as Output -
103: // PORTD4 for 1: led_green as Output -
104: // PORTD5 for 1: led_blue as Output -
105: DDRD = 0x38;
106:
107: //
108: // TIMER_COUNTER_0 - -
109: //
110: // Clock Select = clk (No prescaling)
111: // Timer Overflow Interrupt Enable = Enabled
112: // Counter Frequency = 43,199 kHz
113: // Counter Period = 23,149 usec
114: // Seconds per Count = 90,424 nsec
115: // Counts per Second = 11,059 MHz
116: TIMSK = 0x02; // (1<<TOIE0)
117: TCCR0B = 0x01; // (0<<CS02)|(0<<CS01)|(1<<CS00)
118: //}}AVR_IO_DESIGNER_INIT
119:
120: sei();
121: }
122:
123: ISR(TIMER0_OVF_vect)
124: {
125:
126: #define led_red_SHIFT 0x03
127: #define led_green_SHIFT 0x04
128: #define led_blue_SHIFT 0x05
129:
130: PORTD = ((r >;; counter) << led_red_SHIFT) | ((g > counter) << led_green_SHIFT) |
131: ((b >;; counter) << led_blue_SHIFT);
132: counter++;
133: }
134:
135: int main(void)
136: {
137: init();
138:
139: u16 h;
140:
141: while(1)
142: {
143: for (h = 0; h < 360; h++)
144: {
145: // ф-ция принимает параметр – цвет, насыщенность и яркость
146: // цвет от 0 до 360 == от красного к фиолетовому по радуге
147: // насыщенность == 255 – “чистый” цвет, ближе к 0 – “серый”; на цветовом конусе это означает, что с
148: // минимальной насыщенностью с изменением цвета тот собственно практич. не меняется – в моем
149: // случае это практич. белый с любым значением цвета
150: // яркость понятно, чем меньше, тем ближе к черному.. при маленьких значениях начинаются глюки в виде мерцания..
151: // з.ы. глюки больше (при маленьких значениях насыщенности и яркости) без корректирующей таблицы, с
152: // другой стороны – таблица == четверть памяти контроллера (прошивка занимает 1400/1100 байт с и без таблицы)
153: getRGB(h, 255, 150);
154:
155: delay_ms(10);
156: }
157: }
158:
159: return 0;
160: }
Сделал себе аналогичную лампу.
ОтветитьУдалитьМенять цвета по кругу - как-то скучно. Это проще выдрать мозги из китайского снежка.
Что б меньше мучиться с выбором подходящего алгоритма - записал несколько различных вариантов работы (цикл основных цветов, рандомно из основных, полный рандом, фиксированный цвет и т.п.)
Теперь добавлю и вашу идею - рандомное движение по колесу. По сути это получится как цикл основных цветов, но с различной скоростью движения (включая отрицательную).
Питание - от miniUSB. Найти дома лишнюю зарядку для телефона сейчас не проблема. Можно и к пк подсоединить (только не к ноуту, тока не хватит). Через ПК можно заодно и откорректировать основные параметры (скорость смены, фикс. цвет и пр., возможно добавлю полоностью программируемую подпрограмму), а так же перехватить управление цветом. Тут уже можно использовать лампу как ambX (почти как амбилайт), или как светомузыку. Да и вообще можно хоть движение мыши отслеживать, добавить в софт - не проблема.
Получился в итоге маленький космический корабль. Нужен ли он, когда почти все время лампа будет гореть в одном режиме? Может и нет. Зато такого у китайцев точно не найдешь =)
P.S.
Коррекция гаммы не очень-то и нужна. Лампе не требуется точная цветопередача.
С цветопередачей только один минус - чистый белый цвет поймать сложно.
ну понятно, что по кругу неинтересно.. просто с getRGB можно теперь играться и цветом, и яркостью (хотя там на малых яркостях глюки начинаются, не разбирался, из-за чего, наверное теряются значения при умножениях\делениях).. оставшиеся пол-памяти можно использовать, чтобы подключить софтварный usb (http://www.recursion.jp/avrcdc/cdc-232.html#usage например).. не нашел правда быстро, сколько ему мин. памяти надо для реализации
ОтветитьУдалитьа таблица коррекции в данном случае используется не для уточнения цветопередачи, а для компенсации изменения яркости, точнее того факта, что глаз 75 и 100% яркости уже не различит (и с ней глюков кардинально меньше на маленьких яркостях)