Описание
В этом проекте мы соберём умную теплицу, управляемую через интернет. Сделаем мы это при помощи нашего нового Ethernet Shield'а на чипе W5500 и сервиса iocontrol.ru. Нашей теплицей можно будет управлять и следить за её состоянием со смартфона, ноутбука, настольного компьютера или чего угодно, что имеет подключение к сети Интернет и современный браузер.
Видео
Нам понадобится
- 1x Ethernet Shield W5500
- 1x Piranha ULTRA
- 1x Trema Shield
- 1x Проставки для Shield'а
- 1x i2C Hub (Trema-модуль)
- 1x Датчик температуры и влажности, I2C-flash
- 1x Датчик освещенности, люксметр, I2C-flash
- 2x Силовой ключ (Trema-модуль V2.0)
- 1x Подобранный под нагрузку и напряжение источник питания. В нашем случае это Источник питания на 12В. 2А.
- 1x Провод RJ45-RJ45
- 1x Маршрутизатор со свободным разъёмом LAN и подключением к сети Интернет.
- Учётная запись на сайте iocontrol.ru
Создание и настройка панели на iocontrol.ru
- Создаём или входим в учётную запись на сайте iocontrol
- Нажимаем "Создать панель". Придумываем название панели, например "mySmartGreenhouse" (название панели должно быть уникальным на сайте. Если панель с таким именем уже есть, сайт уведомит об этом). Нажимаем Создать.
- Создаём следующие переменные с указанными типами
- fan, целочисленная
- fanThreshold, целочисленная
- humSensor, целочисленная
- lightThreshold, целочисленная
- Lights, целочисленная
- LightsPWM, целочисленная
- Luminosity, целочисленная
- Auto, целочисленная
- Temp, вещественная с плавающей точкой
- Теперь необходимо настроить вид карточек переменных. Для этого заходим в настройки каждой карточки, нажав на шестерёнку в правом верхнем углу карточки, затем выбираем соответствующие пункты из списков настроек (таблица ниже) и нажимаем на кнопку Сохранить. Подробнее про настройку карточек переменных можно узнать по этой ссылке
Схема настроек карточек переменных в панели на сайте
| Название | Вид карточки | Минимум | Максимум | Шаг | Подпись |
|---|---|---|---|---|---|
| fan | Кнопка | - | - | - | - |
| fanThreshold | Ползунок | 40 | 99 | 1 | % |
| humSensor | Вывод значения | - | - | - | % |
| lightThreshold | Ползунок | 0 | 300 | 1 | LUX |
| Lights | Кнопка | - | - | - | - |
| LightsPWM | Ползунок | 0 | 255 | 1 | - |
| Luminosity | Вывод значения | - | - | - | LUX |
| Auto | Кнопка | - | - | - | - |
| Temp | Вывод значения | - | - | - | °C |
Подключение
Устанавливаем модуль Ethernet Shield W5500 на Piranha ULTRA

Устанавливаем сверху Trema Shield через проставки

Подключаем все модули к Trema Shield
По умолчанию все модули FLASH-I2C имеют установленный адрес 0х09.
— Перед подключением 1 модуля к шине I2C настоятельно рекомендуется изменить адрес модуля.
— При подключении 2 и более FLASH-I2C модулей к шине необходимо в обязательном порядке предварительно изменить адрес каждого модуля, после чего уже подключать их к шине.
Более подробно о том, как это сделать, а так же о многом другом, что касается работы FLASH-I2C модулей, вы можете прочесть в этой статье.

