Расширитель на 16 цифровых пинов (ввод-вывод) с интерфейсом i2c — MCP23017. С практическим применением для системы полива. | mysku

Расширитель на 16 цифровых пинов (ввод-вывод) с интерфейсом i2c — MCP23017. С практическим применением для системы полива.

Перейти в магазин

Я уже делал немало обзоров посвященных дачной автоматике. Этот обзор из той же серии, зимой самое время вспомнить дачные доработки и реализовать задуманное. Микросхема из обзора позволяет получить 16 двунаправленных выводов с доступом по шине i2c. Причем полученные пины программно можно подтягивать, а значит не нужны внешние резисторы. Под катом кратко про микросхему и готовое устройство построенное с ее применением. Все кто любит мастерить огородные (и не только) штуки приглашаются. Колхозинг, пайка и программирование ожидают Вас.

Перед тем как начать писать, вспомнил специфического местного автора и хотел написать: «ШОК!!! управление поливом по разным интерфейсам, в том числе с телефона… ». Я каждый раз пытался понять почему шок, да еще большими буквами и с восклицательными знаками, по моему, шок вызывают несколько иные вещи. Ну да ладно, начнем про наше устройство.

10 микросхем доехали довольно быстро, порядка 2-х недель. Упакованы были в жесткую тару для микросхем, поэтому повреждены не были.Сама микросхема:

Содержит управляющие входы шины I2C: SDA и SCL. VDD — вход питания, VSS — вход земли. A0-A2 — позволяют задать адрес микросхемы на шине I2C (если у вас планируется использовать несколько таких микросхем, либо иных устройств с пересекающимися адресами). Собственно, вновь получаемые пины представлены двумя портами по 8-выводов: GPA0-7 и GPB0-7, каждый пин может быть самостоятельно настроен на чтение или запись. Микросхема способна генерировать прерывание при изменении сигнала на одном из выводов порта, выходы прерываний: INTA и INTB. Вывод RESET позволяет сбросить микросхему в исходное состояние подачей низкого уровня, поэтому нужно его подтянуть к питанию. Со стороны контроллера выводы SDA и SCL следует подтянуть к питанию резисторами 4.7 кОм один раз, не нужно подтяжек каждому устройству подключаемому к шине I2C. Типовой вариант подключения выглядит следующим образом:

Подробная документация по микросхеме.

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


Собственно, плата содержит все выводы данной микросхемы. На каждый пин имеется два винтовых клеммника, собственно сам пин и второй, который можно подключить для каждого порта (А и В) либо к земле, либо к питанию перемычкой. Также, имеются адресные входы микросхемы, с помощью перемычек можно перебрать все возможные комбинации. На отдельных пинах выведены выходы прерываний (А и В). Имеется встроенный DC-DC преобразователь на 5 В. Несколько пинов питания и земли. Также индикация светодиодом подачи питания. Ну и, конечно, I2C шина для подключения к контроллеру.

Герберы для заказа можно скачать тут. Платка для открытия в Sprint Layout тут. Выглядит в программе она так:

Подключим Arduino Nano к тестовой плате:

Вторые выводы шины В я подключил к земле, к выводу GPB1 подключил кнопку изготовленную в этом обзоре. Вторые выводы шины А я подключил к питанию, так как для тестов использовал 3-х цветный светодиод с общим анодом, анод светодиода подключил к питанию, красный к выводу GPA7, зеленый к GPA6, синий к GPA5. Выход прерывания шины В подключил ко входу 3 Arduino Nano. Питаться наша конструкция будет от платы Arduino. Для работы с микросхемой есть замечательная библиотека от Adafruit.

Код для проверки работы светодиода вместе с кнопкой:


#include <Wire.h>
#include "Adafruit_MCP23017.h"

Adafruit_MCP23017 mcp;

void setup() {
mcp.begin();      // use default address 0
mcp.pinMode(9, INPUT);
mcp.pullUp(9, HIGH);  // turn on a 100K pullup internally
mcp.pinMode(7, OUTPUT);
mcp.digitalWrite(7, HIGH);
}

void loop() {
mcp.digitalWrite(7, mcp.digitalRead(9));
}

Если кнопка замыкает вывод GPB1 на землю, то красный светодиод светит. Видео теста:

Проведем немного более сложный тест для работы с прерываниями.

Код


