シュウジマブログ

Apple製品,技術系の話をするブログ

High Precision AD/DA Board用自作ライブラリ「HPADDAlibrary」

GitHubでMITライセンスにて公開中です.

github.com

クソみたいな英語でReadMeを書きましたので,ブログに日本語で丁寧に書こうと思います.

なぜ作ったか(公式との違い)

プログラムは公式のものを半分ほど利用しています.

公式のプログラムはそこそこ長いmain文を持っていたので,それを関数化して,mainを無くしました.

それだけでも結構使えるのですが,差動入力と通常入力の併用ができないため,その機能を盛り込みました.

ついでに公式のプログラムで気に入らなかったところを修正(defineマクロは殲滅)しているので,結構いろんなところが修正されています.

試用方法

Raspberry Piで以下のコマンドを入力してください.

git clone https://github.com/shujima/HPADDAlibrary.git
cd ./HPADDAlibrary
make
sudo ./Test

main.cはテストプログラムで実行すると6項目のテストが表示されます.それぞれ内容は

  • ADS1256のIDをチェック
  • ADS1256で単入力×8の計測
  • ADS1256で差動入力×4の計測
  • ADS1256で単入力×2 + 差動入力×3の計測
  • DAC8532のテスト(正弦波出力)
  • AD(0と1)の入力をそのままDA(0と1)に出力

です.これらのプログラムはmain.cの中にswitch文でそれぞれ分けて書かれていますので,プログラムを作るときに参考にしてください.

他のプログラムへの組み込み方

HPADDAlibrary.cとHPADDAlibrary.hはライブラリ本体です.

このライブラリを他のプログラムで使用したいときには,この2つHPADDAlibrary.cとHPADDAlibrary.hを使用したいプログラムと同じディレクトリにコピーした上で,

#include "HPADDAlibrary.h"

してください.またgccでコンパイルするときには,使用する上流のライブラリ「bcm2835」を読み込む必要があるため「-lbcm2835」オプションをつけてください.

例:

gcc -o foo foo.c HPADDAlibrary.c HPADDAlibrary.h -lbcm2835

付属のMakefileも参考になるかと思われます.

プログラムの簡単な解説

基板はADS1256とDAC8532が載っていますが,大半がADS1256の関数になります.

理由は,ADS1256は内部にレジスタを持っており,設定を書き込んだり,読み込んだりする必要があるためです.

一方のDAC8532はただ送った値がすぐさまアナログ値で出力されるだけなので非常に簡単です.

ADS1256のレジスタ

ADS1256の方は内部に11のレジスタを持っています.

f:id:masa_flyu:20181208222300j:plain

とりあえずいじるのは

  • MUX
  • ADCON
  • DRATE

あたりです.

MUXレジスタ

ADS1256は高精度AD変換ユニット自体は1つしか持っていません.その入り口(正側,負側の2つ)につなぐ入力を8つ+1つから選べるようになっています.

この入り口を選択するのがMUXレジスタです.

f:id:masa_flyu:20181209012053j:plain

通常,負側の入力はAGNDに接続します.

ただし,差動入力としてGNDをそれぞれ独立させたい場合は,負側もピン番号を指定します.

私のライブラリでは両者で

  • ADS1256_GetAdc( uint8_t ch )
  • ADS1256_GetAdcDiff( uint8_t positive_no , uint8_t negative_no )

関数を分けています.

8つのピンを同時に取得することは構造的にできません.関数も用意していません.

ADCON

Gainを設定することで入力を大きくできます.デフォルトでは1倍(オフ)になっています.

DRATE

データ取得の頻度を変更できます.

ADCONとDRATEは変更可能です.

使用できる関数

AD/DA共通

int initHPADDAboard()
  • 初期化(ADS1256,DAC8532)
  • 引数:無し
  • 戻り値:成功=0,失敗=1
void closeHPADDAboard()
  • SPIを閉じる(できれば呼ぶべきだが,プログラムを閉じれば普通は自動で処理してくれる)
  • 引数:無し
  • 戻り値:無し
void delay_us(uint64_t micros)
  • ただのウェイト
  • 引数:
    • 待ち時間[us]
  • 戻り値:無し

DAで利用

void DAC8532_Write( int dac_channel , unsigned int val)
  • DAC8532の出力を1つ変更する
  • 引数
    • dac_channel : チャンネル番号(0 or 1)
    • val : デジタル値(0 〜65535) ,DAC8532_VoltToValue関数の利用を推奨
  • 戻り値:無し
unsigned int DAC8532_VoltToValue( double volt , double volt_ref)
  • 電圧をデジタル値に変換する
  • 引数:
    • volt : 指定電圧 [V] ( 0 〜 5.0 [V] )
    • volt_ref : 基準電圧 [V] ( 3.3 or 5.0 [V] )
  • 戻り値:DAC8532出力用のデジタル値 ( 0 〜 65535 )

ADで利用

int32_t ADS1256_GetAdc(uint8_t _ch);
  • ADの値を読む(単入力用,負極はAGNDを利用する)
  • 引数
    • _ch : チャンネル番号
int32_t ADS1256_GetAdcDiff(uint8_t positive_no , uint8_t negative_no );
  • ADの値を読む(差動入力用,正極と負極を指定する)
  • 引数
    • positive_no : 正側の入力ポート(0〜7)
    • negative_no : 負側の入力ポート(0〜7)
  • 戻り値: AD値
double ADS1256_ValueToVolt(uint32_t value , double vref);
  • function: AD値を電圧に変換する
  • parameter:
    • value : AD値
    • vref:基準電圧[V] ( 3.3 or 5.0[V] )
  • 戻り値: 変換後の電圧値[V]

AD プリント関係

void ADS1256_PrintAllValue();
  • AD値8個を表示する
void ADS1256_PrintAllValueDiff();
  • 隣どうしで差動を取ったAD値を4つ表示する
void ADS1256_PrintAllReg();
  • ADS1256の全てのレジスタの値を表示する

AD設定

double ADS1256_SetSampleRate(double rate)
  • ADS1256のサンプリングレートを設定する
  • 引数:
    • rate:サンプリングレート
      • サンプリングレートは2.5,5.10,15...15000,30000と飛び飛びにしか設定できない.間の値を入力すると,それより大きい値に設定する.
      • サンプリングレートは1回ごとの計測間隔.8チャンネル読む場合は8倍の時間がかかるので注意.
  • 戻り値:実際に設定されたサンプリングレート
int ADS1256_SetGain(int gain)
  • ADS1256の入力ゲインを設定する
  • 引数:
    • gain:ゲイン(倍率)
      • ゲインは1,2,4,8,16,32,64に設定可能
      • ADコンバータの入力限界(-0.6〜5[V])はゲイン通過後の数値なので,読める値が狭くなるので注意
  • 戻り値:実際に設定されたゲイン
uint8_t ADS1256_ReadChipID(void);
  • ADS1256のチップIDを確認する *戻り値:チップID(普通は3になる)
static void ADS1256_WriteReg(uint8_t RegID, uint8_t RegValue);
  • レジスタに書き込む
  • 引数:
    • _RegID : レジスタ番号
    • _RegValue : 書き込む値
static uint8_t ADS1256_ReadReg(uint8_t _RegID);
  • レジスタを読み込む
  • 引数:
    • _RegID: レジスタ番号
  • 戻り値:レジスタの値
static void ADS1256_WriteCmd(uint8_t _cmd);
  • ADS1256にコマンドを送出する
  • 引数
    • _cmd : コマンド

プライベート関数(通常使用しない)

void setCS_DAC8532(char b)
  • function: set SPI CS pin value of DAC8532
  • parameter:
  • b : bool value for SPI CS status (0 : connection start , 1: connection end)
  • The return value: NULL
static int32_t ADS1256_ReadData(void);
  • function: read ADC value
  • parameter: NULL
  • The return value: NULL
static void ADS1256_DelayDATA(void);
  • function: delay
  • parameter: NULL
  • The return value: NULL
void ADS1256_WaitDRDY(void);
  • function: delay time wait for automatic calibration
  • parameter: NULL
  • The return value: NULL
void ADS1256_ChangeMUX(int8_t positive_no , int8_t negative_no );
  • function: set ADS1256 MUX for changing input of ADC
  • parameter:
    • positive_no :input port no of positive side (0 - 7 or -1)
      * Nomally it should be set to 0 - 7. When set to -1 , AGND becomes positive input.
      
    • negative_no :input port no of negative side (-1 or 0 - 7)
      * Nomally it should be set to -1. When use Differential Input, it should be set to 0 - 7.
      
  • The return value: NULL
void ADS1256_SetCS(char b);
  • function: set SPI CS pin value of ADS1256
  • parameter:
    • b : bool value for SPI CS status (0 : connection start , 1: connection end)
  • The return value: NULL
static void ADS1256_Send8Bit(uint8_t _data);
  • function: SPI bus to send 8 bit data
  • parameter:
    • _data: data
  • The return value: NULL
static uint8_t ADS1256_Recive8Bit(void);
  • function: SPI bus receive function
  • parameter: NULL
  • The return value: NULL

関数の基本的な使い方

ADを使いたいとき

最小限では,

initHPADDAboard();  //ボードの初期化
printf("%f\n",ADS1256_ValueToVolt(ADS1256_GetAdc(0), 5.0 ) );

って感じで使えます.5.0は基準の電圧でVREFジャンパピンで決定できます.

他に事前に設定しておくことができるのは

ADS1256_SetSampleRate(rate); //サンプルレート
ADS1256_SetGain(gain);  //入力ゲイン

くらいしかありません.サンプルレートは値の計測間隔で,初期値が2.5[サンプル毎秒]です.最速30000[サンプル毎秒]まで設定可能です.

入力ゲインは初期値1で,64まで設定可能ですが,わからなければ1でよいでしょう.

他にも設定項目はあるのですが通常の利用用途では使いません.

個別で設定したい場合はデータシートを見ながら

ADS1256_WriteReg( _RegID, _RegValue); //レジスタの書き込み

などで設定してください.

DAを使いたいとき

DAは設定項目が無く関数も2つしかありません.5.0は基準の電圧でVREFジャンパピンで決定できます.

initHPADDAboard();
DAC8532_Write( 0 , DAC8532_VoltToValue( 3.14 , 5.0 ) );
当ブログをご利用いただく際には免責事項をお読みください。