Salam kepada semua pembaca bagian DIY atau Do-it-yourself pada Habr! Artikel hari ini akan membahas tentang sakelar sentuh pada chip TTP223 |
lembar data . Saklar beroperasi pada mikrokontroler nRF52832 |
datasheet , modul YJ-17103 dengan antena cetak dan konektor untuk antena eksternal MHF4 digunakan. Sakelar sentuh ditenagai oleh baterai CR2430 atau CR2450. Konsumsi dalam mode transmisi tidak lebih dari 8mA, dalam mode tidur tidak lebih dari 6mA.

Seperti semua proyek sebelumnya, ini juga merupakan proyek Arduino, program ini ditulis dalam IDE Arduino. Implementasi perangkat lunak perangkat ini didasarkan pada protokol Mysensors |
Perpustakaan GitHub ,
dukungan GitHub untuk papan nRF5 di Mysensors. Forum komunitas berbahasa Inggris -
http://forum.mysensors.org , forum komunitas berbahasa Rusia -
http://mysensors.ru/forum/(Bagi mereka yang ingin belajar -
Dokumentasi ,
Protokol Serial ,
API ,
Protokol ,
Parser | bagi mereka yang ingin membantu dalam pengembangan proyek -
Dokumentasi )
Papan sakelar sentuh dikembangkan dalam program Diptrace, dengan mempertimbangkan pembuatan selanjutnya sesuai dengan metode Laser Iron Technology (LUT). Papan ini dikembangkan dalam ukuran 60x60mm (panel kaca standar memiliki dimensi 80x80mm). Sirkuit itu dicetak pada halaman-halaman majalah Antenna dan ditransfer oleh besi Bosch dengan pengaturan "Len" (daya maksimum) ke pelat fiberglass berlapis dua sisi foil 1.5mm, 35μm (karena kekurangan yang lain).

Etsa dilakukan dengan larutan besi klorida, yang sebelumnya dibuat dalam proporsi 1,5 bagian sendok per 250 ml air hangat. Prosesnya memakan waktu 15 menit.
Lubang-lubang untuk transisi interlayer dan untuk pemasangan dudukan baterai dibor dengan bor mini DREMEL 3000 yang dipasang pada dudukan bor DREMEL 220. Lubang-lubang untuk transisi antar pemain dibor dengan bor 0,4 mm, lubang untuk dudukan baterai dengan bor 1,1 mm. Pemangkasan di sepanjang batas papan dilakukan dengan bor mini yang sama dengan nozzle DREMEL 540 (roda pemotong d = 32.0mm). Penanaman dilakukan di respirator.
Penyalaan papan etsa dilakukan menggunakan paduan Rose dalam larutan air (1 sendok teh asam sitrat mengkristal dalam 300 ml air).
Proses penyolderan memakan waktu sekitar satu jam, sebagian besar waktu dihabiskan untuk menyolder kawat (kaleng, diameter 0,4 mm) di lubang untuk transisi antar pemain.
Papan dicuci dengan pembersih aerosol FLUX OFF.


Pengembangan casing perangkat dilakukan dalam editor desain berbantuan komputer tiga dimensi. Dimensi case 78.5mm X 78.5mm X 12mm.

Model rumah yang selesai dan penutup baterai disimpan dalam format STL, maka perlu disiapkan model ini untuk dicetak pada printer SLA (menambahkan dukungan, orientasi). Pada titik ini, masalah kecil muncul, karena area cetak printer SLA rumah tangga kecil. Model tubuh perangkat dalam posisi paling optimal relatif terhadap waktu pencetakan tidak sesuai dengan ukuran area cetak. Ketika menempatkan model pada 45 derajat, itu juga memberikan hasil yang mengecewakan, berat dukungan sama dengan berat model kasus. Diputuskan untuk mencetak model secara vertikal, membuat dukungan di salah satu sisi depan, yang sebelumnya setuju dengan fakta pemrosesan pos. Butuh 5 jam untuk menutup casing dengan pengaturan lapisan 50 mikron. Selanjutnya, pemrosesan dilakukan menggunakan amplas berbutir halus (saya tidak akan menulis nomornya, karena saya tidak tahu :)). Penutup baterai dicetak selama 40 menit.