#include <Wire.h>
#include <Adafruit_MCP23017.h>

Adafruit_MCP23017 mcp;

byte ledPin=7;
byte arduinoIntPin=3;
byte arduinoInterrupt=1;
volatile boolean awakenByInterrupt = false;
byte mcpPinB=9;

void setup(){
pinMode(arduinoIntPin,INPUT);
mcp.begin();      // use default address 0
mcp.setupInterrupts(false,false,LOW);
// similar, but on port B.
mcp.pinMode(mcpPinB, INPUT);
mcp.pullUp(mcpPinB, HIGH);  // turn on a 100K pullup internall
mcp.setupInterruptPin(mcpPinB,FALLING);
// We will setup a pin for flashing from the int routine
mcp.pinMode(ledPin, OUTPUT);  // use the p13 LED as debugging
mcp.digitalWrite(ledPin,HIGH);
}

void intCallBack(){
awakenByInterrupt=true;
}

void handleInterrupt(){
uint8_t pin=mcp.getLastInterruptPin();
uint8_t val=mcp.getLastInterruptPinValue();

uint8_t flashes=4;
if(val!=LOW) flashes=3;

for(int i=0;i<flashes;i++){
delay(100);
mcp.digitalWrite(ledPin,LOW);
delay(100);
mcp.digitalWrite(ledPin,HIGH);
}
cleanInterrupts();
}

void cleanInterrupts(){
EIFR=0x01;
awakenByInterrupt=false;
}

void loop(){
attachInterrupt(arduinoInterrupt,intCallBack,FALLING);
while(!awakenByInterrupt);
detachInterrupt(arduinoInterrupt);
if(awakenByInterrupt) handleInterrupt();
}

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

В целом, микросхема сделана очень удачно и ее удобно использовать в своих проектах. В отличие от pcf8574 она дает полноценные выводы, с током до 20 мА. Следует сказать, что на одну шину I2C можно прицепить несколько таких микросхем, задавая каждой свой адрес, таким образом, получим просто огромное количество цифровых входов и выходов (конечно если устраивает не высокая скорость шины I2C).

Применил я эту микросхему в своем новом устройстве дачного полива. Прошлое устройство описано здесь. Там я использовал сдвиговые регистры 74HC595. С данной микросхемой устройство реализовать будет проще. Кстати, следует заметить, что один из первых моих обзоров был про китайские управляемые шаровые краны, которые успешно поливают огород уже 3 сезона. На даче подобных кранов используется 11 штук, проблема этим летом была выявлена только с одним — внутрь попала вода, поэтому следует промазать шов стыка пластиковых крышек герметиком, что я и проделал.

В этот раз плату я заказал в Китае, воспользовался акцией 2$ с бесплатной доставкой от jlcpcb.com за 3 недели платки доехали. В целом сервис меня устроил. Преимущества: цена, высокое качество. Недостатки: нельзя делать панелизацию (одну из моих плат с линиями разлома развернули (предложив доплатить 64$), невозможность выбора цвета, и средство автоматического определения размеров у них почему-то прибавляет относительно моих измерений и измерений других сервисов пару мм (а выход за пределы 10 на 10 см — влечет существенное увеличение цены). Вообще любое изменение параметров устремляет цену вверх, поэтому там стоит заказывать большие цельные платы, используя только стандартные настройки.
Плата выглядит хорошо:


Шелкография, контактные площадки — все очень точно совпадает с макетом. Для сравнения плата изготовленная dirtypcbs.com:


Качество очень сильно отличается не в лучшую сторону, зато есть возможность выбора цвета и допускается панелизация.

Начнем сборку, припаиваем контроллер ATmega1284P (можно использовать и ATmega 644 — по выводам они совпадают), я решил протестировать первое устройство, поэтому взял подходящий контроллер с максимальным функционалом. Также припаиваем смд детали и разъем для программирования (ICSP), получилась минимальная конструкция, пригодная для теста:

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

Припаиваем остальные детали. под микросхемы L293D я установил разъемы:


После смывки флюса, припаивания DC-DC преобразователя и вставки микросхем L293D:


Подключим питание и видим работу нашей прошлой прошивки:

Тест остальных пинов (ввиду их большого количества) удобно проводить маленькой платкой со светодиодами и ограничительными резисторами:

Тут на муське немало примеров своих аудио систем, наша плата полива сможет с некоторыми из них поконкурировать по качеству звука :), тест пищалки:

