Version 1.0

Initial version.
This commit is contained in:
Alexey Zholtikov 2022-12-11 10:37:51 +03:00
parent 481a8f7237
commit 56e903d236
10 changed files with 5578 additions and 2 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
.pio
.vscode
.DS_Store

View File

@ -1,3 +1,39 @@
# RF-Water-Leakage-Sensor # RF water leakage sensor
Water leakage sensor on ATmega168/328 + RF24. Water leakage sensor on ATmega168/328 + RF24.
## Features
1. Power consumption in sleep mode approximately 10 μA. Up to 2 years of operation on one CR2450 battery (estimated).
2. Transmits battery level charge and sensor status (DRY) every hour (can be changed up to 65535 seconds).
3. When triggered transmits an alarm (ALARM) every minute. The sensor must be reset to stop transmitting.
4. Automatic restart in case of a hang-up.
## Note
A gateway is required. For details see "RF Gateway".
## Full config example for Home Assistant
```yml
mqtt:
sensor:
- name: "NAME"
device_class: "voltage"
unit_of_measurement: "V"
state_topic: "homeassistant/rf_sensor/ID/water_leakage"
value_template: "{{ value_json.battery }}"
expire_after: 4500
force_update: true
qos: 2
binary_sensor:
- name: "NAME"
device_class: "moisture"
state_topic: "homeassistant/rf_sensor/ID/water_leakage"
value_template: "{{ value_json.state }}"
payload_on: "ALARM"
payload_off: "DRY"
expire_after: 4500
force_update: true
qos: 2
```

BIN
hardware/BOM.xlsx Normal file

Binary file not shown.

BIN
hardware/CR2450 holder.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

BIN
hardware/Gerber.zip Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 580 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 978 KiB

5296
hardware/Schematic.pdf Normal file

File diff suppressed because it is too large Load Diff

137
platformio.ini Normal file
View File

@ -0,0 +1,137 @@
[env:ATmega168]
platform = atmelavr
board = ATmega168
board_build.mcu = atmega168
board_build.f_cpu = 8000000L
framework = arduino
upload_protocol = usbasp
build_flags =
-D ALARM=1
-D DRY=0
-D portUSE_WDTO=WDTO_1S
-D WATER_LEAKAGE=5
-D ID=$UNIX_TIME
board_fuses.hfuse = 0xDE
board_fuses.lfuse = 0xE2
board_fuses.efuse = 0x07
upload_flags =
-Pusb
-e
lib_deps =
feilipu/FreeRTOS@^10.5.0-0
nrf24/RF24@^1.4.5
[env:ATmega168P]
platform = atmelavr
board = ATmega168P
board_build.mcu = atmega168p
board_build.f_cpu = 8000000L
framework = arduino
upload_protocol = usbasp
build_flags =
-D ALARM=1
-D DRY=0
-D portUSE_WDTO=WDTO_1S
-D WATER_LEAKAGE=5
-D ID=$UNIX_TIME
board_fuses.hfuse = 0xDE
board_fuses.lfuse = 0xE2
board_fuses.efuse = 0x07
upload_flags =
-Pusb
-e
lib_deps =
feilipu/FreeRTOS@^10.5.0-0
nrf24/RF24@^1.4.5
[env:ATmega168PB]
platform = atmelavr
board = ATmega168PB
board_build.mcu = atmega168pb
board_build.f_cpu = 8000000L
framework = arduino
upload_protocol = usbasp
build_flags =
-D ALARM=1
-D DRY=0
-D portUSE_WDTO=WDTO_1S
-D WATER_LEAKAGE=5
-D ID=$UNIX_TIME
board_fuses.hfuse = 0xDE
board_fuses.lfuse = 0xE2
board_fuses.efuse = 0x07
upload_flags =
-Pusb
-e
lib_deps =
feilipu/FreeRTOS@^10.5.0-0
nrf24/RF24@^1.4.5
[env:ATmega328]
platform = atmelavr
board = ATmega328
board_build.mcu = atmega328
board_build.f_cpu = 8000000L
framework = arduino
upload_protocol = usbasp
build_flags =
-D ALARM=1
-D DRY=0
-D portUSE_WDTO=WDTO_1S
-D WATER_LEAKAGE=5
-D ID=$UNIX_TIME
board_fuses.hfuse = 0xDE
board_fuses.lfuse = 0xE2
board_fuses.efuse = 0x07
upload_flags =
-Pusb
-e
lib_deps =
feilipu/FreeRTOS@^10.5.0-0
nrf24/RF24@^1.4.5
[env:ATmega328P]
platform = atmelavr
board = ATmega328P
board_build.mcu = atmega328p
board_build.f_cpu = 8000000L
framework = arduino
upload_protocol = usbasp
build_flags =
-D ALARM=1
-D DRY=0
-D portUSE_WDTO=WDTO_1S
-D WATER_LEAKAGE=5
-D ID=$UNIX_TIME
board_fuses.hfuse = 0xDE
board_fuses.lfuse = 0xE2
board_fuses.efuse = 0x07
upload_flags =
-Pusb
-e
lib_deps =
feilipu/FreeRTOS@^10.5.0-0
nrf24/RF24@^1.4.5
[env:ATmega328PB]
platform = atmelavr
board = ATmega328PB
board_build.mcu = atmega328pb
board_build.f_cpu = 8000000L
framework = arduino
upload_protocol = usbasp
build_flags =
-D ALARM=1
-D DRY=0
-D portUSE_WDTO=WDTO_1S
-D WATER_LEAKAGE=5
-D ID=$UNIX_TIME
board_fuses.hfuse = 0xDE
board_fuses.lfuse = 0xE2
board_fuses.efuse = 0x07
upload_flags =
-Pusb
-e
lib_deps =
feilipu/FreeRTOS@^10.5.0-0
nrf24/RF24@^1.4.5

104
src/main.cpp Normal file
View File

@ -0,0 +1,104 @@
#include "Arduino.h"
#include "Arduino_FreeRTOS.h"
#include "RF24.h"
#include "avr/interrupt.h"
#include "semphr.h"
typedef struct
{
int16_t sensor_id{0};
int16_t sensor_type{0};
int16_t value_1{0};
int16_t value_2{0};
int16_t value_3{0};
int16_t value_4{0};
int16_t value_5{0};
} transmitted_data_t;
void sendBatteryLevelCharge(void *pvParameters);
void sendAlarmStatus(void *pvParameters);
float getBatteryLevelCharge(void);
RF24 radio(9, 10);
TaskHandle_t xSendBatteryLevelCharge;
void setup()
{
EICRA |= (1 << ISC01) | (1 << ISC00);
EIMSK |= (1 << INT0);
ADCSRA &= ~(1 << ADEN);
radio.begin();
radio.setChannel(120);
radio.setDataRate(RF24_250KBPS);
radio.setPALevel(RF24_PA_MAX);
radio.setPayloadSize(14);
radio.setAddressWidth(3);
radio.setCRCLength(RF24_CRC_8);
radio.setRetries(15, 15);
radio.openWritingPipe(0xDDEEFF);
radio.powerDown();
xTaskCreate(sendBatteryLevelCharge, "Send Battery Level Charge", configMINIMAL_STACK_SIZE, NULL, 1, &xSendBatteryLevelCharge);
}
void loop()
{
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
portENTER_CRITICAL();
sleep_enable();
portEXIT_CRITICAL();
sleep_cpu();
sleep_reset();
}
void sendBatteryLevelCharge(void *pvParameters)
{
(void)pvParameters;
for (;;)
{
transmitted_data_t sensor{abs((int16_t)ID), WATER_LEAKAGE};
sensor.value_1 = getBatteryLevelCharge() * 100;
sensor.value_2 = DRY;
radio.powerUp();
radio.flush_tx();
radio.write(&sensor, sizeof(transmitted_data_t));
radio.powerDown();
vTaskDelay(3600);
}
vTaskDelete(NULL);
}
void sendAlarmStatus(void *pvParameters)
{
(void)pvParameters;
for (;;)
{
transmitted_data_t sensor{abs((int16_t)ID), WATER_LEAKAGE};
sensor.value_2 = ALARM;
radio.powerUp();
radio.flush_tx();
radio.write(&sensor, sizeof(transmitted_data_t));
radio.powerDown();
vTaskDelay(60);
}
vTaskDelete(NULL);
}
float getBatteryLevelCharge()
{
ADMUX = (1 << REFS0) | (1 << MUX3) | (1 << MUX2) | (1 << MUX1);
ADCSRA |= (1 << ADEN);
delay(10);
ADCSRA |= (1 << ADSC);
while (bit_is_set(ADCSRA, ADSC))
;
ADCSRA &= ~(1 << ADEN);
float value = ((1024 * 1.1) / (ADCL + ADCH * 256));
return value;
}
ISR(INT0_vect)
{
cli();
vTaskDelete(xSendBatteryLevelCharge);
xTaskCreate(sendAlarmStatus, "Send Alarm Status", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
}