Сенсорный мини выключатель EFEKTA co стеклянной панелью.

Приветствую всех читателей блога Mysku!!! В сегодняшней статье хочу поделится с вами новым проектом. На этот раз это сенсорный выключатель со стеклянной панелью. Устройство компактное, размерами 42х42мм(стандартные стеклянные панель имеет размеры 80х80мм). История этого устройства началась давно, около года назад.

Превые варианты были на микроконтролере atmega328, но в итоге все закончилось микроконтролером nRF52832.

Сенсорная часть устройства работает на микросхемах TTP223. Оба сенсора обслуживает одно прерывание. Питание от батарейки CR2477, через повышающий преобразователь на микросхеме TPS610981.



В устройстве реализована схема отключения питания на полевых транзисторах. После нажатия на кнопку микроконтролер сам перехватывает управление питанием и далее кнопка может использоватся для сервисных режимов(в моем случает это сопряжение с другими устройствами, отключение питания и сброс к заводским установкам(factory reset)).
Присутствуют 2 rgb светодиода для индикаций состояний и сервисных режимов. Так же добавлен пьезоизлучатель для имитации клика при прикосновении к сенсорным кнопкам и звуковой индикации сервичных режимов. Светодиоды и пьезоизлучатель можно включать и отключать по желанию пользователя. Делается это через контролер умного дома, отправкой команд на технические сенсоры, так же реализована возможность изменения пользователем интервалов отправки заряда батареи и уровня сигнала так же через контролер умного дома. В моем случае это МАЖОРДОМО.

Потребление в режиме передачи 7мА(250кбит, 10мс), потребление во сне 40мкА, потребление в выключенном состоянии менее 1мкА(=потреблению повышающего преобразователя в «холостом» режиме). Выведен rx, tx, swd разьем для програмирования. Используется миниатюрный разьем 2х3p с шагом 1.27. Для програмирования изготовлен специальный переходник.


Как и всегда в основе работы устройства лежит протокол MySensors. Данный сенсорный выключатель планируется применять в системе управления рулонными шторами. Но в целом применение ограничено только вашей фантазией. Например уже сейчас сын(7 лет) сделал 3 заказа на версии выключателя: для включения и выключения света в туалете с ванной(крепится будет невысоко от пола), для включения света в длинном и темном коридоре при путешествии в туалет с ванной и еще один как прикроватный, для быстрого включения света в своей комнате чтобы монстры разбежались.




Корпус по традиции печатался на SLA принтере, устройство миниатюрное, корпус получился небольшой, применение даной технологии печати оправдано.
Посмотреть отпечатанную модель





В корпус и крышку батарейного отсека вклеены магнитики.

Видосики с тестами данного устрройства:







Для желающих повторить:

Код тестовой программы выключателя в системе управления рулонными шторами для Arduino IDE
int8_t timer_status = 0;
boolean sens_flag1 = 0;
boolean sens_flag2 = 0;
boolean switch_a = 0;
boolean switch_b = 0;
uint16_t temp;
float vcc;
int battery;
int old_battery;
uint32_t oldmillis;
uint32_t newmillis;
uint32_t interrupt_time;
uint32_t SLEEP_TIME = 7000;
uint32_t SLEEP_TIME_W;
uint32_t SLEEP_TIME_W2;
int NrfRSSI;
uint16_t NrfRSSI2;
boolean wait_off;

#define MY_DEBUG

#define MY_RADIO_NRF5_ESB
#define MY_PASSIVE_NODE
#define MY_NODE_ID 120
#define MY_PARENT_NODE_ID 0
#define MY_PARENT_NODE_IS_STATIC
#define MY_TRANSPORT_UPLINK_CHECK_DISABLED
#define POWER_CHILD_ID 110
#define UP_POWER_SWITCH_ID 1
#define DOWN_POWER_SWITCH_ID 2
#define CHILD_ID_nRF52_RSSI_RX 3

#define BAT_COOF 0.0092957746478873
#define BAT_MIN 200
#define BAT_MAX 290

#include <MySensors.h>
MyMessage upMsg(UP_POWER_SWITCH_ID, V_STATUS);
MyMessage downMsg(DOWN_POWER_SWITCH_ID, V_STATUS);
MyMessage powerMsg(POWER_CHILD_ID, V_VAR1);
MyMessage msgRF52RssiReceiv(CHILD_ID_nRF52_RSSI_RX, V_VAR1);

