I2Cで接続できるADS1115を使用して、電圧の測定を行ってみました。
使用するADS1115は、16BitA/Dコンバータで、4つのシングルエンド入力または2つの差動入力、およびプログラムブルコンパレータを使用できます。
今回は、シングルエンド入力または2つの差動入力を使用して、電圧の測定に挑戦したいと思います。
ADS1115は、基板に実装されたものを使用しました。
KKHMF ADS1115(amazon 他)
回路図は下記のとおりです。

A0~A3までのアナログ入力は、1KΩの抵抗を並列および直列に接続して、500Ω、1KΩ、2KΩ、3KΩで抵抗分割しています。
上記の基板実装品では、I2Cのプルアップ抵抗は実装されいるので、AKI80側でのプルアップは必要ありません。またADDR(5pin)は無接続なので、I2Cアドレスは、0x48となります。
まずは、ADS1115のデフォルトの設定で試して見たいと思います。
デフォルトの設定では、入力端子は、差動入力でAIN0とAIN1を使用します。上の回路図で、R3(1KΩ)の両端を測定する形になります。AIN0がプラス側、AIN1がマイナス側になりますので、上の測定結果では、テスタで実測すると約-0.795Vとなりました。
では、TMPZ84C015上のモニタで、プログラムを走らせ、AS1115での測定値を確認してみます。
まず初めに、SDCCで作成したプログラムを確認していきます。
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
uint8_tなどのbit数を意識した型名表現のため、stdint.hヘッダーフィルを読み込みます。
また、絶対値(abs)の関数を取得するために、stdlib.hヘッダーファイルも読み込みます。
extern void i2c_init(void);
extern uint8_t i2c_read(uint8_t,uint8_t,uint16_t *);
extern uint8_t i2c_write(uint8_t,uint8_t,uint16_t *);
extern void sleep(uint16_t);
i2c_init、i2c_read、i2c_write、sleepの外部関数を読み込みます。
uint8_t addr=0x48; // I2C address
uint8_t config_len = 3; // config register 3:config adress + config register[high 8bit] + config register[low 8bit]
uint8_t data_len = 2; // Conversion register[high 8bit] + Conversion register[low 8bit]
uint8_t data_addr = 0x00; // Address pointer Register 00:Conversion register
uint8_t config_addr = 0x01; // Address pointer Register 01:config register
uint8_t config_buff[3]; // config register 3 byte (config adress + config register[high 8bit] + config register[low 8bit])
uint8_t data_buff[2]; // Conversion register 2 byte (Conversion register 2 byte (Conversion register[high 8bit] + Conversion register[low 8bit])
uint8_t polarity = '+'; // polarity
int16_t data16bit; // data16bit = Conversion register[high 8bit] + Conversion register[low 8bit]
int16_t data12bit; // data12bit = Conversion register[high 8bit] + Conversion register[low :high4bit]
int16_t data;
uint16_t *buff1 = config_buff; // pointer :config_buff
uint16_t *buff2 = data_buff; // pointer :data_buff
addrにi2cアドレスを設定します。
config_lenには、i2cでconfig register の長さここでは、3を設定します。
data_lenは、Conversion registerの長さここでは、2を設定します。
data_addrは、 Address pointer Registerで 、 00:Conversion register を設定します。
config_addrは、Address pointer Registerで 、01:config register を設定します。
config_buff[3]は、config adress + config register[high 8bit] + config register[low 8bit]として配列を3byte確保します。
data_buff[2]は、Conversion register[high 8bit] + Conversion register[low 8bit]として配列を2byte確保します 。
polarityは極性をセットします。
data16bitは、Conversion registerで読み込んだ16bitデータを格納します。
data12bitは、Conversion registerで得られたdata16bitから、bit16~bit04までを格納します。
dataは、data12bitに係数をかけたものを格納します。
*buff1 は config_buffの配列をポインタで渡します。
*buff2 は data_buffの配列をポインタで渡します。
i2c_init();
config_buff[0] = 0x01; //Address pointer Register 01:config register
config_buff[1] = 0b10000101; //config register: b14_12:000 Differential AIN0-AIN1 B11_9:010 ±2.048V
config_buff[2] = 0b10000011; //config register: B7-5:100 Data rate 128sps
i2c_write(addr,config_len,buff1); //Config regiseter Write
sleep(500);
I2C(PCA9564)を初期化します。
config registerの設定を行います。
i2cのconfig registerの書き込みでは、Address pointer Register+config register(high8bit)+config register(low8bit)で書き込みが必要になりますので、
config_buff[0]には、01:config register
config_buff[1] = 0b10000101; ここではデフォルトの設定、
bit14~12:は入力の000 を設定、Differential AIN0-AIN1となります。
bit11~9:はProgrammable gain amplifier configurationの010を設定、 ±2.048V となります。
config_buff[2] = 0b10000011;
bit7~5:はData rateの100を設定、 128spsとなります。
i2c_write(addr,config_len,buff1)で、Config regiseterを書き込みします。
i2c_write(addr,1,&data_addr); //Address pointer Register 00:Conversion register Write
i2c_read(addr,data_len,buff2); //Conversion register Read
printf("High_byte=%2x Low byte=%2x\n",data_buff[0],data_buff[1]);
data16bit = (data_buff[0] << 8) | data_buff[1];
printf("data16bit=(%x) %d\n",data16bit,data16bit);
printf("data16bit=%d\n",abs(data16bit));
if (data16bit < 0){
data12bit = data16bit >> 4 | 0xf000;
polarity = '-';
}else{
data12bit = data16bit >> 4 | 0x0000;
polarity = '+';
}
printf("data12bit=(%x) %d\n",data12bit,data12bit);
printf("data12bit=%d\n",abs(data12bit));
data = data12bit ;
printf("Differential AIN0(P)-AIN1(N) =%c%1d.%3dV\n",polarity,abs(data / 1000),abs(data % 1000));
Conversion registerからのデータ取り出し手順は
Conversion registerを指定するための書き込み + Conversion register の読み出し となります。
i2c_write(addr,1,&data_addr); 00:Conversion registeを指定して書き込み
i2c_read(addr,data_len,buff2); Conversion registeの読み込み
data16bit = (data_buff[0] << 8) | data_buff[1]; でdata_buff[0]およびdata_buff[0]をdata16bit に格納。
data16bit の極性判定をします。
マイナスの場合、data12bitに data16bitを右に4bitシフトして、上位4ビットを1111でマスクします。
プラスの場合、data12bitに data16bitを右に4bitシフトして、上位4ビットを0000でマスクします。
data12bitに係数をかけます。
±6.144 V 3倍
±4.096 V 2倍
±2.048 V 0倍
±1.024 V 1/2倍
data = data12bit ±2.048 V なのでそのまま値を渡します。
prinrf文ではpolarity の後 整数桁をabs(data / 1000)、小数点以下3桁をabs(data % 1000)で表示させています。
以上のプログラムで実際に動作させてみましょう。
コンパイルします。ファイル名は、i2c_ads1115_read0_main.cです。
$ sdcc -mz80 --out-fmt-ihx --code-loc 0x8000 --no-std-crt0 -o i2c_ads1115_read0_main.ihx mycrt0.rel i2c_ads1115_read0_main.c i2c_init.rel i2c_write.rel i2c_read.rel putchar.rel sleep.rel
Conflicting flags in area _CODE
Conflicting flags in area _DATA
Conflicting flags in area _CODE
Conflicting flags in area _DATA
Conflicting flags in area _CODE
Conflicting flags in area _DATA
Conflicting flags in area _CODE
Conflicting flags in area _DATA
Conflicting flags in area _CODE
Conflicting flags in area _DATA
Conflicting flags in area _CODE
Conflicting flags in area _DATA
モニタで読み込み実行してみます。
>l 20800000DDE5DD210000DD3921F4FF39F9DD36F90021020039EB4B4221000039DD75FCDDDF
2080200074FDDD7EFCDD77FEDD7EFDDD77FFC5D5CDFE81D1C13E01126B622336851313627F
中略
208F80003001833FED6A10F65FC906097D6C2600CB1DED6AED523001193F1710F5CB1050ED
138FA0005FEBC9E9C1E1E5C5AF474FEDB121FFFFED42C97C
00000001FF
OK
>
>j 8000 y:
High_byte=ce Low byte=72
data16bit=(ce72) -12686
data16bit=12686
data12bit=(fce7) -793
data12bit=793
Differential AIN0(P)-AIN1(N) =-0.793V
>
Conversion registeは ce72です。10進数表示で -12686 絶対値表示で 12686
12ビット表記(data12bit)では fce7です。 10進数表示で -793 絶対値表示で 793
小数点表示で -0.793Vです
Conversion registe * 62.5μV(±2.048の時)ですので -792875μV =-0.792875V
実際のテスタの測定では、0.795Vでした。
プログラムは下記のとおりです。
// I2C(PCA9564) ADC(ads1115) read
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
extern void i2c_init(void);
extern uint8_t i2c_read(uint8_t,uint8_t,uint16_t *);
extern uint8_t i2c_write(uint8_t,uint8_t,uint16_t *);
extern void sleep(uint16_t);
int main(){
uint8_t addr=0x48; // I2C address
uint8_t config_len = 3; // config register 3:config adress + config register[high 8bit] + config register[low 8bit]
uint8_t data_len = 2; // Conversion register[high 8bit] + Conversion register[low 8bit]
uint8_t data_addr = 0x00; // Address pointer Register 00:Conversion register
uint8_t config_addr = 0x01; // Address pointer Register 01:config register
uint8_t config_buff[3]; // config register 3 byte (config adress + config register[high 8bit] + config register[low 8bit])
uint8_t data_buff[2]; // Conversion register 2 byte (Conversion register 2 byte (Conversion register[high 8bit] + Conversion register[low 8bit])
uint8_t polarity = '+'; // polarity
int16_t data16bit; // data16bit = Conversion register[high 8bit] + Conversion register[low 8bit]
int16_t data12bit; // data12bit = Conversion register[high 8bit] + Conversion register[low :high4bit]
int16_t data;
uint16_t *buff1 = config_buff; // pointer :config_buff
uint16_t *buff2 = data_buff; // pointer :data_buff
i2c_init();
config_buff[0] = 0x01; //Address pointer Register 01:config register
config_buff[1] = 0b10000101; //config register: b14_12:000 Differential AIN0-AIN1 B11_9:010 ±2.048V
config_buff[2] = 0b10000011; //config register: B7-5:100 Data rate 128sps
i2c_write(addr,config_len,buff1); //Config regiseter Write
sleep(500);
// i2c_write(addr,1,&config_addr); //Config regiseter read
// i2c_read(addr,data_len,buff2);
// printf("config_High_byte=%2x config_Low byte=%2x\n",data_buff[0],data_buff[1]);
i2c_write(addr,1,&data_addr); //Address pointer Register 00:Conversion register Write
i2c_read(addr,data_len,buff2); //Conversion register Read
printf("High_byte=%2x Low byte=%2x\n",data_buff[0],data_buff[1]);
data16bit = (data_buff[0] << 8) | data_buff[1];
printf("data16bit=(%x) %d\n",data16bit,data16bit);
printf("data16bit=%d\n",abs(data16bit));
if (data16bit < 0){
data12bit = data16bit >> 4 | 0xf000;
polarity = '-';
}else{
data12bit = data16bit >> 4 | 0x0000;
polarity = '+';
}
printf("data12bit=(%x) %d\n",data12bit,data12bit);
printf("data12bit=%d\n",abs(data12bit));
data = data12bit ;
printf("Differential AIN0(P)-AIN1(N) =%c%1d.%3dV\n",polarity,abs(data / 1000),abs(data % 1000));
return(0);
}
上記プログラムをもとに新たにプログラムを作成し各入力の電圧を測定してみました。
作成したプログラムは最後に載せています。(i2c_ads1115_read_main.c)
コンパイルします
$ sdcc -mz80 --out-fmt-ihx --code-loc 0x8000 --data-loc 0xa000 --no-std-crt0 -o i2c_ads1115_read_main.ihx mycrt0.rel i2c_ads1115_read_main.c i2c_init.rel i2c_write.rel i2c_read.rel putchar.rel sleep.rel
Conflicting flags in area _CODE
Conflicting flags in area _DATA
Conflicting flags in area _CODE
Conflicting flags in area _DATA
Conflicting flags in area _CODE
Conflicting flags in area _DATA
Conflicting flags in area _CODE
Conflicting flags in area _DATA
Conflicting flags in area _CODE
Conflicting flags in area _DATA
Conflicting flags in area _CODE
Conflicting flags in area _DATA
モニタで読み込みます。
>l
20800000DDE5DD210000DD3921E5FF39F9DD36EA0021020039DD75F9DD74FADD7EF9DD77BC
20802000FDDD7EFADD77FE21000039DD75EBDD74ECDD7EEBDD77FBDD7EECDD77FCCD8788C0
中略
209620002600547BE680B220100610ED6A17933001833FED6A10F65FC906097D6C2600CB75
209640001DED6AED523001193F1710F5CB10505FEBC9E9C1E1E5C5AF474FEDB121FFFFED50
0296600042C9FD
00000001FF
OK
>
実行してみます。
>j 8000 y:
Single-ended AIN0(P)-GND(N) =+0.398V
Single-ended AIN1(P)-GND(N) =+1.190V
Single-ended AIN2(P)-GND(N) =+2.784V
Single-ended AIN3(P)-GND(N) =+5.175V
Differential AIN0(P)-AIN1(N) =-0.793V
Differential AIN0(P)-AIN3(N) =-4.779V
Differential AIN1(P)-AIN3(N) =-3.987V
Differential AIN2(P)-AIN3(N) =-2.392V
>
テスタでの実測値の対比
ADS1115 実測値
Single-ended AIN0(P)-GND(N) =+0.398V 0.4V
Single-ended AIN1(P)-GND(N) =+1.190V 1.195V
Single-ended AIN2(P)-GND(N) =+2.784V 2.79V
Single-ended AIN3(P)-GND(N) =+5.175V 5.19V
Differential AIN0(P)-AIN1(N) =-0.793V -0.795V
Differential AIN0(P)-AIN3(N) =-4.779V -4.79V
Differential AIN1(P)-AIN3(N) =-3.987V -3.995V
Differential AIN2(P)-AIN3(N) =-2.392V -2.4V
プログラムは下記のとおりです。
// I2C(PCA9564) ADC(ads1115) read
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
extern void i2c_init(void);
extern uint8_t i2c_read(uint8_t,uint8_t,uint16_t *);
extern uint8_t i2c_write(uint8_t,uint8_t,uint16_t *);
extern void sleep(uint16_t);
int main(){
uint8_t addr=0x48; // I2C address
uint8_t config_len = 3; // config register 3:config adress + config register[high 8bit] + config register[low 8bit]
uint8_t data_len = 2; // Conversion register[high 8bit] + Conversion register[low 8bit]
uint8_t data_addr = 0x00; // Address pointer Register 00:Conversion register
uint8_t config_addr = 0x01; // Address pointer Register 01:config register
uint8_t config_buff[3]; // config register 3 byte (config adress + config register[high 8bit] + config register[low 8bit])
uint8_t data_buff[2]; // Conversion register 2 byte (Conversion register[high 8bit] + Conversion register[low 8bit])
uint8_t polarity = '+'; // polarity
int16_t data16bit; // data16bit = Conversion register[high 8bit] + Conversion register[low 8bit]
int16_t data12bit; // data12bit = Conversion register[high 8bit] + Conversion register[low :high4bit]
int16_t data;
uint16_t *buff1 = config_buff; // pointer :config_buff
uint16_t *buff2 = data_buff; // pointer :data_buff
i2c_init();
// ---------------------------------------------------
// Single-ended AIN0-GND : ±1.024V : Data rate 128sps
// ---------------------------------------------------
config_buff[0] = 0x01; //Address pointer Register 01:config register
config_buff[1] = 0b11000111; //config register: 100:Single-ended AIN0-GND 011:±1.024V
config_buff[2] = 0b10000011; //config register: 100:Data rate 128sps
i2c_write(addr,config_len,buff1); //Config regiseter Write
sleep(100);
// i2c_write(addr,1,&config_addr); //Config regiseter read
// i2c_read(addr,data_len,buff2);
// printf("config_High_byte=%2x config_Low byte=%2x\n",data_buff[0],data_buff[1]);
i2c_write(addr,1,&data_addr); //Address pointer Register 00:Conversion register Write
i2c_read(addr,data_len,buff2); //Conversion register Read
// printf("High_byte=%2x Low byte=%2x\n",data_buff[0],data_buff[1]);
data16bit = (data_buff[0] << 8) | data_buff[1];
if (data16bit < 0){
data12bit = data16bit >> 4 | 0xf000;
polarity = '-';
}else{
data12bit = data16bit >> 4 | 0x0000;
polarity = '+';
}
data = data12bit /2 ; //±1.024V ---> 1/2
printf("Single-ended AIN0(P)-GND(N) =%c%1d.%3dV\n",polarity,abs(data / 1000),abs(data % 1000));
// ---------------------------------------------------
// Single-ended AIN1-GND : ±2.048V : Data rate 128sps
// ---------------------------------------------------
config_buff[0] = 0x01; //Address pointer Register 01:config register
config_buff[1] = 0b11010101; //config register: 101:Single-ended AIN0-GND 010:±2.048V
config_buff[2] = 0b10000011; //config register: 100:Data rate 128sps
i2c_write(addr,config_len,buff1);
sleep(100);
i2c_write(addr,1,&data_addr);
i2c_read(addr,data_len,buff2);
data16bit = (data_buff[0] << 8) | data_buff[1];
if (data16bit < 0){
data12bit = data16bit >> 4 | 0xf000;
polarity = '-';
}else{
data12bit = data16bit >> 4 | 0x0000;
polarity = '+';
}
data = data12bit; //±2.048V ---> 1/1
printf("Single-ended AIN1(P)-GND(N) =%c%1d.%3dV\n",polarity,abs(data / 1000),abs(data % 1000));
// ---------------------------------------------------
// Single-ended AIN2-GND : ±4.096V : Data rate 128sps
// ---------------------------------------------------
config_buff[0] = 0x01; //Address pointer Register 01:config register
config_buff[1] = 0b11100011; //config register: 110:Single-ended AIN2-GND 010:±4.096V
config_buff[2] = 0b10000011; //config register: 100:Data rate 128sps
i2c_write(addr,config_len,buff1);
sleep(100);
i2c_write(addr,1,&data_addr);
i2c_read(addr,data_len,buff2);
data16bit = (data_buff[0] << 8) | data_buff[1];
if (data16bit < 0){
data12bit = data16bit >> 4 | 0xf000;
polarity = '-';
}else{
data12bit = data16bit >> 4 | 0x0000;
polarity = '+';
}
data = data12bit *2; //±4.096V ---> 2
printf("Single-ended AIN2(P)-GND(N) =%c%1d.%3dV\n",polarity,abs(data / 1000),abs(data % 1000));
// ---------------------------------------------------
// Single-ended AIN3-GND : ±6.144V : Data rate 128sps
// ---------------------------------------------------
config_buff[0] = 0x01; //Address pointer Register 01:config register
config_buff[1] = 0b11110001; //config register: 111:Single-ended AIN3-GND 000:±6.144V
config_buff[2] = 0b10000011; //config register: 100:Data rate 128sps
i2c_write(addr,config_len,buff1);
sleep(100);
i2c_write(addr,1,&data_addr);
i2c_read(addr,data_len,buff2);
data16bit = (data_buff[0] << 8) | data_buff[1];
if (data16bit < 0){
data12bit = data16bit >> 4 | 0xf000;
polarity = '-';
}else{
data12bit = data16bit >> 4 | 0x0000;
polarity = '+';
}
data = data12bit *3; //±6.144V ---> 3
printf("Single-ended AIN3(P)-GND(N) =%c%1d.%3dV\n",polarity,abs(data / 1000),abs(data % 1000));
// ---------------------------------------------------
// Differential AIN0-AIN1 : ±2.048V : Data rate 128sps
// ---------------------------------------------------
config_buff[0] = 0x01; //Address pointer Register 01:config register
config_buff[1] = 0b10000101; //config register: 000: Differential AIN0-AIN1 010:±2.048V
config_buff[2] = 0b10000011; //config register: 100:Data rate 128sps
i2c_write(addr,config_len,buff1);
sleep(100);
i2c_write(addr,1,&data_addr);
i2c_read(addr,data_len,buff2);
data16bit = (data_buff[0] << 8) | data_buff[1];
if (data16bit < 0){
data12bit = data16bit >> 4 | 0xf000;
polarity = '-';
}else{
data12bit = data16bit >> 4 | 0x0000;
polarity = '+';
}
data = data12bit; //±2.048V ---> 1/1
printf("Differential AIN0(P)-AIN1(N) =%c%1d.%3dV\n",polarity,abs(data / 1000),abs(data % 1000));
// ---------------------------------------------------
// Differential AIN0-AIN3 : ±6.144V : Data rate 128sps
// ---------------------------------------------------
config_buff[0] = 0x01; //Address pointer Register 01:config register
config_buff[1] = 0b10010001; //config register: 001: Differential AIN0-AIN3 000:±6.144V
config_buff[2] = 0b10000011; //config register: 100:Data rate 128sps
i2c_write(addr,config_len,buff1);
sleep(100);
i2c_write(addr,1,&data_addr);
i2c_read(addr,data_len,buff2);
data16bit = (data_buff[0] << 8) | data_buff[1];
if (data16bit < 0){
data12bit = data16bit >> 4 | 0xf000;
polarity = '-';
}else{
data12bit = data16bit >> 4 | 0x0000;
polarity = '+';
}
data = data12bit *3; //±6.144V ---> 3
printf("Differential AIN0(P)-AIN3(N) =%c%1d.%3dV\n",polarity,abs(data / 1000),abs(data % 1000));
// ---------------------------------------------------
// Differential AIN1-AIN3 : ±6.144V : Data rate 128sps
// ---------------------------------------------------
config_buff[0] = 0x01; //Address pointer Register 01:config register
config_buff[1] = 0b10100001; //config register: 010: Differential AIN0-AIN3 000:±6.144V
config_buff[2] = 0b10000011; //config register: 100:Data rate 128sps
i2c_write(addr,config_len,buff1);
sleep(100);
i2c_write(addr,1,&data_addr);
i2c_read(addr,data_len,buff2);
data16bit = (data_buff[0] << 8) | data_buff[1];
if (data16bit < 0){
data12bit = data16bit >> 4 | 0xf000;
polarity = '-';
}else{
data12bit = data16bit >> 4 | 0x0000;
polarity = '+';
}
data = data12bit *3; //±6.144V ---> 3
printf("Differential AIN1(P)-AIN3(N) =%c%1d.%3dV\n",polarity,abs(data / 1000),abs(data % 1000));
// ---------------------------------------------------
// Differential AIN2-AIN3 : ±4.096V : Data rate 128sps
// ---------------------------------------------------
config_buff[0] = 0x01; //Address pointer Register 01:config register
config_buff[1] = 0b10110011; //config register: 011: Differential AIN2-AIN3 001:±4.096V
config_buff[2] = 0b10000011; //config register: 100:Data rate 128sps
i2c_write(addr,config_len,buff1);
sleep(100);
i2c_write(addr,1,&data_addr);
i2c_read(addr,data_len,buff2);
data16bit = (data_buff[0] << 8) | data_buff[1];
if (data16bit < 0){
data12bit = data16bit >> 4 | 0xf000;
polarity = '-';
}else{
data12bit = data16bit >> 4 | 0x0000;
polarity = '+';
}
data = data12bit *2; //±4.096V ---> 2
printf("Differential AIN2(P)-AIN3(N) =%c%1d.%3dV\n",polarity,abs(data / 1000),abs(data % 1000));
printf("\n");
return(0);
}