MAD7991は4チャンネルのADコンバータ(AD7991)を搭載したモジュールです。 I2Cシリアルインターフェースでコントロールすることができます。 4チャンネルの入力として使うか、3チャンネル入力とリファレンス入力として使うかを選択できます。
ADコンバータAD7991のデータシートはアナログデバイスの こちらのページからダウンロードできます。
ArduinoとMAD7991との接続は次の回路図の通りです。 SCL, SDAはボード内で既にプルアップされています。
Raspberry Piを使う場合の接続は次の通りです。
AD7991を直接使う場合は、ピン番号が異なります。 また、I2Cの信号線、SCL, SDAは2.2kΩの抵抗でプルアップが必要です。
setup()でI2Cの動作周波数は3.4MHz(ハイスピードモード)に設定します。 I2Cのアドレスはボードの取り扱い説明書右下の「仕様」にある通り0x28です。 A/D変換のデータを読み込むだめには、AD7991のレジスタ、上位4ビットで設定します。
#include <Wire.h> #define AD7991_ADDRESS 0x28 // AD7991のI2Cアドレス (データシート参照) #define MAX_CLOCK 3400000 // I2Cの動作周波数 340kHz #define REG_CH0 0x10 // チャンネル0 #define REG_CH1 0x20 // チャンネル1 #define REG_CH2 0x40 // チャンネル2 #define REG_CH3 0x80 // チャンネル3 void setup() { // put your setup code here, to run once: Wire.begin(); // 接続の初期化 Wire.setClock(MAX_CLOCK); // I2Cの動作周波数 Serial.begin(115200); } uint16_t readADC(uint8_t channel) { Wire.beginTransmission(AD7991_ADDRESS); Wire.write(channel); // チャンネル選択 Wire.endTransmission(); delay(10); // データ準備の待機 Wire.requestFrom(AD7991_ADDRESS, 2); // 2バイトのデータを要求 if (Wire.available() == 2) { uint8_t msb = Wire.read(); uint8_t lsb = Wire.read(); return ((uint16_t)(msb&0x07) << 8)+lsb; // 12ビットデータの取得 } return 0; // エラー時 } void loop() { char chr[256]; // put your main code here, to run repeatedly: uint16_t adcValue = readADC(REG_CH0);// チャンネル0からデータを取得 sprintf(chr,"%04x ",adcValue); Serial.print(chr); adcValue = readADC(REG_CH1); // チャンネル1からデータを取得 sprintf(chr,"%04x ",adcValue); Serial.print(chr); adcValue = readADC(REG_CH2); // チャンネル2からデータを取得 sprintf(chr,"%04x ",adcValue); Serial.print(chr); adcValue = readADC(REG_CH3); // チャンネル3からデータを取得 sprintf(chr,"%04x\n",adcValue); Serial.print(chr); delay(50); // 50ms待つ }
#include <wiringPiI2C.h> #include <stdio.h> #include <unistd.h> // usleep() のため #define I2C_ADDR 0x28 // I2Cデバイスのアドレス #define REG_CH0 0x10 #define REG_CH1 0x20 #define REG_CH2 0x40 #define REG_CH3 0x80 uint8_t mChSel[4]={REG_CH0, REG_CH1, REG_CH2, REG_CH3}; uint16_t readAD(int fd, uint8_t channel) { wiringPiI2CWrite(fd, channel); usleep(1000); // 1ms 待機 // 2バイトのデータを取得 char data[2]; if (read(fd, data, 2) != 2) { return 0; } // 12ビットデータに変換(MSBの下位4ビットとLSBを結合) uint16_t adc_value = ((data[0] & 0x0F) << 8) | data[1]; return(adc_value); } int main() { int fd; uint16_t adc[4]; // I2Cデバイスを開く fd = wiringPiI2CSetup(I2C_ADDR); if (fd == -1) { printf("I2Cデバイスを開けませんでした\n"); return 1; } while(1){ for(int i=0; i<4; i++){ adc[i]=readAD(fd,mChSel[i]); } for(int i=0; i<4; i++){ printf("%04x ",adc[i]); } printf("\n"); usleep(50000); // 50ms 待機 } return 0; }
上のプログラムではレジスターの読み込みにread(fd, data, 2)という関数を使っています。 最初は以下のwiringPiI2CRead()関数を使っていました。 しかし、下のプログラムではdata[0]とdata[1]が同じ値 、lsb側のdata[1]がmsb側のdata[0]と同じ、になってしまいました。
data[0] = wiringPiI2CRead(fd); data[1] = wiringPiI2CRead(fd);
I2Cの動作クロックを設定するには、WiringPiには関数が準備されていません。 /boot/firmware/config.txtを編集します。編集の後でrebootします。
dtparam=i2c_arm=on dtparam=i2c_arm_baudrate=340000