Скетч проекта
Для работы данного скетча необходимо заменить значение переменной myPanelName на название Вашей панели, которую мы создали раньше. Например: const char* myPanelName = "mySmartGreenhouse".
// Подключаем библиотеку для работы с сервисом ioContol
#include <iocontrol.h>
// Подключаем стандартную библиотеки для работы с Ethernet Shield'ом по шине SPI
#include <SPI.h>
#include <Ethernet.h>
// Подключаем библиотеку для работы с аппаратной шиной I2C, до подключения библиотек iarduino_I2C_DSL и iarduino_I2C_SHT.
#include <Wire.h>
// Подключаем библиотеки датчиков влажности и освещённости
#include <iarduino_I2C_DSL.h>
#include <iarduino_I2C_SHT.h>
// Определяем выводы силовых ключей вентилятора и светодиодной ленты
#define FAN_PIN 2
#define LED_PIN 3
// Определяем постоянные On и Off
#define On true
#define Off false
// Инстанцируем (создаём) объекты библиотек датчиков
iarduino_I2C_DSL lumSensor;
iarduino_I2C_SHT humSensor;
// Название панели на сайте iocontrol.ru
const char* myPanelName = "название_Вашей_панели_на_сайте_iocontrol.ru";
// Название переменных на сайте
const char* panelFan = "fan";
const char* panelFanThreshold = "fanThreshold";
const char* panelHumSensor = "humSensor";
const char* panelLightThreshold = "lightThreshold";
const char* panelLights = "Lights";
const char* panelLightsPWM = "lightsPWM";
const char* panelLuminosity = "Luminosity";
const char* panelAuto = "Auto";
const char* panelTemperature = "Temp";
// Создаём объект клиента класса EthernetClient
EthernetClient client;
// Создаём объект iocontrol, передавая в конструктор название панели и клиента
iocontrol mypanel(myPanelName, client);
// Задаём статический IP-адрес на тот случай,
// если динамическое присвоение адреса даст сбой
IPAddress ip(192, 168, 1, 177);
IPAddress myDns(192, 168, 1, 1);
//
// MAC адреса Ethernet шилда. Должен быть уникальным в сети
byte mac[] = {
0xFE, 0xED, 0xDE, 0xAD, 0xFA, 0xCC
};
// Переменные интервала и гистерезиса на вентилятора
unsigned long currentMillis = 0; // текущие millis
unsigned long interval = 60000; // интервал в мс
bool fanHyst = false; // флаг гистерезиса вентилятора
// Переменные для чтения с сайта ioControl
bool Auto = false; // флаг автоматической работы
// Переменные для записи на сайт ioControl
int hum; // влажность
uint16_t lum; // освещённость
float tem; // температура
void setup()
{
// Инициируем работу с последовательным портом на скорости 9600 бод
Serial.begin(9600);
// Выводим в монитор последовательного порта
// сообщение о начале инициализации Shield'а
Serial.println("Initialize Ethernet with DHCP:");
// Если соединение с динамической адресацией не было установлено, то
if (Ethernet.begin(mac) == 0) {
// Выводим сообщение об этом в монитор последовательного порта и
Serial.println("Failed to configure Ethernet using DHCP");
// проверяем наличие самого Shield'а
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
// Если Shield не найден, то выводим соответствующее
// сообщение в монитор порта
Serial.println("Ethernet shield was not found.");
// Останавливаем скетч
while (true) {
delay(1);
}
}
// Проверяем наличие соединения
if (Ethernet.linkStatus() == LinkOFF) {
// Если соединение не установлено, то выводим
// соответствующее сообщение в монитор порта
Serial.println("Ethernet cable is not connected.");
}
// Пробуем установить соединение, используя статический IP-адрес
Ethernet.begin(mac, ip, myDns);
// Выводи IP-адрес в последовательный порт
Serial.print("My IP address: ");
Serial.println(Ethernet.localIP());
}
// Если соединение с динамической адресацией было установлено, то
else {
// Выводи IP-адрес в последовательный порт
Serial.print(" DHCP assigned IP ");
Serial.println(Ethernet.localIP());
}
delay(1000);
// Инициируем датчик освещённости
lumSensor.begin();
// Инициируем датчик влажности и температуры
humSensor.begin();
// Вызываем функцию первого запроса к сервису ioControl
mypanel.begin();
}
void loop()
{
// Записываем переменные из объекта mypanel в локальные переменные
bool fan = mypanel.readBool(panelFan);
int fanThreshold = mypanel.readInt(panelFanThreshold);
int lightThreshold = mypanel.readInt(panelLightThreshold);
bool lights = mypanel.readBool(panelLights);
int lightsPWM = mypanel.readInt(panelLightsPWM);
// Записываем флаг автоматической работы в глобальную переменную
Auto = mypanel.readBool(panelAuto);
// Если влажность превысила установленный порог
if (hum > fanThreshold && Auto) {
// устанавливаем флаг вентилятора
fanHyst = true;
// записываем текущие millis
currentMillis = millis();
// включаем вентилятор
fanOn();
}
// Если не автоматический режим и флаг вентилятора установлен
else if (!Auto && fan) {
// включаем вентилятор
fanOn();
}
// Иначе, если флаг гистерезиса вентилятора не установлен
else if (!fanHyst) {
// Выключаем вентилятор
fanOff();
}
// Если флаг гистерезиса вентилятора установлен
// и текущие истёк интервал
if (fanHyst && (millis() - currentMillis > interval)) {
// сбрасываем флаг гистерезиса вентилятора
fanHyst = false;
}
// Если освещённость меньше установленного порога
if (lum < lightThreshold && Auto) {
// Включаем свет
lightsIn(lum);
}
// Если не автоматический режим и флаг света установлен
else if (!Auto && lights) {
// Включаем свет
lightsIn(mypanel.readInt(panelLightsPWM));
}
// Иначе
else {
// выключаем свет
lightsOut();
}
// Записываем показания датчика влажности в переменную
hum = int(humSensor.getHum());
// Записываем показания датчика освещённости в переменную
lum = lumSensor.getLux();
// Записываем показания датчика температуры в переменную
tem = humSensor.getTem();
// Записываем показания всех датчиков в объект mypanel
mypanel.write(panelHumSensor, hum);
mypanel.write(panelLuminosity, lum);
mypanel.write(panelTemperature, tem);
// Если показания успешно записаны на сайт ioControl
if (mypanel.writeUpdate() == OK) {
// выводим показания в последовательный порт
Serial.println("Updated");
Serial.println("hum: ");
Serial.println(hum);
Serial.println("lum: ");
Serial.println(lum);
}
// Читаем все переменные панели с сайта в объект mypanel
mypanel.readUpdate();
}
// Функция включения вентилятора
void fanOn()
{
// Устанавливаем вывод к которому подключён вентилятор в режим "выход"
pinMode(FAN_PIN, OUTPUT);
// Устанавливаем уровень логической "1" на выводе вентилятора
digitalWrite(FAN_PIN, HIGH);
// Если установлен автоматический режим работы, обновляем переключатель
// вентилятора на сайте
if (Auto)
mypanel.write(panelFan, On);
}
// Функция выключения вентилятора
void fanOff()
{
// Устанавливаем вывод к которому подключён вентилятор в режим "вход"
pinMode(FAN_PIN, INPUT);
// Если установлен автоматический режим работы, обновляем переключатель
// вентилятора на сайте
if (Auto)
mypanel.write(panelFan, Off);
}
// Функция включения светодиодной ленты
void lightsIn(int l)
{
// Создаём переменную для расчёта ШИМ
uint8_t pwm = 0;
// Если установлен автоматический режим работы
if (Auto)
// устанавливаем ШИМ обратно пропорционально освещённости
pwm = uint8_t(map(l, 0, 300, 255, 0));
// Иначе
else
// устанавливаем ШИМ, переданный функции
pwm = uint8_t(l);
// Устанавливаем вывод к которому подключена светодиодная лента
// в режим "выход"
pinMode(LED_PIN, OUTPUT);
// Устанавливаем ШИМ на выводе
analogWrite(LED_PIN, pwm);
// Если установлен автоматический режим работы, обновляем переключатель
// света на сайте
if (Auto)
mypanel.write(panelLights, On);
}
// Функция выключения светодиодной ленты
void lightsOut()
{
// Устанавливаем вывод к которому подключён вентилятор в режим "вход"
pinMode(LED_PIN, INPUT);
// Если установлен автоматический режим работы, обновляем переключатель
// света на сайте
if (Auto)
mypanel.write(panelLights, Off);
}

Обсуждение