隠居エンジニアのものづくり

自転車 電子工作 ラジコン ロボカップジュニア CAD レーザー加工機

オシロスコープについて その2(デジタルストレージオシロスコープモジュール)

新しい機種の情報をアップしましたので、こちらも御参照下さい。

blackbox-crusher.hatenablog.com

 

そもそも確認したい事はオシロスコープが適切?

何故、この問いになるかと言うと”実際に波形観測したい事は何?”を取材するとUARTやI2Cなどの通信を見たいと言うのが多いからです。

確かにオシロスコープでbitを読めば見れるのですが、読み取れるデータ数は画面に収まる範囲に限定されますし、なにより根気が必要な上に不正確です。

目的がUARTやI2Cなどのシリアルバスの観測でしたら、ロジックアナライザがお勧めです。

f:id:Blackbox_crusher:20210302235928j:plain

上図はI2C設定にしたロジックアナライザにてArduinoUNOとダイセン電子工業製4CHモーターコントローラーDSR1202間の通信を観測した結果です。

この様に400パケット・キロバイト級のデータが観測できます。

使用したロジックアナライザ秋月電子通商さんで9,000円で購入可能な”ZEROPLUSロジックアナライザLAP-C(16032)”です。

このLAP-Cはかなりのロングセラーで、オプションも充実しています。

オプションモジュールの”LAP-Cシリーズ用オシロスコープモジュール DSO”(秋月価格12,800円)を増設(ケーブル接続するだけです)すると2CHデジタルストレージオシロになります。

この組み合わせは動作確認やトラブルシューティングには強力なアイテムです。

最も安価なミックスドシグナル測定器ではないかと思います(9,000円 + 12,800円)。

f:id:Blackbox_crusher:20210303002505j:plain

上図が"LAP-C(16032)+ LAP-Cシリーズ用オシロスコープモジュール DSO"によるオシロスコープロジックアナライザの同時観測画面です。

SDAの波形観測から、立ち上がりのナマリも少なくハードの問題(抵抗値など)が無さそうな事が分かると同時に、ソフトウエアで設定した通信内容とパケットの内容に差異が無いことを確認できます。

 

購入前では分かりにくい点について解説します。

LAP-C(16032)の運用状態は以下の3パターンです。

●16CH ロジックアナライザ(LAP-C単独運用)

●1CH デジタルストレージオシロスコープ + 7CH ロジックアナライザ

 ※オシロスコープ機能のメモリ消費が大きい為にパケット数は少なくなります。(上図参照下さい)

 

●2CH デジタルストレージオシロスコープ 

オシロスコープ使用時、モジュールの側で設定するプローブ倍率・電圧レンジはアプリ側で同じ値に設定する必要があります。

※LAP-C 32CHタイプの場合は2CH デジタルストレージオシロ + ロジアナが可能な様です(LAP-C: How to measure the electrical parameters and communication protocol of USB PD device - YouTube

 

I2C通信テストに使用したプログラムはTJ3COREからArduinoに移行したチームが4CHモーターコントローラーDSR1202が使えない(すぐに暴走する?)との声が多かったので作ってみたプログラムです(DSR1202初期版FWでの検証なので、あくまで参考と言うことで)。

/*
ダイセン電子工業製4CHモーターコントローラーDSR1202用
パワーコントロール
前進 1 ~ 100
後進 -1 ~ -100
停止 0
電磁ブレーキ 1000
※6CHモーターコントローラーDSR6316CH共通化されている為、5CH,6CHはI2Cへ空送りしています
*/

#include <Wire.h>
volatile byte address = 0x14;
char Motor_Power[6] = { 0,0,0,0,0,0 };

void setup()
{
 Wire.begin();
 Wire.setClock(400000);
}

void loop()
{
 Motor(0, 0);
 Motor(1, 0);
 Motor(2, 0);
 Motor(3, 0);
 MotorDrive();
// delay(200);

 Motor(0, 100);
 Motor(1, 100);
 Motor(2, 100);
 Motor(3, 100);
 MotorDrive();
// delay(200);

 Motor(0, 0);
 Motor(1, 0);
 Motor(2, 0);
 Motor(3, 0);
 MotorDrive();
// delay(200);

 Motor(0, -100);
 Motor(1, -100);
 Motor(2, -100);
 Motor(3, -100);
 MotorDrive();
// delay(200);
}

void MotorDrive() // モータ制御値の更新
{
 Wire.beginTransmission(address >> 1);
 Wire.write(Motor_Power,6);
 Wire.endTransmission();
 delay(1);
}

void Motor(int num, int val) // モータ制御用変数設定 ( 0~5ch,パワー )
{
 if (val == 1000)
{
 Motor_Power[num] = 0x80;
}
else
{
 constrain(val, -100, 100);
 if (val < 0)
 {
  val = abs(val);
  bitWrite(val, 7, 1);
  Motor_Power[num] = val;
 }
else
{
 Motor_Power[num] = val;
}
}
}