Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Manufacturing Technology >> Производственный процесс

Бутылка для воды с питанием от Arduino

Компоненты и расходные материалы

SparkFun Arduino Pro Mini 328 - 5 В / 16 МГц
× 1
Водонепроницаемый ультразвуковой датчик
× 1
Часы реального времени (RTC)
× 1
SparkFun 4-значный 7-сегментный дисплей с общим катодом
× 1
Зуммер
× 1
Кнопочный переключатель SparkFun, 12 мм
× 1
NPN-транзистор общего назначения
× 1
Литий-ионный аккумулятор 1000 мАч
× 1
USB-зарядное устройство для литий-ионных аккумуляторов Adafruit
× 1
Резистор 221 Ом
× 8
Резистор 1 кОм
× 4
Резистор 4,75 кОм
× 2

Необходимые инструменты и машины

Паяльник (общий)
Пистолет для горячего клея (общий)

Приложения и онлайн-сервисы

IDE Arduino

Об этом проекте

Введение:

Употребление достаточного количества воды очень важно для нашего здоровья. Употребление большего количества воды может сделать кожу более чистой, улучшить общее состояние здоровья, повысить продуктивность и работу мозга, повысить уровень энергии и даже потерять вес.

В нашей загруженной жизни действительно сложно не забыть пить достаточно воды. И большую часть времени мы забываем пить достаточно воды, будь то дома, в офисе или в дороге. Около 75% американцев постоянно страдают хроническим обезвоживанием.

Итак, чтобы выработать здоровую привычку пить воду, важно ежедневно отслеживать потребление воды.

Чтобы отслеживать потребление воды, я сделал свою бутылку с водой умной, используя Arduino. Это может:

1. Отслеживайте свое ежедневное потребление воды

2. Отслеживайте свое среднее потребление воды за неделю

3. Напомнить мне взять воды

4. Отслеживайте время последнего приема

5. Работайте без подзарядки более одного месяца.

Создание модуля RTC

Для регистрации или отслеживания информации о водозаборе требуется, чтобы информация о текущем времени и дате сохранялась вместе с накопленными данными. Микросхема часов реального времени (RTC), такая как DS1307 с подходящей резервной батареей, может использоваться для предоставления необходимой информации. Процесс программирования микросхемы RTC (программно) также очень прост и поддерживается в большинстве сред программирования.

Вот дизайн компактного модуля RTC, основанного на популярной микросхеме RTC IC DS1307, для ваших повседневных проектов микроконтроллеров. Последовательные часы реального времени (RTC) DS1307 - это часы / календарь с полным двоично-десятичным кодированием (BCD) с низким энергопотреблением, плюс 56 байтов NV SRAM. Адрес и данные передаются последовательно через двунаправленную шину I2C. Часы / календарь в 24-часовом / 12-часовом формате предоставляют информацию о секундах, минутах, часах, дне, дате, месяце и году, включая поправки на високосный год.

Изготовим модуль часов реального времени по прилагаемой схеме. Для правильной работы DS1307 RTC требуется внешний кристалл. Для вывода SCL и SDA IC требуется два подтягивающих резистора. Величина резистора может составлять от 2 кОм до 10 кОм. Я использовал 4,7к. Во время пайки я старался сделать модуль как можно меньше, потому что место для моей схемы ограничено. Вы можете использовать DS3231 вместо DS1307, и IC имеет внутренний кварцевый генератор. Таким образом, вам не нужно добавлять внешний кристалл. Вы также можете купить готовый крошечный модуль RTC, если не хотите делать его самостоятельно. Поскольку вся система будет работать от батареи, по этой причине я подключил вывод VBAT RTC к земле без использования батарейки.

Важные контакты DS1307:

  • Контакт 5 В :Когда на этом выводе высокий уровень, тогда ds1307 отправляет данные, а когда он низкий, он работает с ячейкой кнопки резервного копирования.
  • GND :Это контакт заземления для модуля. Заземление аккумулятора и источник питания связаны друг с другом.
  • SCL :Это тактовый вывод I2C, который взаимодействует с микроконтроллером. Должен подключаться к контакту Arduino SCL.
  • ПДД :Это вывод данных I2C, который взаимодействует с микроконтроллером. Должен подключаться к выводу Arduino SDA.
  • VBAT :Вход батареи для любого стандартного литиевого элемента 3 В или другого источника энергии. Если не используется, должно быть заземлено.

Изготовление семисегментной табло

В качестве модуля дисплея здесь я использовал автономный компактный модуль с общим катодом, содержащий четыре 7-сегментных светодиодных цифровых дисплея, пригодных для отображения числовых данных с помощью некоторых простых символов.

Каждый сегмент в модуле дисплея мультиплексирован, что означает, что он имеет одни и те же точки подключения анода. И каждая из четырех цифр в модуле имеет свою общую точку подключения катода. Это позволяет включать и выключать каждую цифру независимо. Кроме того, этот метод мультиплексирования превращает огромное количество выводов микроконтроллера, необходимых для управления дисплеем, всего в одиннадцать или двенадцать (вместо тридцати двух)!

Для светодиодных сегментов дисплея требуются токоограничивающие резисторы при питании от логического вывода 5 В. Номинальное сопротивление резистора обычно составляет от 330 до 470 Ом для 5 В. Для работы от литий-ионной батареи оно может составлять 220 Ом. Также рекомендуется, чтобы управляющие транзисторы обеспечивали дополнительный управляющий ток для светодиодных сегментов, поскольку каждый вывод микроконтроллера может отдавать или потреблять ток около 40 мА. Когда все (семь) сегментов дисплея включаются одновременно (цифра 8), потребляемый ток превысит этот предел в 40 мА. На изображении ниже показана основная схема подключения токоограничивающих резисторов и задающих транзисторов.

Эта 4-значная 7-сегментная секция дисплея подключена к четырем 7-сегментным светодиодным дисплеям с общим катодом и четырем транзисторам 2N2222 NPN. Резисторы 1K используются для ограничения тока базы, а резисторы 220R ограничивают рабочий ток сегментов светодиодного дисплея.

На плате Arduino цифровые выходы от D10 до D17 используются для управления сегментами (от a до g и dp), а цифровые выходы от D6 до D9 используются для цифр (D0-D3) светодиодного дисплея 4 × 7.

К модулю дисплея добавлен кнопочный переключатель для доступа к различным параметрам. Он также будет использоваться для вывода Arduino из спящего режима с помощью внешнего аппаратного прерывания. Итак, кнопка подключена к цифровому выводу №2 Arduino (INT0).

Подключение платы дисплея к Arduino Mini Pro

В соответствии со схемой, представленной перед тем, как припаять все штырьки сегментов к мини-штырю Arduino. Затем припаяйте 4 общий вывод к коллекторному выводу транзистора. Базы транзистора подключаются к выводу Arduino. После подключения дисплея подключите кнопочный переключатель к цифровому контакту 2 Arduino (INT 0). Убедитесь, что вы подключили кнопку к контакту 2 Arduino, потому что мы реализуем внешнее аппаратное прерывание, чтобы вывести Arduino из спящего режима с помощью этой кнопки.

Подключение модуля RTC и зуммера

Теперь подключите модуль RTC, который вы сделали ранее, к плате Arduino. Вывод SDA модуля должен быть подключен к выводу SDA (A4) вывода Arduino, а вывод SCL модуля должен быть подключен к выводу SCL (A5) Arduino. Затем подключите зуммер к плате Arduino.

Подключения:

RTC ------> Arduino Mini Pro

  • SDA ------> A4
  • SCL ------> A5
  • Зуммер ------> D3

Крепление ультразвукового датчика к бутылочной крышке

Сделайте отверстие в крышке бутылки, как показано на рисунке. Вытащите четыре провода ультразвукового датчика через отверстие и закрепите ультразвуковой датчик в центре крышки бутылки. Датчик должен быть прикреплен к внутренней стороне крышки флакона в центральном положении.

Подключения:

Ультразвуковой датчик ------> Arduino Mini Pro

  • VCC ------> VCC
  • GND ------> GND
  • Триггер ------> D4
  • Эхо ------> D5

Загрузка программы и тестирование

После завершения всех подключений самое время загрузить программу на плату Arduino и протестировать ее работоспособность. Для корректной работы программы вам потребуется несколько библиотек. Для взаимодействия с кнопками вам необходимо добавить библиотеку OneButton. Поскольку устройство будет работать от аккумулятора, важным моментом является энергопотребление. Я реализовал спящий режим в моем скетче Arduino. Сторожевой таймер и внешнее аппаратное прерывание использовались для вывода Arduino из спящего режима. Arduino снимает показания датчика трижды, усредняет их и вычисляет необходимую информацию и отображает информацию в течение 10 секунд, а затем переходит в спящий режим на 1 минуту. Он просыпается в любое время при нажатии кнопки, подключенной к INT0 (цифровой контакт 2). Итак, если вы хотите увидеть информацию о потреблении воды, просто нажмите кнопку выбора в любое время. Он проснется для вас. Без нажатия какой-либо кнопки чтение будет производиться каждые 1 минуту. Для реализации спящего режима я использовал библиотеку Arduino Low-Power. Для чтения времени из модуля DS1307 RTC я использовал библиотеку DS1307RTC. Итак, для компиляции прилагаемой программы добавьте всю библиотеку в свое окружение.

