Arduino as I2C GPIO expander
ฝัง
- เผยแพร่เมื่อ 5 ก.พ. 2025
- Использование Arduino UNO, Nano или Pro Mini в качестве I2C расширителя GPIO (не забудьте подтянуть к VCC через резисторы 4.7 кОм SDA и SCL на слейве и про конвертер уровней при использовании с ESP8266!).
Поддерживаются функциональные аналоги стандартным методам работы с портами (pinMode, digitalWrite, digitalRead, analogWrite, analogRead). Через 5 сек. бездействия плата уйдет в сон, но проснется сразу же при очередном обращении.
Скетч клиента I2C (для заливки в AVR): drive.google.c...
Скетч с примером использования (пригоден для AVR и ESP8266): drive.google.c...
Чуть усложнив протокол обмена с мастером, можно создать I2C "обертку" для специфических датчиков, требующих сложного подключения.
PS: код клиента, пригодный для Mega (исправьте в .h файле константу последнего пина на используемую вашей платой) или дальнейшего расширения протокола: drive.google.c...
спасибо, очень мило! Буду юзать ваши наработки для димера 220В лампы накала)
Спасибо за столь интересное и полезное решение! Не подскажете, как на Slave управлять сервой? При передаче с мастера значения через WireIO.analogWrite(servo_pin, 118); в логах я вижу в дебаге переданное значение, но если на слэйве прочитать значение через analogRead(servo), то получаю странные цифры, например 981.
Я думаю правильно только расширением протокола обмена командами сервы и использованием соответствующей библиотеки на слейве.
И зачем читать пин сервы? И это очевидно не "аналоговый" пин, чтобы его analogRead читать.
На слейве подключена библиотека сервы, разумеется. Из добавленого на слейв:
#include
#define incomingValue 13
Servo myservo;
myservo.attach(servo_pin);
в лупе:
int encoderValue = analogRead(incomingValue);
Serial.println(encoderValue);
myservo.write(encoderValue);
Только вот почему-то в дебаге все здорово, а если делать int encoderValue = analogRead(incomingValue); то в переменную encoderValue попадает какое-то левое значение.
А на какой плате 13 пин связан с АЦП? И почему серва управляется на удаленной плате значением пина удаленной платы же? Я еще понимаю, если бы с мастера управлять сервой.
Серва на слейве управляется удаленно с мастера через энкодер. Мастер передает значение энкодера на 4 пин слэйва. Значение приходит на слейв, я его вижу в дебаге . Далее на слейве читаю полученное значение в переменную encoderValue и пишу его в myservo.write. Но суть в том, что не присваивается корректное значение командой analogRead(). Ничего не понимаю, потратил уйму времени на такую простую операцию. Скетч залил сюда. yadi.sk/d/leSAWTUJ3DEb9Y
Я не знаю что и сказать... :)
Еще раз спрашиваю, что за плата в качестве слейва? UNO или подобная или Леонардо или Мега?
Как вы передаете на пин 4 слейва информацию с энкодера? Чем?
Вы понимаете, что обмен информацией в подобном случае должен идти по I2C протоколу, а иначе в этом вообще никакого смысла нет?!
интересное решение, жаль в коде мало комментариев. подскажите, каким образом организовано хранение в буфере i2c мастера (esp8266), если слейв прочитает например 2 байта, а в буфере мастера будет 5, то при следующем приёме на слеиве они не вылезут? в общем как очищается буфер отправки в wire.h?
Мастер выдает команду в пределах транзакции. Если команда на чтение - то он сразу ждет результат. Откуда в буфере могут остаться данные? Обмен синхронный.
Видимо не откуда, но не совсем понятно.
т.е. если связь отвалится в процессе передачи например Wire.write("message"); то программа не зависнет ожидая бита подтверждения, а по команде Wire.endTransmission(); данные будут "отправлены" сеанс полностью завершается? как долго может ждать мастер ответа от слейва? другими словами нужно ли как-то убедится перед новым сеансом связи, что все предыдущие завершены?
Вводите в протокол обмена обязательное подтверждение приема и исполнения команды - будет у вас 100% обратная связь.
не точно выражаюсь, такую проверку обязательно сделаю, но нет чёткого понимания, что при неудачном сеансе связи или обрыве линии i2c программа не зависнет в недрах wire.h. т.е. каждый новый сеанс связи абсолютно не связан с предыдущим, наверное нужно смотреть код wire.h как там всё устроено,..
Привет, я снова со своими вопросами, а можно таким способом привязать вашу умною реле, и ище место uno использовать megu, вес фрамеварк можно аставить esp8266, и получить много gpio?
Можно, но скетч все равно придется немного переделать.
Другое дело, что если WiFi не нужен, то правильнее, конечно, на Mega с Ethernet shield все сделать.
Ну конечно лучше с w5100 но тогда почти всё надо переделать, а с есп8266 только добавить...
Надежность сложной системы в разы ниже простой.
Спасибо большое за видео!
Дайте пожалуйста ссылку на конвертер уровней.
Любой или на транзисторах, или на TXS010xE (для данного примера достаточно двухканального), выбирайте:
www.aliexpress.com/af/level-converter.html?SearchText=level+converter
Спасибо! Я почему спросил - для данного примера нужен высокоскоростной двунаправленный конвертер, который желательно чтобы работал на 800kHZ - это получается конвертер на TXS010xE ?
Без разницы, транзисторы тоже миллионы переключений в секунду обеспечивают. В видео конвертер на транзисторах.
Добрый вечер Спасибо Вам за видео можно Вас попросит не могу запустить на
Raspberry Pi 3 онлайн радио majordomo нет как я понимаю проигрывателя для этого например vlc
Заранее спасибо за ответ
Здравствуйте.
Простите, но я не специалист по Raspberry и по Majordomo. Для меня они не более чем умный клиент для отладки глупых вещей. :)
Спасибо большое. Искал подобное решение - не нашел. Вы случайно не планировали объединить Ваше умное реле и ардуино экспандер? Я сейчас экспериментирую с веб-сервером на Arduino Mega, а ESP-12 в качестве шилда управляется АТ командами. Использовал схему: istarik.ru/blog/esp8266/29.html Но не нравиться стабильность работы такой схемы, поэтому хочу сделать по-человечески, веб-сервер на ESP-12(master), а датчики, кнопки, реле на Меге(slave).
А чего их объединять? :)
Там поправить не так уж и много кода придется. Все вхождения pinMode, digitalRead и digitalWrite и другой список доступных для подключения реле и кнопок GPIO.
Вот только с ИК придется повозиться, если его переносить на слейв. С DHT все просто, расширяем протокол обмена данными двумя командами чтения температуры и чтения влажности. А вот постоянно опрашивать ИК мастером - не самая удачная идея (ИМХО). Правильнее один пин на слейве и мастере зарезервировать для "внешнего прерывания" по приходу данных от ИК на слейве. Впрочем, кнопки тоже могут не опрашиваться постоянно, а генерировать прерывание при изменении состояния.
У Mega ног слишком много, 5 бит на номер пина в текущем протоколе не хватит, обмен станет минимум двухбайтным, немного пострадает компактность протокола, но это неизбежно и при расширении количества команд.
Спасибо. Наверное проще не переносить ИК и DHT, им всего по одной ноге нужно, а вот кнопки и 16-канальный блок реле так и просятся на Мегу.
Mega дороговата для экспандера, вот Pro Mini в самый раз. 20 пинов, из них 6 аналоговых, правда 2 работают только как аналоговые входы (A6, A7). :)
Ну и 74HC595 в каскаде никто не отменял для размножения цифровых выходов. :)
Действительно очень просто внедрил скетч в умное реле, работает шикарно, спасибо. А вот задействовать более 32 ног Меги так и не смог. Прокопался пол ночи :) не хватает мозгов, может направите что нужно менять. Мега нужна чтобы можно было подключить 16 кнопок 16 реле и еще осталось место... :)
Я же говорил, что 5 бит на номер пина недостаточно! Надо первым байтом слать только команду, а вторым - пины. Тогда до 256 пинов можно будет использовать. Но придется и прием и передачу переделать соответственно.
Не понимаю ничего. Команды Slave успешно получает от мастера, но мастер не получает ничего в ответ. Например, командой WireIO.digitalRead(13) на мастере пытаюсь прочитать состояние 13 пина слэйва, которое меняется периодически, но команда приходит, а ответ на мастер не возвращается. Симплекс какой-то. Железо: ESP8266 NodeMCU (Мастер) + ArduinoProMini (слэйв). В библиотеке менял номера SDA/SCL на свои. Чтобы не согласовывать уровни, ProMini запитал от 3.3 В. Может в этом проблема? Еще на слейв я заливаю пример номер два.
А на мастер Вы копируете файлы из примера №2?
Ну и подтяжка SDA и SCL к VCC через R 4K7 на слейве и минимизация длины проводов.
Скорость I2C понизить. На ESP setClockStretchLimit раскомментировать и поиграться его значением.
Простите, я не понял что значит копируете на мастер файлы из примера №2? Я распаковал архив WireSlave2, отредактировал номера SDA/SCL под себя, скопировал файлы в библиотеку ардуино. Далее я прошиваю одной и той же библиотекой оба контроллера. В примере№2 содержится только файл для Slave (WireSlave2.ino), остальные три - библиотека. На мастере я инициализирую ногу второго контроллера WireIO.pinMode(13, INPUT_PULLUP); и раз в секунду его читаю WireIO.digitalRead(13). Но в ответ я получаю всегда 0, хотя на слэйве состояние ноги 13 меняется. setClockStretchLimit раскоментировал и пробовал разные значения. Подтяжку к VCC делал. Грешу на то, что у меня на I2С еще висит OLED экран.
Вы из архива №2 все файлы кроме .ino в мастер скопировали?
Отключите OLED экран и проверьте без него. Скорость I2C пробовали уменьшать?
Я кажется понял ошибку. Вечером попробую отписаться. Я правильно понял, что на мастер нужно перенести содержимое файлов .cpp и .h из второго архива?
Да, они другие относительно первого архива и нужны именно мастеру. Слейв использует из них только .h-файл с общими параметрами.
привет , както у мениа неработает slave2, a на slave1 mega raботает толко до 31 пина, где может быть проблема?
Из второго кода надо все .cpp и .h фалы скопировать в код мастера взамен совместимых с первым кодом.
И константы SDA и SCL изменить на значения в Меге и максимальный номер пина.
Или невозможно это реализовать?
Мне это неинтересно, но никаких трудностей в этом нет.
Если вам нужно много реле - то проще к ESP подключить 74HC595 хоть каскадом хоть одну. Вот с опросом кнопок сложнее. Но даже если перейти на внешний GPIO-расширитель, с кнопками все равно придется повозиться.
спасибо заработало... а к есп привезать w5100 небило вам интересно? провод есть провод. тогда можно есп исползовать как ум а мегу как силу... на такои плате мега+есп :robotdyn.com/catalog/boards/mega_wifi_r3_atmega2560_esp8266_flash_32mb_usb_ttl_ch340g_micro_usb/
После привязки к UNO я могу W5100 к чему угодно прикрутить, только зачем?
Кроме вас никому 500 реле не нужно к одному модулю подключать. :)
А если не нужен WiFi, то ESP8266 становится весьма сомнительным выбором при наличии STM32 на нормальном ARM ядре за сущие копейки.
лу4е било би на меге вес код переделать все реле, но там много работы а на есп вы узе всио сделали...
У меня нет Меги, не на чем отлаживаться, а то за неделю я бы перенес основной код на Мегу, тем более что нужную часть веб-сервера я уже портировал с ESP.
В любом случае, библиотека веб-сервера для ESP работает только с WiFi, поэтому добавление W5100 на ESP все равно потребует переписать библиотеку, а значит ESP не нужна вообще в этом случае.