Программируйте микроконтроллер PIC как подчиненное устройство I2C для пользовательского датчика и интерфейса ввода / вывода
Нет интерфейса I2C с этим датчиком? Нет проблем. Запрограммируйте микросхему PIC в качестве ведомого устройства I2C для пользовательского интерфейса датчиков и ввода / вывода. Здесь мы используем три датчика DHT22 на одном интерфейсе I2C.
Шина с интегральной схемой (I2C) является распространенной и удобной технологией для подключения устройств к встроенным контроллерам. Этот популярный протокол последовательного интерфейса позволяет микроконтроллерной плате, такой как Arduino UNO, взаимодействовать с периферийным устройством, например с датчиком, с использованием двух коммуникационных проводов, часов и данных (SCL и SDA) и двух проводов питания (Vcc и GND). Каждое периферийное устройство I2C адресуется, позволяя подключать несколько устройств к тем же соединениям I2C, что является основной причиной его популярности.
Но что вы будете делать, если периферийное устройство, которое вы хотите использовать, не использует протокол связи I2C? Одним из решений является сворачивание собственного интерфейса I2C. Этот проект представляет собой относительно простой и недорогой способ сделать именно это.
В частности, мы будем использовать экономичную микросхему PIC12F1840 в качестве подчиненного устройства I2C, которое будет взаимодействовать с Arduino UNO, а также с большинством любых плат микроконтроллера с использованием одного ведущего / множественного подчиненного устройства, схемы I2C.

Схема проекта на макетах
Чтобы проиллюстрировать технику таким образом, чтобы какая-то полезность, микросхема PIC будет взаимодействовать с тремя датчиками влажности и температуры DHT22 (aka AM2302). Конечным результатом является простой способ развертывания всех трех датчиков с использованием одной шины I2C. Этот метод можно расширить, включив в него другие пользовательские сенсорные приложения, а также пользовательские расширения ввода / вывода и их комбинации.
Аппаратное обеспечение
Схема состоит из интерфейса PIC I2C и, отдельно, трех датчиков DHT. Интерфейс PIC I2C содержит 12F1840 IC, несколько компонентов поддержки, заголовок / перемычку (JP1) для подключения платы к ведущему устройству и три дополнительных заголовка / перемычки для подключения трех сенсорных плат. Четыре соединения на J1 для Arduino UNO составляют + 5v, GND, SDA и SCL, которые доступны на заголовках платы Arduino. 12F1840 включает в себя 6 контактов ввода / вывода. Два из этих контактов, RA1 и RA2, образуют линии SDA и SCL для связи I2C. Я включил 10K, I2C подтягивающие резисторы (R1 и R2) в этих строках, и они работают нормально, но вы можете настроить значения в своем приложении.
Кроме того, эти резисторы могут потребоваться полностью устранить, если у вас уже есть подтягивающие резисторы на линиях I2C в вашей системе. Три контакта ввода / вывода RA0, RA4 и RA5 подключаются к линиям данных на датчиках DHT22 # 1, # 2 и # 3 соответственно. Оставшийся контакт (RA3) не используется и остается несвязным. С помощью дополнительных схем расширения этот вывод может функционировать как вход общего назначения или включить аппаратный сброс (MCLR).

Рисунок 1. Схема для платы PIC I2C
Часть | Описание |
---|---|
U1 | PIC 12F1840 / P |
С1 | Конденсатор 0.1uf |
R1, R2 | Резистор 10K |
J1, DHT1-3 | 4-контактный разъем / перемычка |
Кабели | 3 X 4-контактный |
Каждый из датчиков монтируется на отдельной плате с намерением разместить их на некотором расстоянии друг от друга и подключить к плате I2C с помощью 4-контактных кабелей. Поскольку можно использовать только 3 из 4 контактов на DHT22, вы можете заменить 3-контактный кабель и разъемы (при необходимости подключив соответствующие соединения).

Датчик влажности и температуры DHT22 или AM2302: контакты: 1-Vdd, 2-Data, 3 n / c, 4-GND
Платы датчиков также относительно просты, содержат только датчик DHT22, нагрузочный резистор на линии передачи данных и байпасный конденсатор через линии электропередачи.

Рисунок 2. Схема для одного датчика DHT22. Для каждого из 3 датчиков требуется одна плата
Часть | Описание |
---|---|
DHT22 | Датчик DHT22 |
С1 | 0, 01 uf конденсатор |
R1 | 4.7K резистор |
J1 | 4-контактный разъем / перемычка |
Проект, представленный, предназначен для использования с 5v, но я также тестировал его на 3, 3 В, и он отлично работает, поскольку это напряжение находится в рабочем диапазоне как PIC IC, так и DHT22.
Внедрение пользовательского датчика I2C
PIC 12F1840 является примером усовершенствованной 8-битной архитектуры среднего класса Microchip. Это 8-контактный микроконтроллер, который включает в себя большое количество функций периферийного устройства. Главным из этих функций периферийного устройства для данного проекта является основной синхронный последовательный порт или MSSP. Эта функция позволяет нам реализовать интерфейс I2C таким образом, что чип будет функционировать как подчиненное устройство I2C. Возможно, самое главное, программное обеспечение «тяжелая атлетика» уже сделано для нас в заявке на приложение (AN734C). Код в этой заметке приложения составляет основу нашего механизма I2C. Он управляется прерываниями и позволит чипу по существу функционировать как 32-байтовый массив памяти, позволяющий считывать и записывать в двух направлениях между ведущим и ведомым устройствами. Прилагаемая программа включает код из примечания к приложению, измененный только для использования с 12F1840.
Ведущее устройство I2C (в этом примере, Arduino UNO) будет выдавать команды подчиненному устройству I2C, записывая в ячейку выбора в массиве памяти. PIC, как подчиненное устройство I2C, выполнит команды (то есть, считывает датчики DHT22) и сообщит информацию о состоянии и информацию о датчике через массив памяти. Затем мастер считывает массив памяти для извлечения показаний датчика.
Карта памяти
Мы будем ссылаться на 32-байтовый массив памяти как Array (0) через Array (31). Массив (0) служит местом, где мастер (Arduino) выдаст команду и где подчиненный (PIC) будет сообщать о состоянии, которое будет считаться ведущим. В этом отношении ПИК вернет одно из трех значений, как описано в таблице. Эти значения укажут состояние включения питания, успешное выполнение допустимой команды и получение плохой или неизвестной команды.
ARRAY (0) STATUS - значение, установленное PIC для отчета о состоянии. | |
---|---|
0x00 | Значение мощности. Кроме того, значение, установленное при сбросе программного обеспечения PIC |
0x01 | Последняя команда выполнена успешно |
0xF1 | Была запрошена команда Bad (неизвестная) |
Arduino будет записывать в Array (0) с одним из четырех возможных значений команд, как описано ниже. Они поручат ПОС либо прочитать один из датчиков DHT, либо выполнить сброс.
ARRAY (0) COMMAND - значение, установленное Arduino для выдачи команды. | |
---|---|
0x02 | Читайте датчик DHT №1 |
0x03 | Считать датчик DHT №2 |
0x04 | Прочитать датчик DHT №3 |
0x10 | Выполните программный сброс ПОС |
Когда команда считывания датчика была выдана, путем записи 0x02, 0x03 или 0x04 в Array (0), и PIC вернул успешное состояние выполнения, записав 0x01 в Array (0), данные датчика будут доступны для Arduino путем считывания массива памяти.
DHT22 возвращает 5 байтов, чтобы указать влажность (относительную влажность или относительную влажность) и температуру (градусы Цельсия) следующим образом: интеграл RH, RH десятичный, интеграл температуры, десятичная величина температуры и контрольная сумма, которая представляет собой сумму суммы всех четырех байтов И 255. Эти 5 байтов будут записаны в разные ячейки памяти с помощью ПОС после команд считывающего датчика. Ячейки Array (16) -Array (31) - это неиспользуемая свободная память, доступная для пользовательского использования.
ARRAY. - Значения, установленные PIC для чтения Arduino. | |
---|---|
Массив (1) -Array (5) | Датчик DHT №1: интеграл RH, RH-десятичный, интеграл температуры, временный десятичный, контрольная сумма |
Массив (6) -Array (10) | Датчик DHT №1: интеграл RH, RH-десятичный, интеграл температуры, временный десятичный, контрольная сумма |
Массив (11) -Array (15) | Датчик DHT №1: интеграл RH, RH-десятичный, интеграл температуры, временный десятичный, контрольная сумма |
Массив (16) -Array (32) | Доступно для использования |
Окончательная команда доступна 0x10 и приведет к программному сбросу PIC 12F1840. Обычно эту команду не нужно использовать, но она может быть полезна в случае неожиданной ситуации.
Чтение датчика температуры и влажности DHT22
Работа считывания датчиков DHT22 и сохранение их в массиве памяти также падает на чип PIC. Низкая цена, доступность и относительная надежность DHT22 сделали ее повсеместной. Однако последовательный протокол, используемый чипом, требует очень точного времени. Эти требования к синхронизации могут быть проблематичными для систем с относительно медленным вводом-выводом или с системами (например, с интегральными микросхемами System on Chip (SOC)), чьи множественные высокоприоритетные функции могут сделать требуемые выделенные временные требования неудобными. В этом отношении имеет смысл «отгрузить нагрузку» на заданную ИС.
Связь с датчиком осуществляется через определенный «однопроводный» последовательный протокол, который не следует путать с однопроводным протоколом Dallas / Maxim Semiconductor - они совершенно разные. В нем задействованы три соединения (Vcc, GND и Data). Штырь данных - это место, где все манипуляции происходят, и тщательное прочтение таблицы данных даст подробности.
Вкратце, следующие шаги описывают взаимодействие со стороны ПИК, необходимое для считывания датчика, и прилагаемая программа MPASM была прокомментирована для облегчения следования потоку программы.
1. Установите выходную линию данных, установите ее на низком уровне и подождите 18 микросекунд.
2. Возьмите линию передачи данных в течение 30 микросекунд.
3. Задайте линию данных для ввода и мониторинга ее состояния. DHT22 должен установить низкое значение в течение 80 микросекунд, а затем максимум на 80 микросекунд.
4. Шаги 1-3 являются преамбулой к потоку данных. Затем DHT22 установит линию передачи данных на 50 микросекунд, которая сигнализирует о начале бит данных.
5. Здесь он становится немного сложнее. После начального времени бит DHT22 приведет к тому, что линия передачи данных будет высока для ~ 27 микросекунд или в течение 70 микросекунд. Первый сигнал бит данных равен «0», а последний сигнализирует, что бит данных равен «1».
6. Следуя бит данных (на шаге 5 выше), DHT22 перейдет в другой бит начального бита 50 микросекунд, за которым следует другой бит данных (либо «0», либо «1», как описано выше в 5), и эта последовательность повторяется для 40 бит, составляющих 5 байтов данных датчика (интеграл RH, RH десятичный, температурный интеграл, десятичная температура и контрольная сумма).
Вы можете видеть, что протокол требует точного времени и что время для считывания датчика является переменным в том смысле, что оно зависит от количества «0» и «1» бит в чтении. Одна из стратегий состоит в том, чтобы измерить каждый из интервалов и затем решить, соответствует ли бит данных интервалу «0» или «1». Я выбрал другую стратегию, описанную ниже, которая менее требовательна и очень надежна.

