« ADコンバータMCP3425と計装アンプLT1167で作るK熱電対温度計 - オフセットの自動補正 | トップページ | このブログのPIC/SPIソースのきむしげさんの新しいskSPILIB.c対応 - MCP3553を例に »

2015年5月21日 (木)

22ビット(20.6bit)ADコンバータMCP3553の使い方

16bitのADコンバータMCP3425に飽きたらず22bitのADコンバータMCP3553に手を出してみました。22bitとは言ってもタイトルにあるとおり実質的(Effective Resolution)には20.6bitですが。

本家のデータシート(PDF、日本語)はここにあります。
  「Microchip - MCP3550/1/3 低電力、単チャネル、22ビット デルタ-シグマADC

MCP3425がI2Cなのに対しこちらはSPIです。
サンプリング・レートは60/sとけっこう速いです。
電源は2.7V~5.0Vが標準(?)のようです。かなり広い範囲で使えます。
Vrefは外部から与えます。ここはMCP3425とは違います。
せっかくだから内蔵してくれればいいのにと思うのですが、さすがに22bitともなるとそれに見合う基準電圧源がないのでしょうか。
私の場合は抵抗比を求めるのが目的なので電圧計に要求するは不確かさではなく分解能と(温度や電源電圧に対する)安定性なのでどうにかなるでしょう。

なおこのシリーズには3550、3551というのがあります。そちらは高級品で電源ノイズの除去機能(50/60 Hz Rejection)なんてものがついていますしEffective Resolutionはなんと21.9bitになります。

  ==> 「22ビット(21.9bit)ADコンバータMCP3551の使い方 - MCP3553との分解能の比較

=======

なぜこういうのに手を出したかというといろいろ理由やきっかけがあるのですが、それは別の記事に書く予定なのでさっそく本題に入ります。

インターフェースはSPIなんですが使い方によってはI2Cなみというかそれ以上に簡単です。

SDIピンがありません。PICのSDOの接続は不要です。
他にSPIデバイスを使わなければ(あるいは他のデバイスがあってもSDカードI/Fのときにやったようにアナログスイッチでデバイスを切り替えるような使い方であれば)/CSはLowにおとしっぱなしという使い方ができます。
この場合連続変換モード(Continuous Conversion Mode)になります。特に/CSをLowにおとっしっぱなしのときは2-WIRE CONTINUOUS CONVERSION OPERATIONと言うようです。

この連続変換モードのときはクロックを送れば最新の(直近の)測定値がもどってきます。“クロックを送れば”というのは0x00を送信すればという意味です(もちろん0xFFでもなんでもいいです。このデータはMCP3553は受け取っていないのですから)

SPIのモードは Mode 0,0とMode 1,1が使えるのですが、モードによって測定値のバイト数が異なります。つまり送信すべきバイト数が異なりますので注意が必要です。

  「記事一覧(測定、電子工作、天文計算
     ==> 測定
          ==> 電圧
               ==> ADコンバータ
                    ==> 「16bitADコンバータMCP3425の使い方と特性
                    ==> MCP3353
                         ==> この記事
                         ==> 「熱電対起電力を直接測定できる22bit(20.6bit)ADコンバータMCP3553

--------

実験風景

PICはI2CとSPIが使えるいつものPIC18F26K22です。SPIにMCP3553、I2CにLCDを接続してあります。
基準電圧源はREF5030(3.0V)です(温度係数が小さそうなのでこれにしたのですが最悪ミニ恒温槽に入れてしまうつもりです)
Imgp96141000

-------

実験中のソースです。

上の写真にあるようにPICと同じブレッドボードの載せてやっつけでやっているのでノイズ対策らしきものはまだ何もやっていません。というかどう見ても近くにノイズ源があります。
この状態での実質的な分解能を下の結果から逆算すると悲しいことに16.7bit 17.6bitです (^^;;
(16 + 3.3 - 1.6 = 17.7、 3.3は分解能の一桁向上分、1.7というのは測定回数10の平方根から)

ノイズが原因なら(本来の分解能は高いので)平均をとれば改善するのではないかと思い)私が必要とする)MCP3425の10倍くらいの分解能が得られるまで平均をとる測定回数をふやしてみました。

そうすると10回の平均でMCP3425の10倍くらいの分解能が得られました。つまり16bit+3.3bitで19.3bitになりました。分解能が悪化している原因を見つけ一つ一つクリアして一回の測定でこの程度の実質的な分解能が得られるようにするのが今後の課題です。

-----

ソースはMode 0,0のときにあわせて作ってあります。
この場合データのバイト数は4になります。最初のバイトの頭3bitは測定データではありません。4bit目から22bitがデータです(Mode 1,1のときはデータは3バイトになり、全体的に1bit左にずれます)
最初のバイトの2bit目と3bit目はオーバーフローフラッグです。下のプログラムではオーバーフローのデータは(あんまり意味はありませんが)無視するようにしてあります。
コンパイルするときはdoubleを32bitにします。floatだと仮数部は16bitしかありません。

ウェイトのかけ方を変更しました(プログラムの最後の方の取り消し線と赤字のところです)またSPIモード設定を2回行っていたので一回ですませました。 2015.05.22)

電圧が負のときの計算方法が間違ってましたので修正しました。すみません m(._.)m  2015.05.26


I2Cに関しては
  「I2Cのソース - PIC12F1822/16F1705/16F1938/18F26K22 - LCD(ACM1602)を例にして
  今回使っているLCDはこれとは別のものです。
    「I2C薄型液晶ディスプレイ(LCD)・AQM1602XAの使い方

SPIに関しては
  PICでSPI SDカードを読み書きする
  「このブログのPIC/SPIソースのきむしげさんの新しいskSPILIB.c対応 - MCP3553を例に

