Дождемер с опрокидывающимся ведром
Компоненты и расходные материалы
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 2 | ||||
| × | 2 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 |
Необходимые инструменты и машины
| ||||
|
Об этом проекте
Это дождемер с опрокидывающимся ведром, созданный на основе дождемеров, используемых профессиональными метеорологами. Устройство работает, переливая дождевую воду в опрокидывающееся ведро, напоминающее качели, причем на каждом конце есть ведро, вмещающее около 2 мл дождевой воды. Когда одна сторона наполняется, ведро опрокидывается, и дождевая вода начинает собираться в противоположном ведре. Каждый раз, когда ковш наклоняется, геркон временно включается, отправляя сигнал на аппаратное прерывание Arduino. Arduino отслеживает каждый «наконечник» ведра и преобразует «наконечники» в количество осадков (дюймы дождя) в зависимости от объема ведра и площади поверхности сборного резервуара (16,605 кв. Дюйма).
Внутренний дисплейный блок имеет меню выбора для отображения итоговых значений «текущий час», «предыдущий час», «текущий день» и «предыдущий день».
Для каждого наконечника ведра в файл SD-карты записывается событие с отметкой даты. Этот файл впоследствии можно будет импортировать в Excel для анализа и построения диаграмм.
Хотя у меня нет видео, показывающего реальный «наконечник ковша», на этом видео показан датчик, регистрирующий фактическое количество осадков.
Шаг 1
Распечатайте все перечисленные компоненты. Я использовал ПЭТГ для всех компонентов, так как это материал, который хорошо подходит для УФ-излучения и температурного воздействия при использовании на открытом воздухе. Для верхнего фильтра обязательно отключите все горизонтальные оболочки (верхнюю и нижнюю), чтобы создать пористую деталь.
Шаг 2
Перед началом сборки печатной платы передней панели вставьте ЖК-дисплей на плату PY-5 * 10CM (без пайки) так, чтобы контакт 1 ЖК-дисплея находился в отверстии C-1 на плате. Просверлите перфорированную плату в местах четырех монтажных отверстий ЖК-платы. Теперь снимите ЖК-дисплей для последующей сборки.
Шаг 3
Соберите печатную плату передней панели. Поместите ИС регистра сдвига 74HC595N, переключатели и резисторы, как показано. Проложите все необходимые провода (см. Электрическую схему) к точкам расположения, которые будут прикреплены к ЖК-дисплею, а также на участке длиной 6 дюймов, который будет увеличен для последующего подключения ко второй плате.
Шаг 4
Установите ЖК-дисплей на плату передней панели, используя распечатанные прокладки, чтобы поднять ЖК-дисплей и очистить ИС. Закрепите с помощью болтов и гаек размером 3 мм x 15 мм. (Все застежки доступны в магазинах Fastenal и / или McMaster Carr)
Шаг 5
Соберите главную печатную плату, вставив Arduino с контактом D12 в отверстие R27 на печатной плате. Добавьте конденсатор и резисторы и проложите всю проводку до места, прежде чем вставлять модули SD и RTC. Ссылка на электрическую схему для получения всех подробностей.
Шаг 6
Соберите SD-ридер в отверстиях от A-3 до B-10. Соберите TinyRTC в отверстиях с C-24 по I-24. Спаяйте все соединения.
Шаг 7
В шкафу управления внутренним блоком просверлите отверстия в любом месте, которое лучше всего соответствует вашим потребностям, для двух проводов, идущих к наружному блоку, а также отверстия для проводов, идущих от внешнего источника питания или стенной бородавки. Пропустите провода внутрь корпуса и припаяйте в соответствующих местах. Вставьте основную плату в корпус и прикрепите двумя винтами длиной 3 мм x 6 мм. Вставьте кнопку переключателя через переднюю крышку и прикрепите переднюю печатную плату к передней панели с помощью длинных винтов 3 мм x 6 мм. Примечание. Я использовал небольшую точеную латунную деталь для кнопки переключателя вместо печатной части, так как она мне больше понравилась.
Шаг 8
Прикрепите переднюю крышку с помощью винта M3-0,5 x 10 мм с плоской головкой
.
Шаг 9
Подключите USB к ПК и загрузите программу RTC, чтобы установить время. После того, как часы установлены, загрузите основную программу. Вставьте SD-карту. Проверьте блок, закоротив провода, идущие к геркону на наружном блоке. Общее количество осадков должно увеличиваться при каждом коротком замыкании (контакт замкнут). Убедитесь, что SD-карта считывает дату, прочитав ее с помощью текстового редактора, такого как Блокнот или WordPad на компьютере. Должен быть файл с названием «Text.txt». В файле будет указана дата для каждого события "подсказки".
Шаг 10
Присоедините геркон к вспомогательной базе. Используйте проволочные стяжки для фиксации на месте. Присоедините магнит к баку и установите ведро с помощью короткого отрезка латунной трубки диаметром 1/8 дюйма (длиной около 2 дюймов). Обратите внимание, перед сборкой просуньте сверло 1/8 дюйма через отверстия в ведре для очистки. Ковш должен легко опрокидываться без трения. При необходимости используйте небольшой круглый напильник в отверстиях ведра. Добавьте небольшую шайбу 1/8 дюйма на внешняя сторона ковша, чтобы немного уменьшить расстояние. Определите, как вы будете устанавливать наружный блок. Я использовал алюминиевый уголок 1 дюйм. Прикрепите основание к уголку или кронштейну с помощью шестигранных болтов 1/4-20, установленных изнутри наружу. Прикрепите вспомогательное основание к нижней части внешнего блока с помощью винтов M3-0,5x 10 мм.
Шаг 11
Вставьте воронку в верхний корпус. Отрежьте прибл. 24 куска оцинкованной проволоки 18 калибра длиной 2 дюйма. Удерживая кусок проволоки плоскогубцами, нагрейте горелкой или зажигалкой и осторожно вдавите в пластиковый верх. Эти проволоки не позволят птицам сесть на устройство. Вы хотите измерить количество дождя не птичий помет. Прикрепите верх к основному корпусу с помощью (4) винтов M3-0,5x 6 мм. Установите фильтр в верхнюю часть воронки. Этот фильтр не пропускает листья и предотвращает засорение .. Не забывайте время от времени проверять и очищать по мере необходимости.
Шаг 12
Установите наружный блок и проложите провода к внутреннему блоку. Убедитесь, что верх наружного блока выровнен в обоих направлениях.
Шаг 13
Включите блок и долейте воды в наружный блок, чтобы проверить его работу.
Шаг 14 (необязательно)
Чтобы проверить точность, вы можете ОЧЕНЬ МЕДЛЕННО добавить одну чашку воды и убедиться, что единица измерения составляет 0,87 дюйма осадков. (Одна чашка =14,44 кубических дюймов. Площадь коллектора составляет 16,605 дюймов [Осадки =14,44 куб. Дюймов. /16.605"=0.87 "]. Вы можете настроить поправочный коэффициент в основной программе, если ваше устройство отличается от моего.
Поздравляю !! Наслаждайтесь возможностью отслеживать количество осадков.
Код
- Код Arduino для установки времени RTC
- Код основной программы Arduino для датчика дождя
Код Arduino для установки времени на RTC Arduino
Сначала загрузите этот код, чтобы установить время на RTC. Отредактируйте код, указав фактическую дату и время перед загрузкой в Arduino.#include "Wire.h" #define DS1307_I2C_ADDRESS 0x68 // I2C-адрес Tiny RTCbyte second, minute, hour, dayOfWeek, dayOfMonth, month, year; / / Преобразование обычных десятичных чисел в двоично-десятичные байты 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)); // от 0 до 7 запускает clockWire.write (decToBcd (minute)); Wire.write (decToBcd (hour)); // Если вы хотите, чтобы 12 часов утра / вечера, вам нужно установить // бит 6 (также необходимо изменить readDateDs1307) Wire.write (decToBcd (dayOfWeek)); Wire.write (decToBcd (dayOfMonth)); Wire.write (decToBcd (месяц)); Wire.write (decToBcd (год)); Wire.endTransmission ();} // Функция получает дату и время от ds1307 и печатает resultvoid getDateDs1307 () {// Сбрасывает регистр pointerWire.beginTransmission ( DS1307_I2C_ADDRESS); Wire.write (decToBcd (0)); Wire.endTransmission (); Wire.requestFrom (DS1307_I2C_ADDRESS, 7); second =bcdToDec (Wire.read () &0x7f); minute =bcdTread () () ( ); час =bcdToDec (Wire.read () &0x3f); // Необходимо изменить это, если 12 часов утра / pmdayOfWeek =bcdToDec (Wire.read ()); dayOfMonth =bcdToDec (Wire.read ()); month =bcdToDec (Wire.read ()); year =bcdToDec (Wire. read ()); Serial.print (час, DEC); Serial.print (":"); Serial.print (минуты, DEC); Serial.print (":"); Serial.print (секунда, DEC); Serial.print (""); Serial.print (месяц, DEC); Serial.print ("/"); Serial.print (dayOfMonth, DEC); Serial.print ("/"); Serial.print (год, DEC); Serial.print (""); Serial.println (); // Serial.print ("День недели:");} void setup () {Wire.begin (); Serial.begin (19200); setDateDs1307 (); // Устанавливаем текущее время;} void loop () {delay (2000); getDateDs1307 (); // получаем данные времени из крошечного RTC}
Код основной программы Arduino для датчика дождя Arduino
Основная программа для датчика дождя. Перед компиляцией программы убедитесь, что вы установили все связанные библиотеки. Справочный веб-сайт [https://roboindia.com/tutorials/arduino-3-pin-serial-lcd/] для получения инструкций по обновлению библиотеки LiquidCrystal./ * Tipping Bucket Rain Gauge Написано Бобом Торренсом * / # include#include #include #include "RTClib.h" #include // включает библиотеку LiquidCrystal (специальная версия) ref https://roboindia.com/ tutorials / arduino-3-pin-serial-lcd /// Определение ЖК-дисплея и контактов для взаимодействия. LiquidCrystal_SR lcd (6, 5, 9); // Контакт 6 - разрешение данных / SER, Контакт 5 - Часы / SCL, Контакт 9 -SCKRTC_DS3231 rtc; int backlight =7; // вывод, к которому подключен светодиод к выводу 7 (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_hour; float Bucket_tip_current_day_total =0; float Bucket_tip_previous_day_total =0; int current_minute; int loop_minute; int current_hour; int loop_hour; int current_day; int loop_day; int tip_counter; float conversion_factor =.00854; // дюймы дождя на наконечник - рассчитываются путем измерения объема ковша и площади коллектора (16,605 кв. дюймов) volatile unsigned long backlightOfftime; volatile unsigned long backlightOnDuration =30000; // продолжительность (в миллисекундах), в течение которой подсветка остается включенной после нажатия кнопки выбора меню String print_time (DateTime timestamp) {char message [120]; int Год =отметка времени.год (); int Месяц =timestamp.month (); int Day =отметка времени.day (); int Hour =отметка времени. час (); int Минуты =отметка времени.минуты (); int Second =отметка времени.second (); sprintf (сообщение, «% 02d:% 02d:% 02d% 02d /% 02d», час, минута, секунда, месяц, день); return message;} Файл myFile; void setup () {lcd.begin (16,2); // Инициализирует интерфейс для ЖК-экрана и задает размеры (ширину и высоту) дисплея lcd.home (); // Установка курсора в исходное положение, т.е. 0,0 rtc.begin (); // инициируем использование переменных часов реального времени pinMode (10, OUTPUT); pinMode (подсветка, ВЫХОД); // Объявить светодиод как выход digitalWrite (backlight, HIGH); // включение подсветки ЖК-дисплея backlightOfftime =millis () + backlightOnDuration; // устанавливаем начальную задержку включения подсветки ЖК-дисплея if (! SD.begin (4)) {lcd.print ("insert SD Card"); возвращение; } // Настраиваем наш цифровой вывод как прерывание для bucket pinMode (interruptPin_bucket, INPUT_PULLUP); attachInterrupt (digitalPinToInterrupt (interruptPin_bucket), count, FALLING); // Настраиваем наш цифровой вывод как прерывание для bucket pinMode (interruptPin_menu, INPUT_PULLUP); attachInterrupt (digitalPinToInterrupt (interruptPin_menu), меню, RISING); myFile =SD.open ("test.txt", FILE_WRITE); if (myFile) {myFile.println («Датчик дождя готов - устройство включено»); myFile.close (); } DateTime now =rtc.now (); current_minute =now.minute (); loop_minute =now.minute (); current_hour =сейчас. час (); loop_hour =now.hour (); lcd.setCursor (0,0); lcd.print (время печати (сейчас)); // Выводит "Arduino" на ЖК-дисплей lcd.setCursor (1,1); lcd.print («Дождемер»); } недействительный цикл () {DateTime now =rtc.now (); current_minute =now.minute (); loop_minute =now.minute (); current_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 (подсветка, НИЗКАЯ); } if (Bucket_Tip_Occurence ==1) {Bucket_Tip_Occurence =0; tip_counter =tip_counter + 1; DateTime now =rtc.now (); myFile =SD.open ("test.txt", FILE_WRITE); myFile.print («Событие»); 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 (коэффициент_конверсии, 5); myFile.println (); myFile.close (); задержка (200); } else {// Проверяем текущий часовой статус DateTime now =rtc.now (); loop_hour =now.hour ();} переключатель (Menu_Select) {case 1:lcd.clear (); lcd.setCursor (0,0); lcd.print («Текущий час»); lcd.setCursor (0,1); lcd.print (tip_counter * conversion_factor); задержка (500); ломать; случай 2:lcd.clear (); lcd.setCursor (0,0); lcd.print («Предыдущий час»); lcd.setCursor (0,1); lcd.print (Bucket_tip_previous_hour_total); задержка (500); ломать; случай 3:lcd.clear (); lcd.setCursor (0,0); lcd.print («Текущий день»); lcd.setCursor (0,1); lcd.print (Bucket_tip_current_day_total + tip_counter * conversion_factor); задержка (500); ломать; случай 4:lcd.clear (); lcd.setCursor (0,0); lcd.print («Предыдущий день»); lcd.setCursor (0,1); lcd.print (Bucket_tip_previous_day_total); // lcd.print (print_time (сейчас)); задержка (500); ломать; }} 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 + Bucket_tip_current_day_total; tip_counter =0; / * Необязательная запись в файл только с почасовой суммой myFile =SD.open ("test.txt", FILE_WRITE); myFile.print («Почасовая сводка»); myFile.print (Bucket_tip_previous_hour_total); 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 (Bucket_tip_previous_hour_total); myFile.println (); myFile.close (); задержка (200); * /} // Итого за текущий час 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; / * Необязательная запись в файл только с итогом предыдущего дня myFile =SD.open ("test.txt", FILE_WRITE); myFile.print («Всего за день»); myFile.print (Bucket_tip_previous_day_total); myFile.print (время печати (сейчас)); myFile.close (); * /} // инициировать прерывание из m bucket reed switchvoid count () {static unsigned long last_interrupt_time_bucket =0; беззнаковый длинный interrupt_time_bucket =millis (); // Если прерывания приходят быстрее 300 мс, предположим, что это отскок, и игнорируем if (interrupt_time_bucket - last_interrupt_time_bucket> 300) {Bucket_Tip_Occurence =1; } last_interrupt_time_bucket =interrupt_time_bucket;} // инициировать прерывание fromm menu toggle switchvoid menu () {static unsigned long last_interrupt_time_menu =0; беззнаковое длинное interrupt_time_menu =millis (); // Если прерывания приходят быстрее, чем 300 мс, предположим, что это дребезг, и игнорируем if (interrupt_time_menu - last_interrupt_time_menu> 300) {if (digitalRead (backlight) ==LOW) {digitalWrite (backlight, HIGH); // включает подсветку, если она была ранее выключена} else Menu_Select =Menu_Select + 1; если (Menu_Select> 4) {Menu_Select =1; } backlightOfftime =millis () + backlightOnDuration; Menu_Select =Menu_Select; last_interrupt_time_menu =interrupt_time_menu; }}
Изготовленные на заказ детали и корпуса
STL для 3D-печати Основание наружного блока. Я напечатал из PETG с заполнением 30% файл STL для 3D-печати крышки наружного блока. Я напечатал с помощью PETG с заполнением 30% Файл STL для 3D-печати воронки для наружного блока. Я напечатал с использованием PETG с заполнением 30%. Файл STL для 3D-печати фильтра наружного блока. Я печатал с использованием PETG с заполнением 20%. Эта часть должна быть напечатана без горизонтальных нижних или верхних слоев, создавая «пористый» фильтр. Файл STL для 3D-печати вспомогательного основания, к которому ведро прикрепляется через стержень поворота. Я напечатал с использованием PETG с 30% -ным заполнением. Файл STL для 3D-печати ведра. Я распечатал с использованием PETG с 30% -ным заполнением. Файл STL для печати корпуса внутреннего блока. Я напечатал с помощью PETG с заполнением 30% .STL-файл для 3D-печати передней крышки внутреннего блока. Я распечатал файл STL с заполнением PETG на 30%, чтобы напечатать разделители, чтобы ЖК-дисплей оставался поднятым над ИС регистра сдвига. Я напечатал с использованием PETG с заполнением 30%. Модель наружного блока Fusion 360 rain_gauge_assembly ___ small_profile_v15_CFg0dGwM8s.f3d.STP-файл наружного блока rain_gauge_assembly ___ small_profile_v15_jWCS0hjSDq.stepSTEP Cad-модель внутреннего блока controller_box_v1_fwltgu6D0S.stepFusion 36 CAD-модель наружного блока controller_box_v1_NxtSrPG4Vo.f3zSTL файл для 3D-печати кнопки переключенияСхема
Схема подключения проекта rain_gauge_NtjqXF6QEw.fzzПроизводственный процесс