Оглавление:

Arduino и PCF8591 ADC DAC IC: 7 шагов
Arduino и PCF8591 ADC DAC IC: 7 шагов

Видео: Arduino и PCF8591 ADC DAC IC: 7 шагов

Видео: Arduino и PCF8591 ADC DAC IC: 7 шагов
Видео: MCP4921 12bit цифро-аналоговый преобразователь 2024, Июль
Anonim
Arduino и PCF8591 ADC DAC IC
Arduino и PCF8591 ADC DAC IC

Вы когда-нибудь хотели больше аналоговых входных контактов в своем проекте Arduino, но не хотели раскошелиться на Mega? Или вы хотите генерировать аналоговые сигналы? Тогда ознакомьтесь с предметом нашего руководства - микросхемой NXP PCF8591.

Он решает обе эти проблемы, поскольку имеет один ЦАП (цифро-аналоговый) преобразователь, а также четыре АЦП (аналого-цифровые преобразователи) - все они доступны через шину I2C. PCF8591 доступен в вариантах DIP, поверхностного монтажа и модуля, что позволяет легко экспериментировать.

Прежде чем двигаться дальше, загрузите технический паспорт. PCF8591 может работать как от 5 В, так и от 3,3 В, поэтому, если вы используете Arduino Due, Raspberry Pi или другую плату разработки на 3,3 В, все в порядке. Теперь мы сначала объясним ЦАП, а затем АЦП.

Шаг 1. Использование ЦАП (цифро-аналоговый преобразователь)

Использование ЦАП (цифро-аналоговый преобразователь)
Использование ЦАП (цифро-аналоговый преобразователь)

ЦАП на PCF8591 имеет разрешение 8 бит, поэтому он может генерировать теоретический сигнал от нуля вольт до опорного напряжения (Vref) за 255 шагов. В демонстрационных целях мы будем использовать Vref 5 В, и вы можете использовать более низкое значение Vref, такое как 3,3 В, или любое другое максимальное значение, которое вы хотите, но оно должно быть меньше напряжения питания.

Обратите внимание, что при нагрузке на аналоговый выход (реальная ситуация) максимальное выходное напряжение будет падать - в таблице данных (которую вы загрузили) показано падение на 10% для нагрузки 10 кОм. Теперь о нашей демонстрационной схеме.

