Picoには12ビット4チャネルのA-Dコンバータが内蔵されています。ENOB(effective number of bits:有効ビット数)が9.5なので、もう少し高いビット数がほしいという想定で外部にICを追加します。
ADS1110のおもなスペック
- ビット数 16
- チャネル数 1
- 基準電圧 2.048V ±0.05%、ドリフト5ppm/℃
- 電源電圧 2.7~5.5V
- 消費電流 240µA
- 入力 差動、シングルエンド
- 変換方式 ΔΣ型
- データ・レート 15SPS(16ビット)
- インターフェース I2C
- I2C転送速度 最大3.4MHz
- スレーブ・アドレス 発注時に指定できる。表面にED0の印字は0x48
- プログラマブル・ゲイン・アンプ 1/2/4/8倍が設定できる
接続
ボード化されたADS1110は、ebayで購入しました(購入時400円)。Digi-KeyでICは約500円です。

|ADS1110ボードの端子| Picoの端子(GPIO) |名称|
|------------|------------|:-------------:|:------|
|Vin+| -| -|
|Vin-| -| -|
|Vcc| 3.3V| 3.3V|
|GND| GND|GND|
|SCL| GP9| SCL|
|SDA| GP8| SDA|
プルアップ抵抗10kΩがSDA/SCLに入っていました。
ADS1110の入力には、直流標準電圧電流発生器TR6142で電圧を入力しています。1.0000だと小数点第4位まで正確です。
プログラムads1110.c
フォルダ名はads1110としました。CMakeLists.txtは省略します。17回以前を参考にしてください。
設定用レジスタのアドレスはありません。
◆設定レジスタ デフォルト b10001100
b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 |
---|---|---|---|---|---|---|---|
ST/DRDY | 0 | 0 | SC | DR1 | DR0 | PGA1 | PGA0 |
SC=0は連続変換、'1'は1回のみの変換。 DR1,DR0はサンプリング・レート。デフォルト15SPSで16ビット。 PGA1,PGA0はアンプの増幅度。'00'=×1、'01'=×2、'10'=×4、'11'=×8。
設定時に書き込むデータは、PGAによって変化します。PGAに倍率nを設定したら、読み取った電圧をnで割ります。
x1の入力電圧はVrefなので約2.5V、x2のときはVrefの半分、x4のときはVrefの1/4、x8x4のときはVrefの1/8になります。増幅度を上げると分解能は向上しますが、許容入力電圧が下がります。
読み出すレジスタのアドレスはありません。
読み出したデータは2バイトで、0から32767までのデータです。2の補数形式で、D15は符号を表します。
D15 D14 D13 D12 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0
内部の基準電源電圧は2.48Vですが、1.0000V入力に対して少し低めに出ていたので、2.028とわずかに変更しました。
I2Cの転送速度はPicoの上限1MHzにしました。
/**
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
# include <stdio.h>
# include "pico/stdlib.h"
# include "hardware/i2c.h"
# define I2C_PORT i2c0
static int addr = 0x48;
static float Vref = 2.028;
void setup_I2C(){
// This example will use I2C0 on GPIO8 (SDA) and GPIO9 (SCL) running at 1MHz.
i2c_init(I2C_PORT, 1000 * 1000);
gpio_set_function(8, GPIO_FUNC_I2C);
gpio_set_function(9, GPIO_FUNC_I2C);
gpio_pull_up(8);
gpio_pull_up(9);
}
float readADC(uint8_t PGAgain){
printf(" SamplingRate is 15 <-16bit\n");
uint8_t val = 0b10001100;
switch (PGAgain) {
case 1: val = val | 0x00; break;
case 2: val = val | 0x01; break;
case 4: val = val | 0x02; break;
case 8: val = val | 0x03; break;
default:
printf("PGA 1 2 4 8");
}
i2c_write_blocking(I2C_PORT, addr, &val, 1, true);
uint8_t buffer[2];
i2c_read_blocking(I2C_PORT, addr, buffer, 2, false);
uint16_t temp = (buffer[0]<<8) | buffer[1];
int16_t tempSign = -(temp & 0b1000000000000000) | (temp & 0b0111111111111111);
float V = Vref * tempSign / 32767;
return V / PGAgain;
}
int main() {
stdio_init_all();
printf("\nstart ADS1110\n");
setup_I2C();
printf("input: %.5fV\n", readADC(2));
return 0;
}
PGA=1のときの実行結果です。入力電圧=1.0000V、Reset、入力電圧=-1.0000V、Resetと4回実行しています。

PGA=2のときの実行結果です。入力電圧=1.0000V、Reset、入力電圧=-1.0000V、Resetと4回実行しています。
最初の実行時に1/2になりました。バグが残っているようです。