In diesem Artikel möchte ich ein neues Projekt mit Ihnen teilen. Diesmal handelt es sich um einen Touch-Schalter mit einer Glasplatte. Das Gerät ist kompakt und misst 42x42 mm (Standardglasplatten haben die Größe 80x80 mm). Die Geschichte dieses Geräts begann vor etwa einem Jahr.

Die ersten Prototypen basierten auf dem Mikrocontroller ATmega328, am Ende wurde jedoch der Mikrocontroller nRF52832 verwendet.

Der Touch-Bereich des Geräts arbeitet mit TTP223-Chips. Beide Sensoren werden von einer einzigen Unterbrechung bedient. Die Stromversorgung erfolgt durch eine CR2477-Batterie über einen Hochspannungswandler mit dem TPS610981-Chip. .


Im Gerät wurde ein Schaltkreis für die Abschaltung der Stromversorgung mit Leistungstransistoren implementiert. Nach dem Drücken der Taste übernimmt der Mikrocontroller die Steuerung der Stromversorgung, und die Taste kann dann für Service-Modi verwendet werden (in meinem Fall ist das die Kopplung mit anderen Geräten, das Abschalten der Stromversorgung und zurücksetzen auf die Werkseinstellungen).
Es sind 2 RGB-LEDs zur Anzeige von Status und Servicemodi vorhanden. Ein Piezo-Lautsprecher wurde ebenfalls hinzugefügt, um beim Berühren der Sensortasten Klickgeräusche zu imitieren und akustische Rückmeldungen zu geben. Die LEDs und der Piezo-Lautsprecher können auf Wunsch des Benutzers ein- und ausgeschaltet werden. Dies erfolgt über den Smart Home-Controller, indem Befehle an die technischen Sensoren gesendet werden. Außerdem besteht die Möglichkeit, dass der Benutzer die Intervalle für das Senden des Batteriestatus und des Signalpegels ebenfalls über den Smart Home-Controller ändert. In meinem Fall ist das .
Der Stromverbrauch im Übertragungsmodus beträgt 7 mA (250 kbit, 10 ms), der Verbrauch im Schlafmodus 40 µA und im ausgeschalteten Zustand weniger als 1 µA (= dem Verbrauch des Boost-Converters im Leerlauf). Es sind Anschlüsse für RX, TX und SWD für die Programmierung vorgesehen. Verwendet wird ein Miniaturstecker mit 2x3 Pins in einem Abstand von 1,27 mm. Für die Programmierung wurde ein spezieller Adapter hergestellt.

Wie immer basiert die Funktionsweise des Geräts auf dem Protokoll . Der geplante Sensor-Schalter soll im Steuerungssystem für Rollos eingesetzt werden. Aber letztendlich sind die Anwendungsmöglichkeiten nur von Ihrer Fantasie begrenzt. Beispielsweise hat mein Sohn (7 Jahre) bereits drei Bestellungen für verschiedene Schalterversionen aufgegeben: für das Ein- und Ausschalten des Lichts im Badezimmer (der Schalter wird niedrig montiert), für das Einschalten des Lichts im langen, dunklen Flur auf dem Weg zum Badezimmer und einen weiteren als Nachttischlampe, um schnell das Licht in seinem Zimmer einzuschalten, damit die Monster verschwinden.



Das Gehäuse wurde traditionell mit einem SLA-Drucker gedruckt. Das Gerät ist kompakt, das Gehäuse ist klein, der Einsatz dieser Drucktechnologie ist gerechtfertigt.
Gedrucktes Modell ansehen


Im Gehäuse und im Deckel des Batteriefachs sind Magnete eingelegt.
Videos mit Tests des Geräts:



Für diejenigen, die es nachbauen möchten:
Der Code des Testprogramms für den Schalter im Steuerungssystem für Rollos für Arduino IDE
Arduino Verdrahtung
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);
}Gehäuse-Dateien im STL-Format —
Gerber-Dateien der Leiterplatte —
Fragen zu diesem Projekt sowie zu Schwierigkeiten bei Ihren Arduino- und Mysensors-Entwicklungen beantworten wir gerne in unserem Telegram-Chat — .
Quelle: habr.com