Рисунок 3. Стратегия различать «0» от «1» бит в последовательном потоке
После преамбулы мы ждем окончания начального битового времени, а затем задерживаем около 43 микросекунд, а затем читаем строку данных. Если линия данных низкая, бит был «0», и мы будем в следующем стартовом битовом времени. В этом случае мы записываем бит как «0» и дождитесь окончания начала бит до начала следующего бит. Если линия данных высока, бит равен «1», и мы все еще находимся в битном времени. В этом случае мы записываем бит как «1», а затем ждем следующего начального времени бит, чтобы начать, а затем дождитесь окончания начального времени бит перед чтением следующего бита.
Когда ПИК закончит считывание запрошенного датчика DHT22, данные доступны для чтения через интерфейс I2C. В этом случае Array (0) будет считан как 0x01, что указывает на успешное завершение последней команды.
Получение данных датчиков с помощью Arduino UNO
Доступ к ячейкам памяти для запроса и считывания данных датчика через интерфейс I2C осуществляется обычным способом. Читатели, которые запрограммировали функции Arduino для I2C, распознают этапы, и добавленный эскиз был прокомментирован для облегчения потока программы.
Во-первых, вам нужно заявление,
#include
для использования библиотеки I2C.
Затем вам понадобится адрес I2C ПОС. Это устанавливается в коде PIC MPASM по строке программы:
#define I2C_ADDRESS 0x32; Slave address
Этот адрес должен быть сдвинут вправо одним битом, чтобы сформировать адрес, который будет использовать Arduino. Те, кто знаком с 7-разрядной схемой адресации I2C, распознают этот, часто неудобный шаг. Правое смещение 0x32 дает нам 0x19, и это будет адрес I2C, который использует Arduino. Конечно, вы можете установить этот адрес в коде MPASM на любой доступный адрес I2C, который у вас есть.
Чтобы начать катить мяч, используйте заявление Wire.begin (); // присоединяем шину как master - обычно в setup ().
Ниже приведены шаги для выдачи команды для считывания датчика №2 следующим образом (для переменной «адрес» установлено значение 0x19):
Wire.beginTransmission(address);
Wire.write(0); // buffer index pointer
Wire.write(0); // buffer index pointer
Wire.write(3); // command byte (3=read DHT22 #2)
Wire.write(3); // command byte (3=read DHT22 #2)
Wire.endTransmission();
delay(50); // wait for it to be done - 50 msec to start
Задержка в этой последней строке ожидает завершения считывания датчика и, вероятно, дольше, чем нужно, но лучше всего быть консервативным. Вы можете попытаться уменьшить задержку, если это необходимо вашему приложению.
На этом этапе данные из датчика DHT # 2 должны быть в массиве (6) -Array (11). Чтобы получить данные, используйте следующее:
Сначала прочитайте байт статуса в Array (0)
Wire.beginTransmission(address);
Wire.write(0); // buffer index pointer
Wire.write(0); // buffer index pointer
Wire.endTransmission();
Wire.requestFrom(address, 1);
// update the status byte
DHT(0)=Wire.read();
Убедитесь, что байт статуса (теперь в DHT (0)) равен 0x01, что указывает на успешное завершение команды. Затем получите 5 байтов данных DHT (из массива (6) -Array (11)) со следующими утверждениями:
Wire.beginTransmission(address);
Wire.write(6); // buffer index pointer (point to data for DHT #2)
Wire.write(6); // buffer index pointer (point to data for DHT #2)
Wire.endTransmission();
Wire.requestFrom(address, 5);
После того, как мы поместим эти данные в программный массив DHT (6) = - DHT (10), мы преобразуем данные в RH и температуру и, наконец, проверим, что CRC хорош:
// Humidity
RHz2=DHT(6);
RHz2*=256;
RHz2+=DHT(7);
RHz2/=10;
// Temperature
TempCz2=DHT(8)&0x7f;
TempCz2*=256;
TempCz2+=DHT(9);
TempCz2/=10;
if(DHT(8)&0x80)
{
TempCz2*=-1;
}
TempFz2=TempCz2 * 9 / 5 +32;
// checksum
if ((DHT(6)+DHT(7)+DHT(8)+DHT(9) & 255) != DHT(10))
{
Serial.print(" *** BAD CRC! *** ");
}
else{
Serial.print(" CRC is good ");
}
Два других датчика DHT22 считываются таким же образом, используя соответствующие коды команд.
Включенный пример эскиза Arduino просто считывает все три датчика каждые 5 секунд и отображает данные на последовательном мониторе.

