Подключение батареи ноутбука к arduino по i2c

Обновлено: 06.07.2024

Измерение уровня заряда Аккумулятора на Ардуино

Отслеживание уровня заряда аккумулятора или батареи является одной из основных задач при разработке автономных устройств. Особенно она актуальна для устройств, которые работают удалённо и сообщают о своём статусе, используя, например, GSM канал*. Даже когда устройство находится рядом с вами, индикация уровня заряда аккумулятора поможет сделать его использование более удобным. В данной статье мы рассмотрим простой способ отслеживания уровня заряда аккумулятора или батареи при помощи Ардуино.

*Знакомые с GSM модулями могут возразить, что в их составе уже присутствуют средства мониторинга заряда аккумулятора, и не нужно изобретать велосипед. Справедливое замечание. Но при условии, что для GSM модуля не используется стабилизация напряжения, скажем, от 12-вольтового аккумулятора. В этом случае модуль не сможет оценить уровень заряда аккумулятора. Таким образом, не стоит преуменьшать актуальность данной темы.

Теория

Предлагаемый способ отслеживания уровня заряда основан на измерении напряжения источника питания. Возьмем, к примеру, литий-ионный аккумулятор. В процессе разрядки его напряжение изменяется от 4.2 В до 3 В. Выполняя периодические замеры напряжения и сопоставляя полученный результат с приведённым диапазоном 4.2. 3 В, мы можем оценить уровень заряда. Но не всё так однозначно. Дело в том, что напряжение аккумулятора при разряде изменяется не линейно. Это видно из графика разряда литий-ионного аккумулятора, который легко найти в google по запросу li-ion discharge graph:

График разряда аккумулятора Panasonic NCR18650B

Данный график позаимствован с сайта batteryuniversity. На нём отражён процесс разряда аккумулятора Panasonic NCR18650B 3200мАч разными токами от 0.2C до 2C. Как видите, напряжение аккумулятора изменяется более-менее линейно лишь при разряде большими токами. Здесь можно вспомнить математику и посчитать процент оставшегося заряда по линейной формуле. Но это, скорее, частный случай. Пожалуй, более актуальны случаи, когда устройство потребляет незначительные токи, поэтому ориентироваться мы будем на красную и синюю кривые.

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

Следующий момент, который я беру во внимание – это то, что высокая детализация уровня заряда (в тех же процентах, которые дают нам 100 значений) бывает нужна крайне редко. В большинстве случаев достаточно понимания: когда уровень заряда находится в "зелёной зоне", когда в "жёлтой", а когда нужно быть готовым к отключению устройства из-за разряда аккумулятора. Поэтому наиболее рациональным представляется подход, когда мы выделяем 3-4 пороговых напряжения и относительно них определяем уровень заряда. Грубо говоря, если напряжение литий-ионного аккумулятора больше 4 В, то заряд высокий; если меньше 3.2 В – аккумулятор вот-вот разрядится, а между этими двумя значениями выделяем еще несколько зон. Если необходимо выразить заряд именно в процентах – пожалуйста: выделяем 10 зон и показываем результат десятками (10%, 20% и т.д.).

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

Реализация

Итак, задача поставлена: необходимо измерять напряжение источника питания нашего устройства. Я бы выделил 2 возможных варианта реализации:

  • измерять напряжение, используя АЦП Ардуино;
  • воспользоваться датчиком напряжения, например, INA219.

Первый вариант хорош тем, что для него ничего не требуется. Разве что пара резисторов. А датчик напряжения – это уже дополнительный компонент. Зато он позволит более точно измерять напряжение. Кроме того INA219 измеряет потребляемый ток и мощность, поэтому имеет потенциал для дальнейшего развития в плане мониторинга питания (с его помощью можно построить ту же кривую разряда аккумулятора, определить его ёмкость, спрогнозировать время работы устройства), но это уже отдельная тема.

Вариант 1. Измерение напряжения при помощи Ардуино.

Все платы Ардуино имеют в своём составе АЦП. У популярных плат (UNO, NANO, MEGA2560) разрядность АЦП составляет 10 бит, у более продвинутых (Due, Zero) – 12 бит. АЦП позволяет измерять напряжение в диапазоне от 0 В до опорного напряжения Vref. Значение Vref в общем случае соответствует напряжению питания платы – 5 В или 3.3 В, но может быть привязано к внутреннему стабилизатору. Для лучшего понимания принципов использования АЦП предлагаю рассмотреть следующий скетч.

Загрузите скетч в Ардуино, соедините A0 с выводом 5V и откройте монитор порта. Вы должны увидеть следующий результат:

Arduino analogRead 1023

Этот скетч измеряет напряжение на входе A0 и выводит результат в монитор порта. Разрешение АЦП используемой мной Ардуино УНО составляет 10 бит, а значит, результатом измерений будет число от 0 до 1023 (2^10 значений). При этом значение 0 будет говорить об отсутствии напряжения, а максимальное значение – 1023 – о его равенстве (а так же превышении, что мы не будем рассматривать) опорному напряжению Vref, каким бы оно ни было. У меня в монитор порта выводится как раз число 1023. Поскольку опорным напряжением АЦП по умолчанию является напряжение питания Ардуино – 5 вольт, выдаваемые USB портом компьютера (разумеется, это не точное значение), можно утверждать, что напряжение на входе A0 тоже составляет 5 вольт.

Попробуем отсоединить A0 от вывода 5V и подсоединить к 3v3. Теперь у меня в монитор порта выводится значение 687. Зная опорное напряжение, нетрудно вычислить напряжение на A0:

(5 В / 1024) * 687 = 3.35 В

Для получения более точного результата следует измерить напряжение, выдаваемое USB портом.

Если же вывод A0 соединить с «землёй», то в монитор порта будет выводиться значение 0.

Вернёмся к нашей задаче. Питание от аккумулятора не всегда предполагает наличие стабильного напряжения, которое может использоваться как опорное для АЦП. В таких случаях в качестве Vref следует использовать напряжение от внутреннего стабилизатора Ардуино. Для большинства плат, в том числе Ардуино УНО, это напряжение составляет 1.1 В. Это означает, что измеряемое напряжение необходимо понизить при помощи делителя, чтобы оно не превышало 1.1 В. Здесь нам помогут пара резисторов номиналом в несколько десятков-сотен кОм, включенные по следующей схеме:

Делитель напряжения на резисторах

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

Сам коэффициент рассчитывается по следующей формуле:

Остаётся лишь подобрать номиналы резисторов таким образом, чтобы понизить напряжение аккумулятора до нужного нам уровня. Для измерения напряжения аккумулятора 18650 я выбрал номиналы 47k и 10k. Реальное сопротивление будет отличаться, поэтому их нужно обязательно измерить мультиметром. Выбранные мной номиналы дают коэффициент

0.175, что позволяет измерять напряжение до 1.1 В / 0.175 = 6,27 В. Ниже приведены схема, пример скетча, реализующий описанный функционал, и результат его работы. Предполагается, что Ардуино питается от аккумулятора, поэтому результаты выводятся на дисплей 1602, а не в Serial.

Определение уровня заряда аккумулятора. Делитель напряжения

Результат измерения уровня заряда 18650 lcd1602

На фото видно, что результат измерения напряжения при помощи Ардуино и делителя не сильно отличается от того значения, что показывает мультиметр. Это хороший результат.

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

Опорное напряжение, выдаваемое внутренним стабилизатором, не обязательно будет 1.1 В, и может отличаться от одного микроконтроллера к другому. Даташит допускает разброс от 1.0 до 1.2 В. Поэтому для получения более точных измерений можно вычислить значение Vref и использовать его в скетче при расчетах. Его легко найти путём измерения заранее известного напряжения (обозначим его как V(A0)):

Vref = V(A0) * 1024 / analogRead(A0)

Вариант 2. Использование датчика напряжения INA219.

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

Определение уровня заряда аккумулятора. INA219

В этот раз я решил выделить 10 уровней заряда, чтобы отображать его в процентах. Скетч и результат его работы ниже:

Измерение уровня заряда 18650. LCD1602

Заключение

Конечно, предложенный способ не претендует на высокую точность. Существуют специализированные микросхемы мониторинга питания, которые определяют оставшуюся ёмкость аккумулятора с учётом нагрузки и других параметров. Они находят применение в ноутбуках, телефонах и другой портативной технике. Но вряд ли вы найдёте что-то подобное в любительских проектах – не тот уровень. Таким образом, определение уровня заряда аккумулятора по напряжению – приемлемая альтернатива, не требующая серьёзных аппаратных или программных ресурсов.

Наваял на досуге несколько скетчей для общения с батареей ноутбука. Подключать как I2C устройство - SDA SCL GND. Проверял на bq20z955 с дефолтными паролями. Если у Вас другой контроллер - сверяйтесь с данными из даташита.

. ВНИМАНИЕ. Всё что Вы делаете - Вы делаете на свой страх и риск . Операции 6, 7 и 8 пишут данные в батарею и могут окирпичить её !

Один из скетчей:

Другие скетчи смотрите на github .

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

ua6em аватар

а описание или хотя бы ссылки привести, почитать.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

ua6em Что конкретно описать ? На гребенке АКБ обычно выведены + GND SDA SCL. Распиновка разная - надо изучать схему.

Стандартные данные Smart Battery стандартизированы и с вероятностью 95% будут считаны.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

АКБ имеют свойство терять ёмкость. Замена банок часто не спасает - контроллер блокируется. Этим скетчем можно разблокировать контроллер, стереть ошибки и прописать емкость нового пакета банок и вернуть АКБ к жизни. Это как черновик, ибо контроллеров много и паролей к ним еще больше .


  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

DetSimen аватар

Для самсунговских батарей падёт?

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

DetSimen Главное понять какой там контроллер. Обычно без разборки это не известно . Стандартную информацию должен по любому отдать, ноутбук же именно её считывает.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

DetSimen аватар

Тоись, если батарея неразборная, то тока ломать и плющить.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Для начала нужно узнать распиновку, подключиться и прочитать информацию.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Altcms аватар

Тоись, если батарея неразборная, то тока ломать и плющить.

Если банки менять то всё равно ломать прийдётся.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

у меня коллега тут хвастался, ковырял батарею, несколько банок 18650 были 0В. Дак он выяснил, что внутри аккумулятора создалось давление, а там механизм при давлении газа размыкающий цепь. Потом типа воткнул иглу, сделал пшик и аккумулятор ожил. Сомнительный "ремонт", конечно, но как супер временное решение пойдет. главное не взарваца

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

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

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

так это же СУПЕР. проект. Жду не дождусь работоспособного универсального экземпляра.

Можно ли напрямую связаться с автором? Есть ряд вопросов

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Ghost_d Универсальный это сложно - чипов развелось как грязи и каждый со своими заморочками .

Что вас интересует ?

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Интересно, а если дефолтный пароль не подойдет? Можно перебором его подобрать?

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Можно конечно же, но это может занять не один год.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Спасибо, получилось считать данные благодаря вашему скетчу. Контроллер 20z955 Буду благодарен, если подскажите что не так с аккумом, почему он не заряжается?
  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Battery Status: 48D0 Hex

В следующей строке как раз расшифровка. Если размер буфера в библиотеке Wire исправили, то пробуйте: 1,2,3,4,5,6,7,8 1,2,3,4,9

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Спасибо, так и сделал.

Но напряжение на гребенке аккума так и не появилось. Хотя количество циклов, дата и PFStatus обновились. Предохранитель живой.

Может контроллер как-то пнуть нужно после перепрошивки?

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

На отключенном от ноутбука АКБ нет питания на гребенке ! Надо либо подключать к ноуту, либо "заземлить" SYSPRES.

