GPRS-логгер для теплицы
- Платформы: Iskra Neo
- Языки программирования: Arduino (C++)
- Тэги: GPRS, SIM900, теплица, мониторинг погоды, конструктор ПВХ.
Что это?
Каждый садовод и дачник знает, чтобы собрать хороший урожай, необходимо уйму времени провести на огороде. Но вряд ли кому-нибудь придёт в голову находиться круглые сутки возле любимой грядки. А ведь так хочется, находясь дома или на работе, быть уверенным, что твоим помидоркам ничего не угрожает.
Одним из инструментов для решения этой задачи является мобильный Интернет. В этой статье мы расскажем как собрать устройство, способное осуществлять постоянный мониторинг окружающей среды, считывая данные с различных датчиков, и передавать их на популярный сервис «народный мониторинг», используя GPRS.
Что нам понадобится?
- Крепёжные элементы: винты, саморезы, гайки
- SIM-карта
- Конструктор ПВХ
Как собрать?
- Возьмите платформу Iskra Neo и нижнюю панель кубa (7x7), соедините её с помощью винтов и гаек, так чтобы гайки располагались между панелью и платформой.
- Вставьте сим-карту в GPRS Shield и установите его сверху на платформу Iskra Neo.
- Боковые панели куба (7x7) соедините с нижней панелью (7x7). Установите Troyka Shield сверху на GPRS Shield.
- Возьмите панель куба (7x5) и, спользуя винты или саморезы, закрепите на ней датчик газа MQ2 и датчик температуры и влажности DHT11.
- Используя 3-проводные шлейфы, подключите через Troyka Shield датчик газа MQ2 к аналоговому пину
A2
, а цифровой датчик DHT11 к цифровому пину11
. Далее панель куба (7x5) с установленными датчиками закрепите между боковыми панелями куба, так чтобы датчики были направлены внутрь. - Возьмите переднюю панель куба (6x7) и соедините её с нижней панелью и панелью с датчиками, заранее откусив бокорезами секции, мешающие выводу антенны. Прикрутите антенну в SMA-разъём.
- Возьмите датчик освещённости, прикрутите его к панели для крепления Troyka-модулей, и с помощью четырёх панелей конструктора (3x2) соорудите «башенку».
- В продолжение установите «башенку» с датчиком на верхнюю панель куба (7x7), и установите получившуюся конструкцию на левую, правую и заднюю панели. Подключите датчик освещённости через стандартный 3-проводные шлейф через Troyka Shield к аналоговому пину
A4
. - Заднюю панель куба (7x3) закрепите между левой и правой панелями внизу, напротив разъёмов USB и внешнего питания платформы Iskra Neo, заранее отделив бокорезами секции, мешающие ей устойчиво зафиксироваться.
- Подключите датчик влажности почвы через 3-проводной шлейф через Troyka Shield к аналоговому пину
A0
. В результате должна получиться такая схема: - Возьмите заднюю панель куба (7x2) и установите её между левой и правой панелями в верхней части. В заключение возьмите панель крестиков (1x6) и установите между задними панелями (7x3) и (7x2).
Алгоритм
- Сразу после подачи питания проверяем есть ли связь с GPRS устройством.
- Если связи нет, повторяем запрос снова и ждём подтверждения связи.
- Пытаемся установить GPRS-соединение с заданными настройками.
- Если GPRS-соединения нет, повторяем попытку снова и ждём подтверждения.
- Пытаемся подключиться к серверу.
- Если подключение нет, повторяем запрос снова и ждём подтверждения сервера.
- Считываем значения с датчиков.
- Формируем и оправляем TCP-запрос в специальном формате для «народного мониторинга»
- Повторяем весь выше описанный цикл каждые 5 минут.
Исходный код
- GPRS_Logger.ino
// библиотека для работы с GPRS устройством #include <GPRS_Shield_Arduino.h> // библиотека для эмуляции Serial-порта // она нужна для работы библиотеки GPRS_Shield_Arduino #include <SoftwareSerial.h> // библиотека для работы с датчиком DHT11 #include <dht11.h> // даём разумное имя для пина к которому подключен датчик DHT11 #define DHT11_PIN 11 // даём разумное имя для пина к которому подключен датчик влажности почвы #define MOISTURE_PIN A0 // даём разумное имя для пина к которому подключен датчик уровня CO2 #define MQ2_PIN A2 // даём разумное имя для пина к которому подключен датчик уровня освещённости #define LIGHT_PIN A4 // IMEI GPRS Shield, он указан на лицевой стороне шилда // по IMEI устройство будет идентифицироваться в проекте // поэтому он должен быть уникальным #define IMEI "868204005187692" // часть запроса в специальном формате для народного мониторинга, содержащая: // IMEI устройства, название фирмы и GPS-координаты #define CLIENT "#"IMEI"#Амперка#55.7467#37.6627#2.0\r\n" // интервал между отправками данных в миллисекундах (5 минут) #define INTERVAL 300000 // размер массива, содержащий TCP-запрос #define LEN 370 // буфер для отправки данных на народный мониторинг // согласно установленной сервисом форме char tcpBuffer[LEN]; // переменная для хранения времени работы программы // с последнего запуска отправки данных на сервер unsigned long previousMillis = 0; // переменная температуры воздуха int temp = 0; // переменная влажности воздуха int humi = 0; // переменная влажности почвы int moisture = 0; // переменная уровня CO2 int mq2 = 0; // переменная уровня освещённости int light = 0; // создаём объект класса dht11 dht11 DHT; // создаём объект класса GPRS и передаём в него объект Serial1 GPRS gprs(Serial1); // можно указать дополнительные параметры — пины PK и ST // по умолчанию: PK = 2, ST = 3 // GPRS gprs(Serial1, 2, 3); void setup() { // открываем последовательный порт для мониторинга действий в программе Serial.begin(9600); // открываем Serial-соединение с GPRS Shield Serial1.begin(9600); } void loop() { // включаем GPRS шилд gprs.powerOn(); // проверяем есть ли связь с GPRS устройством while (!gprs.init()) { // если связи нет, ждём 1 секунду // и выводим сообщение об ошибке // процесс повторяется в цикле // пока не появится ответ от GPRS устройства delay(1000); Serial.print("GPRS Init error\r\n"); } // вывод об удачной инициализации GPRS Shield Serial.println("GPRS init success"); delay(3000); // пытаемся установить GPRS-соединение // с заданными настройками, которые предоставляются операторами связи while (!gprs.join("internet.beeline.ru", "beeline", "beeline")) { // если GPRS-соединения нет // выводим сообщение об ошибке и ждём 1 секунду // процесс повторяется в цикле // пока не появится положительный ответ от GPRS устройства Serial.println("Gprs join network error"); delay(1000); } // выводим сообщение об удачной установке GPRS-соединения Serial.println("GPRS OK"); // получаем и выводим локальный IP адрес Serial.print("IP Address is "); Serial.println(gprs.getIPAddress()); // пытаемся подключиться к серверу // указывая тип соединения, адрес сервера и номер порта while (!gprs.connect(TCP, "narodmon.ru", 8283)) { // если сервер не отвечает или отвечает ошибкой // выводим сообщение об ошибке и ждём 1 секунду // процесс повторяется в цикле // пока не появится положительный ответ от сервера Serial.println("Connect error"); delay(1000); } // выводим сообщение об удачном подключении к серверу Serial.println("Connect success"); // вызываем функцию считывания всех показателей с датчиков readSensors(); // выводим показания датчиков в последовательный порт serialPrint(); // вызываем функцию, которая формирует и отправляет tcp-запрос // в специальном формате для «народного мониторинга» tcpRequest(); // разрываем все GPRS-соединения gprs.close(); // деактивируем интерфейс GPRS gprs.disconnect(); // выводим сообщение об удачном завершении операции Serial.println("OK"); // выключаем GPRS-шилд gprs.powerOff(); // проверяем не прошел ли нужный интервал времени while (millis() - previousMillis < INTERVAL) { // ждём 5 минут } //если прошел, то сохраняем текущее время previousMillis = millis(); } // функция записи данных с датчиков в массив // в специальном формате для «народного мониторинга» void tcpRequest() { /* помните, что при выполнении операций с массивами символов, например strcat(str1, str2); контроль нарушения их границ не выполняется, поэтому программист должен сам позаботиться о достаточном размере массива str1, позволяющем вместить как его исходное содержимое, так и содержимое массива str2 */ // добавляем к строке tcpBuffer строку CLIENT strcat(tcpBuffer, CLIENT); // функция добавления в TCP-запрос значения температуры воздуха tcpTemp(); // функция добавления в TCP-запрос значения влажности воздуха tcpHumi(); // функция добавления в TCP-запрос значения влажности почвы tcpMoisture(); // функция добавления в TCP-запрос состояния уровня CO2 tcpGas(); // функция добавления в TCP-запрос значения освещённости tcpLight(); // добавляем к строке tcpBuffer два символа «##», // которые свидетельствуют об окончании запроса strcat(tcpBuffer, "##"); // отправляем массив TCP-запроса на сервис «народного мониторинга» gprs.send(tcpBuffer); // очищаем буфер clearTcpBuffer(); } // Функция добавление в TCP-запрос данные о температуре воздуха void tcpTemp() { // переменная для символьного представления // значения температуры воздуха char s_temp[8]; // преобразуем целое число 10 системы исчисления // из переменной temp в строковое представление в массив s_temp[] itoa(temp, s_temp, 10); // добавляем к буферу символы «.00», для дробной части strcat(s_temp, ".00"); // добавляем к буферу разделительный символ «#» strcat(tcpBuffer, "#"); // добавляем к буферу уникальный серийный номера датчика // получаем его путём добавления к IMEI GPRS-шилда названия датчика strcat(tcpBuffer, IMEI); strcat(tcpBuffer, "T01"); // добавляем к буферу разделительный символ «#» strcat(tcpBuffer, "#"); // добавляем к буферу строку s_temp strcat(tcpBuffer, s_temp); // добавляем к буферу разделительный символ «#» strcat(tcpBuffer, "#"); // добавляем к буферу время актуальности показаний // если показания датчиков передаются немедленно, // то данный параметр передавать не надо strcat(tcpBuffer, " "); // добавляем к буферу разделительный символ «#» strcat(tcpBuffer, "#"); // добавляем к буферу названия датчика strcat(tcpBuffer, "Датчик температуры"); strcat(tcpBuffer, "\r\n"); } // Функция добавление в TCP-запрос данные о влажности воздуха void tcpHumi() { // переменная для символьного представления // значения влажности воздуха char s_humi[8]; // преобразуем целое число 10 системы исчисления // из переменной humi в строковое представление в массив s_humi[] itoa(humi, s_humi, 10); // добавляем к буферу символы «.00», для дробной части strcat(s_humi, ".00"); // добавляем к буферу разделительный символ «#» strcat(tcpBuffer, "#"); // добавляем к буферу уникальный серийный номера датчика // получаем его путём добавления к IMEI GPRS-шилда названия датчика strcat(tcpBuffer, IMEI); strcat(tcpBuffer, "H01"); // добавляем к буферу разделительный символ «#» strcat(tcpBuffer, "#"); // добавляем к буферу строку s_humi strcat(tcpBuffer, s_humi); // добавляем к буферу разделительный символ «#» strcat(tcpBuffer, "#"); // добавляем к буферу время актуальности показаний // если показания датчиков передаются немедленно, // то данный параметр передавать не надо strcat(tcpBuffer, " "); strcat(tcpBuffer, "#"); // добавляем к буферу названия датчика strcat(tcpBuffer, "Датчик влажности"); strcat(tcpBuffer, "\r\n"); } void tcpMoisture() { // переменная для символьного представления // значения влажности почвы char s_moisture[8]; // преобразуем целое число 10 системы исчисления // из переменной moisture в строковое представление в массив s_moisture[] itoa(moisture, s_moisture, 10); // добавляем к буферу символы «.00», для дробной части strcat(s_moisture, ".00"); // добавляем к буферу разделительный символ «#» strcat(tcpBuffer, "#"); // добавляем к буферу уникальный серийный номера датчика // получаем его путём добавления к IMEI GPRS-шилда названия датчика strcat(tcpBuffer, IMEI); strcat(tcpBuffer, "H02"); // добавляем к буферу разделительный символ «#» strcat(tcpBuffer, "#"); // добавляем к буферу строку s_moisture strcat(tcpBuffer, s_moisture); // добавляем к буферу разделительный символ «#» strcat(tcpBuffer, "#"); // добавляем к буферу время актуальности показаний // если показания датчиков передаются немедленно, // то данный параметр передавать не надо strcat(tcpBuffer, " "); // добавляем к буферу разделительный символ «#» strcat(tcpBuffer, "#"); // добавляем к буферу названия датчика strcat(tcpBuffer, "Датчик влажности почвы"); strcat(tcpBuffer, "\r\n"); } void tcpGas() { // переменная для символьного представления значения CO2 char s_mq2[8]; // преобразуем целое число 10 системы исчисления // из переменной mq2 в строковое представление в массив s_mq2[] itoa(mq2, s_mq2, 10); // добавляем к буферу символы «.00», для дробной части strcat(s_mq2, ".00"); // добавляем к буферу разделительный символ «#» strcat(tcpBuffer, "#"); // добавляем к буферу уникальный серийный номера датчика // получаем его путём добавления к IMEI GPRS-шилда названия датчика strcat(tcpBuffer, IMEI); strcat(tcpBuffer, "MQ2"); // добавляем к буферу разделительный символ «#» strcat(tcpBuffer, "#"); // добавляем к буферу строку s_gas strcat(tcpBuffer, s_mq2); // добавляем к буферу разделительный символ «#» strcat(tcpBuffer, "#"); // добавляем к буферу время актуальности показаний // если показания датчиков передаются немедленно, // то данный параметр передавать не надо strcat(tcpBuffer, " "); // добавляем к буферу разделительный символ «#» strcat(tcpBuffer, "#"); // добавляем к буферу названия датчика strcat(tcpBuffer, "Датчик CO2"); strcat(tcpBuffer, "\r\n"); } void tcpLight() { // переменная для символьного представления значения освещённости char s_light[8]; // преобразуем целое число 10 системы исчисления // из переменной light в строковое представление в массив s_light[] itoa(light, s_light, 10); // добавляем к буферу символы «.00», для дробной части strcat(s_light, ".00"); // добавляем к буферу разделительный символ «#» strcat(tcpBuffer, "#"); // добавляем к буферу уникальный серийный номера датчика // получаем его путём добавления к IMEI GPRS-шилда названия датчика strcat(tcpBuffer, IMEI); strcat(tcpBuffer, "L01"); // добавляем к буферу разделительный символ «#» strcat(tcpBuffer, "#"); // добавляем к буферу строку s_light strcat(tcpBuffer, s_light); // добавляем к буферу разделительный символ «#» strcat(tcpBuffer, "#"); // добавляем к буферу время актуальности показаний // если показания датчиков передаются немедленно, // то данный параметр передавать не надо strcat(tcpBuffer, " "); // добавляем к буферу разделительный символ «#» strcat(tcpBuffer, "#"); // добавляем к буферу названия датчика strcat(tcpBuffer, "Датчик освещения"); strcat(tcpBuffer, "\r\n"); } // функция считывания показателей с датчиков void readSensors() { // считывание данных с датчика DHT11 DHT.read(DHT11_PIN); // присваивание переменной temp значения температуры воздуха temp = DHT.temperature; // присваивание переменной humi значения влажности воздуха humi = DHT.humidity; // считывание значения с датчика влажности почвы moisture = analogRead(MOISTURE_PIN); // считывание значения с датчика уровня CO2 mq2 = analogRead(MQ2_PIN); // считывание значения с датчика уровня освещённости light = analogRead(LIGHT_PIN); // преобразовываем аналоговое 10-битное значение // датчика влажности почвы в диапазон (от 0% до 100%) moisture = map(moisture, 0, 1023, 0, 100); // преобразовываем аналоговое 10-битное значение // датчика уровня CO2 в диапазон (от 0ppm до 8000ppm) mq2 = map(mq2, 0, 1023, 0, 8000); // преобразовываем аналоговое 10-битное значение // датчика уровня освещённости в диапазон (от 0Lx до 2000Lx) light = map(light, 0, 1023, 2000, 0); } void clearTcpBuffer() { for (int t = 0; t < LEN; t++) { // очищаем буфер, // присваивая всем индексам массива значение 0 tcpBuffer[t] = 0; } } // функция вывода значения датчиков в последовательный порт void serialPrint() { Serial.print("temp = "); Serial.println(temp); Serial.print("humi = "); Serial.println(humi); Serial.print("moisture = "); Serial.println(moisture); Serial.print("CO2 = "); Serial.println(mq2); Serial.print("light = "); Serial.println(light); Serial.println(""); }
Для работы выше приведённого скетча вам понадобятся две библиотеки:
- Библиотека DHT11 позволяющая считывать данные с датчика DHT11.
Регистрация GPRS-логгера в «Народном мониторинге»
Как же нам проверить показания датчиков после того, как мы отправили их на сервер «Народного мониторинга? Помимо хранение данных с различных датчиков, «Народный мониторинг» позволяет видеть их в реальном времени через Интернет с привязкой к карте, а также строить на их основании графики и таблицы. При чем загружать на сайт можно самые разные данные: это может быть информация о климатических условиях или, например, данные о напряжении в сети, потребляемой энергии, даже фото и видео с веб-камер.
Для просмотра значений с датчиков необходимо выполнить следующее:
- Зайдите в браузере на сервис «народный мониторинг».
- Зарегистрируйтесь и пройдите авторизацию.
- Добавьте в список новое устройство:и введите IMEI вашего GPRS Shield.
После этого откроется меню со списком датчиков, где можно будет просмотреть данные за определённый промежуток времени, построить на их основании графики или же вывести значения в таблицу.
Демонстрация работы устройства
Что дальше?
Данное устройство можно использовать в самых разнообразных целях. Например если к нему подключить автономное питание, можно узнавать если ли в доме электричество, а с помощью датчиков пространства предостеречь ваш дом от проникновения недоброжелателей.