Сэнсарны міні выключальнік c шкляной панэллю на nRF52832

У сённяшнім артыкуле жадаю падзеліцца з вамі новым праектам. На гэты раз гэта сэнсарны выключальнік са шкляной панэллю. Прылада кампактнае, памерамі 42х42мм (стандартныя шкляныя панэль мае памеры 80х80мм). Гісторыя гэтай прылады пачалася даўно, каля года таму.

Сэнсарны міні выключальнік c шкляной панэллю на nRF52832

Першыя варыянты былі на мікракантролеры atmega328, але ў выніку ўсё скончылася мікракантролерам nRF52832.

Сэнсарны міні выключальнік c шкляной панэллю на nRF52832

Сэнсарная частка прылады працуе на мікрасхемах TTP223. Абодва сэнсара абслугоўвае адно перапыненне. Сілкаванне ад батарэйкі CR2477, праз які падвышае пераўтваральнік на мікрасхеме TPS610981 | Даташыт.

Сэнсарны міні выключальнік c шкляной панэллю на nRF52832
Сэнсарны міні выключальнік c шкляной панэллю на nRF52832

У прыладзе рэалізавана схема адключэння харчавання на палявых транзістарах. Пасля націску на кнопку мікракантролер сам перахапляе кіраванне сілкаваннем і далей кнопка можа выкарыстоўвацца для сэрвісных рэжымаў (у маім злучвае гэта спалучэнне з іншымі прыладамі, адключэнне сілкавання і скід да завадскіх усталёвак (factory reset)).

Прысутнічаюць 2 rgb святлодыёда для індыкацый станаў і сэрвісных рэжымаў. Гэтак жа дададзены пьезоизлучатель для імітацыі кліку пры дакрананні да сэнсарных кнопак і гукавой індыкацыі сервічных рэжымаў. Святлодыёды і пьезоизлучатель можна ўключаць і адключаць па жаданні карыстальніка. Робіцца гэта праз кантралёр разумнай хаты, адпраўкай каманд на тэхнічныя сэнсары, гэтак жа рэалізаваная магчымасць змены карыстачом інтэрвалаў адпраўкі зарада батарэі і ўзроўня сігналу гэтак жа праз кантралёр разумнай хаты. У маім выпадку гэта МАЖАРДОМА.

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

Сэнсарны міні выключальнік c шкляной панэллю на nRF52832

Як і заўсёды ў аснове працы прылады ляжыць пратакол MySensors. Дадзены сэнсарны выключальнік плануецца прымяняць у сістэме кіравання рулоннымі шторамі. Але ў цэлым ужыванне абмежавана толькі вашай фантазіяй. Напрыклад ужо цяпер сын (7 гадоў) зрабіў 3 замовы на версіі выключальніка: для ўключэння і выключэнні святла ў туалеце з ваннай (мацуецца будзе невысока ад падлогі), для ўключэння святла ў доўгім і цёмным калідоры пры вандраванні ў туалет з ваннай і яшчэ адзін як прыложкавы, для хуткага ўключэння святла ў сваім пакоі каб монстры разбегліся.

Сэнсарны міні выключальнік c шкляной панэллю на nRF52832
Сэнсарны міні выключальнік c шкляной панэллю на nRF52832
Сэнсарны міні выключальнік c шкляной панэллю на nRF52832

Корпус па традыцыі друкаваўся на SLA друкарцы, прылада мініятурнае, корпус атрымаўся невялікі, ужыванне гэтай тэхналогіі друку апраўдана.

Паглядзець надрукаваную мадэльСэнсарны міні выключальнік c шкляной панэллю на nRF52832
Сэнсарны міні выключальнік c шкляной панэллю на nRF52832
Сэнсарны міні выключальнік c шкляной панэллю на nRF52832

У корпус і вечка батарэйнага адсека ўклеены магніцікі.

Відасікі з тэстамі дадзенай прылады:



Для жадаючых паўтарыць:

Код тэставай праграмы выключальніка ў сістэме кіравання рулоннымі запавесамі для 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_DISABLED_SERIAL
#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() {
pinMode(31, OUTPUT); //power management pin
digitalWrite(31, HIGH);
delay(3000);
pinMode(3, INPUT); // on off mode button
pinMode(25, OUTPUT); // sens1 led
pinMode(26, OUTPUT); // sens1 led
pinMode(27, OUTPUT); // sens1 led
pinMode(6, OUTPUT); // sens21 led
pinMode(7, OUTPUT); // sens2 led
pinMode(8, OUTPUT); // sens2 led
pinMode(28, OUTPUT); // bizzer
pinMode(2, INPUT); // common interrupt for touch sensors
pinMode(9, INPUT); // touch sensors1
pinMode(10, INPUT); //touch sensors2
pinMode(29, INPUT); // battery
digitalWrite(28, LOW);
digitalWrite(27, HIGH);
digitalWrite(26, HIGH);
digitalWrite(25, HIGH);
digitalWrite(6, HIGH);
digitalWrite(7, HIGH);
digitalWrite(8, HIGH);
}
void before()
{
NRF_POWER->DCDCEN = 1;
analogReadResolution(12);
disableNfc();
turnOffAdc();
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("EFEKTA ON|OFF NODE 2CH", "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;
digitalWrite(6, LOW);
wait(10);
playSound1();
wait(20);
playSound2();
wait(50);
send(upMsg.set(switch_a));
wait(200);
} else {
switch_a = 0;
digitalWrite(6, HIGH);
wait(10);
playSound2();
wait(20);
playSound1();
wait(50);
send(upMsg.set(switch_a));
wait(200);
}
}
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;
digitalWrite(25, LOW);
wait(10);
playSound1();
wait(20);
playSound2();
wait(50);
send(downMsg.set(switch_b));
wait(200);
} else {
switch_b = 0;
digitalWrite(25, HIGH);
wait(10);
playSound2();
wait(20);
playSound1();
wait(50);
send(downMsg.set(switch_b));
wait(200);
}
}
if (digitalRead(9) == LOW && sens_flag1 == 1) {
sens_flag1 = 0;
}
if (digitalRead(10) == LOW && sens_flag2 == 1) {
sens_flag2 = 0;
}
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) {
j = 500000 / j;
k += millis();
while (k > millis()) {
digitalWrite(28, HIGH); delayMicroseconds(j);
digitalWrite(28, LOW ); delayMicroseconds(j);
}
}
void playSound0() {
myTone(1300, 50);
wait(20);
myTone(1300, 50);
wait(50);
}
void playSound() {
myTone(700, 30); 
wait(10);
myTone(700, 30);
wait(10);
myTone(700, 30);
wait(50);
}
void playSound1() {
myTone(200, 10);
wait(10);
myTone(400, 5);
wait(30);
}
void playSound2() {
myTone(400, 10);
wait(10);
myTone(200, 5);
wait(30);
}
void readBatLev() {
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, 1);
wait(2000, C_INTERNAL, I_BATTERY_LEVEL);
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);
}

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

Gerber файлы друкаванай платы гугл драйв

На пытанні па дадзенай распрацоўцы, па цяжкасцях у вашых распрацоўках на ардуінках і Mysensors заўсёды прыйдуць на дапамогу ў нашым тэлеграм чаце. https://t.me/mysensors_rus.

Крыніца: habr.com

Дадаць каментар