Экранный выход из эскиза Arduino
Начало и запуск
Программное обеспечение, необходимое для использования схем, включено здесь и состоит из: исходного кода 12F1840 MPASM, файла кода HEX 12F1840 и эскиза тестов Arduino. Вам нужно будет запрограммировать чип PIC 12F1840. Если вы раньше использовали PIC-чипы, это не должно представлять собой сложный шаг. Если вы не знакомы с чипами PIC, это может показаться сложной задачей. Однако есть много недорогих программистов, в том числе несколько проектов DIY, которые получили большую поддержку. Ассемблер MPASM доступен бесплатно от Microchip.
Кроме того, начиная с более мелкого чипа PIC, такого как 12F1840, задача менее сложна, чем может показаться. Вы можете собрать включенный исходный код MPASM для программирования как есть или внести изменения, такие как адрес I2C. В качестве альтернативы, большинство программистов позволят вам использовать прямой файл кода HEX для программирования чипа с исходным кодом, как указано.
Заключительные мысли
Этот проект призван обеспечить полезное дополнение к более крупному проекту встроенного контроллера. В частности, он хорошо подходит для тех, где вам необходимо контролировать влажность и температуру в нескольких зонах. Он также предназначен в качестве отправной точки для использования шины I2C в пользовательских приложениях. Хотя 12F1840 очень недорог и подходит для этого проекта, расширения могут быть реализованы с использованием более крупных микросхем PIC, которые содержат требуемую функцию MSSP, но также содержат больше GPIO. Таким образом, вполне возможно реализовать недорогие комбинации интерфейсов датчиков и расширения ввода-вывода на основе I2C.
Попробуйте этот проект сами! Получить спецификацию.
Скачать код