Новогодняя лампа-ночник из RGB-светодиодов на плате LaunchPad MSP-EXP430, управляемая ИК-пультом

Новогодняя лампа-ночник из RGB-светодиодов на плате LaunchPad MSP-EXP430, управляемая ИК-пультом

Давно хотелось сделать что-нибудь для дома на RGB-светодиодах. И решил к празднику сделать «новогодний ночник» под елку, как дополнение к приевшимся гирляндам, тем более, что все необходимое имелось в наличии. Ночник по замыслу должен гореть разными цветами, плюс несколько программ мигания. Сделано было 2 штуки, один на снимке. Видео — в конце статьи. .
mc182-2
В качестве контроллера выбор пал на плату контроллера LaunchPad MSP-EXP430G2. Во-первых цена — плату можно заказать по цене 4.30$ (и бесплатная доставка курьерской службой FedEx) на сайте компании Texas Instruments.
Во-вторых — среда программирования Energia, очень похожая на IDE Arduino. Для облегчения программирования, также как и в Arduino IDE, среда программирование поставляется с библиотеками, некоторые из которых правда неработоспособны, с чем мне и пришлось столкнуться при написании программы. Тем не менее проект развивается, для поддержки пользователей есть отдельная ветка на форуме TI, посвященная библиотекам для Energia.
mc182-3
Для управления ночником решил использовать ИК-пульт.

Полный список деталей:

Плата контроллера LaunchPad MSP-EXP430G2 — 1 шт.
RGB — светодиод — 6 шт.
Резистор 220 Ом — 6 шт
Микросхема 74HC595 — 3 шт
Для схемы ИК приемника

ИК-приемник TSOP31238 — 1 шт
Резистор 100 Ом — 1 шт
Конденсатор 10 мкФ 25В — 2 шт.
Конденсатор 0.1 мкФ — 2 шт.
Для платы LaunchPad MSP-EXP430G2 необходимо питание 1.8 — 3.6 В, в наличии имелись блоки питания на 5В, поэтому еще детали для стабилизатора питания на 3.3 В

Микросхема APU1206H-33
Конденсатор 10 мкФ 25В — 2 шт.
mc182-4
А также плафон для лампы, клей, новогодние украшения.
Если кто будет использовать библиотеку IRremote, учтите, что не работает функция отправки ir-кода, мне был нужен только прием. Схема подключения ИК-приемника представлена на рисунке. Выход данных TSOP подсоединен ко входу P1_3 платы LaunchPad.
mc182-5
Я делал 2 устройства, для одного использовал пульт для контроллера RGB-лент, для другого — пульт Marmitek X10
mc182-6OLYMPUS DIGITAL CAMERA
Сначала определимся с назначением клавиш пультов для выбора режимов ночника. Для пульта контроллера RGB-лент достаточно понятно:
(R — R, G — G, B — B, RG — RG, GB — GB, RB — RB, W — WHITE, off — BLACK, крайние правые 4 (черного цвета) — режимы мигания )
для пульта Marmitek:
(1 — R, 2 — G, 3 — B, 4 — RG, 5 — GB, 6 — RB, 0 — WHITE, 6,7,8 — режимы мигания )
Напишем скетч для «отлова» кодов нажимаемых клавиш пультов (коды выводим в монитор последовательного порта)
#include "Energia.h"
//
#include IRremote.h
int RECV_PIN = P1_3;
IRrecv irrecv(RECV_PIN);
IRsend irsend;
decode_results results;
byte_ir_kod;

// коды клавиш для режимов R,G,B,RG,GB.RB,WHITE,BLACK,мигание1,...
const long IR_CODES[12];

void setup()
{
irrecv.enableIRIn(); // Start the receiver
attachInterrupt(RECV_PIN,ext_ir_code,FALLING);
Serial.begin(9600);
Serial.println("start");
}
void loop()
{
if(ir_kod>0)
{
Serial.print(ir_kod,HEX);
ir_kod=0;
}
}
// получение кода пульта
void ext_ir_code()
{
detachInterrupt(RECV_PIN);
if (irrecv.decode(&results)) {
ir_kod=lowByte(results.value);
delay(500);
irrecv.resume(); // Receive the next value
}
attachInterrupt(RECV_PIN,ext_ir_code,FALLING);
}