P.S. MaxError: 119 % - надо еще раз повторить все команды. Если больше 100%, то нормально не откалибруется скорее всего.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Это акб на три ячейки, а контроллер умеет и четыре.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Вроде разобрался с алгоритмом обхода пароля для чипов bq20z. (на моих платах алгоритм работает, но они обе на bq20z8955, а хочется проверить и на других)

Если кто пробовал мои скетчи на чипах bq20z. и не смог снять блокировку стандартными паролями - напишите !

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Чип bq20z955, операции с 1 по 5 проходят успешно, на остальных "wire error". С чем может быть связано?

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

danx43 Покажите что пишет п. 1 . после 1,2,3,4,5.

Попробуйте еще делать небольшие (сек. 30) паузы между операциями .

wire error - это не верное завершение обмена i2c

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
8. Writing DesignCapacity, QMAX, Update status, Ra_table. 8. Writing DesignCapacity, QMAX, Update status, Ra_table. 8. Writing DesignCapacity, QMAX, Update status, Ra_table. 8. Writing DesignCapacity, QMAX, Update status, Ra_table. 8. Writing DesignCapacity, QMAX, Update status, Ra_table. если делать с паузой, то ошибка может и на п. 2 выскакивать
  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Sealed - У Вас ключи не дефолтные !

Можем испытать "раскуренный" алгоритм, если Вы готовы.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Как увидите ключи - перепишите их в первый скетч и пользуйтесь уже им.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Что то не так . Wire error быть не должно

Попробуйте после запуска этого бинарника запустить первоначальный скетч и считать информацию не выполняя операцию № 2.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Всё без изменений. Скажите а может ли повлиять тот факт, что на батарею из-за пробитого мосфета было подано 19 вольт и сгорел управляемый предохранитель, который я востановил?

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Вот это уже не понятно как -

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

ой, не обратил внимание на это, проверю

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Предохранитель пережигается контроллером при возникновении критических ситуация для защиты от возгорания лития. Успел ли сам контроллер пострадать - не ясно.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Здравствуйте, имеется батарея Acer AS10D75, контроллер bq20z955, залочен контроллер, стандартные пароли не подходят, смогу ли я разлочить контроллер с помощью скетчей.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Параметры батареи читаются с помощью Be2works.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Здравствуйте, имеется батарея Acer AS10D75, контроллер bq20z955, залочен контроллер, стандартные пароли не подходят, смогу ли я разлочить контроллер с помощью скетчей.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Yura27 На коте ответил.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Уточните, пожалуйста, какова вероятность, что Ваш скетч с BQ8030 будет работать?

P.S. Хотел свериться с даташитом, но не могу найти его на данный контроллер.

Pack Info.
DesignCapacity: 4218 mAh
FullChargeCapacity: 3631 mAh
CycleCount: 207
Date: 2010.11.22
DesignVoltage: 11100 mV
Wire error - 3

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Emulty Это совсем другой контроллер.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

sfs Этот скетч только для bq20z. чипов.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

А там существенная разница в протоколах/командах/адресах? Подскажите тогда, пожалуйста, откуда Вы брали инфу для bq20, может подправлю для 30

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

У меня нет плат с bq30z. по этому я не разбирался. Отличия 100% есть и то что код от bq20z. не работает тому показатель.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Да, Вы правы. 54 регистр в bq30 имеет совсем другую структуру. Плюс в том, что есть полное описание этого контроллера. Минус - мои скудные познания, тщетные попытки разобраться в Вашей программе и как-то прочитать Operation Status не привели к положительным результатам. Попробовал вместо ReadSMB (word) использовать ReadBlockSMB - опять Wire error - 3. Прочитать хотя бы один байт через ReadSMB (byte) - то же самое.. В общем тупик.

Может подскажете, как прочитать этот статус, какой функцией и в каком формате? Собственно нужно только получить эти 4 байта, чтобы выяснить залочен контроллер или нет.
  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

sfs Судя по описанию читать надо как блок и результат будет лежать в buff[1]. buff[4], в buff[0] длина блока - по идее должно быть 4.

Последовательный протокол обмена данными IIC (также называемый I2C – Inter-Integrated Circuits, межмикросхемное соединение) использует для передачи данных две двунаправленные линии связи, которые называются шина последовательных данных SDA (Serial Data) и шина тактирования SCL (Serial Clock). Также имеются две линии для питания. Шины SDA и SCL подтягиваются к шине питания через резисторы.

В сети есть хотя бы одно ведущее устройство (Master), которое инициализирует передачу данных и генерирует сигналы синхронизации. В сети также есть ведомые устройства (Slave), которые передают данные по запросу ведущего. У каждого ведомого устройства есть уникальный адрес, по которому ведущий и обращается к нему. Адрес устройства указывается в паспорте (datasheet). К одной шине I2C может быть подключено до 127 устройств, в том числе несколько ведущих. К шине можно подключать устройства в процессе работы, т.е. она поддерживает «горячее подключение».

Описание интерфейса I2C

Описание интерфейса I2C

Давайте рассмотрим временную диаграмму обмена по протоколу I2C. Есть несколько различающихся вариантов, рассмотрим один из распространённых. Воспользуемся логическим анализатором, подключённым к шинам SCL и SDA.

Мастер инициирует обмен. Для этого он начинает генерировать тактовые импульсы и посылает их по линии SCL пачкой из 9-ти штук. Одновременно на линии данных SDA он выставляет адрес устройства, с которым необходимо установить связь, которые тактируются первыми 7-ми тактовыми импульсами (отсюда ограничение на диапазон адресов: 2 7 = 128 минус нулевой адрес). Следующий бит посылки – это код операции (чтение или запись) и ещё один бит – бит подтверждения (ACK), что ведомое устройство приняло запрос. Если бит подтверждения не пришёл, на этом обмен заканчивается. Или мастер продолжает посылать повторные запросы.

Это проиллюстрировано на рисунке ниже. Задача такая: подключиться к ведомому устройству с адресом 0x27 и передать ему строку "SOLTAU.RU". В первом случае, для примера, отключим ведомое устройство от шины. Видно, что мастер пытается установить связь с устройством с адресом 0x27, но не получает подтверждения (NAK). Обмен заканчивается.

Попытка мастера установить соединение с ведомым по I2C

Попытка мастера установить соединение с ведомым по I2C

Теперь подключим к шине I2C ведомое устройство и повторим операцию. Ситуация изменилась. На первый пакет с адресом пришло подтверждение (ACK) от ведомого. Обмен продолжился. Информация передаётся также 9-битовыми посылками, но теперь 8 битов занимают данные и 1 бит – бит подтверждения получения ведомым каждого байта данных. Если в какой-то момент связь оборвётся и бит подтверждения не придёт, мастер прекратит передачу.

Временная диаграмма обмена по протоколу I2C

Временная диаграмма обмена по протоколу I2C

2 Реализация I2Cв Arduino

Arduino использует для работы по интерфейсу I2C два порта. Например, в Arduino UNO и Arduino Nano аналоговый порт A4 соответствует SDA, аналоговый порт A5 соответствует SCL.

Реализация I2C в Arduino UNO и Nano

Реализация I2C в Arduino UNO и Nano

Для других моделей плат соответствие выводов такое:

ПлатаПин SDAПин SCL
Arduino Uno, Nano, Pro и Pro MiniA4A5
Arduino Mega2021
Arduino Leonardo23
Arduino Due20, SDA121, SCL1

3 Библиотека "Wire" для работы с IIC

Для облегчения обмена данными с устройствами по шине I2C для Arduino написана стандартная библиотека Wire. Она имеет следующие функции:

ФункцияНазначение
begin(address) инициализация библиотеки и подключение к шине I2C; если не указан адрес, то присоединённое устройство считается ведущим; используется 7-битная адресация;
requestFrom()используется ведущим устройством для запроса определённого количества байтов от ведомого;
beginTransmission(address)начало передачи данных к ведомому устройству по определённому адресу;
endTransmission()прекращение передачи данных ведомому;
write()запись данных от ведомого в ответ на запрос;
available()возвращает количество байт информации, доступных для приёма от ведомого;
read()чтение байта, переданного от ведомого ведущему или от ведущего ведомому;
onReceive()указывает на функцию, которая должна быть вызвана, когда ведомое устройство получит передачу от ведущего;
onRequest()указывает на функцию, которая должна быть вызвана, когда ведущее устройство получит передачу от ведомого.

4 Подключение I2C устройствак Arduino

Давайте посмотрим, как работать с шиной I2C с помощью Arduino.

Сначала соберём схему, как на рисунке. Будем управлять яркостью светодиода, используя цифровой 64-позиционный потенциометр AD5171 (см. техническое описание), который подключается к шине I2C. Адрес, по которому мы будем обращаться к потенциометру – 0x2c (44 в десятичной системе).

Подключение цифрового потенциометра к Arduino по шине I2C

Подключение цифрового потенциометра к Arduino по шине I2C

5 Управление устройством по шине IIC

Рассмотрим диаграммы информационного обмена с цифровым потенциометром AD5171, представленные в техническом описании:

Рассмотрим диаграммы чтения и записи цифрового потенциометра AD5171

Рассмотрим диаграммы чтения и записи цифрового потенциометра AD5171

Нас тут интересует диаграмма записи данных в регистр RDAC. Этот регистр используется для управления сопротивлением потенциометра.

Откроем из примеров библиотеки "Wire" скетч: Файл Образцы Wire digital_potentiometer. Загрузим его в память Arduino.

После включения вы видите, как яркость светодиода циклически нарастает, а потом гаснет. При этом мы управляем потенциометром с помощью Arduino по шине I2C.

По ссылкам внизу статьи, в разделе похожих материалов (по тегу), можно найти дополнительные примеры взаимодействия с различными устройствами по интерфейсу IIC, в том числе примеры чтения и записи.

6 Дополнительно о шине I2C

Доступно и интересно рассказывает о шине I2C Джереми Блюм в своём видео:

В предыдущей статье на нашем сайте мы рассмотрели использование интерфейса SPI в плате Arduino. А здесь мы рассмотрим еще один очень популярный в настоящее время протокол последовательной связи I2C (Inter Integrated Circuits - последовательная шина обмена данными между интегральными схемами ) и как его использовать в плате Arduino. Если сравнивать протоколы I2C и SPI, то I2C использует только 2 линии (провода), а SPI использует 4 линии, I2C может иметь несколько ведущих (Master) и несколько ведомых (Slave), а SPI может иметь только одного ведущего и нескольких ведомых. То есть если в вашем проекте сразу несколько микроконтроллеров должны быть ведущими, то тогда вам нужно использовать интерфейс (протокол) I2C. Протокол I2C обычно используется для взаимодействия с гироскопами, акселерометрами, датчиками давления, LED дисплеями и т.д.

Внешний вид проекта использования интерфейса I2C в Arduino

В этом проекте мы будем использовать протокол I2C для обмена данными между двумя платами Arduino и передавать между ними значения (от 0 до 127) с помощью потенциометра. Эти принятые значения будут отображаться на ЖК дисплеях, подключенных к каждой плате Arduino. Одна из плат Arduino будет выступать в роли ведущего (Master), а другая – в роли ведомого (Slave).

Что такое протокол I2C и как он работает

Термин IIC расшифровывается как “Inter Integrated Circuits” и часто обозначается как I2C или даже как TWI (2-wire interface protocol), но во всех случаях за этими обозначениями скрывается один и тот же протокол. I2C представляет собой протокол синхронной связи – это значит что оба устройства, которые обмениваются информацией с помощью данного протокола должны использовать общий сигнал синхронизации. Поскольку в этом протоколе используются всего 2 линии (провода), то по одной из них должен передаваться сигнал синхронизации, а по другой – полезная информация.

Впервые протокол I2C был предложен фирмой Phillips. Протокол в самом простом случае соединяет с помощью 2-х линий 2 устройства, одно из устройств должно быть ведущим, а другое – ведомым. Связь возможна только между ведущим и ведомым. Преимуществом протокола (интерфейса) I2C является то, что к одному ведущему можно подключить несколько ведомых.

