2021年7月29日木曜日

STM32CubeIDE Nucleo-G431KBの実行速度を測定 GPIO

STM32は従来のFシリーズ、Lシリーズの他、Gシリーズ、Hシリーズなどバリエーションが増えています。

STMicroの分類表によると、STM32G4はミックスド・シグナル・アプリケーションに最適化されSTM32F3の上位に位置するようです。基本スペックはCortex-M4/170MHzとなっており、Cortex-M4/180MHzのF4に匹敵します。

Nucleo32のNucleo-G431GBを購入したので実行速度を測定しました。手持ちのF303K8、F446RE、F767ZIを比較対象としました。


左から、F303K8、G431KB、F446RE、F767ZI。

STM32CubeIDEのバージョンは1.7.0です。

G431KBのBuild

Clockの設定


STM32CubeIDEでTarget BoardをNucleo-G431KBとして初期化すると、デフォルトではHSE(外部クロック)が無効化されています。



ボード上にクリスタル(X2)が実装されているようですが、ボード上のはんだブリッジで設定する必要があります。


※赤点線で囲ったあたりがはんだブリッジ

UM2397: STM32G4 Nucleo-32 board User Manualより

HSEを使う場合はSB9とSB10をブリッジします。またMXでクロックのソースを指定するとHSEが使えるようになります。

Pinout & Configuration
  System Core
    RCC
      RCC Mode and Configuration
        High SpeedClock(HSE): Crystal/Ceramic Resonator

※Master Clock Outputを有効化するとPG10よりクロック信号が出力されます。

HSEが有効化された状態


ただし、はんだブリッジのパターン自体はそれほどでもないのですが、周りに微小なSMD部品が配置されているので、はんだ付けに注意が必要です。また、170MHzの信号を測定する環境もないため、今回はHSEは試さずHSIを使うことにしました。HSIでもデフォルトで170MHz駆動することができます。

GPIO出力のの実行速度を測定


実行速度を測定する場合、測定する処理の前後でGPIOをHigh/Low出力して、オシロで間隔を測定することが多いので、手始めとして何も処理をせず単にGPIOをHigh/Lowさせた場合にかかる時間を測定しました。

MXの設定


Target BoardにNucleo G431KBを指定してデフォルトで初期化した後、MXでGPIOを設定します。

Pinout & Configuration
  System Core
    GPIO
      Configuration
        GPIO
          PA12
            GPIO mode: Output Push Pull
            Maximum output speed: Very High
            User Label: PIN_CHK1

PA12はArduinoのD2です。

Projectの設定


Project - properties
  C/C++Build
    Settings
      Tool Settiongs
        MCU GCC Compiler
          Optimization
            Optimization Level: Optimize for speed (-Ofast)

最適化レベルを速度優先にします。なお「-Ofast」を指定すれば、CofigurationがDebugでもReleaseでも実行速度に差は無いようです。

ソースコード(Core/Src/main.cに追加)

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    HAL_GPIO_WritePin(PIN_CHK1_GPIO_Port, PIN_CHK1_Pin, GPIO_PIN_SET);
    HAL_GPIO_WritePin(PIN_CHK1_GPIO_Port, PIN_CHK1_Pin, GPIO_PIN_RESET);
  }
  /* USER CODE END 3 */

実行結果


ch1:PA12(D2)

F303K8のBuild

Pinoutの設定


GPIOの設定で、PA12(ArduinoのD2)をOutputに設定し、PIN_CHK1とラベル付けします。

Clockの設定


HSE→PLLを使って最大クロックの72MHzでBuildすると正常動作しませんでした。


Debuggerで追いかけると、SystemClock_Config()のHAL_RCC_OscConfig()内でエラーが発生し、ErrorHandler()に制御が移ってしまうようです。HSI→PLLを使うと64MHzまでしか設定できませんが、正常動作します。こちらで測定しました。


実行結果

CH1:PA12(D2)

F446REのBuild

Pinoutの設定


GPIOの設定で、PA10(ArduinoのD2)をOutputに設定し、PIN_CHK1とラベル付けします。

Clockの設定


クロックはHSE→PLLで180MHzです。


実行結果

CH1:PA10(D2)

F767ZIのBuild

Pinoutの設定


GPIOの設定で、PF15(ArduinoのD2)をOutputに設定し、PIN_CHK1とラベル付けします。

Clockの設定


クロックはHSE→PLLで216MHzです。


実行時にエラーが発生するのでMXでETHを無効化します。

