Продвинутый дождемер ковшового типа с интеграцией Arduino
Компоненты и материалы
| Arduino Nano R3 | × | 1 шт. |
| Tiny RTC I2C DS1307 (модуль реального времени) | × | 1 шт. |
| SD Card Module (LC Studios) | × | 1 шт. |
| Блок питания 7-12 ВDC (или сетевой адаптер) | × | 1 шт. |
| Adafruit Standard LCD 16×2 (белый на синем) | × | 1 шт. |
| Сдвиговый регистр Texas Instruments SN74HC595N (Serial to Parallel) | × | 1 шт. |
| Резистор 1 кОм | × | 2 шт. |
| Резистор 330 Ом | × | 2 шт. |
| Конденсатор 100 нФ | × | 1 шт. |
| Однооборотный потенциометр 10 кОм | × | 1 шт. |
| PCB-кнопка (мгновенного контакта) | × | 1 шт. |
| Рид-выключатель SPST-NO | × | 1 шт. |
| Магнит (7 мм OD × 7 мм длина) | × | 1 шт. |
| Односторонняя макетная плата 5×10 см | × | 1 шт. |
Необходимые инструменты и оборудование
- 3D-принтер (любой)
- Паяльник
О проекте
Это дождемер ковшового типа, как используют профессиональные метеорологи. Принцип: воронка собирает дождевую воду на ковш, похожий на качели — у каждого конца ковш на ~2 мл. Когда один наполняется, ковш перекачивается, вода собирается в противоположном. Каждое перекачивание замыкает рид-контакт, посылая сигнал на аппаратное прерывание Arduino. Контроллер считает «перекачивания» и переводит их в количество осадков (мм), исходя из объёма ковша и площади приёмной поверхности (16,605 кв. дюйма = 107,1 см²).
Внутренний блок индикации имеет меню: «текущий час», «предыдущий час», «текущие сутки», «предыдущие сутки».
Каждое перекачивание с таймстампом записывается в файл на SD-карте. Файл можно импортировать в Excel для анализа и графиков.
Видео показывает запись реального дождя (сам момент перекачивания не снят).
Шаг 1: 3D-печать всех деталей
Использован PETG — устойчив к УФ и температурным перепадам на улице. Для верхнего фильтра отключите все горизонтальные слои (сверху и снизу) — создаётся пористая структура.
Шаг 2: Подготовка фронтальной платы под LCD
Установите LCD на плату PY-5×10 см (без пайки), пин 1 LCD в отверстие C-1. Пройдитесь дрелью по четырём отверстиям крепления LCD. Снимите LCD для дальнейшей сборки.
Шаг 3: Сборка фронтальной платы
Разместите 74HC595N, кнопки, резисторы как на фото. Проложите все необходимые провода (по схеме) к точкам подключения LCD и 6-дюймовые выводы для соединения со второй платой.
Шаг 4: Монтаж LCD
Установите LCD на фронтальную плату, используя напечатанные распорки для зазора над IC. Крепите винтами M3×15 мм с гайками. (Крепеж есть в Fastenal / McMaster Carr)
Шаг 5: Сборка главной платы
Установите Arduino с пином D12 в отверстие R27. Добавьте конденсатор, резисторы, проложите провода к местам для SD и RTC модулей до их установки. См. схему.
Шаг 6: Установка SD и RTC модулей
SD-ридер в отверстия A-3 – B-10. TinyRTC в C-24 – I-24. Припаяйте все соединения.
Шаг 7: Внутренний блок управления
В корпусе внутреннего блока просверлите отверстия для двух проводов к уличному блоку и питания. Проложите провода, припаяйте. Вставьте главную плату в корпус, закрепите двумя винтами M3×6 мм. Вставьте кнопку меню через переднюю крышку, прикрепите фронтальную плату винтами M3×6 мм. (Автор использовал латунный втулочный элемент вместо напечатанной кнопки — приятнее тактильно.)
Шаг 8: Крепление передней крышки
Винты M3-0.5×10 мм потайные.
Шаг 9: Настройка времени и тест
Подключите USB к ПК, загрузите скетч установки RTC (код ниже). После установки времени загрузите основной скетч. Вставьте SD-карту. Тест: замкните выводы, идущие к рид-контакту уличного блока. Счётчики осадков должны увеличиваться при каждом замыкании. Проверьте SD-карту на ПК (Notepad/WordPad) — должен быть файл Text.txt с таймстампами каждого события.
Шаг 10: Уличный блок — рид-контакт и ковш
Прикрепите рид-контакт к подбазе (styrки). Магнит на ковше, ось — латунная трубка 1/8″ (~50 мм). Перед сборкой просверлите 1/8″ отверстия в ковше для чистоты. Ковш должен перекачиваться свободно, без трения. При необходимости нашлифуйте круглой наждачкой. Добавьте шайбу 1/8″ по краю для уменьшения зазора. Определите способ монтажа уличного блока. Автор использовал алюминиевый угол 1″. База к углу болтами 1/4-20 изнутри наружу. Подбаза к дну уличного блока винтами M3-0.5×10 мм.
Шаг 11: Воронка и защита от птиц
Вставьте воронку в верхний корпус. Нарежьте ~24 куска galvanized wire 18 AWG длиной 2″. Нагрейте кусок зажигалкой/горелкой и вдавите в пластик верха — иглы отпугивают птиц. Нужно измерять дождь, не птичий налёт. Прикрепите верх к корпусу (4) M3-0.5×6 мм. Установите фильтр во воронку — задерживает листья, предотвращает забивание. Периодически проверяйте и чистите.
Шаг 12: Монтаж уличного блока и проводка
Установите уличный блок, проведите провода к внутреннему. Верхний край воронки должен быть идеально горизонтален в обеих плоскостях.
Шаг 13: Питание и проверка
Подайте питание, добавьте воды в уличный блок — проверьте работу.
Шаг 14 (опционально): Проверка точности
Очень медленно влейте 1 стакан (236,6 мл = 14,44 куб. дюйма) воды. Прибор должен показать 0,87″ осадков (14,44 / 16,605 = 0,87). При расхождении скорректируйте conversion_factor в основном скетче.
Поздравляем! Наслаждайтесь точным учётом осадков.
Программный код
Arduino Code to set time on RTC
Загрузите первым для установки времени на RTC. Отредактируйте дату/время перед прошивкой.
#include "Wire.h"
#define DS1307_I2C_ADDRESS 0x68
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
byte decToBcd(byte val) { return ( (val/10*16) + (val%10) ); }
byte bcdToDec(byte val) { return ( (val/16*10) + (val%16) ); }
void setDateDs1307() {
second = 00; minute = 11; hour = 12;
dayOfWeek = 5; dayOfMonth = 24; month = 7; year = 20;
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(decToBcd(0));
Wire.write(decToBcd(second));
Wire.write(decToBcd(minute));
Wire.write(decToBcd(hour));
Wire.write(decToBcd(dayOfWeek));
Wire.write(decToBcd(dayOfMonth));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.endTransmission();
}
void getDateDs1307() {
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(decToBcd(0));
Wire.endTransmission();
Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
second = bcdToDec(Wire.read() & 0x7f);
minute = bcdToDec(Wire.read());
hour = bcdToDec(Wire.read() & 0x3f);
dayOfWeek = bcdToDec(Wire.read());
dayOfMonth = bcdToDec(Wire.read());
month = bcdToDec(Wire.read());
year = bcdToDec(Wire.read());
Serial.print(hour, DEC); Serial.print(":");
Serial.print(minute, DEC); Serial.print(":");
Serial.print(second, DEC); Serial.print(" ");
Serial.print(month, DEC); Serial.print("/");
Serial.print(dayOfMonth, DEC); Serial.print("/");
Serial.print(year, DEC); Serial.println();
}
void setup() {
Wire.begin(); Serial.begin(19200);
setDateDs1307();
}
void loop() {
delay(2000); getDateDs1307();
}
Main Program Arduino code For Rain Gauge
Основной скетч. Установите все библиотеки перед компиляцией. Инструкция по обновлению LiquidCrystal: roboindia.com
/* Tipping Bucket Rain Gauge by Bob Torrence */
#include
#include
#include
#include "RTClib.h"
#include // специальная версия для сдвигового регистра
LiquidCrystal_SR lcd(6, 5, 9); // Data/SER=6, Clock/SCL=5, Latch/SCK=9
RTC_DS3231 rtc;
int backlight = 7; // подсветка LCD на D7
const byte interruptPin_bucket = 3;
const byte interruptPin_menu = 2;
volatile int Bucket_Tip_Occurence;
volatile int Menu_Select;
float Bucket_tip_hour_total = 0;
float Bucket_tip_current_hour_total = 0;
float Bucket_tip_previous_hour_total = 0;
float Bucket_tip_current_day_total = 0;
float Bucket_tip_previous_day_total = 0;
int current_minute, loop_minute, current_hour, loop_hour, current_day, loop_day;
int tip_counter;
float conversion_factor = .00854; // дюймов осадков на одно перекачивание
volatile unsigned long backlightOfftime;
volatile unsigned long backlightOnDuration = 30000; // 30 сек подсветки после нажатия
String print_time(DateTime timestamp) {
char message[120];
sprintf(message, "%02d:%02d:%02d %02d/%02d",
timestamp.hour(), timestamp.minute(), timestamp.second(),
timestamp.month(), timestamp.day());
return message;
}
File myFile;
void setup() {
lcd.begin(16, 2);
lcd.home();
rtc.begin();
pinMode(10, OUTPUT);
pinMode(backlight, OUTPUT);
digitalWrite(backlight, HIGH);
backlightOfftime = millis() + backlightOnDuration;
if (!SD.begin(4)) {
lcd.print("insert SD Card");
return;
}
pinMode(interruptPin_bucket, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin_bucket), count, FALLING);
pinMode(interruptPin_menu, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin_menu), menu, RISING);
myFile = SD.open("test.txt", FILE_WRITE);
if (myFile) {
myFile.println("Rain Gauge Ready - unit powered up");
myFile.close();
}
DateTime now = rtc.now();
current_minute = loop_minute = now.minute();
current_hour = loop_hour = now.hour();
current_day = loop_day = now.day();
lcd.setCursor(0, 0); lcd.print(print_time(now));
lcd.setCursor(1, 1); lcd.print("Rain Gauge");
}
void loop() {
DateTime now = rtc.now();
current_minute = now.minute(); loop_minute = now.minute();
current_hour = now.hour(); loop_hour = now.hour();
current_day = now.day(); loop_day = now.day();
// Цикл по текущим суткам
while (loop_day - current_day == 0) {
// Цикл по текущему часу
while (loop_hour - current_hour == 0) {
if (millis() > backlightOfftime) digitalWrite(backlight, LOW);
if (Bucket_Tip_Occurence == 1) {
Bucket_Tip_Occurence = 0;
tip_counter++;
DateTime now = rtc.now();
myFile = SD.open("test.txt", FILE_WRITE);
myFile.print("Event ");
myFile.print(now.year(), DEC); myFile.print('/');
myFile.print(now.month(), DEC); myFile.print('/');
myFile.print(now.day(), DEC); myFile.print(" ");
myFile.print(now.hour(), DEC); myFile.print(':');
myFile.print(now.minute(), DEC); myFile.print(':');
myFile.print(now.second(), DEC); myFile.print(" ");
myFile.print(conversion_factor, 5); myFile.println();
myFile.close();
delay(200);
} else {
DateTime now = rtc.now();
loop_hour = now.hour();
}
switch (Menu_Select) {
case 1: // Текущий час
lcd.clear(); lcd.setCursor(0, 0); lcd.print("Current Hour");
lcd.setCursor(0, 1); lcd.print(tip_counter * conversion_factor); delay(500); break;
case 2: // Предыдущий час
lcd.clear(); lcd.setCursor(0, 0); lcd.print("Previous Hour");
lcd.setCursor(0, 1); lcd.print(Bucket_tip_previous_hour_total); delay(500); break;
case 3: // Текущие сутки
lcd.clear(); lcd.setCursor(0, 0); lcd.print("Current Day");
lcd.setCursor(0, 1); lcd.print(Bucket_tip_current_day_total + tip_counter * conversion_factor); delay(500); break;
case 4: // Предыдущие сутки
lcd.clear(); lcd.setCursor(0, 0); lcd.print("Previous Day");
lcd.setCursor(0, 1); lcd.print(Bucket_tip_previous_day_total); delay(500); break;
}
}
// Переход к следующему часу
DateTime now = rtc.now();
current_hour = now.hour(); loop_day = now.day(); loop_hour = now.hour();
Bucket_tip_previous_hour_total = tip_counter * conversion_factor;
Bucket_tip_current_day_total += Bucket_tip_previous_hour_total;
tip_counter = 0;
}
// Переход к следующим суткам
Bucket_tip_previous_day_total = Bucket_tip_current_day_total;
Bucket_tip_current_day_total = 0;
Bucket_tip_current_hour_total = 0;
tip_counter = 0;
}
// Прерывание от рид-контакта ковша
void count() {
static unsigned long last_interrupt_time_bucket = 0;
unsigned long interrupt_time_bucket = millis();
if (interrupt_time_bucket - last_interrupt_time_bucket > 300) {
Bucket_Tip_Occurence = 1;
}
last_interrupt_time_bucket = interrupt_time_bucket;
}
// Прерывание от кнопки меню
void menu() {
static unsigned long last_interrupt_time_menu = 0;
unsigned long interrupt_time_menu = millis();
if (interrupt_time_menu - last_interrupt_time_menu > 300) {
if (digitalRead(backlight) == LOW) {
digitalWrite(backlight, HIGH);
} else {
Menu_Select++;
if (Menu_Select > 4) Menu_Select = 1;
}
backlightOfftime = millis() + backlightOnDuration;
last_interrupt_time_menu = interrupt_time_menu;
}
}
3D-модели (STL для печати)
- Основание уличного блока (PETG, 30% наполнение)
- Крышка уличного блока (PETG, 30%)
- Воронка (PETG, 30%)
- Фильтр (PETG, 20%, БЕЗ горизонтальных слоев — пористый)
- Подбаза ковша (PETG, 30%)
- Ковш (PETG, 30%)
- Корпус внутреннего блока (PETG, 30%)
- Передняя крышка внутреннего блока (PETG, 30%)
- Распорки для LCD (PETG, 30%)
- Кнопка меню (PETG)
- Fusion 360 модели:
rain_gauge_assembly___smaller_profile_v15_CFg0dGwM8s.f3d,controller_box_v1_NxtSrPG4Vo.f3z - STEP-файлы:
rain_gauge_assembly___smaller_profile_v15_jWCS0hjSDq.step,controller_box_v1_fwltgu6D0S.step
Схемы
Производственный процесс
- Точные манометры для промышленности и безопасности: конструкция, материалы, производство
- Умные шторы: автоматическое управление светом на Arduino с солнечной энергией
- Итальянские словесные часы на Arduino Nano, NeoPixel, LCD и RTC
- Цифровые высотомеры: Точное измерение и решения для контроля качества
- Микрометрический винт: история, устройство и практическое применение
- Манометры: принцип работы, виды, функции и преимущества
- Тензодатчики: преобразование механического напряжения в точные электрические сигналы
- Вакуумный манометр Пирани: принцип работы, применение и преимущества
- Мембранные манометры: устройство, принцип работы и сферы применения
- Бурдоновские манометры: конструкция, принцип действия и применение