void preHwInit() {
//delay(1000);
pinMode(31, OUTPUT);
digitalWrite(31, HIGH);
delay(3000);
pinMode(3, INPUT);
pinMode(25, OUTPUT);
pinMode(26, OUTPUT);
pinMode(27, OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);

pinMode(28, OUTPUT); // bizzer

pinMode(2, INPUT);
pinMode(9, INPUT);
pinMode(10, INPUT);

pinMode(29, INPUT);

digitalWrite(28, LOW); // off bizzer
digitalWrite(27, HIGH);
digitalWrite(26, HIGH);
digitalWrite(25, HIGH);
digitalWrite(6, HIGH);
digitalWrite(7, HIGH);
digitalWrite(8, HIGH);
}

void before()
{
//digitalWrite(31, HIGH);
NRF_POWER->DCDCEN = 1;
//NRF_UART0->ENABLE = 0;
analogReadResolution(12);
disableNfc();
turnOffAdc();
//wait(2000);
digitalWrite(25, LOW);
digitalWrite(6, LOW);
wait(200);
digitalWrite(25, HIGH);
digitalWrite(6, HIGH);
wait(100);
playSound0();
wait(100);
digitalWrite(25, LOW);
digitalWrite(6, LOW);
wait(200);
digitalWrite(25, HIGH);
digitalWrite(6, HIGH);
wait(3000);

digitalWrite(27, LOW);
digitalWrite(8, LOW);
wait(200);
digitalWrite(27, HIGH);
digitalWrite(8, HIGH);
wait(400);
digitalWrite(6, LOW);
digitalWrite(25, LOW);
wait(200);
digitalWrite(6, HIGH);
digitalWrite(25, HIGH);
wait(400);
digitalWrite(26, LOW);
digitalWrite(7, LOW);
wait(200);
digitalWrite(26, HIGH);
digitalWrite(7, HIGH);
wait(1000);
digitalWrite(26, LOW);
digitalWrite(7, LOW);
}

void setup()
{
digitalWrite(26, HIGH);
digitalWrite(7, HIGH);
wait(50);
playSound();
wait(2000);
readBatLev();
wait(200);
SLEEP_TIME_W = SLEEP_TIME;
}

void presentation()
{
sendSketchInfo(«Power on|off Node», «1.0»);
wait(100);
present(POWER_CHILD_ID, S_CUSTOM, «BATTERY DATA»);
wait(100);
present(UP_POWER_SWITCH_ID, S_BINARY, «UP SWITCH»);
wait(100);
present(DOWN_POWER_SWITCH_ID, S_BINARY, «DOWN SWITCH»);
}

void loop()
{
if (sens_flag1 == 0 && sens_flag2 == 0) {
if (switch_a == 0 && switch_b == 0) {
timer_status = sleep(digitalPinToInterrupt(2), RISING, digitalPinToInterrupt(3), RISING, 3600000, false);
wait_off = 1;
} else {
//oldmillis = millis();
timer_status = sleep(digitalPinToInterrupt(2), RISING, digitalPinToInterrupt(3), RISING, SLEEP_TIME_W, false);
wait_off = 0;
}
}
if (timer_status == 3) {
wait(100);
digitalWrite(27, LOW);
digitalWrite(8, LOW);
wait(2000);
digitalWrite(27, HIGH);
digitalWrite(8, HIGH);
wait(100);
digitalWrite(31, LOW);
}

if (timer_status == 2) {

if (digitalRead(9) == HIGH && sens_flag1 == 0 && switch_b == 0) {
sens_flag1 = 1;
if (switch_a == 0) {
oldmillis = millis();
SLEEP_TIME_W = SLEEP_TIME;
switch_a = 1;
send(upMsg.set(switch_a));
//wait(200);
digitalWrite(6, LOW);
wait(10);
playSound1();
wait(20);
playSound2();
wait(50);
} else {
switch_a = 0;
send(upMsg.set(switch_a));
//wait(200);
digitalWrite(6, HIGH);
wait(10);
playSound2();
wait(20);
playSound1();
wait(50);
}
//sleep_not_pasible = 1;
//digitalWrite(25, HIGH);
//wait(100);

}
if (digitalRead(10) == HIGH && sens_flag2 == 0 && switch_a == 0) {
sens_flag2 = 1;
if (switch_b == 0) {
oldmillis = millis();
SLEEP_TIME_W = SLEEP_TIME;
switch_b = 1;
send(downMsg.set(switch_b));
//wait(200);
digitalWrite(25, LOW);
wait(10);
playSound1();
wait(20);
playSound2();
wait(50);
} else {
switch_b = 0;
send(downMsg.set(switch_b));
//wait(200);
digitalWrite(25, HIGH);
wait(10);
playSound2();
wait(20);
playSound1();
wait(50);
}
//sleep_not_pasible = 1;
//digitalWrite(6, HIGH);
//wait(100);
}

if (digitalRead(9) == LOW && sens_flag1 == 1) {
sens_flag1 = 0;
//digitalWrite(6, HIGH);
//playSound2();
//wait(50);
}

if (digitalRead(10) == LOW && sens_flag2 == 1) {
sens_flag2 = 0;
//digitalWrite(25, HIGH);
//playSound2();
//wait(50);
}
if (switch_a == 1 || switch_b == 1) {
if (wait_off == 0) {
newmillis = millis();
wait(10);
SLEEP_TIME_W2 = SLEEP_TIME_W;
wait(10);
interrupt_time = newmillis — oldmillis;
wait(10);
SLEEP_TIME_W = SLEEP_TIME_W2 — interrupt_time;
wait(10);
Serial.print(«WAS IN A SLEEP: „);
Serial.print(newmillis — oldmillis);
Serial.println(“ MILLISECONDS»);

if (SLEEP_TIME_W < 1000) {
if (switch_a == 1) {
switch_a = 0;
digitalWrite(6, HIGH);
//wait(10);
//playSound2();
//wait(20);
//playSound1();
//wait(50);
//send(upMsg.set(switch_a));
//wait(200);
}
if (switch_b == 1) {
switch_b = 0;
digitalWrite(25, HIGH);
//wait(10);
//playSound2();
//wait(20);
//playSound1();
//wait(50);
//send(downMsg.set(switch_b));
//wait(200);
}
SLEEP_TIME_W = SLEEP_TIME;
wait(50);
}
Serial.println(SLEEP_TIME);
Serial.println(SLEEP_TIME_W);
Serial.println(SLEEP_TIME_W2);
Serial.print(«GO TO SLEEP FOR: „);
Serial.print(SLEEP_TIME_W);
Serial.println(“ MILLISECONDS»);
}
oldmillis = millis();
}
}

if (timer_status == -1) {
if (switch_a == 1 || switch_b == 1) {
if (switch_a == 1) {
switch_a = 0;
digitalWrite(6, HIGH);
wait(10);
playSound2();
wait(20);
playSound1();
wait(50);
send(upMsg.set(switch_a));
wait(200);
}
if (switch_b == 1) {
switch_b = 0;
digitalWrite(25, HIGH);
wait(10);
playSound2();
wait(20);
playSound1();
wait(50);
send(downMsg.set(switch_b));
wait(200);
}
} else {
readBatLev();
}
}
}

void disableNfc() {
NRF_NFCT->TASKS_DISABLE = 1;
NRF_NVMC->CONFIG = 1;
NRF_UICR->NFCPINS = 0;
NRF_NVMC->CONFIG = 0;
}

void turnOffAdc() {
if (NRF_SAADC->ENABLE) {
NRF_SAADC->TASKS_STOP = 1;
while (NRF_SAADC->EVENTS_STOPPED) {}
NRF_SAADC->ENABLE = 0;
while (NRF_SAADC->ENABLE) {}
}
}

void myTone(uint32_t j, uint32_t k) { // Определяем функцию myTone
j = 500000 / j; // Меняем значение переменной j на время одного полупериода в мкс
k += millis(); // Меняем значение переменной к на время завершения вывода сигнала
while (k > millis()) { // Выводим сигнал, пока не истечёт указанное время
digitalWrite(28, HIGH); delayMicroseconds(j); // Устанавливаем на выходе i уровень логической «1» на время j
digitalWrite(28, LOW ); delayMicroseconds(j); // Устанавливаем на выходе i уровень логического «0» на время j
}
}

void playSound0() {
//wait(500);
myTone(1300, 50); // Выводим звуковой сигнал длительностью 0,1 сек с частотой 2048 Гц
wait(20); // Ждём 0,1 сек
myTone(1300, 50);
wait(50);
}

void playSound() {
//wait(500);
myTone(700, 30); // Выводим звуковой сигнал длительностью 0,1 сек с частотой 2048 Гц
wait(10); // Ждём 0,1 сек
myTone(700, 30);
wait(10);
myTone(700, 30);
wait(50); // Ждём 0,1 сек
//myTone(500, 30);
//wait(500);
}

void playSound1() {
//wait(500);
myTone(200, 10); // Выводим звуковой сигнал длительностью 0,1 сек с частотой 2048 Гц
wait(10); // Ждём 0,1 сек
myTone(400, 5);
wait(30); // Ждём 0,1 сек
//myTone(500, 30);
//wait(500);
}

void playSound2() {
//wait(500);
myTone(400, 10); // Выводим звуковой сигнал длительностью 0,1 сек с частотой 2048 Гц
wait(10); // Ждём 0,1 сек
myTone(200, 5);
wait(30); // Ждём 0,1 сек
//myTone(500, 30);
//wait(500);
}

void readBatLev() {
//NRF5_ESB_startListening();
wait(200);
temp = analogRead(29);
vcc = temp * 0.0033 * 100;
battery = map((int)vcc, BAT_MIN, BAT_MAX, 0, 100);
if (battery < 0) {
battery = 0;
}
if (battery > 100) {
battery = 100;
}
sendBatteryLevel(battery);
wait(200);
send(powerMsg.set(temp));
wait(200);
NrfRSSI = transportGetReceivingRSSI();
NrfRSSI2 = map(NrfRSSI, -85, -40, 0, 100);
if (NrfRSSI2 < 0) {
NrfRSSI2 = 0;
}
if (NrfRSSI2 > 100) {
NrfRSSI2 = 100;
}
send(msgRF52RssiReceiv.set(NrfRSSI2));
wait(200);
}


Все комплектующие покупались на АЛИ, приведу ссылки на основные компоненты:
Стеклянная мини панель — ссылка
Микроконтролер nRF52832 — ссылка
Сенсорная микросхема TTP223 — ссылка

Файлы корпуса в stl — гугл драйв

Gerber файлы печатной платы — гугл драйв

На все вопросы по данной разработке, помощь в освоении MySensors обращайтесь в чат @mysensors_rus
Добавить в избранное +33 +50
+
avatar
  • Xylene
  • 28 мая 2019, 18:21
+9
вы бы подробнее писали что и для чего. Я со второго взгляда по диагонали только понял, что это радиопульт ДУ двухкопочный для вашего протокола. А то так и будете без комментариев сидеть ))
+
avatar
  • berk
  • 28 мая 2019, 19:16
0
так вроде бы все знают о таких штуках только в стандартных размерах 80х80мм на батарейках, непомню всех производителей, на языке крутится сонофф. И он как бы не только для «нашего протокола MySensors. Чип кодится в Ардуино ИДЕ, так что БЛЕ еще как минимум. Ну а тем кто владеет Визуал Студио например и силен в Сях, то идем на сайт Нордика и расширяем возможности сильно больше, хоть тот же бле меш.
+
avatar
  • Xylene
  • 28 мая 2019, 21:42
+11
так вроде бы все знают
это когнитивное искажение. 80 % не слышали о ардуино, 90% о вижуал студио, Си и Нордик — матерные слова
+
avatar
  • berk
  • 28 мая 2019, 21:54
0
со всем согласен :), кроме 80%
+
avatar
  • bm_s
  • 29 мая 2019, 07:17
+5
99?…
+
avatar
  • Kabron
  • 28 мая 2019, 18:30
+2
Для желающих повторить:
интереснее всего будет схема.
+
avatar
+2
Отличная разработка. забрал в закладки.
На какой срок хватает батареи? Или я пропустил?
+
avatar
  • berk
  • 28 мая 2019, 21:57
+1
по расчетам на 1,5 лет. но пока у проекта трехмесячная борода. пока в рамках
+
avatar
+9
Господа, товарищи, братья и сёстры!!! Ну вы блин даёте. Ну хоть в заголовках пишите грамотно. Вот как это произнести: ...c стеклянной панелью...? Это же как напрячься надо. За проект плюс.
+
avatar
  • chanov
  • 28 мая 2019, 19:41
+3
А в качестве шлюза (приёмной части) что используется?
+
avatar
  • berk
  • 28 мая 2019, 21:53
+1
стандартный майсенсорс гейт
+
avatar
  • dansar
  • 28 мая 2019, 21:07
0
Корпус у этой nRF не сильно паябельный.
+
avatar
  • Xylene
  • 28 мая 2019, 21:37
0
подогревный столик за 5 долларов из недавнего обзора или бабушкин утюг на худой — и QFN побежден легко и непринужденно
+
avatar
  • berk
  • 28 мая 2019, 21:52
+1
та перестаньте, я его даде на ЛУТ паял, разводишь пасту с флюсом, кидаешь чип, зажимаешь обратным пинцетом, другим пинцетом выравниваешь, потом феном сверху секунд 5-7, готово.
+
avatar
+2
А как сын в темноте найдет куда тыкать? Подсветка же не горит постоянно.
Сенсорные хороши при нормальном питании:





Почему спойлер в комментах не работает?
+
avatar
  • Xylene
  • 28 мая 2019, 22:45
0
можно светонакопительной пластинкой решить думаю
+
avatar
  • berk
  • 28 мая 2019, 23:24
0
почему в темноте пойдет? на фото похожие но отличные по функционалу и применению девайсы. спойлер ставится должен.
+
avatar
0
Ну так чтобы включить свет в темноте нужно увидеть либо нащупать выключатель. Он должен либо светиться либо быть тактильно различимым. Поэтому я сделал стационарные сенсорными, а выключатель, который можно прилепить на любую поверхность, на батарейном питании — механическим. На мой взгляд так удобнее.
Вот точный аналог по функционалу, все в инфраструктуре mysensors, только я domoticz использую:




ЗЫ спойлер не работает, не раскрывается (
+
avatar
  • bird
  • 30 мая 2019, 03:58
0
Дополнительная информация

Так не раскрывается или не создается? Для открытия спойлера после добавления комментария обнови страницу.
+
avatar
  • G99999
  • 29 мая 2019, 00:02
+2
Чип кодится в Ардуино ИДЕ, так что БЛЕ еще как минимум. Ну а тем кто владеет Визуал Студио например и силен в Сях, то идем на сайт Нордика и расширяем возможности сильно больше, хоть тот же бле меш.
Пойду ка я приму увеличитель мозга…
+
avatar
  • Xylene
  • 29 мая 2019, 00:35
0
Arduino IDE BLE Visual Studio C programming language Nordic Semiconductor BLE Mesh ++ Google.ru
+
avatar
  • Fiks
  • 29 мая 2019, 00:40
+1
Да кодится то оно прекрасно… если жаба не мешает. Проскакала она по ссылкам: «187+1038+77=1302 + 3D-принтер» и теперь права качает — требует чтоб сначала купил ей вот этот девайс, а потом уже всё остальное.

+
avatar
0
На самом деле чтобы начать достаточно вот этого https://item.taobao.com/item.htm?id=555560930150
NRF52832 за 150р при покупке некоего количества. А дальше уже от вашего скилла все зависит, большинство вообще не поймет о чем этот топик :-)
+
avatar
0
+
avatar
0
О, ну хоть здесь отвечу, ибо не совместим я с хабром по идейным соображениям.
А то пристал там к автору один «разработчик» с ЧСВ over 8000 что TP223 не нужна можно ножки заряжать/разряжать, noolite лучше и.т.п.
Только он забыл написать, что дрыгать ногой с площадкой и высокоомным резистором — это в разы больше расходовать энергию.
Сам сейчас допиливаю сенсор на pic18. Да, нажатие можно отслеживать и через 70мм диэлектрика (дерево/бетон — ему пофиг), но путем неимоверных страданий мк :) А noolite который на pic12, ЕМНИП, без обратной связи. Это я считаю вообще не вариант. Продавать это должно быть стыдно.
Так что жму руку, всё у вас норм :)
+
avatar
0
а зачем там повышающий преобразователь?
+
avatar
  • berk
  • 29 мая 2019, 16:16
0
вначале было без него, но потом не устоял перед хотелками, пьезоизлучатель на прямом батареечном питании не имел бы смысла, потребление ледов и ограничивать на 2 вольтах еще тот се… с, да и ровномерной яркости не добится. да и у сенсоров ниминал все же 3, не спорю можно и на друх, но не уверен прям в стабильности.
+
avatar
  • Samman
  • 29 мая 2019, 22:22
0
Люди добрые, сами мы не местные, отстали от поезда прогресса… Помогите кто какими разъяснениями и ссылками может про программирование этого бесовского NRF. Разложил перед собой прошитый ST-link-ом и отлаженный через FTDI, блюпуп модуль NRF51822 типа такого , прошитый ST-link-ом в черномагический пробник блюпил на STM32 типа такого и горько заплакал от осознания собственной некомпетентности…
+
avatar
  • Samman
  • 30 мая 2019, 12:50
0
Я не хвастаюсь, прошивал-то не я. Я не могу заставить это работать вместе.
+
avatar
  • Maks_K
  • 03 июня 2019, 12:49
0
Извиняюсь но я не нашел принципиальной схемы сенсора
да и
Присутствуют 2 rgb светодиода для индикаций состояний и сервисных режимов. Так же добавлен пьезоизлучатель для имитации клика при прикосновении к сенсорным кнопкам и звуковой индикации сервичных режимов. Светодиоды и пьезоизлучатель можно включать и отключать по желанию пользователя. Делается это через контролер умного дома, отправкой команд на технические сенсоры,
вызывает вопросы:
что за сервисные режимы?
Что за технические сенсоры?
Какие команды поддерживает сенсор?
может ест подробное описание на hardware.io?