Mini interruptor táctil con panel de vidrio en nRF52832

En el artículo de hoy quiero compartir con ustedes un nuevo proyecto. Esta vez es un interruptor táctil con un panel de vidrio. El dispositivo es compacto, dimensiones 42x42 mm (el panel de vidrio estándar tiene dimensiones 80x80 mm). La historia de este dispositivo comenzó hace mucho tiempo, hace aproximadamente un año.



Las primeras opciones estaban en el microcontrolador atmega328, pero al final todo terminó con el microcontrolador nRF52832.



La parte táctil del dispositivo se ejecuta en chips TTP223. Ambos sensores son atendidos por una interrupción. Alimentado por una batería CR2477, a través del convertidor boost en TPS610981 | Datashit




El dispositivo implementa un circuito de apagado para transistores de efecto de campo. Después de presionar el botón, el microcontrolador intercepta la administración de energía y luego el botón puede usarse para los modos de servicio (en mi caso, se empareja con otros dispositivos, apaga la alimentación y restablece la configuración de fábrica (restablecimiento de fábrica)).


Hay 2 LED rgb para indicar estados y modos de servicio. También se ha agregado un emisor piezoeléctrico para simular un clic cuando toca los botones táctiles y la indicación sonora de los modos de servicio. Los LED y el emisor piezoeléctrico se pueden encender y apagar a petición del usuario. Esto se realiza a través del controlador de casa inteligente, enviando comandos a sensores técnicos, también es posible cambiar los intervalos de usuario para enviar la carga de la batería y el nivel de señal a través del controlador de casa inteligente. En mi caso, es MAJORDOMO .


El consumo en modo de transmisión es de 7 mA (250 kbps, 10 ms), el consumo de reposo es de 40 μA, el consumo fuera de línea es inferior a 1 μA (= consumo del convertidor elevador en modo inactivo). Salida rx, tx, enchufe swd para programación. Se utiliza un conector miniatura de 2x3p en incrementos de 1.27. Se ha realizado un adaptador especial para la programación.



Como siempre, el dispositivo se basa en el protocolo MySensors . Este interruptor táctil está diseñado para usarse en el sistema de control de persianas enrollables. Pero en general, la aplicación está limitada solo por su imaginación. Por ejemplo, ya un hijo (7 años) hizo 3 pedidos para la versión del interruptor: encender y apagar la luz en el inodoro con una bañera (se montará no muy alto del piso), encender la luz en un pasillo largo y oscuro cuando viaja al baño con una bañera y uno más junto a la cama, para encender rápidamente la luz en su habitación para que los monstruos se dispersen.





El estuche se imprimió tradicionalmente en una impresora SLA, el dispositivo es pequeño, el estuche es pequeño, el uso de esta tecnología de impresión está justificado.


Ver modelo impreso



Los imanes están pegados en la carcasa y la tapa de la batería.


Vidosiki con pruebas de este dispositivo:





Para aquellos que desean repetir:


Código de programa de prueba del interruptor automático para el sistema de control de persianas enrollables para Arduino IDE


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

Archivos de casos en stl


Archivos de placa de circuito Gerber


Para preguntas sobre este desarrollo, sobre las dificultades en su desarrollo, Arduino y Mysensors siempre vendrán al rescate en nuestro chat de telegramas.

Source: https://habr.com/ru/post/453868/


All Articles