// PIC18F26K22
// 01 /MCLR .....(1), Pull-up 10k
// 02 RA0/AN0
// 03 RA1/AN1
// 04 RA2/AN2/DACOUT
// 05 RA3/AN3
// 06 RA4
// 07 RA5/AN4
// 08 VSS
// 09 RA7
// 10 RA6/OSC2/CLKO
// 11 RC0
// 12 RC1
// 13 RC2
// 14 RC3/SCL1.....I2C Clock / Pull-up 2.7k(この値に特別な意味はありません)
// 15 RC4/SDA1.....I2C Data / Pull-up 2.7k(この値に特別な意味はありません)
// 16 RC5/SDO1
// 17 RC6/TX1
// 18 RC7/RX1
// 19 VSS .....(3)
// 20 VDD .....(2)
// 21 RB0/INT0
// 22 RB1/SCL2.....SPI Clock
// 23 RB2/SDA2.....SPI Data In
// 24 RB3/SDO2.....SPI Data Out <== MCP3553では使いません。
// 25 RB4.....SPI CS MCP3553 <== このプログラムでは使用していません
// 26 RB5
// 27 RB6/TX2/PGC .....(5)
// 28 RB7/RX2/PGD .....(4)

#include <xc.h>
#include <stdio.h>
#include "MyDef.h"
#include "I2CLib.h"
#include "SPILIB.h"
#include "AQM1602lib.h"

#define COUNT 10

// C:\Program Files (x86)\Microchip\xc8\v1.32\docs\chips\18f26k22.html
#pragma config FOSC = INTIO67
#pragma config WDTEN = OFF

// センサーから読み込んだデータをLCDに16進表示するため
// sprintf()を使いたくないとき用
void putLCDhex(unsigned char ch)
{
    char hex[]="0123456789ABCDEF";

    LCD_Putc(hex[ch>>4]) ;
    LCD_Putc(hex[ch & 0x0f]) ;

}
void interrupt InterFunction( void )
{
     // I2C関連の割り込み処理
     InterI2C() ;
}
void main()
{
    unsigned short i=0;
    unsigned short j;
    unsigned char ct[4];
    double V, Vref=3.0, Vs=0.0;
    char buf[20];

    OSCCON = 0b01110010 ;  // 16MHz
    // for I2C
    ANSELCbits.ANSC3 = 0;
    ANSELCbits.ANSC4 = 0;

    // for SPI
    ANSELBbits.ANSB2 = 0;
    ANSELBbits.ANSB1 = 0;
    TRISB1 = 0;
    TRISB3 = 0;

// OUTPUT
// MCP3553の/CS ..... このプログラムでは使いません。
//    TRISB4 = 0;
//    CS_3553 = 1;

// SPIはひとまずmode 2として初期化します。
//  SPI_Init(SPI_MODE2,SPI_CLOCK_DIV16) ;
// SPIはmode 0として初期化します。
    SPI_Init(SPI_MODE0,SPI_CLOCK_DIV16) ;

    InitI2C_Master() ;

    LCD_Init() ;
    LCD_Clear();

    LCD_Putc(0x30);
    for( j=0; j < 12; j++ ) __delay_ms(40);

    // SPI MODE 0
    // SSP2STAT &= 0xBF;
    // SSP2CON1 &= 0xEF;

    while(1) {
        for( j =0; j < 4; j++ ) {
            ct[j]=SPI_transfer(0x00) ;
        }
        if( (ct[0] & 0x40) || (ct[0] & 0x20) ) continue;
        V=(((double)ct[3]/256.0+ct[2])/256+ct[1])/256+(ct[0]&0x1F);
        V =V / 16 * Vref;
        if( ct[0] & 0x10 ) V = Vref - V;
        if( ct[0] & 0x10 ) V = V - Vref * 2.0;

        if( i == COUNT ) {

            LCD_SetCursor(0, 0);
            for( j =0; j < 4; j++ ) {
               putLCDhex(ct[j]) ;
            }
            sprintf(buf,"%9.5f",Vs/COUNT);
            LCD_SetCursor(0, 1);
            LCD_Puts(buf);
            // for( j=0; j < 5; j++ ) __delay_ms(40);
            i=0;
            Vs = 0.0;
        }
        Vs += V;
        i++;
        // __delay_ms(20);
        // まれにループから抜け出せなくことがあるので何回かループして
// PORTBbits.SDA2がLOWに落ちなかったら抜けるようにした方がいいかも
        while(PORTBbits.SDA2 );

    }
}

 

 

« ADコンバータMCP3425と計装アンプLT1167で作るK熱電対温度計 - オフセットの自動補正 | トップページ | このブログのPIC/SPIソースのきむしげさんの新しいskSPILIB.c対応 - MCP3553を例に »

趣味の電子工作」カテゴリの記事

コメント

この記事へのコメントは終了しました。

トラックバック


この記事へのトラックバック一覧です: 22ビット(20.6bit)ADコンバータMCP3553の使い方:

« ADコンバータMCP3425と計装アンプLT1167で作るK熱電対温度計 - オフセットの自動補正 | トップページ | このブログのPIC/SPIソースのきむしげさんの新しいskSPILIB.c対応 - MCP3553を例に »

フォト

サイト内検索

  • 記事を探されるんでしたらこれがいちばん早くて確実です。私も使ってます (^^;; 検索窓が表示されるのにちょっと時間がかかるのはどうにかしてほしいです。

新着記事

リンク元別アクセス数

  • (アクセス元≒リンク元、原則PCのみ・ドメイン別、サイト内等除く)

人気記事ランキング

  • (原則PCのみ、直近2週間)
無料ブログはココログ