Обратите внимание на использование подтягивающих резисторов 10 кОм на шине I2C и конденсатора 10 мкФ между 5 В и GND. Адрес шины I2C устанавливается комбинацией контактов A0 ~ A2, и если все они подключены к GND, адрес равен 0x90. Аналоговый выход может быть взят с контакта 15 (и есть отдельный аналоговый GND на контакте 13. Также подключите контакт 13 к GND, а цепь GND к Arduino GND.

Для управления ЦАП нам нужно отправить два байта данных. Первый - это управляющий байт, который просто активирует ЦАП и равен 1000000 (или 0x40), а следующий байт - это значение от 0 до 255 (выходной уровень). Это показано на следующем рисунке:

// Пример 52.1 PCF8591 DAC demo

#include "Wire.h" #define PCF8591 (0x90 >> 1) // Адрес шины I2C void setup () {Wire.begin (); } void loop () {for (int i = 0; i <256; i ++) {Wire.beginTransmission (PCF8591); // пробуждаем PCF8591 Wire.write (0x40); // байт управления - включить ЦАП (1000000 бинарный) Wire.write (i); // значение для отправки в DAC Wire.endTransmission (); // конец передачи}

для (int i = 255; i> = 0; --i)

{Wire.beginTransmission (PCF8591); // пробуждаем PCF8591 Wire.write (0x40); // байт управления - включить ЦАП (1000000 бинарный) Wire.write (i); // значение для отправки в DAC Wire.endTransmission (); // конец передачи}}

Вы заметили битовый сдвиг адреса шины в операторе #define? Arduino отправляет 7-битные адреса, но PCF8591 требует 8-битных, поэтому мы сдвигаем байт на один бит.

Шаг 2:

Изображение
Изображение

Результаты скетча показаны на изображении, мы подключили Vref к 5V, а пробник осциллографа и GND к аналоговому выходу и GND соответственно.

Шаг 3:

Изображение
Изображение

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

// Пример 52.2 PCF8591 DAC demo - синусоида

#include "Wire.h" #define PCF8591 (0x90 >> 1) // адрес шины I2C uint8_t sine_wave [256] = {0x80, 0x83, 0x86, 0x89, 0x8C, 0x90, 0x93, 0x96, 0x99, 0x9C, 0x9F, 0xA2, 0xA5, 0xA8, 0xAB, 0xAE, 0xB1, 0xB3, 0xB6, 0xB9, 0xBC, 0xBF, 0xC1, 0xC4, 0xC7, 0xC9, 0xCC, 0xCE, 0xD1, 0xD3, 0xDxD5, 0xD0xD5 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEB, 0xED, 0xEF, 0xF0, 0xF1, 0xF3, 0xF4, 0xF5, 0xF6, 0xF8, 0xF9, 0xFA, 0xFA, 0xFFF, 0xDFE, 0xDFE, 0xFFE, 0xDFE, 0xDFE 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFE, 0xFD, 0xFD, 0xFC, 0xFB, 0xFA, 0xFA, 0xF9, 0xF8, 0xF6, 0xF5, 0xF4, 0x0F3, 0xF3 0xED, 0xEB, 0xEA, 0xE8, 0xE6, 0xE4, 0xE2, 0xE0, 0xDE, 0xDC, 0xDA, 0xD8, 0xD5, 0xD3, 0xD1, 0xCE, 0xCC, 0xC9, 0xC7, 0xC9, 0xC1, 0xC1, 0xBF 0xB3, 0xB1, 0xAE, 0xAB, 0xA8, 0xA5, 0xA2, 0x9F, 0x9C, 0x99, 0x96, 0x93, 0x90, 0x8C, 0x89, 0x86, 0x83, 0x80, 0x7D, 0x7A, 0x77, 0x6x, 0x674 0x67, 0x64, 0x61, 0x5E, 0x5B, 0x58, 0x55, 0x52, 0x4F, 0x4D, 0x4A, 0x47, 0x44, 0x41, 0x3F, 0x 3C, 0x39, 0x37, 0x34, 0x32, 0x2F, 0x2D, 0x2B, 0x28, 0x26, 0x24, 0x22, 0x20, 0x1E, 0x1C, 0x1A, 0x18, 0x16, 0x15, 0x13, 0x11, 0x100, 0x0D0F 0x0B, 0x0A, 0x08, 0x07, 0x06, 0x06, 0x05, 0x04, 0x03, 0x03, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02 0x04, 0x05, 0x06, 0x06, 0x07, 0x08, 0x0A, 0x0B, 0x0C, 0x0D, 0x0F, 0x10, 0x11, 0x13, 0x15, 0x16, 0x18, 0x1A, 0x1C, 0x1E, 0x22, 0x26 0x2B, 0x2D, 0x2F, 0x32, 0x34, 0x37, 0x39, 0x3C, 0x3F, 0x41, 0x44, 0x47, 0x4A, 0x4D, 0x4F, 0x52, 0x55, 0x58, 0x5B, 0x5E, 0x61, 0x64x6, 0x67, 0x61, 0x64, 0x67, 0x70, 0x74, 0x77, 0x7A, 0x7D}; пустая настройка () {Wire.begin (); } void loop () {for (int i = 0; i <256; i ++) {Wire.beginTransmission (PCF8591); // пробуждаем PCF8591 Wire.write (0x40); // байт управления - включить ЦАП (1000000 бинарный) Wire.write (sine_wave ); // значение для отправки в DAC Wire.endTransmission (); // конец передачи}}

Шаг 4:

Изображение
Изображение

Для следующего дампа изображения DSO мы изменили Vref на 3.3V - обратите внимание на изменение максимумов на синусоиде.

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

Шаг 5: Использование АЦП (аналого-цифровых преобразователей)

Если вы использовали функцию analogRead () на своем Arduino (еще в главе 1), то вы уже знакомы с АЦП. Без PCF8591 мы можем считывать напряжение между нулем и Vref, и он вернет значение от нуля до 255, которое прямо пропорционально нулю и Vref.

Например, при измерении 3,3 В должно получиться 168. Разрешение (8-битное) АЦП ниже, чем у встроенного Arduino (10-битного), однако PCF8591 может делать то, что не может АЦП Arduino. Но мы скоро вернемся к этому. Во-первых, чтобы просто прочитать значения каждого вывода АЦП, мы отправляем управляющий байт, чтобы сообщить PCF8591, какой АЦП мы хотим прочитать. Для АЦП от нуля до трех управляющий байт равен 0x00, 0x01, ox02 и 0x03 соответственно.

Затем мы запрашиваем два байта данных обратно у АЦП и сохраняем второй байт для использования. Почему два байта? PCF8591 сначала возвращает ранее измеренное значение, а затем текущий байт. (См. Рисунок 8 в техническом паспорте). Наконец, если вы не используете все выводы АЦП, подключите неиспользуемые к GND. Следующий пример скетча просто извлекает значения с каждого вывода АЦП по одному, а затем отображает их на последовательном мониторе:

#include "Wire.h"

#define PCF8591 (0x90 >> 1) // адрес шины I2C #define ADC0 0x00 // управляющие байты для чтения отдельных АЦП #define ADC1 0x01 #define ADC2 0x02 #define ADC3 0x03 byte value0, value1, value2, value3; пустая настройка () {Wire.begin (); Serial.begin (9600); } void loop () {Wire.beginTransmission (PCF8591); // пробуждаем PCF8591 Wire.write (ADC0); // управляющий байт - чтение ADC0 Wire.endTransmission (); // завершение передачи Wire.requestFrom (PCF8591, 2); value0 = Wire.read (); value0 = Wire.read (); Wire.beginTransmission (PCF8591); // пробуждаем PCF8591 Wire.write (ADC1); // управляющий байт - чтение ADC1 Wire.endTransmission (); // завершение передачи Wire.requestFrom (PCF8591, 2); значение1 = Wire.read (); значение1 = Wire.read (); Wire.beginTransmission (PCF8591); // пробуждаем PCF8591 Wire.write (ADC2); // управляющий байт - чтение ADC2 Wire.endTransmission (); // завершение передачи Wire.requestFrom (PCF8591, 2); значение2 = Wire.read (); значение2 = Wire.read (); Wire.beginTransmission (PCF8591); // пробуждаем PCF8591 Wire.write (ADC3); // управляющий байт - чтение ADC3 Wire.endTransmission (); // завершение передачи Wire.requestFrom (PCF8591, 2); значение3 = Wire.read (); значение3 = Wire.read (); Serial.print (значение0); Serial.print (""); Serial.print (значение1); Serial.print (""); Serial.print (значение2); Serial.print (""); Serial.print (значение3); Serial.print (""); Serial.println (); }

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

Шаг 6:

Для этого измените управляющий байт на запрос автоинкремента, что выполняется установкой бита 2 управляющего байта в 1. Итак, чтобы начать с ADC0, мы используем новый управляющий байт двоичного значения 00000100 или шестнадцатеричного 0x04. Затем запросите пять байтов данных (мы снова игнорируем первый байт), что заставит PCF8591 вернуть все значения в одной цепочке байтов. Этот процесс показан на следующем рисунке:

#include "Wire.h"

#define PCF8591 (0x90 >> 1) // Байт адреса шины I2C значение0, значение1, значение2, значение3; пустая настройка () {Wire.begin (); Serial.begin (9600); } void loop () {Wire.beginTransmission (PCF8591); // пробуждаем PCF8591 Wire.write (0x04); // управляющий байт - считываем ADC0, затем автоматически увеличиваем Wire.endTransmission (); // завершение передачи Wire.requestFrom (PCF8591, 5); value0 = Wire.read (); value0 = Wire.read (); значение1 = Wire.read (); значение2 = Wire.read (); значение3 = Wire.read (); Serial.print (значение0); Serial.print (""); Serial.print (значение1); Serial.print (""); Serial.print (значение2); Serial.print (""); Serial.print (значение3); Serial.print (""); Serial.println (); }

Ранее мы упоминали, что PCF8591 может делать то, чего не может АЦП Arduino, а именно дифференциальный АЦП. В отличие от несимметричного Arduino (т.е. он возвращает разницу между напряжением положительного сигнала и GND, дифференциальный АЦП принимает два сигнала (которые не обязательно должны быть привязаны к земле) и возвращает разницу между двумя сигналами. Это может быть удобно для измерения небольших изменений напряжения для тензодатчиков и т. Д.

Шаг 7:

Изображение
Изображение

Настройка PCF8591 для дифференциального АЦП - это простой вопрос изменения байта управления. Если вы перейдете к седьмой странице спецификации, то рассмотрите различные типы программирования аналогового входа. Ранее мы использовали режим’00’ для четырех входов, однако вы можете выбрать другие, которые четко проиллюстрированы, например изображение.

Таким образом, чтобы установить управляющий байт для двух дифференциальных входов, используйте двоичный код 00110000 или 0x30. Затем нужно просто запросить байты данных и работать с ними. Как вы можете видеть, есть также комбинированный одиночный / дифференциальный и комплексный трехдифференциальный вход. Однако пока оставим их.

Надеюсь, вы нашли это интересным, будь то добавление ЦАП к вашим экспериментам или изучение немного больше об АЦП. Пожалуйста, рассмотрите возможность заказа PCF8591 у PMD Way.

Этот пост предоставлен pmdway.com - все для производителей и любителей электроники с бесплатной доставкой по всему миру.

Рекомендуемые: