Как я сделал полнофункциональную метеостанцию ​​на Arduino

Опубликовано: 2022-03-11

ОБНОВЛЕНИЕ: работа над нашей метеостанцией Arduino продолжилась после публикации этой статьи, кульминацией которой стал выпуск Open Weather Station (OWS). Ознакомьтесь с дополнительными обновлениями, ресурсами, а также кодом и новыми руководствами.

О чем это все?

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

Так в чем проблема?

О, я забыл одно существенное требование: ветер. И здесь у нас есть проблема: вы никогда не знаете, будет ли ветер или нет, если вы не живете прямо рядом с вашим любимым местом для кайтсерфинга.

Я живу в Кордове, Аргентина, примерно в 130 километрах (~80 миль) от озера, где я занимаюсь кайтсерфингом. Это примерно два часа езды, с которыми я могу справиться. Но я не могу смириться с тем, что прогнозы погоды неточны. А там, где я живу, хороший ветер длится всего пару часов. Последнее, что вы хотите сделать, это расчистить свое расписание на понедельник, чтобы заняться кайтсерфингом и проклинать богов на безветренном озере после двух часов езды.

Мне нужно было знать ветровые условия в моем любимом месте для кайтсерфинга в режиме реального времени. Поэтому я решил построить свою собственную метеостанцию.

Измерение погоды в режиме реального времени — во враждебной среде

Цель состояла в том, чтобы доставлять данные о погоде в режиме реального времени в браузер дома:

Общий процесс для метеостанции arduino

Прежде чем я углублюсь в детали, давайте рассмотрим ключевые вопросы и предостережения, связанные с таким проектом:

  • Как я могу создать метеостанцию, которая не будет ни ценной, ни привлекательной для вора?
  • Как свести затраты на оборудование и время разработки к минимуму?
  • Как я могу измерять и получать данные о погоде в режиме реального времени и отображать их удобным способом?
    • Необходимые измерения: ветер и порывы ветра, направление ветра, дождь, атмосферное давление, температура, влажность
    • Подключить станцию ​​к Интернету
    • Храните и извлекайте местные данные о погоде
    • Связь между метеостанцией и сервером
  • Как я могу сократить техническое обслуживание до (почти) нуля?
    • Управление зависанием программного обеспечения
    • Управление потерей подключения
    • Управление потерей энергоснабжения

Поздоровайся с моим маленьким другом!

файл

Вы можете подумать, что перчатка нужна для того, чтобы станция казалась более дружелюбной; но на самом деле он используется для проверки барометрического датчика (давление в перчатке увеличивается внутри надутой перчатки). Справа вы можете увидеть станцию ​​в ее конечном месте, расположенную на вершине соседней башни.

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

файл

Это потрясающе! Итак, как вы это сделали?

Что ж, я рассмотрю каждый пункт по очереди:

«Как я могу создать метеостанцию, которая не будет ни ценной, ни привлекательной для вора?»

Это был решающий фактор, который во многом определял остальную часть процесса проектирования. Для большинства готовых станций стоимостью менее 2000 долларов требовалось USB-подключение к компьютеру. Если бы вор узнал, что рядом со станцией есть компьютер, это был бы конец, так как стоимость замены компьютера и станции превысит мой личный бюджет. Поэтому я решил протестировать несколько аппаратных платформ, чтобы реализовать станцию ​​с нуля, с меньшими затратами.

«Как свести затраты на оборудование и время разработки к минимуму?»

Я один оплачивал расходы на этот побочный проект и выполнял всю работу в свободное время, поэтому, конечно, это было большой проблемой. Я начал с популярного PIC32 и некоторых предварительно собранных микрочиповых модулей Ethernet, но затраты оказались не такими низкими, как я ожидал, и слишком много накладных расходов было связано с аппаратной сборкой и расширением. Затем я начал изучать Arduino: аппаратное и программное обеспечение с открытым исходным кодом для прототипирования электроники с использованием языка C. Это было именно то, что я хотел, и я мог приобрести модули на DealeXtreme. Я смог начать играть, потратив всего 15 долларов и два дня своего времени.

Конечно, у Arduino также есть свои ограничения: всего 2 КБ ОЗУ и 32 КБ для моего скомпилированного программного обеспечения, что не оставляет много места для причудливых строк или бесполезных переменных 1 .

«Как я могу измерять и получать данные о погоде в режиме реального времени и отображать их удобным способом?»

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

Измерение скорости ветра и дождя было немного грязным. Датчики работали, открывая и закрывая переключатель (геркон). Таким образом, мне нужно было реализовать аппаратные прерывания, чтобы поймать датчик, как только он сработает на входе. То есть мне нужно было вызвать какой-то метод:

 attachInterrupt(RAINGAUGE_PIN, countRainCycles, FALLING);

Это прерывание нарушило бы нормальное выполнение кода и вызвало бы функцию countAnemometerCycles или countRainCycles, как только коммутатор испытывает спадающий фронт, вызванный замыканием или размыканием цепи. Несколько переменных увеличиваются при каждом срабатывании переключателя. (Позже вы взвешиваете эти переменные для учета преобразования единиц измерения.)

 void countRainCycles() { rainCyclesCounter++; // This is easy! And it actually works. }

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

Об эффекте подпрыгивания

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

Цепь устранения дребезга

Я реализовал как аппаратную схему устранения дребезга, так и аналогичную версию в программном обеспечении. Но как именно вы реализуете программное устранение дребезга? Легкий! После того, как произойдет первый ожидаемый триггер, «подождите» достаточное время, пока рикошет не уляжется, прежде чем вы начнете прослушивать новые прерывания. Это можно сделать в паре строк C:

 void countRainCycles() { if (nextTimeRainIterrupt == 0 || nextTimeRainIterrupt < millis()) { rainCyclesCounter++; // The interrupts counter nextTimeRainIterrupt = millis() + 100; // Wait 100msecs before next trigger } }

Функция millis() возвращает текущее время выполнения в миллисекундах с момента включения Arduino. Также стоит отметить, что эти переменные должны быть определены как volatile, чтобы указать компилятору не оптимизировать выполнение и, следовательно, избежать неточных значений во время аппаратных прерываний.

Так или иначе, мне нужна была станция для хранения накопленных данных и периодической отправки этих измерений в базу данных MySQL. Поэтому я добавил модуль Ethernet со слотом SD для регистрации значений и извлечения их всякий раз, когда пользователь (сервер) подключается к станции. Во время тестирования дома с ADSL-подключением это работало удивительно хорошо, но я чуть не потерял волосы, когда тестировал это «в полевых условиях» с 3G-Интернетом (используя 3G-модем), так как станция случайным образом перезагружалась, когда я пытался восстановить соединение. измерения! После серьезного тестирования я, наконец, обнаружил, что примеры, представленные по всему Интернету и описывающие «обслуживание» данных подключенному клиенту, не учитывали, что соединение может быть настолько плохим, что соединение с клиентом может быть потеряно в середине передачи пакета, вызывая выходной буфер переполнится. Но почему разрыв соединения может вызвать переполнение буфера? Ну, скажем, начинается сеанс передачи и станция начинает заполнять выходной буфер данными. В идеале клиент использует этот буфер быстрее, чем он заполняется. Однако при подключении через 3G-модем такого не было! Связь с клиентом была слишком плохой, поэтому буфер заполнялся быстрее, чем расходовался, что приводило как к переполнению буфера, так и к внезапной перезагрузке станции.

Чтобы решить эту проблему, мне нужно было добавить в библиотеку Ethernet, поставляемую с Arduino, функцию, которая выглядела примерно так:

 int EthernetClient::free() { if (_sock != MAX_SOCK_NUM) return W5100.getTXFreeSize(_sock); return 0; }

Затем я смог проверить, есть ли у клиента место в буфере, прежде чем пытаться заполнить его дополнительными данными:

 while (file.available() > 0) { if (client.free() > 0) { // This was key to solving the issue c = file.read(); client.print((char)c); } else { // No free buffer? Ok, I'll wait a couple of millis... delay(50); } } file.close();

Кстати, если вы заинтересованы в программировании Arduino, вот отличное руководство.

Еще одной интересной задачей была реализация журнала LIFO. Зачем это было нужно? Что ж, обычно, когда я сохраняю измерения в данный файл, подход прост: открыть файл, добавить новые образцы в конец и закрыть файл. Но скажем, я хочу получить последние 1000 измерений, отсортированных в хронологическом порядке. Эти измерения находятся в конце файла; поэтому я должен открыть файл, переместить курсор в конец, вывести последние измерения, затем вернуть курсор файла к предыдущему измерению и вывести его, ища разделитель выборки, чтобы определить, где начать и где остановиться. У Arduino нет ни оперативной памяти, ни мощности процессора для быстрого выполнения этого процесса, поэтому мне нужен был другой подход. Вместо этого я решил вывести файл в обратном порядке на сервер, а затем вернуть строковые литералы обратно на сервер:

 unsigned long filePosition = file.size(); file.seek(filePosition); while (filePosition >= 0) { if (client.free() > 0){ file.seek(filePosition); c = file.peek(); if (c != -1) { client.print((char)c); } if (filePosition <= 0) { break; } filePosition--; } }

Имея любой опыт PHP-разработчика, легко получить последние образцы с символами в правильном порядке:

 // $output has the reversed string measures, each sample is delimited by ; $rows = split(";", trim($output)); array_walk_recursive($rows, 'reverseString'); if (strlen($rows[0]) == 0) { array_shift($rows); // Remove the first line if empty } function reverseString(&$row, $key) { $row = trim(strrev($row)); } // $rows is now the array of the latest samples :)

Затем на стороне сервера я настраиваю процесс cron для получения последних измерений каждые две минуты и вставки данных в механизм MySQL. Для отображения данных я создал www.kitesurfcordoba.com.ar и использовал jQuery для автоматического обновления графиков (которые сами генерируются с помощью pChart v2.0, отличной библиотеки с открытым исходным кодом).

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

«Как я могу сократить техническое обслуживание до (почти) нуля?»

Это было серьезной проблемой, потому что мне, конечно же, было нелегко добраться до станции — если бы я был готов ехать два часа только для того, чтобы устранить незначительную неисправность, то мне не пришлось бы заставлять ее с самого начала (я не упоминал об этом раньше, но после всего, через что мы прошли, станция на самом деле «она», и ее зовут Дороти).

Итак, о каких ошибках здесь идет речь? Ну, например: может зависнуть софт, может пропасть сеть, может выйти из строя подача энергии (а бывает) и т.д.

По сути, станция должна выполнять как можно больше самовосстановления. Вот почему я использовал как мягкие, так и жесткие сторожевые таймеры. Для тех, кто не знаком, сторожевой таймер — это часть программного или аппаратного обеспечения, которая проверяет, правильно ли работает система, и, если нет, пытается вернуть ее к жизни. Arduino имеет встроенный сторожевой таймер, который вы можете использовать. Я установил его на ожидание в течение 8 секунд: если вызов занимает больше времени, чем это ограничение, программный сторожевой таймер перезагрузит плату.

 wdt_enable(WDTO_8S); // "wdt" stands for "watchdog timer"

Я люблю эту функцию. Однако бывают случаи, когда плата сбрасывается, а модуль Ethernet — нет. Почему? Что ж, это относительно доступная макетная плата, а не очень дорогое отказоустойчивое устройство (с ним уж точно не стоит строить кардиостимулятор). Чтобы преодолеть этот недостаток, мне пришлось взломать Arduino, соединив вход аппаратного сброса с цифровым выходом на самой плате. Чтобы избежать цикла сброса, необходимо добавить пару строк кода:

 void setup() { digitalWrite(RESET_ARDUINO_PIN, HIGH); // Set it to HIGH immediately on boot pinMode(RESET_ARDUINO_PIN, OUTPUT); // We declare it an output ONLY AFTER it's HIGH digitalWrite(RESET_ARDUINO_PIN, HIGH); // Default to HIGH, set to LOW to HARD RESET ...

После этого я смог выполнить аппаратный сброс Arduino и всех модулей поверх него (включая модуль Ethernet), просто вызвав digitalWrite(RESET_ARDUINO_PIN, LOW) , что вернуло Дороти к жизни через пару секунд.

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

Круговая диаграмма

И в конце

Станция работает с декабря 2012 года. На сегодняшний день она не вышла из строя (а если и вышла, то станция восстановилась достаточно быстро, чтобы мы с кайтсерферами этого не заметили). Около 500 кайтсерферов регулярно проверяют метеостанцию, прежде чем отправиться на место. Таким образом, помимо вознаграждения за решение некоторых сложных технических задач, у меня также была возможность предоставить группе людей более приятный опыт кайтсерфинга.

1 Изначально я использовал Arduino Uno. Позже я перешел на Arduino Mega из-за необходимости увеличения оперативной и флэш-памяти.

Связанный: Работа с аудиосэмплированием ESP32