電子工作用で手頃なADCアンプモジュールが無いまま5年経過して、ようやく手頃なADCチップを発見しました。
※「楽ちん」という表現ですが、SPIインターフェース接続のプログラム作りで苦労されたご経験がある方にとって「楽ちん」であるという意味です。ということで本記事は、電子工作中級者向けです。初心者の方は、マイコンとデバイス(SDカード、加速度センサ)のIF接続(SPI,I2C)の練習を積んでから本記事へ挑戦していただくことをお勧めします。初めてでも、1-3か月くらい週末にいじっていれば何とかなると思います。
何かありましたら、お気軽にコメントするか、私にメールしてください。無償です。ich48397@wd5.so-net.ne.jp
●TEXAS ADCチップ:ADS122U04ご紹介
★メリット1:
UARTでマイコンと通信できる(HX711はSIO、アナログデバイスのADCはSPI)とインターフェースの配線でノイズを被るリスクがあったのですが、UARTならその心配がありません。非同期ですが、DRDY線がADCタイミングを教えてくれるのでDRDY線をマイコンピン割り込みで、割り込み関数から3バイト読んで取得するだけで済むので悩みむことは少ないです。
https://www.tij.co.jp/product/jp/ADS122U04#top
★メリット2:
高精度Σデルタ方式ADCチップで1CHなら最高速2000Hzまでサンプリングできます。
2CHでは約200~400Hzで動きます。2CHの差動(ブリッジ回路)入力ができます。
★メリット3:
手頃な価格 海外メーカーのADCチップは、単価と送料が高いので1粒2千円近くしてしまうのですが、テキサスインストルーメント メーカー直販サイトだと東南アジアから直送なので送料安くて納期早いです。 https://www.ti.com/store/ti/ja-jp/p/product/?p=ADS122U04IPW
1個 8ドル台で円レートで変動しますが、1個千円以下で購入できます。
送料は、DHLなのに734円と国内並みの価格で3-4日で到着します。
■デメリット1:
0.65ミリピッチのTSSOPなので、初めてだと練習が必要となります。しかし、超小型なので、HX711よりコンパクトにまとめられます。
TSSOPの半田付けの練習記事は下記リンクの記事で練習してみてください。
わかり易い動画がありました、感謝です。
TSSOPの半田付け練習<何とかできそう>
●秋月の変換基板を使いました。
SSOP20しか0.65mmピッチ変換基板がなかったので、4ピン余ります。
https://akizukidenshi.com/catalog/g/gP-10497/
●半田こてはFX-600,Gootのプリント基板用フラックス、半田吸い取り線
配線図は、仕様書の47ページにあります。RESETを3.3Vにプルアップしてある点が注意です。
※その後、M5Atomを採用して超小型基板作りました。
●動作試験
デバッグ環境:安物千円前後のロジアナがあるとはまった時に便利です。使い方記事はこちら
①ハマった点
ADS122U04仕様書リンク
お盆休みでだらだらやっていたのでまるまる2週間かかりましたが、本気でやれば3日程度でできたはずです。
ADCチップは、仕様書を穴があくほど読み込む必要があります。それをおこたると永遠に動作できません。
1=>レジスタ番号とレジスタコードが違う。
レジスタ書き込みでの使うコードは、rrrxと表記されてます。rrrは3ビットのレジスタ番号でxは使わないビットです。ですので、書き込みコマンドWREG 0x0100 rrrx [レジスタbyte]となってますので、(2021/9/7訂正追記)
0番レジスタ書き込みWREG=0b 0100 0000=0x40 追記:RREGも同様で0番レジスタ読込=0x20
1番レジスタ書き込みWREG=0b 0100 0010=0x42 追記:RREGも同様で1番レジスタ読込=0x22
2番レジスタ書き込みWREG=0b 0100 0100=0x44 追記:RREGも同様で2番レジスタ読込=0x24
3番レジスタ書き込みWREG=0b 0100 0110=0x46 追記:RREGも同様で3番レジスタ読込=0x26
4番レジスタ書き込みWREG=0b 0100 1000=0x48 追記:RREGも同様で3番レジスタ読込=0x28
とレジスタ番号とは異なる表記となることに気づかないで10日間ほど動作しないまま放置してました。
②CPUは、確実なモノを使う
当初M5AtomとESP32を使っていたのですが、シリアルは、ESP32のシリアルライブラリが
バックグランドで動作するので、訳がわからなくなることが多発したので、、ARMの信頼性あるCORTEX M3を搭載したNXP LPC1768という古典的なCPUを使いました。コンパイラはmbedオンラインコンパイラで古いバージョンのOSを使ってコンパイルしました。後日、ESP32とM5Atom版も作ってみます。
※2021年9月7日M5AtomとADS122U04接続動作プログラムと基板できました。
【M5】M5Atomと2CHひずみゲージアンプADS122U04基板作った<小さな2CHひずみアンプ>
●2024年8月 3年ぶりにAD122U04の新基板とプログラム更新しました。
本記事は2021年9月ですが、この小さな基板は、コンセプトモデルで実験には使ってませんでした。3年ぶりに使ってみると
小型のターミナルブロックがねじ締が弱く、接触抵抗がばらついてダメでした。そこで、新基板を作成し、プログラムも更新しました。
今回は、CPUとアンプ基板は分離型です。
★レジスタ設定方法
これさえ間違わなければ動作します。
600spsで手動、Continuousモードで1CHのみを設定しました。
※2022年3月15日訂正
熱心な読者様から連絡があって、レジスタ0x02のBCSがオンに設定してあると、ノイズが多いので
BCSはオフにしたほうが良い設定例になるとのご指摘がありましたので、下記設定例のBCSオンをオフにして
使っていただければ幸いです。私は、2022年4,5,6月でスキー板にADS122U04を初めて取り付けて使いますので、その時にBCSの影響を実験して記事にします。
※2023年6月追記
すみませんが、2022年度は一切ADS122U04を使ってませんでした。RTK開発が忙しくひずみアンプまで手が回りませんでした。下記表内で、BCSの設定が間違ってますので、オフにして使ってください。
●プログラム
mbed用ですが専用のライブラリー等使ってないシンプルな構成ですので、他のマイコンへも
移植は容易だと存じます。mbed OS バージョン 172:65be:20Feb2019 AnnBridge使用
https://gist.github.com/dj1711572002/49837a5b19ac8151bce3af932f267284
//—————-Texsus ADS122U04————————– #include “mbed.h” Serial pc(USBTX,USBRX); Serial device(p9, p10);//p9TX p10RX DigitalOut myled(LED1); InterruptIn DRDY(p8);//DataRdy Pin Timer t; int RREGwait; uint8_t RR0,RR1,RR2,RR3,RR4; int DRDYflag=0; //==================InterruptIn DRDY==================== void flip() {device.putc(0x55); device.putc(0x10); wait_us(10); uint8_t d0=device.getc(); //wait_us(100); uint8_t d1=device.getc(); wait_us(10); uint8_t d2=device.getc(); wait_us(10); int data=d0+d1*256+d2*65536; //pc.printf(“d0=%x,d1=%x,d2=%x,data=%d\n\r”,d0,d1,d2,data); pc.printf(“%d,%8.0f\n\r”,data,t.read_us()); //myled = !myled; //pc.printf(“————-DRDY Falled—————-\n\r”);} //=========================================================== int main() { pc.baud(115200); device.baud(115200); DRDY.fall(&flip); // attach the address of the flip function to the rising edge //ADS122U04 RESET device.putc(0x55); device.putc(0x06); wait_us(1000);// //================Register Setting============================================================================= RREGwait=500;//RREG wait time usec 2*Tbaud(10usec) //—–Register00[7:4(MUX)3:1(GAIN)0(PGA_BYPASS)]————————————————————– device.putc(0x55);//Synchronization word 0x55 device.putc(0x40);//WriteREGister 0x04 0x00(0000register00 Selected) device.putc(0x0E);//7:0(0000 1110=0x0E)[7:4(0000)MUX AINp=AIN0,AINn=AIN1 3:1(111)GAIN128, 0:0(0)PGA enabled] wait_us(1000); device.putc(0x55);//Synchronization word 0x55 device.putc(0x20);//Synchronization word 0x55 wait_us(RREGwait); if (device.readable()) { RR0=device.getc(); } wait_us(1000); pc.printf(“\n\r”); pc.printf(“********0x0E:”); pc.printf(“RR0=%x\n\r”,RR0);//—–Register01[7:5(DataRate)4:(OperationMode)3:(ConversionMode)2:1(VREF)0:(TemperatureSensor mode)]——— device.putc(0x55);//Synchronization word 0x55 device.putc(0x42);// WriteREGister 0x04 0x02(0010register01 Selected) device.putc(0xAE);//7:0(1010 1110=0xAE)[7:5(101)DataRate600sps,4:(0)NormalMode, 3:(1)Continuous conversion mode,2:1(11)VDD-VSS VRef,0:(0)Temp disabled] wait_us(1000); device.putc(0x55);//Synchronization word 0x55 device.putc(0x22);//Synchronization word 0x55 wait_us(RREGwait); if (device.readable()) { RR1=device.getc(); } wait_us(1000); pc.printf(“*********0xA8:”); pc.printf(“RR1=%x\n\r”,RR1);//—–Register02[7:DRDY)6:(DCNT)5:4(CRC)3:(BCS)2:0(IDAC)]—————————————————– device.putc(0x55);//Synchronization word 0x55 device.putc(0x44);// WriteREGister 0x04 0x04(0100register02 Selected) device.putc(0x08);//7:0(0000 1000=0x08)[7:(0)DRDY,6:(0)DCNT disable, 5:4(00)) inverte,3:(1)BCS On,2:0(0)IDAC off] wait_us(1000); device.putc(0x55);//Synchronization word 0x55 device.putc(0x22);//Synchronization word 0x55 wait_us(RREGwait); if (device.readable()) { RR2=device.getc(); } wait_us(1000); pc.printf(“********0x08:”); pc.printf(“RR2=%x\n\r”,RR2);//—-Register03[7:5(I1MUX)4:2(I2MUX)1(RSERVED)0(AUTO)]—————————————————- device.putc(0x55);//Synchronization word 0x55 device.putc(0x46);// WriteREGister 0x04 0x06(0110register03 Selected) device.putc(0x00);//7:0(00000000=0x00)[7:5(000)default,4:2(000)default, 1:(0)Reserved,0:(0)Manual Read wait_us(1000); device.putc(0x55);//Synchronization word 0x55 device.putc(0x23);//Synchronization word 0x55 wait_us(RREGwait); if (device.readable()) { RR3=device.getc(); } wait_us(1000); pc.printf(“*********0x00:”); pc.printf(“RR3=%x\n\r”,RR3); wait_us(1000); //—-Register04[7:(Reserved)6:(GPIO2DIR)5:(GPIO1DIR)4:(GPIO0DIR)3:(GPIO2SEL)2:(GPIO2DAT)1:(GPIO1DAT)0:(GPIODAT0)]—————————————————- device.putc(0x55);//Synchronization word 0x55 device.putc(0x48);// WriteREGister 0x04 0x08(1000register04 Selected) device.putc(0x48);//7:0(0100 1000=0x08)[6:(1)GPIO2output,5:(0)GPIO1Input, 4:(0)GPIO0Input,3:(1)GPIO2SEL DRDY,2:(0)GPIO2DAT Low,1:(0)GPIO1DAT Low,0:(0)GPIO0DAT Low wait_us(1000); device.putc(0x55);//Synchronization word 0x55 device.putc(0x24);//Synchronization word 0x55 wait_us(RREGwait); if (device.readable()) { RR4=device.getc(); } wait_us(1000); pc.printf(“*********0x48:”); pc.printf(“RR4=%x\n\r”,RR4);//Start/Sync device.putc(0x55); device.putc(0x08); wait_us(100);//************************このWAIT重要************************************ t.start(); //====================LOOP====================================== while(0) {} } |
●動作の注意点
今回は600SPSで動作させました。これ以上1000spsになるとUSBシリアル出力のボーレートが
115200bpsだと、割り込みルーチン内で遅延が発生してADサンプリング周期が遅くなります。
460800bpsにすれば、1000ppsは大丈夫でした。
こういう場合はロジアナで解析すると一目瞭然です。
①1000ppsで115200bpsの場合 周期に空がでてしまってます。シリアルの動作時間が遅延原因です。
②1000pps 460800bpsだと正常になります。
●結果
●以後
その2で2CH駆動実験,その3でESP32とM5Atom駆動をレポートいたします。9月いっぱいで完成させたいです。
※8月31日追記 2CHのプラグラム作ってみましたが、特殊な設定でなんとかできました。