前回は、泥縄的にA-DコンバータADS1256のプログラムを書きました。ここでは、レジスタの読み書きを関数にし、本体のプログラム部分をすっきりさせます。
接続
アナログ入力端子は8本あります。デフォルトではch0-ch1の差動入力になっています。24ビットの分解能を考え、ノイズに弱いシングルエンド入力は避け、差動のまま利用します。
本プログラムでのチャネルch | 入力端子 | data |
---|---|---|
0 | ch0-ch1 | 0b00000001 |
1 | ch2-ch3 | 0b00100011 |
2 | ch4-ch5 | 0b01000101 |
3 | ch6-ch7 | 0b01100111 |
ch0にはTL431の出力約2.5V、ch2には単4電池1個の約1.5V、ch1とch3は相互にショートし、0V入力としました。
プログラム
作った関数は次のとおりです。
関数名 | 機 能 |
---|---|
sendCommand(x) | 1バイトのコマンドを送る |
writeRegister(address, value) | レジスタに1バイト書き込む |
writeRegister3(address, value) | レジスタに3バイト書き込む |
readD = readRegister(address) | レジスタから1バイトと読む |
readD3 = readRegister3(address) | レジスタから3バイトと読む |
readADC() | アナログ値を読む |
selectCH(channel) | 0~3のチャネルを指定する |
初期設定値です。
- Auto-Calibration
- PGA x1
- DataRate 2.5SPS
PGAは2倍とかを設定できますが、プログラムではその分を計算していません。増幅したら、その分readADC()の結果voltを割ってください。
DataRateは、データシートにあるどの値でも正常に動作すると思います。2.5SPSは一番遅いレートです。データが用意できたというDRDY信号は見ていないので、十分な時間待ち時間を入れています。
SPIのデータ転送速度は100kbpsと遅いです。細かなディレイを入れて、データシートのタイミングを確保できないので、これ以上のスピードではうまく読み書きができないかもしれません。
コメントアウトしているのが、OFC(Offset Calibration)とFSC(Full–scale Calibration)の24ビットの値です。データシートを読んでも、これを設定しなければならないのか、自己キャリブレーションに任せればよいのかが読み取れませんでした。なので、3か所で読み出すようにして確認作業をしていましたが、それでも解決していません。
ステータス・レジスタのAuto-CalibrationをONにしていますが、これが何をしているかは不明です。
1回の測定のたびにsendCommand(SELFCAL);を実行しています。SELFCALは、自己オフセットおよび自己ゲイン・キャリブレーションの実行コマンドです。これを毎回実行しないと、DataRateをいろいろな数値に変更したら、読み出すデータがでたらめになるケースが増えました。
ADCの読み出しは、4チャネルの読み出しを100回繰り返しています。
clear all
a = arduino('COM10', 'MKRZero', 'Libraries', 'SPI');
global ads1256;
ads1256 = device(a, 'SPIChipSelectPin', 'D7', 'SPIMode', 1, 'BitRate', 100000, 'BitOrder', 'msbfirst');
statusRegister_address = 0x00;
autoCaliblation = 0b00000100;
RESET = 0xfe;
ADDataRateReg_address = 0x03;
PGAReg_address = 0x02;
RDATAC = 0x03;
SELFCAL = 0xf0;
OFC0 = 0x05;
FSC0 = 0x08;
%% main
global readD;
global readD3;
sendCommand(RESET);
pause(0.5);
% readRegister3(OFC0);
% d = double(bitshift(int32(readD3(3)), 16)) + double(bitshift(int32(readD3(2)), 8)) + double(readD3(1));
% fprintf('read OFC is %08s \n', dec2hex(d));
% readRegister3(FSC0);
% d = double(bitshift(int32(readD3(3)), 16)) + double(bitshift(int32(readD3(2)), 8)) + double(readD3(1));
% fprintf('read FSC is %08s \n', dec2hex(d));
% readRegister(statusRegister_address);
% fprintf('read status is %08s \n', dec2bin(readD(3)));
writeRegister(statusRegister_address, 0b00000100); % Auto-Calibration
readRegister(statusRegister_address);
fprintf('read New status is %08s \n', dec2bin(readD(3)));
writeRegister(PGAReg_address, 0b00100000); % PGA x1
pause(0.1);
readRegister(PGAReg_address);
fprintf('read PGA is %08s \n', dec2bin(readD(3)));
writeRegister(ADDataRateReg_address, 0b00000011); % 2.5SPS
pause(0.5);
readRegister(ADDataRateReg_address);
fprintf('read DataRate is %08s \n', dec2bin(readD(3)));
pause(0.5);
sendCommand(SELFCAL);
pause(1);
% readRegister3(OFC0);
% d = double(bitshift(int32(readD3(3)), 16)) + double(bitshift(int32(readD3(2)), 8)) + double(readD3(1));
% fprintf('read OFC is %08s \n', dec2hex(d));
% readRegister3(FSC0);
% d = double(bitshift(int32(readD3(3)), 16)) + double(bitshift(int32(readD3(2)), 8)) + double(readD3(1));
% fprintf('read FSC is %08s \n', dec2hex(d));
global volt;
for j=0:100
for i=0:3
selectCH(i);
readADC();
fprintf('read ch=%d is %.8f \n', i, volt);
sendCommand(SELFCAL);
pause(0.9);
end
fprintf('---\n');
end
% readRegister3(OFC0);
% d = double(bitshift(int32(readD3(3)), 16)) + double(bitshift(int32(readD3(2)), 8)) + double(readD3(1));
% fprintf('read OFC is %08s \n', dec2hex(d));
% readRegister3(FSC0);
% d = double(bitshift(int32(readD3(3)), 16)) + double(bitshift(int32(readD3(2)), 8)) + double(readD3(1));
% fprintf('read FSC is %08s \n', dec2hex(d));
function sendCommand(x)
global ads1256;
writeRead(ads1256, x);
end
function writeRegister(address, value) % 1byte
global ads1256;
WREG = 0x50;
wdata = bitor(WREG, address);
out = [wdata 0 value];
writeRead(ads1256, out, 'uint8') ; % write
end
function writeRegister3(address, value) % 3byte
global ads1256;
WREG = 0x50;
wdata = bitor(WREG, address);
out = [wdata 2 value];
writeRead(ads1256, out, 'uint8') ; % write
end
function readD = readRegister(address) % 1byte
global ads1256;
global readD;
RREG = 0x10;
rdata = bitor(RREG, address);
out = [rdata 0 0xff];
readD = writeRead(ads1256, out, 'uint8') ;
end
function readD3 = readRegister3(address) % 3byte
global ads1256;
global readD3;
RREG = 0x10;
rdata = bitor(RREG, address);
out = [rdata 2 0xff];
readD3 = writeRead(ads1256, out, 'uint8');
end
function volt = readADC()
global ads1256;
global volt;
Vref = 2.5 - 0.003;
out = [0x01,0xff 0xff 0xff];
readD = writeRead(ads1256, out, 'uint8');
ad = double(bitshift(int32(readD(2)), 16)) + double(bitshift(int32(readD(3)), 8)) + double(readD(4));
volt = 2 * Vref * ( ad / 8388607.0);
end
function selectCH(channel) % channel = 0(default), 1, 2, 3 only
Input_Multiplexer_Control_Register_address = 0x01;
SYNC = 0xfc;
WAKEUP = 0x00;
% select ch0-ch1 0000 0001, ch2-ch3 0010 0011, ch4-ch5 0100 0101, ch6-ch7 0110 0111
switch channel
case 0
CH = 0b00000001;
case 1
CH = 0b00100011;
case 2
CH = 0b01000101;
case 3
CH = 0b01100111;
otherwise
CH = 0x01;
end
writeRegister(Input_Multiplexer_Control_Register_address, CH) ;
sendCommand(SYNC);
sendCommand(WAKEUP);
pause(0.5);
end
global 変数の指定は、関数(ローカル)内とその外側の両方に宣言する。
関数の定義は、利用する後に行う。