マイコン内蔵A/Dコンバーター
RXマイコンのメリットとして、内蔵A/DコンバーターのSNが高い事があると思う。
※最近の他社マイコン、ARM、ESP32、PIC32などの現実はあまり詳しく無い。
※かなり昔に比較した時に、確かに優位性があった。
RXマイコン内蔵、A/Dコンバーターも、豊富な変換モード、サンプルホールド、細かいチャネル設定など、非常に柔軟な設定が可能になっている。
広範囲の事柄が関係するので、理解して応用するのは大変だ・・
また、アナログ回路も絡むので、その部分で、デジタル回路には無い難しさがある。
RX72N の場合:
項目 | 内容 |
---|---|
ユニット数 | 2ユニット(S12AD, S12AD1) |
分解能 | 12ビット |
変換時間 | 1チャネル当たり(0.48μs)(12ビット変換モード) |
1チャネル当たり | (0.45μs)(10ビット変換モード) |
1チャネル当たり | (0.42μs)(8ビット変換モード) |
備考 | (A/D変換クロック ADCLK = 60MHz動作時) |
12 ビットの変換時、チャネル辺り、最大 0.48 マイクロ秒で変換出来る。
RX65N Envision Kit、RX72N Envision Kit では、同時に2チャネルが変換可能なアナログチャネルが、pmod コネクタなどにアサイン可能となっている。
※多少残念なのは、電圧リファレンス端子が、内蔵電源に接続されている点がある・・
2M サンプルで同時 2 チャンネルなら、まぁ仕様としては何とか実用性があると思える。
以上の仕様で、簡易なデジタルストレージオシロが作れると思っていた。
そこで、RX65N Envision Kit で簡単な実験を行い、実際にキャプチャーしたデータをLCDに表示して基本的な実験は成功していた。
ただ、RX65N ではCPUのクロックが 120MHz なので、2M サンプルだと、複雑なトリガー条件を作成すると、割り込み処理がオーバーフローするかもしれない・・
DMA 転送にすれば良いと思うかもしれないが、トリガー条件により、電圧の変化を検出する必要があるので、ソフトの介入がどうしても必要となる。
また、アナログのフロントエンド部のハードウェアーとして、どのようなものが適当なのか、検討していた。
最近、PC 上で API レベルシュミレーターを実装した事で、ようやくプロジェクトが動き始めた。
ソフトが重要
データをキャプチャーするのは簡単だが、問題は GUI 関係のソフトウェアーだと思う。
デジタルストレージオシロを実用的に使うには、ソフトの機能、基本的なデザイン(操作の考え方)が重要で、複雑で、大きなボリュームになる。
以前に、工場で使う検査装置として、デジタルストレージオシロの機能が入った物を作った事がある。
その時は、波形のキャプチャーだけ、外部のFPGAとマイコンを組み合わせた機器で行い、波形の表示などは、PCで行った。
その時は PC 上のソフトなので、効率やメモリ、速度などは気にする必要が無く、自由に作れた。
それでも、非常に面倒な作業で、時間や電圧の変換、操作性など、色々苦労した事が蘇る・・
RX65N Envision Kit や RX72N Envision Kit の場合、液晶の解像度も小さいので、操作性も考慮する必要がある。
また、タッチパネルの操作が基本なので、そのようなデザインを考える必要がある。
加えて、外部に接続するハードウェアーもあまり大掛かりにならないようにする事も考慮する必要がある。
最近では、数万円出せば、高性能なデジタルストレージオシロが買えるので、作っても、あまり利用頻度は大きいとは思えないが、ソフトの構成や、基本的な構成などは、一つのアプリケーションとして参考になると思う。
教材として考えれば、それなりに利用価値があるものと思って進めている。
また、オープンソースとする事で、誰でも、「欲しい機能」を追加する事も出来る。
※特殊なトリガー条件などを実装する事が出来ると思う。
PC 上の、API レベルシュミレーションは便利で、暇を見つけてコツコツ進めている。
GUI Widget フレームワークも完成度と機能が充実しつつあるので、GUI などの面でも実装が楽になってきた。
PC では、A/D コンバーターの部分をシュミレーションにより作成して、それを A/D の変換値12ビット整数データとして与え、ソフトを実装している。
キリの良いとこで、実機でも動かして確認する。
A/D の疑似波形を生成
疑似波形としては、サイン波、三角波、矩形波などをサポートして実験を行っている。
※実機では、ノイズなども考慮する必要があるので、最終段階では、ソフトでノイズを混ぜる事も考える必要がある。
//-----------------------------------------------------------------//
/*!
@brief SIN/COS 波形を生成
@param[in] freq 周波数
@param[in] ppv 電圧 (peak to peak)
@param[in] num 生成数
@param[in] ch0 CH0 波形型
@param[in] ch1 CH1 波形型
*/
//-----------------------------------------------------------------//
void make_wave(uint32_t freq, float ppv, uint32_t num, PWAVE_TYPE ch0, PWAVE_TYPE ch1)
noexcept
{
static int32_t count = 0;
auto smpl = get_samplerate();
auto& task = at_cap_task();
auto unit = static_cast<float>(smpl) / static_cast<float>(freq);
auto vgain0 = voltage_to_value(0, ppv);
auto vgain1 = voltage_to_value(1, ppv);
for(uint32_t i = 0; i < num; ++i) {
auto a = static_cast<float>(count % static_cast<int32_t>(unit)) / unit;
task.adv_.x = -pwave_(ch0, a, vgain0);
task.adv_.y = -pwave_(ch1, a, vgain1);
if(task.adv_.x < -CAP_OFS) task.adv_.x = -CAP_OFS;
else if(task.adv_.x > (CAP_OFS-1)) task.adv_.x = CAP_OFS-1;
if(task.adv_.y < -CAP_OFS) task.adv_.y = -CAP_OFS;
else if(task.adv_.y > (CAP_OFS-1)) task.adv_.y = CAP_OFS-1;
task();
++count;
if(count >= CAP_NUM) {
count = 0;
}
}
}
サイン波や、三角波、矩形波は、以下のような関数で生成する。
static float ftri_(float in) noexcept
{
auto a = fmod(in, 1.0f);
if(a >= 0.5f) {
a = 1.0f - a;
}
a -= 0.25f;
return a * 4.0f;
}
static float fsqu_(float in) noexcept
{
auto a = fmod(in, 1.0f);
if(a < 0.5f) {
return 1.0f;
} else {
return -1.0f;
}
}
static float fsquf_(float in, float& back) noexcept
{
auto a = fsqu_(in);
auto d = (a - back) * 0.707f;
auto ans = back + d;
back = a;
return ans;
}
static int16_t pwave_(PWAVE_TYPE pw, float phase, float gain) noexcept
{
static float fsqu_s_ = 0;
static float fsqu_c_ = 0;
int16_t ret = 0;
switch(pw) {
case PWAVE_TYPE::SIN:
ret = static_cast<int16_t>(sinf(phase * vtx::radian_f_) * gain);
break;
case PWAVE_TYPE::COS:
ret = static_cast<int16_t>(cosf(phase * vtx::radian_f_) * gain);
break;
case PWAVE_TYPE::TRI_C:
ret = static_cast<int16_t>(ftri_(phase) * gain);
break;
case PWAVE_TYPE::TRI_S:
ret = static_cast<int16_t>(ftri_(phase + 0.25f) * gain);
break;
case PWAVE_TYPE::SQU_C:
ret = static_cast<int16_t>(fsqu_(phase) * gain);
break;
case PWAVE_TYPE::SQU_S:
ret = static_cast<int16_t>(fsqu_(phase + 0.25f) * gain);
break;
case PWAVE_TYPE::FSQU_C:
ret = static_cast<int16_t>(fsquf_(phase, fsqu_c_) * gain);
break;
case PWAVE_TYPE::FSQU_S:
ret = static_cast<int16_t>(fsquf_(phase + 0.25f, fsqu_s_) * gain);
break;
default:
break;
}
return ret;
}
現在の実装は「capture.hpp」に含めている。
※これは、見直すべきかもしれないが・・
SIN、COS は、同じ物で、位相が 45度異なるだけとも言える。
A/D コンバーターのプリアンプ
サンプリングが 2MHz だと、実用的に扱える周期は 1/10 の 200KHz くらいだろうか・・
その場合でも、1 周期、10 サンプルしか無い・・
オシロスコープとしては、かなり低機能なものなので、あまり高性能なフロントエンドを考える必要は無いものの、経験が無いので、どのような構成にすべきなのか良く判らない。
一番良いのは、実際のオシロスコープを分解して、リバースエンジニアリングを行うのが手っ取り速い気がする・・
最初から最高の物を目指すと、完成しないので、改修していけばいいだろうと思う。
1X、プローブを接続する場合、入力インピーダンスは 1000K オーム程?
※10X プローブでは、9000K オームの入力抵抗が直列に入っているものと思う。
最初、1X、10X プローブを両方使えるようにしようと思ったが、回路が大掛かりになりそうなので、1X のみにしようと思う。
※10Xでは、既に1/10になるので、分圧は必要無いが、それを直でオペアンプに入れると、1X を接続した場合に、過電圧からの保護が難しい。
※アナログスイッチで、過電圧保護機能が充実しているデバイスを使えば良さそうだが、値段が高い。
何となく、機械式リレーを使うのが嫌なので、フォトモスリレーを使って、DC、AC を切り替えている。
オペアンプは、オーディオ用の物だが、以前にオーディオ用 DAC に使った部品が沢山余っている。
この回路には、過大な電圧を制限して、A/D の入力を制限する回路が含まれていない・・
まだ、実際の回路で試していないので、この回路では、駄目かもしれないが・・
レンジ切り替えや、AC、DC 切り替えは、機械式スイッチにすれば良いのかもしれないが、スマートでは無くなる気がする・・・
全体の機能
現在シュミレーターを使い、以下の機能を大体実装した。
チャネル電圧切り替え:
- AC, GND, DC, OFF
- 10V,5V,2V,1V,500mV,200mV,100mV,50mV,10mV
サンプリング切り替え:
- 1us,2us,5us
- 10us,20us,50us
- 100us,200us,500us
- 1ms,2ms,5ms
- 10ms,20ms,50ms
- 100ms,200ms,500ms
トリガー切り替え:
- None,One,Run,CH0-Pos,CH1-Pos,CH0-Neg,CH1-Neg
計測:
- Time Sub,CH0 Sub,CH1 Sub,Time Abs,CH0 Abs,CH1 Abs
まとめ
シュミレーターのおかげで、ソフト部はかなり進んだが、やはりハード部は、進捗が遅い・・・
現状のコードは、シュミレーター「glfw_app/rx_gui_emu」から、定期的に「RX/DSOS_sample」にマージしている。