Схема связи с помощью протокола I2C представлена на следующем рисунке.

Схема связи с помощью протокола I2C

Назначение линий данного интерфейса:

  • Serial Clock (SCL): по ней передается общий сигнал синхронизации, генерируемый ведущим устройством (master);
  • Serial Data (SDA): по ней осуществляется передача данных между ведущим и ведомым.

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

Уровни напряжений для передаваемых сигналов в интерфейсе I2C жестко не определены. В этом плане I2C является достаточно гибким, то есть если устройство запитывается от напряжения 5v, оно для связи с помощью протокола I2C может использовать уровень 5v, а если устройство запитывается от напряжения 3.3v, то оно для связи с помощью протокола I2C может использовать уровень 3v. Но что делать если с помощью данного протокола необходимо связать между собой устройства, работающие от различных питающих напряжений? В этом случае используются преобразователи/переключатели напряжения (voltage shifters).

Существует несколько условий для осуществления передачи данных в протоколе I2C. Инициализация передачи начинается с падения уровня на линии SDA, которое определяется как условие для начала передачи (‘START’ condition) на представленной ниже диаграмме. Как видно из этого рисунка, в то время как на линии SDA происходит падение уровня, в это же самое время на линии SCL ведущий поддерживает напряжение высокого уровня (high).

Принцип передачи данных в протоколе I2C

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

Аналогичным образом, повышение уровня на линии SDA останавливает передачу данных, что на представленной диаграмме обозначено как условие окончания передачи данных (‘STOP’ condition). В это же самое время ведущим на линии SCL поддерживается напряжение высокого уровня (high).

На следующем рисунке представлена структура адреса ведомого в протоколе I2C.

Структура адреса ведомого в протоколе I2C

Бит R/W показывает направление передачи следующих за ним байт, если он установлен в HIGH – это значит что будет передавать ведомый (slave), а если он установлен в low – это значит что будет передавать ведущий (master).

Каждый бит передается в своем временном цикле, то есть нужно 8 временных циклов чтобы передать байт информации. После каждого переданного или принятого байта 9-й временной цикл используется для подтверждения/не подтверждения (ACK/NACK) приема информации. Этот бит подтверждения (ACK bit) формируется либо ведомым, либо ведущим в зависимости от ситуации. Для подтверждения приема информации (ACK) на линии SDA ведущим или ведомым устанавливается низкий уровень (low) в 9 временном цикле, в противном случае происходит не подтверждение приема информации (NACK).

Где применяется протокол I2C

Протокол I2C используется для передачи информации только на короткие расстояния. Он обеспечивает достаточно надежную передачу данных из-за наличия в нем сигнала синхронизации. Обычно данный протокол используется для передачи информации от датчиков или других устройств ведущим устройствам. В данном случае несомненным удобством использования протокола I2C является то, что при обмене данными с ведомыми устройствами ведущий микроконтроллер использует минимум линий (контактов). Если вам нужна связь на более далекие расстояния, то вам необходимо присмотреться к протоколу RS232, если же вам нужна более надежная связь чем в протоколе I2C, то вам лучше использовать протокол SPI.

Протокол I2C в Arduino

На следующем рисунке показаны контакты платы Arduino UNO, которые используются для связи по протоколу I2C.

Контакты платы Arduino UNO, которые используются для связи по протоколу I2C

Линия протокола I2C Контакт платы Arduino UNO
SDA A4
SCL A5

Для осуществления связи по протоколу I2C в плате Arduino используется библиотека <Wire.h>. В ней содержатся следующие функции для связи по протоколу I2C.

1. Wire.begin(address).

Эта команда производит инициализацию библиотеки Wire и осуществляет подключение к шине I2C в качестве ведущего (master) или ведомого (slave). 7-битный адрес ведомого в данной команде является опциональным и если он не указан [Wire.begin()], то устройство (плата Arduino) подключается к шине I2C в качестве ведущего (master).

2. Wire.read().

Эта функция используется для считывания байта, принятого от ведущего или ведомого.