Я кратко объясню здесь только алгоритм расчета. Полный набросок см. В прикрепленной заливке. Расчет выполняется на основе среднего значения пяти показаний датчика, чтобы сделать его достаточно точным. Ежедневные показания сбрасываются через 24 часа и готовятся к новому чтению на новый день.

Среднее количество воды рассчитывается из среднего суточного потребления за предыдущие семь дней. Вы 2 часа не принимали воду, он будет предупреждать пользователя двойным звуковым сигналом каждые 15 минут и останавливается на следующие 2 часа после того, как вы налейте воду.

Загрузите прикрепленный код и загрузите его на свой Arduino Mini Pro. Подключите весь модуль и включите его, чтобы проверить, все ли компоненты работают правильно или нет. Если на дисплее отображается результат, поздравляю! Вы уже сделали самое трудное.

Крепление Arduino с помощью крышки от бутылки

С помощью горячего клея прикрепите Arduino mini к верхней стороне крышки бутылки. Имейте в виду, что вам нужно закрепить все компоненты в крышке бутылки. Добавьте достаточно клея, чтобы он плотно прилегал к крышке бутылки.

Установка модуля батареи и зарядного устройства

Теперь закрепите литий-ионную батарею в верхней части Arduino. Будьте осторожны, не закорачивайте аккумулятор открытым контактом. Затем подсоедините модуль зарядного устройства крышкой. Держите порт USB легкодоступным с внешней стороны, чтобы его можно было легко подключить к зарядному устройству.

Обеспечение водонепроницаемости всех схем

После подключения всех компонентов и модуля самое время сделать наше устройство полностью водонепроницаемым. Это очень важно, потому что это бутылка для воды, и в любой момент вода может попасть в контур и повредить контур. Чтобы сделать его полностью водонепроницаемым, добавьте достаточно клея во все внешние части схем без порта USB. Вы можете сделать колпачок красивым, используя клей, чтобы он получился круглым, как у оригинального колпачка.

Не опускайте крышку бутылки в воду.

Наслаждайтесь

Код

  • Эскиз Arduino
Эскиз Arduino Arduino
 // Функции даты и времени с использованием DS1307 RTC, подключенного через I2C и Wire lib # include  #include  #include  #include  #include " LowPower.h "#include" OneButton.h "Кнопка OneButton (2, true); const byte interruptPin =2; volatile int state =0; const int trigPin =4; const int echoPin =5; int piezoPin =3; const int digit [4] ={9,6,7,8}; int digit_value [4]; int digit_value1 [4]; int button_press_count =1; const int segment [8] ={16,10,12,14,15, 17,11,13}; число константного байта [10] [8] ={{1,1,1,1,1,1,0,0}, // 0 {0,1,1,0,0, 0,0,0}, // 1 {1,1,0,1,1,0,1,0}, // 2 {1,1,1,1,0,0,1,0}, / / 3 {0,1,1,0,0,1,1,0}, // 4 {1,0,1,1,0,1,1,0}, // 5 {1,0,1 , 1,1,1,1,0}, // 6 {1,1,1,0,0,0,0,0}, // 7 {1,1,1,1,1,1,1 , 0}, // 8 {1,1,1,1,0,1,1,0}}; // 9константный байт d [8] ={0,1,1,1,1,0,1,1}; константный байт a [8] ={1,1,1,0,1,1,1,1 }; const byte r [8] ={0,0,0,0,1,0,1,1}; const byte t [8] ={0,0,0,1,1,1,1,1 }; int секунды, минуты, часы; int water_in_ounch [15]; int water_intake_ounch [15]; int water_intake_days [7]; int water_intake_times =0; int previous_water_amount =0; int total_water_intake_today =0; int average_intake_last_week =0; int inatke_day =1; float average_water_level =0; // сохраняем среднее значение нескольких показаний int water_amount_in_ounce =0; // сохраняем рассчитанное количество воды int idle_time =0; int input_day =1; int previous_value =0; void setup () {Serial.begin (9600); pinMode (interruptPin, INPUT_PULLUP); // поместите сюда свой установочный код для однократного запуска:for (int i =6; i <=17; i ++) pinMode (i, OUTPUT); pinMode (trigPin, ВЫХОД); pinMode (echoPin, ВХОД); button.attachClick (нажата); button.attachDoubleClick (двойной щелчок); button.attachLongPressStart (longPressStart); button.attachDuringLongPress (longPress);} long previous_state =millis (); int count =1; int daily_intake =0; int weekly_intake =0; long sleep_time =millis (); void loop () {read_time (); button.tick (); // продолжаем следить за кнопками:вычисление (); daily_intake =total_water_intake_in_day (); weekly_intake =average_water_intake_last_week (); если (button_press_count ==1) {display_d (); display_number (daily_intake); } иначе, если (button_press_count ==2) {display_a (); display_number (weekly_intake); } иначе, если (button_press_count ==3) {display_r (); display_number (water_amount_in_ounce); } else if (button_press_count ==4) {display_first_2 (часы); display_last_2 (минуты); } если (idle_time> =120) {alert (); тревога(); } если ((millis () - время сна)> =15000) {display_off (); attachInterrupt (digitalPinToInterrupt (interruptPin), пусто, ПАДЕНИЕ); LowPower.powerDown (SLEEP_8S, ADC_OFF, BOD_OFF); LowPower.powerDown (SLEEP_8S, ADC_OFF, BOD_OFF); LowPower.powerDown (SLEEP_8S, ADC_OFF, BOD_OFF); LowPower.powerDown (SLEEP_8S, ADC_OFF, BOD_OFF); LowPower.powerDown (SLEEP_8S, ADC_OFF, BOD_OFF); LowPower.powerDown (SLEEP_8S, ADC_OFF, BOD_OFF); detachInterrupt (digitalPinToInterrupt (interruptPin)); sleep_time =миллис (); }} void display_digit (int digit) {for (int i =0; i <8; i ++) {digitalWrite (сегмент [i], число [цифра] [i]); }} void display_number (int число) {int i =0; while (число> 0) {digit_value [2-i] =число% 10; число =число / 10; я ++; } digitalWrite (цифра [1], ВЫСОКИЙ); digitalWrite (цифра [2], LOW); digitalWrite (цифра [3], LOW); display_digit (цифровое_значение [0]); задержка (5); digitalWrite (цифра [1], LOW); digitalWrite (цифра [2], ВЫСОКИЙ); digitalWrite (цифра [3], LOW); display_digit (цифровое_значение [1]); задержка (5); digitalWrite (цифра [1], LOW); digitalWrite (цифра [2], LOW); digitalWrite (цифра [3], ВЫСОКИЙ); display_digit (цифровое_значение [2]); задержка (5); digitalWrite (цифра [3], LOW); digit_value [0] =0; digit_value [1] =0; digit_value [2] =0; } void display_first_2 (int number) {digitalWrite (цифра [2], LOW); digitalWrite (цифра [3], LOW); int я =0; while (число> 0) {digit_value [1-i] =число% 10; число =число / 10; я ++; } digitalWrite (цифра [0], ВЫСОКИЙ); digitalWrite (цифра [1], LOW); display_digit (цифровое_значение [0]); задержка (3); digitalWrite (цифра [0], LOW); digitalWrite (цифра [1], ВЫСОКИЙ); display_digit (цифровое_значение [1]); задержка (3); } void display_last_2 (int number) {digitalWrite (цифра [0], LOW); digitalWrite (цифра [1], LOW); int я =0; в то время как (число> 0) {digit_value1 [1-i] =число% 10; число =число / 10; я ++; } digitalWrite (цифра [2], ВЫСОКИЙ); digitalWrite (цифра [3], LOW); display_digit (digit_value1 [0]); задержка (3); digitalWrite (цифра [2], LOW); digitalWrite (цифра [3], ВЫСОКИЙ); display_digit (digit_value1 [1]); задержка (3); } void display_d () {digitalWrite (цифра [0], ВЫСОКИЙ); для (int я =0; я <8; я ++) {digitalWrite (сегмент [я], д [я]); } задержка (5); digitalWrite (цифра [0], LOW); } void display_a () {digitalWrite (цифра [0], ВЫСОКИЙ); для (int я =0; я <8; я ++) {digitalWrite (сегмент [я], а [я]); } задержка (5); digitalWrite (цифра [0], LOW); } void display_r () {digitalWrite (цифра [0], ВЫСОКИЙ); для (int я =0; я <8; я ++) {digitalWrite (сегмент [я], г [я]); } задержка (5); digitalWrite (цифра [0], LOW); } void display_t () {digitalWrite (цифра [0], ВЫСОКИЙ); для (int я =0; я <8; я ++) {digitalWrite (сегмент [я], т [я]); } задержка (5); digitalWrite (цифра [0], LOW); } void display_off () {digitalWrite (цифра [0], LOW); digitalWrite (цифра [1], LOW); digitalWrite (цифра [2], LOW); digitalWrite (цифра [3], LOW); для (int я =0; я <8; я ++) {digitalWrite (сегмент [я], LOW); } задержка (5); } void read_time () {tmElements_t tm; если (RTC.read (tm)) {секунды =tm.Second; минут =tm.Minute; часы =tm.Hour; }} int distance_in_cm () {длительность, см; // Датчик срабатывает ВЫСОКИМ импульсом длительностью 10 или более микросекунд. // Заранее подайте короткий НИЗКИЙ импульс, чтобы гарантировать чистый ВЫСОКИЙ импульс:digitalWrite (trigPin, LOW); delayMicroseconds (2); digitalWrite (trigPin, HIGH); delayMicroseconds (10); digitalWrite (trigPin, LOW); // Считываем сигнал с датчика:ВЫСОКИЙ импульс, // длительность которого равна времени (в микросекундах) от отправки // эхо-запроса до получения его эха от объекта. duration =pulseIn (echoPin, HIGH); // конвертируем время в расстояние cm =microsecondsToCentimeters (duration); возврат см; } long microsecondsToCentimeters (длинные микросекунды) {// Скорость звука составляет 340 м / с или 29 микросекунд на сантиметр. // Пинг проходит туда и обратно, поэтому, чтобы найти расстояние до объекта, мы берем половину пройденного расстояния. вернуть микросекунды / 29/2; } void alert () {тон (пьезопин, 2000, 50); тон (пьезоПин, 2000, 200); // задержка (10); } void blank () {// тон (пьезопин, 2000, 100); // state ++;} // Эта функция будет вызываться, когда кнопка button1 была нажата 1 раз (и после этого не было 2. нажатий кнопки) .void loaded () {//Serial.println("Button 1 click. "); button_press_count ++; тревога(); если (button_press_count ==5) {button_press_count =1; }} // щелчок // Эта функция будет вызвана, когда кнопка button1 была нажата 2 раза за короткий промежуток времени .void doubleclick () {Serial.println ("Button 1 doubleclick.");} // doubleclick // Эта функция будет вызывается один раз, когда кнопка button1 нажата в течение длительного времени .void longPressStart () {Serial.println ("Button 1 longPress start");} // longPressStart // Эта функция будет вызываться часто, пока кнопка button1 нажата в течение долгое время.void longPress () {Serial.println ("Button 1 longPress ..."); water_intake_ounch [water_intake_times - 1] =0; // игнорировать последнее значение} // longPressvoid вычисление () {float water_level =0; // сохранять уровень на каждом шаге int read_value =0; // считываем показания датчика в см for (int i =0; i <5; i ++) {// берем пять показаний read_value =distance_in_cm (); if (read_value> 16 || read_value <3) {// нестабильное чтение return; // возвращаемся к вызывающей функции, потому что чтение нестабильно} else if (read_value <=16 &&read_value> =3) {// допустимое значение water_level =water_level + read_value; } задержка (10); } average_water_level =17 - уровень воды / 5; // находим среднее значение по пяти показаниям, 17 =высота ботолы water_amount_in_ounce =int (average_water_level * 1.87); // уровень воды 16 см =30 ounch if (water_intake_times ==0) {previous_water_amount =water_amount_in_ounce; water_intake_times =1; } if ((water_amount_in_ounce  previous_water_amount) {// доливается вода // доливается вода здесь previous_water_amount =water_amount_in_ounce; } else if (water_amount_in_ounce ==previous_water_amount) {// вода не расходуется или повторно заполняется idle_time + =1; } if (hours ==23 &&minutes ==59) {// день закончился, и все значения начинаются с нуля для нового дня for (int i =0; i <15; i ++) {water_intake_ounch [i] =0; } water_intake_times =0; input_day ++; если (потребление_день ==8) {потребление_день =1; }}} int total_water_intake_in_day () {// вычисляем общее потребление воды за день total_water_intake_today =0; для (int i =0; i  

Схема


Производственный процесс

  1. Дождеватель лужайки
  2. Посудомоечная машина
  3. Водяной пистолет
  4. Туалет
  5. Пожарный гидрант
  6. Изолированная бутылка
  7. Вода
  8. Шампунь
  9. Гипсокартон
  10. MOSMusic