Безжичен сензорен ключ с допълнително луминесцентно осветление

Поздрави на всички читатели на секцията „Направи си сам или направи сам“ на Habr! Днешната статия ще бъде за сензорния превключвател на чипа TTP223 | фиш. Превключвателят работи на микроконтролера nRF52832 | фиш, е използван модул YJ-17103 с печатна антена и конектор за външна MHF4 антена. Сензорният превключвател работи с батерии CR2430 или CR2450. Консумацията в режим на предаване е не повече от 8 mA, в режим на заспиване не повече от 6 µA.
Безжичен сензорен ключ с допълнително луминесцентно осветление

Както всички предишни проекти, този също е проект на Arduino, програмата е написана в Arduino IDE. Софтуерната реализация на устройството е базирана на протокола Mysensors | GitHub библиотеки, nRF5 платка поддържа GitHub в Mysensors. Англоезичен форум на общността - http://forum.mysensors.org, рускоезичен форум на общността - http://mysensors.ru/forum/
(За тези, които искат да учат - Документация, Сериен протокол, API, Протоколът, анализатора | за желаещите да помогнат (вноски) в развитието на проекта - Документация)

Платката за сензорен превключвател е разработена в програмата Deeptrace, като се вземе предвид последващото производство по метода на технологията за лазерно гладене (LUT). Платката е разработена в размери 60x60mm (стандартен стъклен панел е с размери 80x80mm). Веригата беше отпечатана на страниците на списание Antenna и пренесена с ютия на Bosch с настройка "Len" (максимална мощност) върху двустранно фолио от фибростъкло 1.5 mm, 35 µm (при липса на друго).
Безжичен сензорен ключ с допълнително луминесцентно осветление

Офортът се извършва с разтвор на железен хлорид, предварително приготвен в съотношение 1.5 чаени лъжички на 250 ml топла вода. Процесът отне 15 минути.
Пробиването на отвори за междинни отвори и за закрепване на държача на батерията беше извършено с мини-бормашина DREMEL 3000, монтирана на стойка за бормашина DREMEL 220. Отворите за междинни отвори бяха пробити със свредло 0,4 mm, отворите за държача на батерията с бормашина 1,1 mm . Подрязването по границите на дъската беше извършено със същата мини-бормашина с приставка DREMEL 540 (Кръг на рязане d=32.0mm). Подрязването е извършено в респиратор.
Калайдисването на гравираната дъска се извършва с помощта на розова сплав във воден разтвор (1 чаена лъжичка кристализирана лимонена киселина на 300 ml вода).

Процесът на запояване отне около час, по-голямата част от времето беше изразходвано за запояване на тел (калайдисан, с диаметър 0.4 mm) в отворите за междинни отвори.

Платката беше измита с аерозолен почистващ препарат FLUX OFF.
Безжичен сензорен ключ с допълнително луминесцентно осветление

Безжичен сензорен ключ с допълнително луминесцентно осветление

Дизайнът на корпуса на устройството е извършен в триизмерен редактор за компютърно проектиране. Размери на корпуса 78,5mm X 78,5mm X 12mm.
Безжичен сензорен ключ с допълнително луминесцентно осветление

Завършеният модел на кутията и капака на отделението за батерията беше запазен във формат STL, след което беше необходимо тези модели да се подготвят за печат на SLA принтер (добавяне на опори, ориентация). На този етап възникна малък проблем, тъй като площта за печат на домакинските SLA принтери е малка. Моделът на кутията на устройството в най-оптималната позиция спрямо времето за печат не се вписва в размерите на зоната за печат. При поставяне на модела на 45 градуса също даде разочароващ резултат; теглото на опората беше равно на теглото на модела на тялото. Беше решено моделът да се отпечата вертикално, като се направи опора на една от предните страни, като се съгласи предварително с факта на последваща обработка. Отпечатването на тялото отне 5 часа с настройка на слоя от 50 микрона. След това обработката беше извършена с много фина шкурка (няма да пиша номера, защото не знам :)). Отпечатването на капака на батерията отне 40 минути.
Безжичен сензорен ключ с допълнително луминесцентно осветление

Стъклените панели от Aliexpress се продават с вече залепена пластмасова рамка, нямаше проблеми с премахването на рамката. Премахнах стъкления панел, след като го загрях предварително с обикновен сешоар.
Безжичен сензорен ключ с допълнително луминесцентно осветление

Безжичен сензорен ключ с допълнително луминесцентно осветление

Дифузьорът за LED подсветката е изработен от двойнозалепваща лента с акрилно лепило 3M 9088-200. За флуоресцентно осветление имаше няколко материала за избор, китайска самозалепваща лента и самозалепваща хартия, нарязана на ленти от местната компания Luminofor. Изборът беше направен в полза на местен производител, според моите чувства той светеше по-ярко и по-дълго. Квадрат хартия с флуоресцентен пигмент беше залепен отгоре с 3M 9088-200 двустранна лента.

Стъклото беше залепено към тялото на превключвателя с помощта на двустранна лента с акрилно лепило 3M VHB 4910.
Безжичен сензорен ключ с допълнително луминесцентно осветление

Капакът беше фиксиран с винт M 1,4 X 5 mm.

Цената на устройството беше 890 рубли.

След това дойде програмната част. Имаше някои проблеми. Оказва се, че сензорните чипове TTP223 работят чудесно със стабилизирано захранване от 3.3V и не много добре, когато се захранват директно от добре разредена батерия. При стартиране на устройството със захранване около 2.5 v, плюс след допълнително „изтегляне“ при разработване на презентацията на Mysensors, микросхемата TTP223 (веднага след калибриране) предизвика прекъсване на MK, тъй като беше с активен тригер.

Веригата за захранване на микросхемата беше променена (управление на захранването TTP223 с gpio MK), доставено беше допълнително заземяване и бяха заменени резистори с по-високо съпротивление на rgb led линиите (които се движат от другата страна на капацитивната сензорна платка). Също така беше добавено към софтуера: активиране на мощността за капацитивната микросхема след стартиране на рамката Mysensors и изработване на презентацията. Закъснението за автоматично калибриране на чипа TTP223 при подаване на захранване е удвоено. Всички тези промени напълно премахнаха този проблем.

Преди да видите програмния код, препоръчвам ви да се запознаете с основната структура на скиците в Mysensors.void before()
{
// Дополнительная функция, если сравнивать со стандартной структурой Ардуино скетчей, то before() это подобие setup(), отработка происходит до инициализации транспортного уровня Mysensors, рекомендуется например для инициализации устройств SPI
}

void setup()
{

}

void presentation()
{
//Тут происходит презентация ноды и ее сенсоров на контролере через маршрутизатор
sendSketchInfo("Name of my sensor node", "1.0"); // презентация названия ноды, версии ПО
present(CHILD_ID, S_WHATEVER, "Description"); // презентация сенсоров ноды, описания сенсоров
}

void loop()
{

}

Код за тестване на програмата за докосване:test_sens.ino
/**
ТЕСТОВЫЙ СКЕТЧ СЕНСОРНОГО ВЫКЛЮЧАТЕЛЯ С ПРЕРЫВАНИЯМИ НА NRF_LPCOMP
*/
bool button_flag;
bool sens_flag;
bool send_flag;
bool detection;
bool nosleep;
byte timer;
unsigned long SLEEP_TIME = 21600000; //6 hours
unsigned long oldmillis;
unsigned long newmillis;
unsigned long interrupt_time;
unsigned long SLEEP_TIME_W;
uint16_t currentBatteryPercent;
uint16_t batteryVoltage = 0;
uint16_t battery_vcc_min = 2400;
uint16_t battery_vcc_max = 3000;

#define MY_RADIO_NRF5_ESB
//#define MY_PASSIVE_NODE
#define MY_NODE_ID 30
#define MY_PARENT_NODE_ID 0
#define MY_PARENT_NODE_IS_STATIC
#define MY_TRANSPORT_UPLINK_CHECK_DISABLED
#define IRT_PIN 3 //(PORT0, gpio 5)
#include <MySensors.h>
// see https://www.mysensors.org/download/serial_api_20
#define SENS_CHILD_ID 0
#define CHILD_ID_VOLT 254
MyMessage sensMsg(SENS_CHILD_ID, V_VAR1);
//MyMessage voltMsg(CHILD_ID_VOLT, V_VOLTAGE);

void preHwInit() {
sleep(2000);
pinMode(RED_LED, OUTPUT);
digitalWrite(RED_LED, HIGH);
pinMode(GREEN_LED, OUTPUT);
digitalWrite(GREEN_LED, HIGH);
pinMode(BLUE_LED, OUTPUT);
digitalWrite(BLUE_LED, HIGH);
pinMode(MODE_PIN, INPUT);
pinMode(SENS_PIN, INPUT);
}