Connectiviy
  ETH
    Mode: Disable

実行結果

CH1:PF15(D2)

実行速度比較


機種名 パルス幅(ns) 周波数(MHz) 周期(ns)
G431KB 64 7.716 129.6
F303K8 312 1.522 657
F446RE 55 7.825 127.8
F767ZI 272 1.49 671


G431KBはF446REと同程度の速度でGPIOをHigh/Low出来るのがわかります。しかしF303K8が遅いの当然ですが、F767ZIが異常に遅い結果となりました。Clockが216MHzでコアがCortex-M7なのに何故なのでしょうか。

APB1 peripheral clocksが54MHzとなっているのが原因かと思いましたが、F446REもAPB1 peripheral clocksは45MHzです。

2021年7月25日日曜日

Korg SQ-1のGate信号を拡張 GateEXの製作(2)

試作したGateEXは、Korg SQ-1とつないで自作のKIK01にSync信号を送ると、SQ-1のSync信号が疎で特にハットの刻みが少なくイマイチでした。Sync信号の周期を分割してもっと細かくGate信号を送出できるように改良しました。


SQ-1から送られてくるSync信号の間隔を測定し、分割数で割った間隔でタイマ割り込みをかけ、Gate信号を送出するという動作にしました。

ハードウェアの変更は行わず、変更はファームウェアのみです。Gateタイムを設定していたPOTで、分割数を設定するように変更しました。自作のKIK01は信号の立ち上がりしか見ていないのでGateタイムはSQ-1のSync信号と同じく15msに固定しました。

Gateオフのタイミングと分割したGate出力のタイミングを同じMsTimer2でとっています。Gateオフ時に次のGate信号のTimer割り込みを設定しており、図のようにタイマ割り込みまでの待ち時間はInterval - PULSE_WIDTH[ms]となります。

1回目のGate信号送出はSync信号のハードウェア割り込み時となるため、MsTimer2によるタイマ割り込みは2回め以降になります。「1/1」の場合はタイマ割り込みは行われません。

また、前回のファームウェアではDIPスイッチとシーケンスの割当が逆順になっていました。本来は左から右へ再生されるべきが、右から左の順になっていました。意外とわからないものですw

Arduinoのスケッチ <Gate_Sequencer_02.ino>

//
// Gate Sequencer
//   Sync-in -> Gate sequence
//   Split Sync-in
//
// 2021.07.25
//

#include <MsTimer2.h>

#define PIN_SYNC_IN      (2)
#define PIN_GATE_OUT     (12)
#define PIN_GATE_LED     (11)
#define PIN_DIVISION     (A0)

#define CNT_N            (8)
#define PULSE_WIDTH      (15)

byte sequence[CNT_N] = {0};
int cnt = 0;
int division = 1;
int divisionCnt = 0;
int interval = 0;

void gateOff()
{
  digitalWrite(PIN_GATE_OUT, LOW);
  digitalWrite(PIN_GATE_LED, LOW);

  if (divisionCnt > 0) {
    divisionCnt--;
    MsTimer2::set(interval - PULSE_WIDTH, stepOne);
    MsTimer2::start();
  }
}

void stepOne()
{
  digitalWrite(PIN_GATE_OUT, sequence[cnt]);
  digitalWrite(PIN_GATE_LED, sequence[cnt]);

  cnt++;
  if (cnt >= CNT_N) {
    cnt = 0;
  }

  MsTimer2::set(PULSE_WIDTH, gateOff);
  MsTimer2::start();
}

void step()
{
  static uint32_t prevTime = 0;
  
  uint32_t now = millis();
  interval = (now - prevTime) / division;
  prevTime = now;
  divisionCnt = division;

  stepOne();
  divisionCnt--;
}