Конечно, это была шутка про качество, но пищалка работает и сможет извещать о переключении режимов.

Систематизируем наши пины управления двигателями.

Код


#include <Wire.h>
#include "Adafruit_MCP23017.h"

Adafruit_MCP23017 mcp;
#define addr 0

// time for complite change state motor
#define TIME_POWER_MOTOR 500

// for count motors
template<typename T, size_t n> inline size_t arraySize(const T (&arr)[n]){return n;}

// in setup set count of motors
byte NumberOfMotors = 0;

// drive mode
enum { STOP, OPEN, CLOSE};

// type motor
typedef struct {
uint8_t PinOn; // pin for open motor
uint8_t PinOff; // pin for close motor
unsigned long StartTime; // start time current operation
byte DefaultState; // default state motor
byte CurrentState; // current state motor
} MotorType;

// all motors, format:
// pin for open, pin for close, 0 - last start power, default state, current state (STOP -
// unknown state, if need default set STOP)
MotorType MC[] = {
{15, 14, 0, CLOSE, STOP},
{13, 12, 0, CLOSE, STOP},
{11, 10, 0, CLOSE, STOP},
{ 9,  8, 0, CLOSE, STOP},
{ 0,  1, 0, CLOSE, STOP},
{ 2,  3, 0, CLOSE, STOP},
{ 4,  5, 0, CLOSE, STOP},
{ 6,  7, 0, CLOSE, STOP},
};

void setup() {
mcp.begin(); // use default address 0

NumberOfMotors = arraySize(MC);
for (uint8_t i = 0; i < NumberOfMotors; i++) {
mcp.pinMode(MC[i].PinOn, OUTPUT);
mcp.digitalWrite(MC[i].PinOn, LOW);
mcp.pinMode(MC[i].PinOff, OUTPUT);
mcp.digitalWrite(MC[i].PinOff, LOW);
}
}

void loop() {
for (uint8_t i = 0; i < NumberOfMotors; i++) {
mcp.digitalWrite(MC[i].PinOn, HIGH);
delay(TIME_POWER_MOTOR);
mcp.digitalWrite(MC[i].PinOn, LOW);
mcp.digitalWrite(MC[i].PinOff, HIGH);
delay(TIME_POWER_MOTOR);
mcp.digitalWrite(MC[i].PinOff, LOW);
//break;
}
}

Тест:

Проверим на шаровом кране, задав подходящее время таймаута и ограничив цикл только первым драйвером:

Коммуникационные возможности нашей платы весьма высоки, из коробки поддерживаются следующие модули:

1 — Адаптер Ethernet na чипе enc28j60
2 — Адаптер Ethernet на чипе w5100
3 — Радиомодуль nrf24l01 (как с антенной на плате, таки с внешней)
4 — Радиомодули приемника и передатчика 433 MHz, обзор разных модулей со сравнением я делал здесь, любые из того обзора можно применить.
5 — GSM-модем на SIM800L
Помимо этого, выведен UART Serial, который позволяет прицепить целый ряд устройств (esp8266, bluetooth, специализированные радиомодули и тп). Для использования любых возможностей коммуникаций, достаточно реализовать поддержку требуемых модулей в прошивке.

Примеры подключения




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

Для подключения внешних датчиков и иных устройств, также немало возможностей 11 пинов на штырьках, с возможностью подтяжки 5 из них к питанию резистором. Два вывода на клеммниках. Кроме этого, имеется вход подключенный через операционный усилитель lm358.
Таким образом, легко подключить датчики: влажности почвы (хороший я описывал тут), дождя, освещенности, скорости ветра и тп. Платка позволит организовать контроль наличия воды и работы насоса. Для измерения температуры (воды, воздуха и тп) на синем тройном клеммнике предусмотрено подключение шины 1-wire с датчиками ds18b20.

Спасибо тем кто дочитал до конца! Надеюсь, что обзор будет полезен, напомню основной целью было рассказать о микросхеме MCP23017, показать как ее подключать к Arduino и как писать код по управлению полученным множеством пинов, кроме того, я показал, что в реальных устройствах, она тоже прекрасно может работать. Всех поздравляю с Рождеством!

Хищник после драки проходит реабилитацию, поэтому к устройству равнодушен

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Наверх