Проект создания сенсорного частично универсального пульта под определенные задачи. Пульт создается на базе контроллера MSP430 Lanchpad, купленного ещё по 4.30$ (на данный момент цена 9.99$) и сенсорного блока 430BOOST-SENSE1 (цена 10$).
430BOOST-SENSE1 (Capacitive Touch BoosterPack) — дополнительная плата к набору разработчика MSP430 Value Line LaunchPad development kit (MSP-EXP430G2). На плате расположены некоторые варианты емкостных сенсорных датчиков, включая колесо прокрутки, кнопку и датчик приближения. Кроме того, на плате установлены 9 светодиодов, которые обеспечивают индикацию взаимодействия пользователя с емкостными сенсорными датчиками.
Дополнительно к 430BOOST-SENSE1 прилагается предварительно запрограммированный микроконтроллер MSP430G2452IN20 семейства MSP430 ValueLine для демонстрации работы с емкостными сенсорными датчиками. Таким образом, разработчик имеет возможность ознакомиться с работой сенсорных датчиков без необходимости программирования микросхемы.
При объединении с платой LaunchPad kit, плата 430BOOST-SENSE1 предлагает законченный аппаратный и программный образец разработки, позволяющий быстро и легко заменить любые физические кнопки элементами на основе емкостных сенсорных датчиков.
Изучение даташита помогло найти используемые выводы MSP430 Lanchpad (см. рис.)
С выводов P1.3 — P1.7 будем управлять светодиодами, а выходов P2.0 — P2.5 получать показания с панели.
Для программирования использовалась Arduino-подобная среда программирования Energia. Использовал библиотеку CapTouch. После экспериментов с получением значений при нажатиях на панель, назначение нажатий определим следующее.
Одновременное нажатие P2.0 (на рисунке красное) и P2.5 (D0) последовательный перебор текущего устройства по возрастанию,нажатие P2.5(D0) перебор текущего устройства по убыванию,при этом на светодиодах соответствующая индикация
Нажатие на области P2.1 — P 2.4 и между двумя соседними областями — отправка кода с блинком светодиода D0. Нажатие двумя пальцами P2.0 — переход в режим sleep
Индикация для выводов
P1_0,P1_3,P1_4,P1_5,P1_6,P1_7
приведена в массиве
const boolean LEDS_MODE[11][6]={
{0,0,0,0,0,0}, // спящий режим
{0,0,1,0,0,0}, // выбор пульта 1
{0,0,1,1,0,0}, // выбор пульта 2
{0,0,1,1,1,0}, // выбор пульта 3
{0,0,1,1,1,1}, // выбор пульта 4
{0,1,0,1,1,1}, // выбор пульта 5
{0,1,0,0,1,1}, // выбор пульта 6
{0,1,0,0,0,1}, // выбор пульта 7
{0,1,0,0,0,0} // выбор пульта 8
};
В принципе можно создать 16 пультов по 8 клавиш (а задействуя P_0 в 2 раза больше), но делал для себя для наглядности мне так более удобно.
У меня группа 1 — светодиодные ленты RGB — у меня 2 шт. Вторая группа — новогодняя лампа-ночник Остального пока нет — но есть задумки кое-какие.
Для отправки кодов через ИК-светодиодов собирался использовать библиотеку IRRemote. Казалось все просто и работы максимум на рабочую неделю, но оказалось все не так.
Часть проекта с выбором режимов, индикацией и выбором кодов для отправки была написана быстро. Вот код
#include «CapTouch.h»
const int PINS[]={0,P2_0,P2_1,P2_2,P2_3,P2_4,P2_5};
const int LEDS[]={0,P1_0,P1_3,P1_4,P1_5,P1_6,P1_7};
const boolean LEDS_MODE[11][6]={
{0,0,0,0,0,0}, // спящий режим
{0,0,1,0,0,0}, // выбор пульта 1
{0,0,1,1,0,0}, // выбор пульта 2
{0,0,1,1,1,0}, // выбор пульта 3
{0,0,1,1,1,1}, // выбор пульта 4
{0,1,0,1,1,1}, // выбор пульта 5
{0,1,0,0,1,1}, // выбор пульта 6
{0,1,0,0,0,1}, // выбор пульта 7
{0,1,0,0,0,0} // выбор пульта 8
};
const int choice_command[]={0,1,1,1,1,0,1,0,1,1,0,0,1,0,0,0};
int mode=0;
int sleep=0;
int base_counts[7];
unsigned int count, base_count,delta_count;
int state = 0;
static const unsigned int threshold = 150;
static const unsigned int threshold2 = 250;
CapTouch touch1;
void setup() {
Serial.begin(9600);
for(int i=1;i<7;i++)
{touch1.add(PINS[i]);
base_counts[i]=touch1.measure(PINS[i]);
pinMode(LEDS[i], OUTPUT);
}
}
void loop()
{
change_mode(get_pressed());
establish_leds(mode);
delay(500);
}
// проверка touch-клавиш на нажатие
int get_pressed()
{
int pos=0;
for(int i=0;i<7;i++)
{
count = touch1.measure(PINS[i]);
if(base_counts[i] < count)
{base_counts[i] = (base_counts[i] + count) >> 1;
delta_count = 0;}
else
{delta_count = base_counts[i] — count;}
if(delta_count > threshold)
{
uint16_t bitmask = 1;
if (i >0)
{for (int j = 0; j < i-1; ++j)
bitmask <<= 1;
}
pos=pos+bitmask;
if(delta_count>280 && i==1)
sleep=1;
}
else
{base_count = base_count — 1;}
delay(10);
}
return pos;
}
// установить светодиоды для режима
void establish_leds(int mode)
{
for(int i=1;i<7;i++)
digitalWrite(LEDS[i],LEDS_MODE[mode][i-1]);
}
// изменить режим после нажатия
void change_mode(int pos)
{
// анализ нажатий
// переход в спящий режим
if(sleep==1)
{mode=0;sleep=0;
return;}
// выбор следующего режима
if(bitRead(pos,0) && bitRead(pos,5))
{mode=mode+1;mode=min(8,mode);
return;}
// выбор предыдущего режима
if(bitRead(pos,5))
{mode=mode-1;mode=max(1,mode);
return;}
// отправка кода
byte bpos;
bpos=lowByte(pos);
bitClear(bitClear(bpos,0),5);
bpos=bpos>>1;
if(mode>0 && choice_command[bpos])
{send_command(mode,bpos);
return;}
}
// изменить режим после нажатия
void send_command(int high,byte low)
{
byte bsend;
bsend=lowByte(high)<<4;
bsend+=low;
Serial.println(bsend,HEX);
digitalWrite(P1_0,HIGH);
delay(500);
digitalWrite(P1_0,LOW);
}
Дальше начались проблемы. При подключении библиотеки IRremote, скетч терял нажатия на две области, а при попытке отправить код через ИК-светодиод скетч вообще не работал. Для отправки кодов использовал второй комплект M430. Два модуля связаны по последовательному порту. Прием байта из последовательного порта, выбор кода из таблицы и отправка через ик светодиод (используется библиотека IRremote).
Вот скетч
#include «IRremote.h»
IRsend irsend;
int inChar;
boolean stringComplete = false;
// список кодов
long irkod[128]={
0x12,0x24,0x36,0x48,0,0x6c,0,0xff,0x5a,0,0,1,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,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,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
};
void setup()
{
Serial.begin(9600);
}
void loop() {
if (stringComplete) {
//irsend.sendRC5(irkod[inChar], 12);
irsend.sendRC5(inChar, 12);
stringComplete = false;
}
}
void serialEvent() {
while (Serial.available())
{
// get the new byte:
inChar = (int)Serial.read();
stringComplete = true;
}
}
Прикрепленные файлы:
- captouch_41.zip (3 Кб)
- irsend_1.zip (1 Кб)