void setup() {
  pinMode(PIN_SYNC_IN, INPUT);
  pinMode(PIN_GATE_OUT, OUTPUT);
  pinMode(PIN_GATE_LED, OUTPUT);

  // DIP switch
  pinMode(3, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
  pinMode(6, INPUT_PULLUP);
  pinMode(7, INPUT_PULLUP);
  pinMode(8, INPUT_PULLUP);
  pinMode(9, INPUT_PULLUP);
  pinMode(10, INPUT_PULLUP);

  attachInterrupt(digitalPinToInterrupt(PIN_SYNC_IN), step, RISING);
}

void loop() {
  // Read DIP switch
  sequence[0] = !digitalRead(10);
  sequence[1] = !digitalRead(9);
  sequence[2] = !digitalRead(8);
  sequence[3] = !digitalRead(7);
  sequence[4] = !digitalRead(6);
  sequence[5] = !digitalRead(5);
  sequence[6] = !digitalRead(4);
  sequence[7] = !digitalRead(3);

  // Read division
  division = analogRead(PIN_DIVISION) / 256 + 1;  // 1 ~ 4
}

入出力波形

ch1:Sync-in ch2:Gate-out

SQ-1のSpeedを最速にし、GateExのDivisionを1/4に設定。

メモ


オシロで出力波形を観測すると、ジッターというか波形の間隔が揺れることがあります。millis()ではなくmicros()関数、MsTimer2ではなくTimer1を使うようにして(us単位で制御できる)分解能を上げると改善するかもしれません。

ハードウェアを改修するなら、押すとシーケンスの頭から再生し直す(シーケンス・リセット)ボタンがあると良さそうです。SQ-1のシーケンスとは1音単位では同期していますが、フレーズとしてはズレてしまいます。SQ-1側のスタート/ストップで一応は対応できます。

2021年7月21日水曜日

LME49600HPAの電源電流測定 Behringer UMC404HDのヘッドホン出力改善に向けて

LME49600はヘッドホンをドライブするのにちょうどいい優秀なバッファICです。最初は秋月で入手したのですが、秋月では取り扱い終了しています。

オーディオインターフェイスとしてベリンガーのUMC404HDを使っていますが、ヘッドホン出力がショボすぎます。ファースインプレッションで述べたようにすぐに出力がクリップしてしまいます。とてもではないですがAKG K701をドライブしきれません。ボリュームつまみを回すとガリがひどく実用に耐えないレベルだと思います。

というわけで、UMC404HDのヘッドホン出力をましにするために、LME49600_HPA V2.1を使って新たにヘッドホンアンプを製作しようと思います。

LME49600HPA V2.1は、DCサーボバージョンとACカップリングバージョンを製作し運用していて、音質的に不満はないのですが、±9V以上の両電源が必要となります。商用電源を利用すると、必要なのは2出力のトランスと安定化電源です。

DCサーボバージョン

ACカップリングバージョン

安定化電源は自作してもよいのですが、中華製(AIYIMA)の基板を入手し評価しました。 評価結果により電源はサーボなしバージョンを使うことにして、必要なトランスの定格出力を検討します。

テスト概略図

LME49600HPAの出力にヘッドホンの代わりに抵抗を負荷としてつなぎ、トランスから出力され安定化電源に入る電流をテスタで測定しました。入力波形生成(Wavegen)とオシロ(Scope)にはAnalog Discovery 2を使用しました。実験用のトランスはHDB-30で定格出力1Aが2系統です。何も考えなければこのトランスを使えばいいのですが、必要な電源電流を求めスペースと値段の節約を図りたいと思います。

LME49600HPA回路図

テストしたのはDCサーボバージョンです。OPアンプはMUSES8820を使用しました。

実験のようす

負荷は、100Ωの酸金抵抗を並列にして、100Ω、50Ω、33Ωとしました。

入力信号を2Vpp/1kHzのサイン波とし、出力に負荷をかけると出力波形がクリップします。

入力電圧:2Vpp 無負荷

入力電圧:2Vpp 負荷:33Ω

入力電圧は最大1.5Vppとし、1Vppと1.5Vppの場合で出力を測定しました。

測定結果


入力電圧(Vpp) 1
入力電圧(Vrms) 0.353553391

負荷抵抗(Ω) 無負荷 100 50 33
出力電圧(Vpp) 10.4 10.4 10.4 10.4
出力電圧(Vrms) 3.676955262 3.676955262 3.676955262 3.676955262
出力電流(mA) 0 104 208 315.1515152
出力電力(mW) 0 135.2 270.4 409.6969697
増幅率 10.4 10.4 10.4 10.4
AC入力電流+(mA) 48 81 118 154
AC入力電流-(mA) 51 83 121 159
入力電圧(Vpp) 1.5
入力電圧(Vrms) 0.530330086

負荷抵抗(Ω) 無負荷 100 50 33
出力電圧(Vpp) 15.6 15.6 15.6 15.6
出力電圧(Vrms) 5.515432893 5.515432893 5.515432893 5.515432893
出力電流(mA) 0 156 312 472.7272727
出力電力(mW) 0 304.2 608.4 921.8181818
増幅率 10.4 10.4 10.4 10.4
AC入力電流+(mA) 48 100 155 210
AC入力電流-(mA) 51 103 160 216

測定例


入力電圧:1Vpp 負荷抵抗:33Ω

入力電圧:1.5Vpp 負荷抵抗:33Ω

グラフ


出力電流対入力電流
入力電圧:1Vpp

入力電圧:1.5Vpp

LME49600の出力電流の定格は250mAなので電源電流(トランスの出力電流)は150mA以下と見積もればよさそうです。

出力電力対入力電流
入力電圧:1Vpp

入力電圧:1.5Vpp

AKG K701の定格電力は200mWなので電源電流(トランスの出力電流)は100mA以下と見積もればよさそうです。

負荷抵抗対入力電流
入力電圧:1Vpp

入力電圧:1.5Vpp

AKG K701のインピーダンスは62Ωなので電源電流(トランスの出力電流)は150mA以下と見積もればよさそうです。

余裕をみてトランスの定格出力は200mA×2、出力電圧を±15Vとして6VA以上あれば良さそうです。

2021年7月4日日曜日

スマホホルダー Bovon BV-034

XOSSのサイコンを使用していますが、ナビ機能はないのでスマホをナビとして使うためにスマホホルダーを購入しました。




もっとガッチリとした製品もありますが、これは全体的にシリコンゴムで出来ていてスマホをマウントしないとフニャフニャとしています。走行時にガチャガチャいうこともありません。

サイコン、スマホのマウントのみ

ゴムバンドをぐいっと引っ張ってスマホを取り付けます。

サイコン、スマホを取り付けた状態

ややいい加減な取り付け方ですが、この状態で60kmほど走っても走行中に外れるということはありませんでした。ワンアクションで取り外しできるわけではないので、コンビニに寄ったりスマホで写真を撮るなどでスマホを着脱する場面では少しだけ面倒かもしれません。

ナビアプリは、ゼンリンの自転車NAVITIMEを使っています。自分の向かっている方向が大きく表示されるのでわかりやすいと思います。課金しなくてもそこそこ使えます。

スマホはGoogle Pixel3aを使っていますが、指紋認証が裏側にあってホルダーにマウントすると指紋認証が使えなくなります。Pixel 3aは顔認証がないので、画面消灯までの時間を長めにするなど工夫が必要です。

ハンドルへの取付もシリコン製のベルトなので、ナビが必要ないときに取り外すのも比較的簡単だと思います。

2021年7月3日土曜日

中華製可変両電源基板をテストしました

AliExpressでAIYIMA製の可変両電源基板を2種購入したので動作確認しました。どちらもLM317/LM337を使った安定化電源で、一方はサーボ回路が入っています。

サーボ有版


回路図

製品の回路図ではありませんが、おそらくこの回路のバリエーションだと思います。

ノーマル版


回路図

こちらは製品の回路図ですが、一部製品の定数と異なっています。

電源電流を測定


トロイダルトランスHDB-30からACを入力し、出力は±12Vになるように調整しました。電源基板の出力負荷を変更して入力のAC電流をテスタで測定しました。




負荷は、無負荷、220Ω、100Ωとしました。

負荷(Ω) 出力電流(mA) Normal+(mA) Normal-(mA) Servo+(mA) Servo-(mA)
なし 0 6 6 15 28
220 55 65 72 63 111
100 120 135 147 122 204


負荷を変えても出力電圧の変動は見られませんでした。

サーボ有版は負側の入力電流が大きく、正負のバランスが悪いようです。

テスタの誤差かもしれないので、正負でテスタの機種を入れ替えて測定した結果、100Ω負荷で正:123mA、負:202mAでした。問題ないレベルです。

ブリッジダイオードに並列に入っているコンデンサ


両方ともブリッジダイオードが1パッケージになっているものではなく、整流用のダイオードを4本使っています。また、ダイオードに並列に0.1uFのフィルムコンデンサが入っています。

あまり見たことがなかったのですが、「居酒屋ガレージ」さんの「整流ノイズ防止コンデンサ」によるとこのコンデンサはノイズを防止する働きがあるそうです。

メモ


トランスの入力側に安全のためヒューズを入れているのですが、0.5Aのヒューズだと電源を切った時に、ヒューズが切断してしまいます。1A品だとOKです。トランスの逆起電力によるものでしょうか。それにしても回路が切れたときに大きな電流が流れるのは不思議な感じですね。