С кодами клавиш определились, заносим их в массив
// x10 marmitek
const long IR_CODES[12]={0x00,0x08,0x04,0x0C,0x02,0x0A,0x09,0x09,0x06,0x0E,0x01,0x03};
или
// для контроллера RGB лент keys24
const long IR_CODES[12]={0xDF,0x9F,0x5F,0xEF,0xAF,0x6F,0x1F,0xBF,0x2F,0x0F,0x37,0x17};

Экономить выводы LaunchPad для управления 6 RGB-светодиодами будем использовать микросхемы 74HC595 (преобразователь последовательного интерфейса в параллельный), при этом мы можем обойтись 3 выводами контроллера. Используем библиотеку SPI.
Выводы соединяем следующим образом
LaunchPad 74HC595
P2_0 — RCK 12
P1_7 — MOSI 14
P1_5 — SCK 11

mc182-8
И схема
mc182-9
Т.к. все сделано на макетной плате и соединения проводами, используются выводы Q1-Q6 микросхемы 74HC595.
Создадим в программе двумерный массив, с данными для разных режимов (16 — с запасом, может пригодиться под какой-нибудь пульт).
const byte MODES[16][8]={
{0x12,1,0x12,2,0x12,3,0x12,1}, // R
{0x24,1,0x24,2,0x24,3,0x24,1}, // G
{0x48,1,0x48,3,0x48,1,0x48,1}, // B
{0x36,1,0x36,2,0x36,3,0x36,1}, // RG
{0x6C,1,0x6C,2,0x6C,3,0x6C,1}, // GB
{0x5A,1,0x5A,3,0x5A,1,0x5A,1}, // BR
{0xFF,1,0xFF,1,0xFF,1,0xFF,1}, // WHITE
{0,1,0,2,0,1,0,1}, // BLACK
{0x12,5,0x24,5,0x48,5,0x5A,5}, // prg1 r1b1g1y1
{0x48,10,0x6C,10,0x48,10,0x6C,10}, // prg2 b3gb1b3gb1
{0x48,20,0x22,20,0x12,20,0x12,20}, // prg3
{0x12,1,0x12,1,0x12,1,0x12,1}, // prg4
{0x48,1,0x22,3,0x12,1,0x12,1}, // prg5
{0x12,1,0x12,1,0x12,1,0x12,1}, // prg6
{0x48,1,0x22,3,0x12,1,0x12,1}, // prg7
{0x12,1,0x12,1,0x12,1,0x12,1} // prg8
};
int offset0=0;
int offset1 = 1; // выбранная программа
int offset2 = 1; // фрагмент(кадр) программы
int offset3 = 1; // длительность кадра
int my_channel=1;

Индекс массива — программа свечения, нечетные байты одномерных массивов — последовательные данные(цвет) отправляемые SPI, четные — длительность в сек. свечения. По прерыванию получаем код с пульта, ищем наличие кода в массиве IR_CODES (процедура ir_code_control()), при наличии выставляем значения переменных
offset1 — номер режима,
offset2=1, offset3=1 — индекс первых фрагменты последовательностей.
Каждую секунду в цикле loop() вызывается программа process_step(), которая отправляет данные(цвет) по SPI данные в микросхемы 74HC595.
// 74hc595 - ms430
// 12 - P2_0
// 14 - P1_7
// 11 - P1_5
// 10 - +
#include "Energia.h"

#define REG_SELECT 8 // пин, управляющий защёлкой (SS в терминах SPI)

#include IRremote.h
int RECV_PIN = P1_3;
IRrecv irrecv(RECV_PIN);
IRsend irsend;
decode_results results;

// x10 marmitek
//const long IR_CODES[12]={0x00,0x08,0x04,0x0C,0x02,0x0A,0x09,0x09,0x06,0x0E,0x01,0x03};
// для контроллера RGB лент keys24
const long IR_CODES[12]={0xDF,0x9F,0x5F,0xEF,0xAF,0x6F,0x1F,0xBF,0x2F,0x0F,0x37,0x17};
const byte MODES[16][8]={
{0x12,1,0x12,2,0x12,3,0x12,1}, // R
{0x24,1,0x24,2,0x24,3,0x24,1}, // G
{0x48,1,0x48,3,0x48,1,0x48,1}, // B
{0x36,1,0x36,2,0x36,3,0x36,1}, // RG
{0x6C,1,0x6C,2,0x6C,3,0x6C,1}, // GB
{0x5A,1,0x5A,3,0x5A,1,0x5A,1}, // BR
{0xFF,1,0xFF,1,0xFF,1,0xFF,1}, // WHITE
{0,1,0,2,0,1,0,1}, // BLACK
{0x12,5,0x24,5,0x48,5,0x5A,5}, // prg1 r1b1g1y1
{0x48,10,0x6C,10,0x48,10,0x6C,10}, //prg2b3gb1b3gb1
{0x48,20,0x22,20,0x12,20,0x12,20}, // prg3
{0x12,1,0x12,1,0x12,1,0x12,1}, // prg4
{0x48,1,0x22,3,0x12,1,0x12,1}, // prg5
{0x12,1,0x12,1,0x12,1,0x12,1}, // prg6
{0x48,1,0x22,3,0x12,1,0x12,1}, // prg7
{0x12,1,0x12,1,0x12,1,0x12,1} // prg8
};
int offset0=0;
int offset1 = 1; // выбранная программа
int offset2 = 1; // фрагмент(кадр) прогаммы
int offset3 = 1; // длительность кадра
int my_channel=1;

void setup()
{
/* Инициализируем шину SPI. Если используется программная реализация,
* то вы должны сами настроить пины, по которым будет работать SPI.
*/
SPI.begin();
Serial.begin(9600);
pinMode(REG_SELECT, OUTPUT);
digitalWrite(REG_SELECT, LOW); // выбор ведомого - нашего регистра
SPI.transfer(0); // очищаем содержимое регистра
digitalWrite(REG_SELECT, HIGH);

irrecv.enableIRIn(); // Start the receiver
Serial.println("start");
attachInterrupt(RECV_PIN,ext_ir_code,FALLING);
}

void loop()
{
delay(1000);
process_step();
}

void process_step(){
// получение кода отправки
offset3=offset3-1;
if(offset3==0)
{
offset2=offset2+1;offset2=offset2%4;
offset3=MODES[offset1-1][offset2*2+1];
} /* Записываем значение в сдвиговый регистр */
digitalWrite(REG_SELECT, LOW);
SPI.transfer(255-MODES[offset1-1][offset2*2]);
SPI.transfer(255-MODES[offset1-1][offset2*2]);
SPI.transfer(255-MODES[offset1-1][offset2*2]);
digitalWrite(REG_SELECT, HIGH);
offset0++;
if(offset0==8) offset0=0;
}
// получение кода пульта
void ext_ir_code()
{
detachInterrupt(RECV_PIN);
if (irrecv.decode(&results)) {
byte ir_kod=lowByte(results.value);
// проверка кода
ir_code_control(ir_kod);
delay(500);
irrecv.resume(); // Receive the next value
}
attachInterrupt(RECV_PIN,ext_ir_code,FALLING);
}
// проверка кода
void ir_code_control(byte kod)
{
for(int i=0;i<12;i++) { if(kod==IR_CODES[i]) { offset1=i+1; offset2=1;offset3=1; return;} } }

3 comments

  1. Новогодня гирлянда Большие шарики Космос Экономик 30 светодиодов, 5.8 метров, 8 режимов мигания

  2. You made some first rate points there. I looked on the internet for the issue and found most people will go together with along with your website. http://perfectslots2016.ru

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>