AD7793 — малошумящий 24-разрядный сигма-дельта АЦП с тремя дифференциальными аналоговыми входами.
АЦП AD7793 предназначен для высокоточного измерения постоянного напряжения, может применяться для измерения напряжения термопар и других датчиков с выходным напряжением в несколько единиц или десятков мВ. Так имеет два выхода стабилизированного тока для питания термометров сопротивления.
Входное напряжение АЦП ограничено напряжением опорного источника питания которое может иметь значения 1,25 или 2,5 В. В данной статье рассмотрен пример использования внутреннего источника опорного напряжения которое имеет значение 1,17 В.
АЦП имеет три дифференциальных входа, вход IN3 может использоваться как вход для подачи внешнего опорного напряжения. Входы АЦП могут работать в дифференциальном и несимметричном режиме.
Схема подключения к Arduino
Характеристики AD7793:
- Напряжение питания цифровое от 2,7 до 5,25 В
- Напряжение питания аналоговое от 2,7 до 5,25 В
- Эффективное разрешение до 23 бит
- Ток потребления 400 мкА
- Ток потребления в режиме ожидания не более 1 мкА
- Частота измерения от 4,17 Гц до 500 Гц
- 3 дифференциальных входа
- Внутренний источник опорного напряжения 1.17 ± 0.01%
- Режим измерения напряжения аналогового питания
- Встроенный датчик температуры (точность ±2°С, необходима калибровка)
- Самокалибровка шкалы измерения и нуля
- Два источника тока для питания датчиков
- Встроенный программируемый усилитель входного сигнала с множителем от 1 до 128
Разрешение в зависимости от множителя входного усилителя (bit) и режима работы входа (Uref = 2.5 V)
несимметричный (дифференциальный) вход
Разрешение в зависимости от множителя входного усилителя (мкВ) (Uref = 2.5 V)
Управление АЦП 4-проводное SPI, используются пины CS, DOUT, DIN, SCLK. Режим работы шины SPI показаны на рисунках (чтение/запись)
В режиме записи данных в регистр сигнал разрешения работы CS необходимо перевести низкий уровень, далее подавать синхроимпульсы SCLK одновременно с данными DIN, запись битов происходит на восходящем фронте синхроимпульса.
При чтении после перевода сигнала разрешения работы CS в низкий уровень необходимо дождаться сигнала готовности АЦП, как только уровень DOUT/RDY станет низким, можно считывать данные. Считывание бита происходит на восходящем фронте синхроимпульса.
Управление АЦП осуществляется через несколько регистров, некоторые из них доступны для записи и чтения, другие только для чтения:
Communications Register During a Write Operation — регистр связи (Write)
При записи или чтении регистров сначала необходимо воспользоваться регистром связи. В нем задается адрес для чтения или записи последующего регистра.
Status Register During a Read Operation — регистр состояния (Read)
- RDY — бит готовности АЦП к считываю данных
- ERR — ошибка считывания
- 0/1 — тип чипа (AD7792/AD7793)
- CH0…CH2 — индикатор активного входа
Mode Register — регистр режима (Raad/Write)
16-и битный регистр содержит настройки частоты опроса АЦП, режим работы, управление внешней и внутренней синхронизацией.
- MD0…MD2 — режим работы
- FS0…FS3 — частота опроса АЦП
Configuration Register — регистр конфигурации (Raad/Write)
16-и битный регистр содержит основные настройки работы АЦП
- U/B — дифференциальный / несимметричный вход
- G0…G2 — коэффициент усиления усилителя
- BUF — буферизация
- REFSEL — выбор внутреннего или внешнего источника опорного напряжения
Data Register — регистр данных (Read)
24-х битный регистр данных, доступен только для чтения
ID Register — Идентификационный регистр (Read)
Идентификационный номер для AD7792/AD7793 сохраняется в реестре идентификаторов.
IO Register — (Raad/Write)
Регистр для управления источниками тока.
OFFSET Register — регистр смещения (Raad/Write)
24-х битный регистр, содержит коэффициент смещения шкалы.
FULL-SCALE Register — масштабный регистр (Raad/Write)
24-х битный регистр, содержит калибровочные коэффициенты шкалы.
Ниже показан пример скетча позволяющий провести измерения напряжения аналогового питания, напряжение подаваемое на вход 1 с множителем 16 работающего в дифференциальном режиме, а так же напряжение встроенного датчика температуры.
// AD7793 #define SCLK 2 #define CS 3 #define DIN 4 #define DOUT 5 #define AVDD_MONITOR 0b111 // CONF #define TEMP_SENSOR 0b110 // CONF #define CH1 0b000 // CONF #define CH2 0b001 // CONF #define CH3 0b011 // CONF #define BIPOLAR 0b00000000 // CONF #define UNIPOLAR 0b00010000 // CONF #define BIPOLAR 0b00000000 // CONF #define UNIPOLAR 0b00010000 // CONF #define GAIN_1 0b000 // CONF #define GAIN_2 0b001 // CONF #define GAIN_4 0b010 // CONF #define GAIN_8 0b011 // CONF #define GAIN_16 0b100 // CONF #define GAIN_32 0b101 // CONF #define GAIN_64 0b110 // CONF #define GAIN_128 0b111 // CONF #define F_ADC_500 0b0001 // MODE #define F_ADC_250 0b0010 // MODE #define F_ADC_125 0b0011 // MODE #define F_ADC_62_5 0b0100 // MODE #define F_ADC_50_0 0b0101 // MODE #define F_ADC_39_2 0b0110 // MODE #define F_ADC_33_3 0b0111 // MODE #define F_ADC_19_6 0b1000 // MODE #define F_ADC_16_7 0b1001 // MODE #define F_ADC_12_5 0b1011 // MODE #define F_ADC_10_0 0b1100 // MODE #define F_ADC_8_33 0b1101 // MODE #define F_ADC_6_25 0b1110 // MODE #define F_ADC_4_17 0b1111 // MODE void setup(){ Serial.begin(9600); pinMode(SCLK,OUTPUT);pinMode(CS,OUTPUT);pinMode(DIN,OUTPUT);pinMode(DOUT,INPUT); digitalWrite(SCLK,HIGH);digitalWrite(CS,HIGH);digitalWrite(DIN,HIGH); delay(100); reset(); write_byte(0x08,(0x20<<8)|F_ADC_4_17, 16);// MODE REGISTER write_byte(0x10,((BIPOLAR|GAIN_1)<<8)|0x90|AVDD_MONITOR, 16); // CONFIGURATION REGISTER write_byte(0x08,(0xC0<<8)|0x0A, 16);// MODE REGISTER System Zero-Scale Calibration write_byte(0x08,(0xE0<<8)|0x0A, 16);// MODE REGISTER System Full-Scale Calibration Serial.print("Stat ");Serial.println(read_byte(0x40,8),BIN);// STATUS REGISTER Serial.print("ID ");Serial.println(read_byte(0x60,8),BIN);// ID REGISTER Serial.print("Ofst ");Serial.println(read_byte(0x70,24));//OFFSET REGISTER Serial.print("ful ");Serial.println(read_byte(0x78,24));//OFULL-SCALE REGISTER write_byte(0x28,0x00, 8);// IO REGISTER } void loop(){ // READ ADC ////////////////////////////////////////////////////////////////// write_byte(0x08,(0x20<<8)|F_ADC_4_17, 16);// MODE REGISTER write_byte(0x10,((BIPOLAR|GAIN_1)<<8)|0x90|CH1, 16); // CONFIGURATION REGISTER long adc = read_byte(0x58,24); // BIPOLAR Serial.print("Data b_B ");Serial.println(adc-0x800000);//DATA REGISTER Serial.print("Data V_B ");Serial.println((1.17/0x800000*(adc-0x800000)),6);//DATA REGISTER // UNIPOLAR // Serial.print("Data b_U ");Serial.println(adc);//DATA REGISTER // Serial.print("Data V_U ");Serial.println((1.17/0xFFFFFF*adc),6);//DATA REGISTER Serial.println(); delay(5); // READ AVDD /////////////////////////////////////////////////////////////////// write_byte(0x08,(0x20<<8)|F_ADC_4_17, 16);// MODE REGISTER write_byte(0x10,((BIPOLAR|GAIN_1)<<8)|0x90|AVDD_MONITOR, 16); // CONFIGURATION REGISTER adc = read_byte(0x58,24); // BIPOLAR Serial.print("Data AV b_B ");Serial.println(adc-0x800000);//DATA REGISTER Serial.print("Data AV V_B ");Serial.println((1.17/0x800000*(adc-0x800000)*6),4);//DATA REGISTER Serial.println(); delay(5); // TEMP SENSOR /////////////////////////////////////////////////////////////////// write_byte(0x08,(0x20<<8)|F_ADC_4_17, 16);// MODE REGISTER write_byte(0x10,((BIPOLAR|GAIN_1)<<8)|0x90|TEMP_SENSOR, 16); // CONFIGURATION REGISTER adc = read_byte(0x58,24); // BIPOLAR Serial.print("Data T b_B ");Serial.println(adc-0x800000);//DATA REGISTER Serial.print("Data T V_B ");Serial.println(1.170/0x800000*(adc-0x800000),4);//DATA REGISTER Serial.println(); delay(1000); } void write_byte(byte reg, long data, int bit_){ digitalWrite(CS,LOW); for(int i = 7; i >= 0; i--){ digitalWrite(SCLK,LOW); digitalWrite(DIN, (reg >> i) & 1); digitalWrite(SCLK,HIGH); } for(int i = bit_-1; i >= 0; i--){ digitalWrite(SCLK,LOW); digitalWrite(DIN, (data >> i) & 1); digitalWrite(SCLK,HIGH); } digitalWrite(CS,HIGH); } long read_byte(byte reg, int bit_){ digitalWrite(CS,LOW); while(digitalRead(DOUT)!=LOW); for(int i = 7; i >= 0; i--){ digitalWrite(SCLK,LOW); digitalWrite(DIN, (reg >> i) & 1); digitalWrite(SCLK,HIGH); } while(digitalRead(DOUT)!=LOW); long data_out=0; long dat; for(int i = bit_-1; i >= 0; i--){ digitalWrite(SCLK,LOW); digitalWrite(SCLK,HIGH); dat = digitalRead(DOUT); data_out |= (dat<<i); } digitalWrite(CS,HIGH); return data_out; } void reset(){ digitalWrite(CS,LOW); for(int i = 31; i >= 0; i--){ digitalWrite(SCLK,LOW); digitalWrite(DIN, HIGH); digitalWrite(SCLK,HIGH); } digitalWrite(CS,HIGH); }
При старте в секции setup() происходит режим калибровки нуля и коэффициента шкалы АЦП. Вход работает в дифференциальном режиме.
Красным выделено:
- Напряжение подаваемое на вход АЦП и его цифровое значение
- Напряжение аналогового питания и его цифровое значение
- Напряжение встроенного датчика температуры (0,81 мВ на 1 ºС) и его цифровое значение
Далее показан пример измерения напряжения с коэффициентом усиления 16:
// AD7793 #define SCLK 2 #define CS 3 #define DIN 4 #define DOUT 5 #define AVDD_MONITOR 0b111 // CONF #define TEMP_SENSOR 0b110 // CONF #define CH1 0b000 // CONF #define CH2 0b001 // CONF #define CH3 0b011 // CONF #define BIPOLAR 0b00000000 // CONF #define UNIPOLAR 0b00010000 // CONF #define BIPOLAR 0b00000000 // CONF #define UNIPOLAR 0b00010000 // CONF #define GAIN_1 0b000 // CONF #define GAIN_2 0b001 // CONF #define GAIN_4 0b010 // CONF #define GAIN_8 0b011 // CONF #define GAIN_16 0b100 // CONF #define GAIN_32 0b101 // CONF #define GAIN_64 0b110 // CONF #define GAIN_128 0b111 // CONF #define F_ADC_500 0b0001 // MODE #define F_ADC_250 0b0010 // MODE #define F_ADC_125 0b0011 // MODE #define F_ADC_62_5 0b0100 // MODE #define F_ADC_50_0 0b0101 // MODE #define F_ADC_39_2 0b0110 // MODE #define F_ADC_33_3 0b0111 // MODE #define F_ADC_19_6 0b1000 // MODE #define F_ADC_16_7 0b1001 // MODE #define F_ADC_12_5 0b1011 // MODE #define F_ADC_10_0 0b1100 // MODE #define F_ADC_8_33 0b1101 // MODE #define F_ADC_6_25 0b1110 // MODE #define F_ADC_4_17 0b1111 // MODE void setup(){ Serial.begin(9600); pinMode(SCLK,OUTPUT);pinMode(CS,OUTPUT);pinMode(DIN,OUTPUT);pinMode(DOUT,INPUT); digitalWrite(SCLK,HIGH);digitalWrite(CS,HIGH);digitalWrite(DIN,HIGH); delay(100); reset(); write_byte(0x08,(0x20<<8)|F_ADC_4_17, 16);// MODE REGISTER write_byte(0x10,((BIPOLAR|GAIN_1)<<8)|0x90|AVDD_MONITOR, 16); // CONFIGURATION REGISTER write_byte(0x08,(0xC0<<8)|0x0A, 16);// MODE REGISTER System Zero-Scale Calibration write_byte(0x08,(0xE0<<8)|0x0A, 16);// MODE REGISTER System Full-Scale Calibration Serial.print("Stat ");Serial.println(read_byte(0x40,8),BIN);// STATUS REGISTER Serial.print("ID ");Serial.println(read_byte(0x60,8),BIN);// ID REGISTER Serial.print("Ofst ");Serial.println(read_byte(0x70,24));//OFFSET REGISTER Serial.print("ful ");Serial.println(read_byte(0x78,24));//OFULL-SCALE REGISTER write_byte(0x28,0x00, 8);// IO REGISTER } void loop(){ // READ ADC ////////////////////////////////////////////////////////////////// write_byte(0x08,(0x20<<8)|F_ADC_4_17, 16);// MODE REGISTER write_byte(0x10,((BIPOLAR|GAIN_16)<<8)|0x90|CH1, 16); // CONFIGURATION REGISTER long adc = read_byte(0x58,24); // BIPOLAR Serial.print("Data b_B ");Serial.println(adc-0x800000);//DATA REGISTER Serial.print("Data V_B ");Serial.println((1170.00/0x800000*(adc-0x800000))/16,3);//DATA REGISTER delay(500); } void write_byte(byte reg, long data, int bit_){ digitalWrite(CS,LOW); for(int i = 7; i >= 0; i--){ digitalWrite(SCLK,LOW); digitalWrite(DIN, (reg >> i) & 1); digitalWrite(SCLK,HIGH); } for(int i = bit_-1; i >= 0; i--){ digitalWrite(SCLK,LOW); digitalWrite(DIN, (data >> i) & 1); digitalWrite(SCLK,HIGH); } digitalWrite(CS,HIGH); } long read_byte(byte reg, int bit_){ digitalWrite(CS,LOW); while(digitalRead(DOUT)!=LOW); for(int i = 7; i >= 0; i--){ digitalWrite(SCLK,LOW); digitalWrite(DIN, (reg >> i) & 1); digitalWrite(SCLK,HIGH); } while(digitalRead(DOUT)!=LOW); long data_out=0; long dat; for(int i = bit_-1; i >= 0; i--){ digitalWrite(SCLK,LOW); digitalWrite(SCLK,HIGH); dat = digitalRead(DOUT); data_out |= (dat<<i); } digitalWrite(CS,HIGH); return data_out; } void reset(){ digitalWrite(CS,LOW); for(int i = 31; i >= 0; i--){ digitalWrite(SCLK,LOW); digitalWrite(DIN, HIGH); digitalWrite(SCLK,HIGH); } digitalWrite(CS,HIGH); }
На вход подается отрицательное напряжение в 66,1 мВ
При старте в мониторе порта можно увидеть данные регистров
Результаты измерения (частота опроса 4.17 Гц, множитель 16, дифференциальный вход)
Как видно на скриншотах, показания измерения AD7793 достаточно точны и стабильны
Даташит — ad7793.pdf