АЦП AD7793 (Arduino)

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 достаточно точны и стабильны

В7-78(0,0005%)

Даташит — ad7793.pdf 

Форум — http://forum.rcl-radio.ru/viewtopic.php?id=505

Добавить комментарий

Войти с помощью: