Mini-tuŝŝaltilo kun vitra panelo sur nRF52832

En la hodiaŭa artikolo mi volas dividi kun vi novan projekton. Ĉi-foje temas pri tuŝŝaltilo kun vitra panelo. La aparato estas kompakta, mezurante 42x42mm (normaj vitropaneloj havas dimensiojn 80x80mm). La historio de ĉi tiu aparato komenciĝis antaŭ longe, antaŭ proksimume unu jaro.

Mini-tuŝŝaltilo kun vitra panelo sur nRF52832

La unuaj opcioj estis sur la mikroregilo atmega328, sed finfine ĉio finiĝis per la mikroregilo nRF52832.

Mini-tuŝŝaltilo kun vitra panelo sur nRF52832

La tuŝa parto de la aparato funkcias per blatoj TTP223. Ambaŭ sensiloj estas servataj per unu interrompo. Funkciigita de CR2477-kuirilaro, per akcela konvertilo sur la blato TPS610981 | datumpaĝo.

Mini-tuŝŝaltilo kun vitra panelo sur nRF52832
Mini-tuŝŝaltilo kun vitra panelo sur nRF52832

La aparato efektivigas malŝaltan cirkviton uzante kampefikan transistorojn. Post premado de la butono, la mikroregilo mem kaptas potencokontrolon kaj tiam la butono povas esti uzata por servaj reĝimoj (en mia kazo, ĉi tio estas parigo kun aliaj aparatoj, malŝalti la potencon kaj restarigi al fabrikaj agordoj).

Estas 2 RGB LED-oj por indiki statojn kaj servoreĝimojn. Piezo-elsendilo ankaŭ estis aldonita por simuli klakon dum tuŝado de tuŝbutonoj kaj sonindiko de servoreĝimoj. La LED-oj kaj piezo-elsendilo povas esti ŝaltitaj kaj malŝaltitaj laŭ la bontrovo de la uzanto. Ĉi tio estas farita per la inteligenta hejma regilo sendante komandojn al teknikaj sensiloj; la uzanto ankaŭ povas ŝanĝi la intervalojn por sendi baterioŝargon kaj signalnivelon ankaŭ per la inteligenta hejma regilo. En mia kazo ĝi estas MAJORDOMO.

Konsumo en elsenda reĝimo estas 7mA (250kbit, 10ms), konsumo en dormo estas 40µA, konsumo en la malŝaltita stato estas malpli ol 1µA (=konsumo de la boost-konvertilo en "senaktiva" reĝimo). Rx, tx, swd-konektilo por programado estas provizita. Miniatura 2x3p konektilo kun tonalto de 1.27 estas uzata. Speciala adaptilo estas farita por programado.

Mini-tuŝŝaltilo kun vitra panelo sur nRF52832

Kiel ĉiam, la funkciado de la aparato baziĝas sur la protokolo Miaj Sensiloj. Ĉi tiu tuŝŝaltilo estas planita por esti uzata en la rulsistemo de kontrolsistemo. Sed ĝenerale, la apliko estas limigita nur de via imago. Ekzemple mia filo (7-jara) jam faris 3 mendojn por ŝaltilversioj: por ŝalti kaj malŝalti la lumon en necesejo kun banujo (ĝi estos muntita malalte de la planko), por ŝalti la lumon en longa kaj malhela koridoro kiam vojaĝas al necesejo kun bankuvo, kaj alia kiel litrando, por rapide ŝalti la lumon en via ĉambro por ke la monstroj forkuru.

Mini-tuŝŝaltilo kun vitra panelo sur nRF52832
Mini-tuŝŝaltilo kun vitra panelo sur nRF52832
Mini-tuŝŝaltilo kun vitra panelo sur nRF52832

La kazo estis tradicie presita sur SLA-presilo, la aparato estas miniatura, la kazo montriĝis malgranda, la uzo de ĉi tiu presa teknologio estas pravigita.

Vidu presitan modelonMini-tuŝŝaltilo kun vitra panelo sur nRF52832
Mini-tuŝŝaltilo kun vitra panelo sur nRF52832
Mini-tuŝŝaltilo kun vitra panelo sur nRF52832

Magnetoj estas gluitaj en la kazon kaj la kuirilan kupeon.

Filmetoj kun provoj de ĉi tiu aparato:



Por tiuj, kiuj volas ripeti:

Testprogramkodo por ŝaltilo en rulkurtena kontrolsistemo por Arduino IDE

Arduino-Drataro

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);
}

Kazdosieroj en stl - google drive

Gerber PCB-dosieroj - google drive

Por demandoj pri ĉi tiu evoluo, pri malfacilaĵoj en viaj evoluoj sur Arduinos kaj Mysensors ĉiam venos al la savo en nia telegrama babilejo - https://t.me/mysensors_rus.

fonto: www.habr.com

Aldoni komenton