Panel kaca dengan Aliexpress dijual dengan bingkai plastik yang sudah direkatkan, tidak ada masalah melepas bingkai. Saya melepas pra-pemanasan panel kaca dengan pengering rambut biasa.


Diffuser untuk lampu latar LED terbuat dari pita dua sisi dengan perekat akrilik 9088-200 3M. Untuk penerangan neon, ada beberapa bahan untuk dipilih, pita perekat China dan kertas perekat dipotong menjadi kaset perusahaan domestik Luminophore. Pilihannya dibuat untuk produsen dalam negeri, menurut perasaan saya, itu bersinar lebih terang dan lebih lama. Sebuah kotak yang terbuat dari kertas dengan pigmen fluoresens ditempelkan di atas selotip 3M 9088-200.
Kaca dilekatkan ke kasus pemutus sirkuit menggunakan pita dua sisi dengan perekat akrilik 3M VHB 4910.

Penutup diperbaiki dengan sekrup M 1.4 X 5mm.
Biaya perangkat adalah 890 rubel.
Berikutnya adalah bagian perangkat lunak. Tidak masalah Ternyata sirkuit mikro sensor TTP223 bekerja dengan sempurna dengan daya yang stabil pada 3.3V dan tidak terlalu baik ketika ditenagai langsung dari baterai yang baik. Pada awal perangkat dengan daya di wilayah 2.5v, ditambah setelah "drawdown" tambahan ketika mengerjakan presentasi Mysensors, chip TTP223 (segera setelah kalibrasi) menyebabkan MK terganggu karena dengan pemicu aktif.
Sirkuit untuk memasok daya ke chip (manajemen daya TTP223 dengan gpio MK) diubah, tambahan ground disuplai, pada garis yang dipimpin rgb (yang melewati sisi lain dari papan sensor kapasitif), resistor dengan resistansi yang lebih tinggi diganti. Itu juga ditambahkan ke perangkat lunak: aktivasi daya untuk sirkuit mikro kapasitif setelah memulai kerangka kerja Mysensors dan mengerjakan presentasi. Penundaan untuk kalibrasi otomatis chip TTP223 menjadi dua kali lipat saat daya diberikan padanya. Semua perubahan ini sepenuhnya memperbaiki masalah ini.
Sebelum melihat kode program, saya sarankan Anda membiasakan diri dengan struktur dasar sketsa di 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()
{
}
Kode uji untuk program sakelar sentuh: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
Sakelar ini memiliki tombol sentuh dan tombol jam di bagian belakang perangkat. Tombol jam ini akan digunakan untuk mode layanan, mode air snap, memusatkan perhatian perangkat. Tombol ini menerapkan anti bouncing besi. Garis sensor kapasitif dan garis tombol jam melalui dioda Schottky terhubung dan terhubung ke pin analog p0.05, garis ke pin p0.25 dan p0.27 MK menuju ke sensor kapasitif dan tombol jam untuk membaca status setelah mengaktifkan interupsi pada pin p0. 05 Pada pin p0.05, interupsi melalui pembanding (NRF_LPCOMP) oleh EVENTS_UP diaktifkan. Saya mendapat inspirasi untuk menyelesaikan masalah di
sini dan di
sini .
Sakelar ditambahkan ke jaringan Mysensors, dikelola oleh pengontrol rumah pintar, Magordomo (
lokasi proyek )
Kode PHP untuk ditambahkan ke metode sakelar 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'); } }
Tonton hasilnya di video

Kemudian, sebuah opsi dibuat dengan boost converter, tetapi ini tidak terkait dengan pengoperasian chip kapasitif TTP223, ada lebih banyak keinginan untuk penerangan yang baik dan seragam ketika mengerjakan keran selama masa pakai baterai.
Proyek Github -
github.com/smartboxchannel/EFEKTA_WIRELESS_TOUCH_SWITCHMysensors
situs komunitas berbahasa Rusia
Telegram chat Mysensors - solusi cepat untuk masalah dengan Mysensors, tips, trik, memasang papan, bekerja dengan atmega 328, stm32, nRF5 mikrokontroler dalam Arduino IDE -
@mysensors_rus