void before()
{
NRF_POWER->DCDCEN = 1;
NRF_UART0->ENABLE = 0;
sleep(1000);
digitalWrite(BLUE_LED, LOW);
sleep(150);
digitalWrite(BLUE_LED, HIGH);
}

void presentation() {
sendSketchInfo("EFEKTA Sens 1CH Sensor", "1.1");
present(SENS_CHILD_ID, S_CUSTOM, "SWITCH STATUS");
//present(CHILD_ID_VOLT, S_MULTIMETER, "Battery");
}

void setup() {
digitalWrite(BLUE_LED, LOW);
sleep(100);
digitalWrite(BLUE_LED, HIGH);
sleep(200);
digitalWrite(BLUE_LED, LOW);
sleep(100);
digitalWrite(BLUE_LED, HIGH);
lpComp();
detection = false;
SLEEP_TIME_W = SLEEP_TIME;
pinMode(31, OUTPUT);
digitalWrite(31, HIGH);
/*
while (timer < 10) {
timer++;
digitalWrite(GREEN_LED, LOW);
wait(5);
digitalWrite(GREEN_LED, HIGH);
wait(500);
}
timer = 0;
*/
sleep(7000);
while (timer < 3) {
timer++;
digitalWrite(GREEN_LED, LOW);
sleep(15);
digitalWrite(GREEN_LED, HIGH);
sleep(85);
}
timer = 0;
sleep(1000);
}

void loop() {

if (detection) {
if (digitalRead(MODE_PIN) == 1 && button_flag == 0 && digitalRead(SENS_PIN) == 0) {
//back side button detection
button_flag = 1;
nosleep = 1;
}
if (digitalRead(MODE_PIN) == 1 && button_flag == 1 && digitalRead(SENS_PIN) == 0) {
digitalWrite(RED_LED, LOW);
wait(10);
digitalWrite(RED_LED, HIGH);
wait(50);
}
if (digitalRead(MODE_PIN) == 0 && button_flag == 1 && digitalRead(SENS_PIN) == 0) {
nosleep = 0;
button_flag = 0;
digitalWrite(RED_LED, HIGH);
lpComp_reset();
}

if (digitalRead(SENS_PIN) == 1 && sens_flag == 0 && digitalRead(MODE_PIN) == 0) {
//sens detection
sens_flag = 1;
nosleep = 1;
newmillis = millis();
interrupt_time = newmillis - oldmillis;
SLEEP_TIME_W = SLEEP_TIME_W - interrupt_time;
if (send(sensMsg.set(detection))) {
send_flag = 1;
}
}
if (digitalRead(SENS_PIN) == 1 && sens_flag == 1 && digitalRead(MODE_PIN) == 0) {
if (send_flag == 1) {
while (timer < 10) {
timer++;
digitalWrite(GREEN_LED, LOW);
wait(20);
digitalWrite(GREEN_LED, HIGH);
wait(30);
}
timer = 0;
} else {
while (timer < 10) {
timer++;
digitalWrite(RED_LED, LOW);
wait(20);
digitalWrite(RED_LED, HIGH);
wait(30);
}
timer = 0;
}
}
if (digitalRead(SENS_PIN) == 0 && sens_flag == 1 && digitalRead(MODE_PIN) == 0) {
sens_flag = 0;
nosleep = 0;
send_flag = 0;
digitalWrite(GREEN_LED, HIGH);
sleep(500);
lpComp_reset();
}
if (SLEEP_TIME_W < 60000) {
SLEEP_TIME_W = SLEEP_TIME;
sendBatteryStatus();
}
}
else {
//if (detection == -1) {
SLEEP_TIME_W = SLEEP_TIME;
sendBatteryStatus();
}
if (nosleep == 0) {
oldmillis = millis();
sleep(SLEEP_TIME_W);
}
}

void sendBatteryStatus() {
wait(20);
batteryVoltage = hwCPUVoltage();
wait(2);

if (batteryVoltage > battery_vcc_max) {
currentBatteryPercent = 100;
}
else if (batteryVoltage < battery_vcc_min) {
currentBatteryPercent = 0;
} else {
currentBatteryPercent = (100 * (batteryVoltage - battery_vcc_min)) / (battery_vcc_max - battery_vcc_min);
}

sendBatteryLevel(currentBatteryPercent, 1);
wait(2000, C_INTERNAL, I_BATTERY_LEVEL);
//send(powerMsg.set(batteryVoltage), 1);
//wait(2000, 1, V_VAR1);
}

void lpComp() {
NRF_LPCOMP->PSEL = IRT_PIN;
NRF_LPCOMP->ANADETECT = 1;
NRF_LPCOMP->INTENSET = B0100;
NRF_LPCOMP->ENABLE = 1;
NRF_LPCOMP->TASKS_START = 1;
NVIC_SetPriority(LPCOMP_IRQn, 15);
NVIC_ClearPendingIRQ(LPCOMP_IRQn);
NVIC_EnableIRQ(LPCOMP_IRQn);
}

void s_lpComp() {
if ((NRF_LPCOMP->ENABLE) && (NRF_LPCOMP->EVENTS_READY)) {
NRF_LPCOMP->INTENCLR = B0100;
}
}

void r_lpComp() {
NRF_LPCOMP->INTENSET = B0100;
}

#if __CORTEX_M == 0x04
#define NRF5_RESET_EVENT(event)
event = 0;
(void)event
#else
#define NRF5_RESET_EVENT(event) event = 0
#endif

extern "C" {
void LPCOMP_IRQHandler(void) {
detection = true;
NRF5_RESET_EVENT(NRF_LPCOMP->EVENTS_UP);
NRF_LPCOMP->EVENTS_UP = 0;
MY_HW_RTC->CC[0] = (MY_HW_RTC->COUNTER + 2);
}
}

void lpComp_reset () {
s_lpComp();
detection = false;
NRF_LPCOMP->EVENTS_UP = 0;
r_lpComp();
}

MyBoardNRF5.cpp
#ifdef MYBOARDNRF5
#include <variant.h>

/*
* Pins descriptions. Attributes are ignored by arduino-nrf5 variant.
* Definition taken from Arduino Primo Core with ordered ports
*/
const PinDescription g_APinDescription[]=
{
{ NOT_A_PORT, 0, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER}, // LFCLK
{ NOT_A_PORT, 1, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER}, // LFCLK
{ PORT0, 2, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), ADC_A0, PWM4, NOT_ON_TIMER},
{ PORT0, 3, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), ADC_A1, PWM5, NOT_ON_TIMER},
{ PORT0, 4, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), ADC_A2, PWM6, NOT_ON_TIMER},
{ PORT0, 5, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), ADC_A3, PWM7, NOT_ON_TIMER},
{ PORT0, 6, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER}, // INT3
{ PORT0, 7, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER}, // INT4
{ PORT0, 8, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), No_ADC_Channel, PWM10, NOT_ON_TIMER}, //USER_LED
{ PORT0, 9, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER}, // NFC1
{ PORT0, 10, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER}, // NFC2
{ PORT0, 11, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER}, // TX
{ PORT0, 12, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER}, // RX
{ PORT0, 13, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER}, // SDA
{ PORT0, 14, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER}, // SCL
{ PORT0, 15, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER}, // SDA1
{ PORT0, 16, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER}, // SCL1
{ PORT0, 17, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER}, // TP4
{ PORT0, 18, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER}, // TP5
{ PORT0, 19, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER}, // INT2
{ PORT0, 20, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER}, // INT1
{ PORT0, 21, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER}, // INT1
{ PORT0, 22, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), No_ADC_Channel, PWM9, NOT_ON_TIMER},
{ PORT0, 23, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), No_ADC_Channel, PWM8, NOT_ON_TIMER},
{ PORT0, 24, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER}, // INT
{ PORT0, 25, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), No_ADC_Channel, PWM11, NOT_ON_TIMER}, //RED_LED
{ PORT0, 26, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), No_ADC_Channel, PWM11, NOT_ON_TIMER}, //GREEN_LED
{ PORT0, 27, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), No_ADC_Channel, PWM11, NOT_ON_TIMER}, //BLUE_LED
{ PORT0, 28, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), ADC_A4, PWM3, NOT_ON_TIMER},
{ PORT0, 29, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), ADC_A5, PWM2, NOT_ON_TIMER},
{ PORT0, 30, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), ADC_A6, PWM1, NOT_ON_TIMER},
{ PORT0, 31, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), ADC_A7, PWM0, NOT_ON_TIMER}
};

// Don't remove this line
#include <compat_pin_mapping.h>

#endif

MyBoardNRF5.h
#ifndef _MYBOARDNRF5_H_
#define _MYBOARDNRF5_H_

#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus

// Number of pins defined in PinDescription array
#define PINS_COUNT (32u)
#define NUM_DIGITAL_PINS (32u)
#define NUM_ANALOG_INPUTS (8u)
#define NUM_ANALOG_OUTPUTS (8u)

/*
* LEDs
*
* This is optional
*
* With My Sensors, you can use
* hwPinMode() instead of pinMode()
* hwPinMode() allows to use advanced modes like OUTPUT_H0H1 to drive LEDs.
* https://github.com/mysensors/MySensors/blob/development/drivers/NRF5/nrf5_wiring_constants.h
*
*/
#define PIN_LED1 (16)
#define PIN_LED2 (15)
#define PIN_LED3 (17)
#define RED_LED (PIN_LED1)
#define GREEN_LED (PIN_LED2)
#define BLUE_LED (PIN_LED3)
#define INTERRUPT_PIN (5)
#define MODE_PIN (25)
#define SENS_PIN (27)

/*
* Analog ports
*
* If you change g_APinDescription, replace PIN_AIN0 with
* port numbers mapped by the g_APinDescription Array.
* You can add PIN_AIN0 to the g_APinDescription Array if
* you want provide analog ports MCU independed, you can add
* PIN_AIN0..PIN_AIN7 to your custom g_APinDescription Array
* defined in MyBoardNRF5.cpp
*/
static const uint8_t A0 = ADC_A0;
static const uint8_t A1 = ADC_A1;
static const uint8_t A2 = ADC_A2;
static const uint8_t A3 = ADC_A3;
static const uint8_t A4 = ADC_A4;
static const uint8_t A5 = ADC_A5;
static const uint8_t A6 = ADC_A6;
static const uint8_t A7 = ADC_A7;

/*
* Serial interfaces
*
* RX and TX are required.
* If you have no serial port, use unused pins
* CTS and RTS are optional.
*/
#define PIN_SERIAL_RX (11)
#define PIN_SERIAL_TX (12)

#ifdef __cplusplus
}
#endif

#endif

Превключвателят има сензорен бутон и тактичен бутон на гърба на устройството. Този тактичен бутон ще се използва за сервизни режими, режим на свързване по въздуха и нулиране на устройството. Бутонът има желязна функция против отскачане. Линията на капацитивния сензор и линията на бутона на часовника са свързани чрез диоди на Шотки и свързани към аналоговия щифт p0.05, а също и от капацитивния сензор и бутона на часовника има линии към MK щифтовете p0.25 и p0.27 .0.05 за състояния на четене след активиране на прекъсването на пин p0.05. На пин pXNUMX се активира прекъсване през компаратора (NRF_LPCOMP) чрез EVENTS_UP. Получих вдъхновение да реша проблема тук и тук.

Превключвателят беше добавен към мрежата Mysensors, управлявана от интелигентния домашен контролер Majordomo (уебсайт на проекта)

PHP код за добавяне на превключвател към метода statusUpdate

if (getGlobal("MysensorsButton01.status")==1) {
if (getGlobal('MysensorsRelay04.status') == 0) {
setGlobal('MysensorsRelay04.status', '1');
} else if (getGlobal('MysensorsRelay04.status') == 1) {
setGlobal('MysensorsRelay04.status', '0');
} 
}

Вижте резултата във видеото

Безжичен сензорен ключ с допълнително луминесцентно осветление

По-късно беше направена опция с усилващ преобразувател, но това не е свързано с работата на капацитивната микросхема TTP223, има повече желание за добро и равномерно осветяване при натискане на клавишите през целия живот на батерията.

ВиждамБезжичен сензорен ключ с допълнително луминесцентно осветление

Безжичен сензорен ключ с допълнително луминесцентно осветление

Проект Github - github.com/smartboxchannel/EFEKTA_WIRELESS_TOUCH_SWITCH

рускоговорящи сайт на общността Mysensors

Телеграм чат Mysensors — бързо решение на проблеми с Mysensors, съвети, трикове, инсталиране на платки, работа с микроконтролери atmega 328, stm32, nRF5 в Arduino IDE — @mysensors_rus

Малко снимкиБезжичен сензорен ключ с допълнително луминесцентно осветление

Безжичен сензорен ключ с допълнително луминесцентно осветление

Безжичен сензорен ключ с допълнително луминесцентно осветление

Безжичен сензорен ключ с допълнително луминесцентно осветление

Безжичен сензорен ключ с допълнително луминесцентно осветление

Източник: www.habr.com

Добавяне на нов коментар