В этом уроке - создание системы домашнего орошения растений на основе микроконтроллера Arduino (Ардуино). Есть тонны похожих проектов и обучающих программ, уже размещенных в Интернете, но, возможно, данный урок - это некая иная альтернатива, которая натолкнет на дополнительные мысли и идеи.
Шаг 1: Готовим инструменты и детали
Что нам понадобится:
- 1 шт. - Arduino Uno (или чип atmega328 и программист)
- 1 шт. - резистор 10 кОм
- 1 шт. - резистор 20 кОм
- 1 шт. - ULN2803a (или MOSFETS + диоды)
- 1 шт. - дисплей TM1637
- 2 шт. - гигрометрические датчики
- 1 шт. - кратковременная кнопка
- 1 шт. - релейная плата
- 2 шт. - насосы
- 1 шт. - 2-полюсная клемма
- Сокеты (опционально, но настоятельно рекомендуется иметь возможность легко перепрограммировать чип atmega, если это необходимо)
И в зависимости от того, используете ли вы Arduino или Atmega:
- 1 шт. - 16 МГц кристалл
- 2 шт. - 22 пФ конденсатора
- 1 шт. - 10 мкФ конденсатор
- 1 шт. - 1N4001 диод
- Соединительные провода и кабели
- Трубка
- Макетная плата
- Источники питания (5 В или более и один блок питания для ваших насосов)
Вам понадобятся также основные инструменты, например:
- Паяльник
- Плоскогубцы
- Кабельный стриппер
- Цифровой мультиметр
Шаг 2: Схема подключения
Выше можно увидеть схемы как для автономной версии atmega328, так и для подключения к Arduino Uno. Поскольку устройство должно запускаться сам по себе после завершения урока, не будут нужны никакие функции arduino и просто используется чистый чип. Можно использовать чип от arduino или использовать arduino в качестве программера для другого чипа. Как можно увидеть из схема шины земли и питания (GND и 5V) есть с обеих сторон макетной платы. Все соединения GND и 5V на схеме идут на них.
Также ниже посмотрите распиновку чипа atmega в сравнении с ардуино:
Если вы собираетесь припаять все на печатной плате, обязательно используйте цифровой мультиметр, чтобы проверить все соединения и убедиться, что все силовые рельсы питаются от 5В. Если вы собираетесь использовать блок питания с напряжением более 5 В, добавьте соответствующие регуляторы напряжения (7805, например). Рекомендуется паять гнездо на плату вместо чипа напрямую, так что можно было бы легко вытащить его снова для перепрограммирования, поскольку нужно выполнять тонкую настройку.
Помимо этого, нужно иметь возможность воссоздать все соединения из схемы выше.
В уроке использован модуль ULN2803A, потому что выходные выводы atmega (и, следовательно, вероятно, arduino тоже) не обеспечивают достаточный ток для переключения реле. Реле требует около 60 мА, но на выводах atmega не должны быть превышения выше 40 мА. Кроме того вы не должны переключать индуктивные нагрузки как реле непосредственно так или иначе. Модуль защищает чип от повреждений. Модуль создает падение напряжения, поэтому, если ваше реле не может питаться с мощностью менее 5 В, используйте соответственно MOSFET и обратные диоды.
Шаг 3: Подключение реле и насосов
Плата реле состоит из 3 терминалов для каждого входа: NO, NC и COM. Уже есть привычка переключаться как на нейтраль, так и на фазу для каждого насоса, с конкретным источником питания, который был использован, было точное понимание какой провод куда идет. Это не всегда так, поскольку у вас может не быть защиты от полярности.
Отрезаем провода от источника питания и подключаем их к COM-портам. Затем подключаем разомкнутые клеммы к насосам. Когда реле включается, разомкнутое соединение закрывается и насос запускается. Чтобы иметь возможность использовать 1 блок питания для нескольких насосов, мы подключили закрытый порт к COM-порту следующего набора терминалов.
На всякий случай, для общего понимания, ниже пример того как подключить к Arduino Uno светодиод через модуль реле:
Когда насос 1 включен, терминалы 1 и 2 включаются, нейтраль и фаза соединены через клеммы «NO» и «COM», обычно закрытый терминал теперь открыт. Мы не включаем оба насоса одновременно, а включаем последовательно. Более подробное объяснение и пример того, как модули реле работают будет в следующих материалах.
Шаг 4: Код
Когда все подключено, пришло время погрузиться в код. Библиотека для 7-сегментного дисплея находится здесь.
Гигрометры будут корродировать довольно быстро, если они будут постоянно подключены к 5V, поэтому их нужно питать током только когда нам действительно нужно измерить влажность. По этой причине они не подключены к шине питания.
const int hygrometer1 = A0; //Hygrometer sensor at pin A0 const int hygrometer2 = A1; //Hygrometer sensor at pin A int Pump1_1 = 11; // Pump 1, cable 1 int Pump1_2 = 2; // Pump 1, cable 2 int Pump2_1 = 3; // Pump 2, cable 1 int Pump2_2 = 4; // Pump 2, cable 2 int Hygro1 = 9; // VCC Hygrometer 1 int Hygro2 = 10 ; // VCC Hygrometer 2 int value1; int value2; int runs1 = 0; // counts how many times the pumps have been turned on int runs2 = 0; #include "SevenSegmentTM1637.h" const byte PIN_CLK = 8; // define CLK pin (any digital pin) const byte PIN_DIO = 7; // define DIO pin (any digital pin) int inPin = 6; // input of the push button int val = 0; int push_count = 0; // counts how many times the button was pushed int buttonState = 0; // saves the state of the button, low or high SevenSegmentTM1637 display(PIN_CLK, PIN_DIO); unsigned long previousMillis = 0; // taken from the blink with delay example const long interval = 1800000; // only measure every 30 minutes void setup() { display.begin(); // init the display display.setBacklight(20); // set the brightness of the display to 20 % Serial.begin(9600); // set all the pin modes accordingly pinMode(Pump1_1, OUTPUT); pinMode(Pump1_2, OUTPUT); pinMode(Pump2_1, OUTPUT); pinMode(Pump2_2, OUTPUT); pinMode(Hygro1, OUTPUT); pinMode(Hygro2, OUTPUT); pinMode(8, OUTPUT); pinMode(inPin, INPUT); // set all the pins to their initial states digitalWrite(8, LOW); digitalWrite(Pump1_1, LOW); digitalWrite(Pump1_2, LOW); digitalWrite(Pump2_1, LOW); digitalWrite(Pump2_2, LOW); digitalWrite(Hygro1, LOW); digitalWrite(Hygro2, LOW); // display that the system is booting display.clear(); display.print("INIT"); delay(2000); display.clear(); } void loop() { // we are counting how many milli seconds have passed since the system booted, if we completed a 30 min intervall, run measure(), else run buttons() unsigned long currentMillis = millis(); if (currentMillis - previousMillis >= interval || previousMillis == 0) { // note the || previousMillis == 0, we also want to measure on bootup, it's easier to identify mistakes // save the last time we measured the moisture previousMillis = currentMillis; measure(); } buttons(); } void measure() { display.clear(); display.print("read"); digitalWrite(Hygro1, HIGH); // supply the hygrometer with voltage digitalWrite(Hygro2, HIGH); // supply the hygrometer with voltage delay(2000); value1 = analogRead(hygrometer1); // read the value (0-1023) value2 = analogRead(hygrometer2); // read the value (0-1023) delay(2000); digitalWrite(Hygro1, LOW); // turn off the hygrometer digitalWrite(Hygro2, LOW); // turn off the hygrometer display.clear(); if (value1 <= 550) // check if the plant is well watered (lower values mean well watered) { display.clear(); display.print("1 OK"); delay(2000); display.clear(); } else { digitalWrite(Pump1_1, HIGH); digitalWrite(Pump1_2, HIGH); delay(20000); // time in ms how long the pump is turned on, 20 s here digitalWrite(Pump1_1, LOW); digitalWrite(Pump1_2, LOW); runs1++; // increment the number of times pump 1 has run } if (value2 <= 450) { display.clear(); display.print("2 OK"); delay(2000); display.clear(); } else { digitalWrite(Pump2_1, HIGH); digitalWrite(Pump2_2, HIGH); delay(20000); // time in ms how long the pump is turned on, 20 s here digitalWrite(Pump2_1, LOW); digitalWrite(Pump2_2, LOW); runs2++; // increment the number of times pump 2 has run } } // the script to print the values and cycle through the display void buttons() { val = digitalRead(inPin); // read state of the button if (val != buttonState && val == HIGH){ // make sure we detect a change from LOW to HIGH push_count++; // count that the button has been pushed } else { // do nothing } buttonState = val; // save the current state switch (push_count) { case 0: display.clear(); display.print("sns1"); delay(2000); display.clear(); push_count++; break; case 1: display.print(value1); break; case 2: display.clear(); display.print("sns2"); delay(2000); display.clear(); push_count++; break; case 3: display.print(value2); break; case 4: display.clear(); display.print("no 1"); delay(2000); display.clear(); push_count++; break; case 5: display.print(runs1); break; case 6: display.clear(); display.print("no 2"); delay(2000); display.clear(); push_count++; break; case 7: display.print(runs2); break; default: push_count=0; } }
Шаг 5: Итоговый результат
Теперь вы знаете, что с помощью микроконтроллеров подобных Arduino при сильном желании можно создать всё что угодно.
На этом всё, желаем вам отличных проектов.