3. Wire.write().

Эта функция используется для записи данных в устройство, являющееся ведомым или ведущим.

От ведомого ведущему (Slave to Master): ведомый записывает (передает) данные ведущему когда в ведущем работает функция Wire.RequestFrom().

От ведущему ведомому (Master to Slave): в этом случае функция Wire.write() должна использоваться между вызовами функций Wire.beginTransmission() и Wire.endTransmission().

Функцию Wire.write() можно использовать в следующих вариантах:

  • Wire.write(value); value - значение передаваемого одиночного байта;
  • Wire.write(string) – для передачи последовательности байт;
  • Wire.write(data, length); data – массив данных для передачи в виде байт, length – число байт для передачи.

4. Wire.beginTransmission(address).

Эта функция используется для начали передачи по протоколу I2C устройству с заданным адресом ведомого (slave address). После этого вызывается функция Wire.write() с заданной последовательностью байт для передачи, а после нее функция endTransmission() для завершения процесса передачи.

5. Wire.endTransmission().

Эта функция используется для завершения процесса передачи ведомому устройству, который до этого был инициирован функциями beginTransmission() и Wire.write().

6. Wire.onRequest().

Эта функция вызывается когда ведущий запрашивает данные с помощью функции Wire.requestFrom() от ведомого устройства. В этом случае мы можем использовать функцию Wire.write() для передачи данных ведущему.

7. Wire.onReceive().

Эта функция вызывается когда ведомое устройство получает данные от ведущего. В этом случае мы можем использовать функцию Wire.read() для считывания данных передаваемых ведущим.

8. Wire.requestFrom(address,quantity).

Эта функция используется в ведущем устройстве чтобы запросить байты (данные) с ведомого устройства. После этого используется функция Wire.read() чтобы принять данные переданные ведомым устройством.
address: 7-битный адрес устройства, с которого запрашиваются байты (данные).
quantity: число запрашиваемых байт.

Необходимые компоненты

  1. Плата Arduino Uno – 2 шт. (купить на AliExpress).
  2. ЖК дисплей 16х2 – 2 шт. (купить на AliExpress).
  3. Потенциометр 10 кОм – 4 шт. (купить на AliExpress).
  4. Макетная плата.
  5. Соединительные провода.

Работа схемы

Схема проекта по применению интерфейса I2C в плате Arduino представлена на следующем рисунке.

Схема проекта по применению интерфейса I2C в плате Arduino

Для демонстрации возможностей использования связи по протоколу I2C мы использовали две платы Arduino Uno с подключенными к ним ЖК дисплеями и потенциометрами. С помощью потенциометров будут определяться значения, передаваемые между платами в направлениях ведущий-ведомый и ведомый-ведущий.

Мы будем считывать аналоговое значение напряжения, подаваемое на контакт A0 платы Arduino с помощью потенциометра и преобразовывать его в цифровое значение в диапазоне от 0 до 1023 (с помощью АЦП на этом контакте). В дальнейшем эти значения с выхода АЦП (аналогово-цифрового преобразователя) будут преобразовываться в диапазон 0-127 поскольку мы можем передавать только 7-битные данные при помощи протокола I2C. Интерфейс I2C мы будем использовать на выделенных для него в плате Arduino контактах A4 и A5.

Значения на ЖК дисплее, подключенном к ведомой плате Arduino, будут изменяться в зависимости от положения потенциометра на ведущей стороне и наоборот.

Демонстрация работы проекта

Объяснение программ для Arduino

Нам будут необходимы две программы – одна для ведущей платы Arduino, а другая – для ведомой. Полные тексты обоих программ приведены в конце статьи, здесь же мы рассмотрим их основные фрагменты.

Объяснение программы для ведущей (Master) платы Arduino

1. Первым делом в программе мы должны подключить библиотеку Wire для задействования возможностей протокола I2C и библиотеку для работы с ЖК дисплеем. Также нам необходимо сообщить плате Arduino к каким ее контактам подключен ЖК дисплей.

Читайте также: