初めてのRaspberry Pi Pico ㉓ C言語 16ビットADC LTC2461


 Picoには12ビット4チャネルのA-Dコンバータが内蔵されています。ENOB(effective number of bits:有効ビット数)が9.5なので、もう少し高いビット数がほしいという想定で外部にICを追加します。

LTC2461のおもなスペック

  • ビット数 16
  • チャネル数 1(シングルエンド)
  • 基準電圧 内蔵あり1.25V
  • 変換レート 60もしくは30回/秒
  • インターフェース I2C(最大400kHz)
  • スレーブ・アドレス 0x14(デフォルト)
  • 動作電圧 2.7~5.5V
  • ピン数 12ピンMSOP

接続

 MSOPパッケージのLTC2461をDigi-Keyから購入しました。リード線のピッチは0.65mmの12ピンです。秋月電子通商のDIP変換ボードにはんだ付けしてから利用しました。はんだ付けは、こちらを参照ください。
 マニュアルに従って、Vcc、REFout、Comp端子からは0.1uFの積層セラミック・コンデンサをGND端子に接続しました。スレーブ・アドレス設定のA0ピンはGNDに落とし、0x14に設定しました。REF-端子はGNDへつなぎました。

LTC2461の端子 Picoの端子(GPIO) 名称
1 REFout - -
2 Comp - -
3 A0 GND GND
4 GND GND GND
5 SCL GP9 SCL
6 SDA GP8 SDA
7 GND GND GND
8 REF- GND GND
9 IN - -
10 GND GND GND
11 GND GND GND
12 Vcc 3.3V 3.3V

 LTC2461の入力には、直流標準電圧電流発生器TR6142で電圧を入力しています。1.0000だと小数点第4位まで正確です。

プログラムLTC2461.c

 フォルダ名はLTC2461としました。CMakeLists.txtは省略します。17回以前を参考にしてください。

 LTC2461データシート

 設定用レジスタのアドレスはありません。

  b7 EN1、b6 EN0、b5 SPD、b4 SLP、b3 -、b2 -、b1 -、b0 -

 EN1、EN0が'10'で、次の2ビットが有効になります。

  SPD;スピード・ビット。SLP;スリープ・ビット

 設定時に書き込むデータは、EN1とEN2のイネーブル・ビットはデフォルトの’10’、スピード・ビットSPDはデフォルトの60Hzではなくバックグランド・オフセット較正が行われる30Hzの'1'に変更し、リファレンス電圧をスリープ(SLPビット)させないようにデフォルトの'0'のままにしました。下位4ビットはダミーの'f'とし、0xafを書き込みます。

 読み出すレジスタのアドレスはありません。
 読み出したデータは2バイトで、0から65535までのデータです。65535はVrefの電圧に相当します。
  D15 D14 D13 D12 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0

 内部の基準電源電圧は1.25Vですが、1.0000V入力に対して少し低めに出ていたので、1.2509とわずかに変更しました。
 デバイスの仕様上、読み出したデータは1回前の変換結果です。

/**
 * 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
#define READ_BIT 0x80
static int addr = 0x14;
static float Vref = 1.2509;

void setup_I2C(){
    // This example will use I2C0 on GPIO8 (SDA) and GPIO9 (SCL) running at 100kHz.
    i2c_init(I2C_PORT, 100 * 1000);
    gpio_set_function(8, GPIO_FUNC_I2C);
    gpio_set_function(9, GPIO_FUNC_I2C);
    gpio_pull_up(8);
    gpio_pull_up(9);
}

static void I2C_read_registers(uint8_t reg, uint8_t *buf, uint16_t len) {
    // For this particular device, we send the device the register we want to read
    // first, then subsequently read from the device. The register is auto incrementing
    // so we don't need to keep sending the register we want, just the first.
    reg = reg | READ_BIT;
    i2c_write_blocking(I2C_PORT, addr, &reg, 1, true); 
    i2c_read_blocking(I2C_PORT, addr, buf, len, false);
}

static void I2C_write_register(uint8_t reg, uint8_t data) {
    uint8_t buf[2];
    //buf[0] = reg & 0x7f;  // remove read bit as this is a write
    buf[0] = reg;
    buf[1] = data;
    i2c_write_blocking(I2C_PORT, addr, buf, 2, true);
}

int main() {
    stdio_init_all();
    printf("\nstart\n");
    setup_I2C();

    uint8_t val = 0xaf;
    i2c_write_blocking(I2C_PORT, addr, &val, 1, true);
    sleep_ms(100);

    uint8_t buffer[2];
    i2c_read_blocking(I2C_PORT, addr, buffer, 2, false);
    //I2C_read_registers(0x01,buffer,2);
    uint16_t temp = (buffer[0]<<8) | buffer[1];
    // printf(" 0x%x 0x%x \n", buffer[0], buffer[1]);
    // printf(" %d \n", temp);
    float V = Vref * temp / 65535;
    printf("input: %.5fV\n", V);

    return 0;
}

 実行結果です。入力電圧は1.0000Vです。何度もResetスイッチを押して再測定しています。