■STM32 NucleoボードのADCを使う

22_232_1nuadc.jpg
前回Lチカを行ったNucleoボードですが、今度はエフェクターのパラメータ変更を想定してADC(アナログ・デジタル・コンバータ)を使ってみます。アナログ電圧値をデジタル数値に変換することにより、ポット(可変抵抗)をどれだけ回転させたか取得できます。

実際の運用ではバックグラウンドで自動的に複数ポットの値を取得し続ける必要が出てくると思いますので、DMA(Direct Memory Access)を利用します。DMAとは、CPUを介さずデータ転送できるというよくわからないけど便利な機能らしいです。



Nucleoボード(NUCLEO-F303RE)とポットとの接続は下記の通りです。ポットは抵抗値5kΩ以上でBカーブのものがよいでしょう。

ポットの1番ピン→NucleoボードのGND
ポットの2番ピン→NucleoボードのA0
ポットの3番ピン→Nucleoボードの3V3(5Vと間違えないように!)

ポットは1つですが、2チャネル分セットアップしていきます。ソフトの基本操作については前回記事をご参照ください。変更する箇所を記載していますが、ソフトのバージョンによりデフォルト値が違うかもしれませんので、スクリーンショットも確認した方がよいだろうと思います。



<STM32CubeMX(5.0.0) Pinout & Configurationタブ>
左側列のAnalog→ADC1を開く

・中央列上側 Mode
 IN1 : IN1 Single-ended
 IN2 : IN2 Single-ended
 →右側IC画像の14番ピン(PA0)と15番ピン(PA1)が自動的に切り替わる

・中央列下側 Configuration→Parameter Settingsタブ
22_232_2nuadcss1.png
Clock Prescaler : Syncronous clock mode divided by 4
Continuous Conversion Mode : Enabled
DMA Continous Request : Enabled
Number Of Conversion : 2
 →Scan Conversion Mode がEnableに切り替わり、Rank 2 が追加される
Rank 1 Sampling Time : 19.5 Cycles
Rank 2 Channel : Channel 2
Rank 2 Sampling Time : 19.5 Cycles

・中央列下側 Configuration→DMA Settingsタブ
22_232_3nuadcss2.png
Addボタンで行が追加される
 DMA Request : ADC1
 Mode : Circular ※Normalの場合ADC値取得が1回だけとなる



<TrueSTUDIO(9.1.0)>
main.cに2箇所追加記載する

/* USER CODE BEGIN 0 */の下 ADC値を格納する配列を定義
uint16_t adcValue[2];

/* USER CODE BEGIN 2 */の下 ADC値取得開始
HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adcValue, 2);

デバッグ画面で一時停止中adcValueにマウスカーソルを合わせると、取得したADC値が確認できます。
22_232_4nuadcss3.png
ポットのシャフトを動かし、再開と一時停止をするとadcValue[0]が0~4095の間で変化します。ポットの2番ピンをNucleoボードのA1につないだ場合は、adcValue[1]が変化します。細かい設定はまた別の機会に見直すとして、とりあえず値を取得できているようなのでOKでしょう。



<補足情報>
・設定したチャネル数のADC値取得後に何かしらの処理を行う場合、/* USER CODE BEGIN 4 */の下に以下のように記載する
void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc){
// 処理
}

・ADC値取得を中止する場合は下記関数を使う
HAL_ADC_Stop_DMA(&hadc1);



<参考ページ>
STM32でADCをやってみる2(DMAを使ったレギュラ変換) - ガレスタさんのDIY日記
STM32マイコンでADCを使ってみる話 - JP7FKFの備忘録

■タグ : マイコン

■STM32 NucleoボードのLチカ

22_231_1nu.jpg
将来的にデジタル信号処理を行うことを考えると、32ビットマイコンを使いこなすことが必要になってくると思います。今回STM32 Nucleoボードを購入したので、ボード上のLEDの点滅(Lチカ)までの手順をメモしておきます。

使用したNucleoボード:NUCLEO-F303RE(STM32F303RE搭載) ※miniBタイプのUSBケーブルが必要



<開発環境>
下記2つのソフトをインストールします。
TrueSTUDIO for STM32 9.1.0
STM32CubeMX 5.0.0 ※Java Runtime Environmentが必要

TrueSTUDIOはProバージョンが無料になったのが最近なので、SW4STM32というソフトの方が利用者が多いかもしれません。Mbedというブラウザで動くプログラミング環境もありますが、デバッグを考えると物足りなくなりそうなので採用しませんでした。

※STM32CubeMXのバージョン5.0.0に合わせて内容を修正しました。(2018年12月12日追記)



<Lチカまでの手順>
1) TrueSTUDIOを起動
2) ワークスペース指定ダイアログが出てくるので作業に使うフォルダを指定し、TrueSTUDIOを終了
  ※全角文字やスペースが入らないようにする
3) STM32CubeMXを起動
4) New ProjectのACCESS TO BOARD SELECTORボタンを押し、使用するボードを選択
  ※情報が自動更新される場合あり
5) Pinout & Configurationが表示されるがそのまま(LEDが繋がっているPA5ピンがGPIO_Outputに設定済)
6) Project ManagerのProjectを以下のように入力した後、右上のあたりGENERATE CODEボタンを押す
  Project Name:プロジェクト名を入力
  Project Location:2)で指定したTrueSTUDIOのワークスペースフォルダを選択
  ToolChain / IDE:TrueSTUDIO
  ※ファームウェアをダウンロードするか聞かれたらYesを選択
7) コード生成終了後Open Projectを選択するとTrueSTUDIOが起動する
8) プロジェクト・エクスプローラー(左列)からSrcフォルダ内main.cを開く
9) 110行目あたり「/* USER CODE BEGIN 3 */」の下に以下の記述を追加する
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
HAL_Delay(500);
10) プロジェクト→プロジェクトのビルド(または金槌のボタン)
11) Nucleoボードを接続
12) 実行→デバッグ(または虫と矢印のボタン) 画面が切り替わる 
  ※ST-LINKを更新するよう指示が出る場合あり
13) 再開ボタンを押すとNucleoボードのLEDが点滅 終了ボタンで前の画面に戻る

■タグ : マイコン

■RasPd3 操作方法

RasPd3の内部プログラムが概ね完成したので、自分用に取扱説明書のようなものを記載しておきます。LCDの文字が小さいですがなんとか大丈夫そうです。そのうちタップテンポやチューナーも実装できたらいいなと思っています。



03_230_1raspd3sh.jpg
<コントロール類と略称>
・左側ロータリーエンコーダ:LR
・中央ロータリーエンコーダ:CR
・右側ロータリーエンコーダ:RR
・左側押しボタンスイッチ:LS
・中央押しボタンスイッチ:CS
・右側押しボタンスイッチ:RS
・左側フットスイッチ:LF
・右側フットスイッチ:RF



<画面中央 緑色領域>
・エフェクトの種類とエフェクトパラメータを「プリセット」として8パターン(A~H)保存
(Pure Dataのプログラムを「パッチ」と呼ぶので、混同しないよう「プリセット」という呼称にしている。)
・プリセット1つにつき直列に6つのエフェクト(上3つ→下3つへ繋がっている)
・エフェクトは内蔵エフェクト20種類から選択(1つのプリセット内で複数重複使用は不可)
・エフェクトオン状態のエフェクトの名前右横に白色の丸印がつく
・「RF割当」を設定したエフェクトの名前右横に紫色の四角形がつく

※RF割当:プリセット内部モード(後述)時、RF押下でオンオフが切り替わるエフェクトを割り当てられる。
【例】ディストーション(オン)とコーラス(オフ)にRF割当を設定しておくと、RF押下時にディストーションをオフ、コーラスをオンという風に切り替えられる。

<画面右側 青色領域>
・プリセットの切替順番を3パターン保存
・フットスイッチで上下にプリセットを切り替える

<画面下側 灰色領域>
・エフェクトパラメータを表示
・エフェクトオンの場合、右に[ON]が表示される
・「RF割当」を設定している場合、右に[EN]が表示される



<2種類のモード(●プリセット切替、◆プリセット内部)と操作方法>
※LSを押しながらCSを押す:データ保存、押し続けるとシャットダウン(両モード共通)

●プリセット切替モード
複数のプリセットをフットスイッチで切り替えるモード。プリセット切替の順番を編集できる。

LR:カーソル左右移動
CR:カーソル上下移動
RR:プリセットA~Hまたは「X」を選択
※「X」を選択すると、フットスイッチでのプリセット切替時にX以降への切替がキャンセルされる。
【例】A→B→C→D→X→F→E→Gの場合…Dの後はA、Aの前はDに切り替わる。

LS:「プリセット内部モード」へ切替
CS、RS:なし
LF:プリセット切替(下側へ)
RF:プリセット切替(上側へ)

◆プリセット内部モード
1つのプリセット内で単独もしくは複数のエフェクトのオン・オフを切り替えるモード。エフェクトの種類やパラメータを編集できる。

LR:カーソル左右(エフェクト順番)移動
CR:カーソル上下(プリセット間)移動
RR:エフェクトの種類またはバイパスを選択
(エフェクトパラメータ編集時は、各ロータリーエンコーダでパラメータを増減させる)

LS:押す度にエフェクトパラメータ上段→エフェクトパラメータ下段→エフェクトの種類へと編集箇所切替
CS:「プリセット切替モード」へ切替
RS:「RF割当」設定/解除
LF:選択中のエフェクトをオン/オフ(オンの時、左側LED点灯)
RF:「RF割当」が設定されたエフェクトをオン/オフ

■更新情報・雑記

第6回エフェクタービルダーズ・コンテストに向けて揺れ系エフェクターを開発中です。



■ATtiny85 タップテンポ付LFO その2

14_229_1atLFO2.png
前回のLFOをさらに発展させました。主な変更点は下記の通りです。考え方は前回と同じで、一定間隔でPWMのデューティ比を変更します。
・1周期126分割→510分割(PWMの分解能8ビット分をフルに生かせる)
・PWM周波数31.25kHz→250kHz(出力ピンPB0→PB1)
・タイマー割り込みを使ってPWMデューティ比を変更、タップ時間計測

タイマー・割り込みに関する詳細説明は省きます。ATtiny85(日本語データシートpdf)は2つのタイマーがあり、Timer0でデューティ比変更時間の管理とタップテンポの時間計測をし、Timer1でPWMを使います。該当レジスタを変更することにより様々な設定を行うわけですが、見慣れないビット演算が出てくるので最初は戸惑うかもしれません。
参考ページ→C言語入門::付録 ビット演算びんずめ堂)・AVRでのタイマとPWMの使い方うしこlog)・AVRでの割り込みの使い方うしこlog

今回のスケッチでは三角波を生成しています。ATtiny85のPWMを最高速で動作させるため、Arduino IDEのツールメニューから「Timer1 Clock: "64MHz"」を選択し「ブートローダを書き込む」という操作を行っておく必要があります。

▽Arduinoスケッチ
表示/非表示切替(94行)



<タップ時間計測について>
Timer0に比較A割り込みを設定している関係で、millis関数で時刻を取得しようとしてもうまくいきません。タップ時間の測定は割り込み回数をカウントすることにより行います。Timer0はクロック8MHz、8分周なので最小時間単位は1usです。OCR0Aを200にすると200usごとに割り込みが発生します。

【例】0.2msごとに割り込みが発生(OCR0A=200)→割り込みが50回発生(timeCount=50)→経過時間10ms(0.2ms×50)

OCR0Aを更新する時に、更新前の時間(timeTemp)を計算しておく必要があります(スケッチ最下部)。TCNT0も加味した方がより正確ですが、そこまでの精度は必要ないでしょう。タップについては1回目と2回目の区別はなく、毎回前回タップからの経過時間を計算します。経過時間が設定可能なLFO周期内であるときだけ、実際に周期を変更することになります。



<デューティ比変更間隔時間の計算処理について>
OCR0Aを200とし、割り込みが発生する度にデューティ比を変更すると、周期は102ms(0.2ms×510)です。OCR0Aは255まで(8ビット)なので、このままでは周期を長く設定できません。分周比を変えることも考えましたが時間分解能が悪くなります。そこで長い周期を得るために、何回か割り込みが発生した時にデューティ比を変更するようにします。

【例】0.2msごとに割り込みが発生(OCR0A=200)→割り込みが10回発生(rateCountNum=10)するごとにデューティ比変更→周期1020ms(0.2ms×10×510)

次は逆に周期から割り込み間隔と回数を計算します(上記スケッチのrateCalc関数)。ちょっと無理やり感がありますが、100~255usの割り込み間隔で割った商(=割り込み回数)と余り(=誤差)を全て計算し、余りが最小になる時を採用します。割り込み間隔はあまりに狭いと問題がありそうなので、100us以上としました。

【例】最適値計算:周期1030ms(1030000us)→デューティ比変更間隔時間2019us(1030000÷510切捨)→224us(割り込み間隔)×9(回数)+3us(誤差)
計算値設定後:0.224msごとに割り込みが発生(OCR0A=224)→割り込みが9回発生(rateCountNum=9)するごとにデューティ比変更→周期1028ms(0.224ms×9×510)


ほとんどの場合で周期の誤差は2ms以内に収まります。実は上記例では2019usを+1usして再計算したほうが誤差が減るのですが、そこまでの計算はしないことにします。

■タグ : マイコン

管理人

ブログ内検索

メールフォーム

当ブログに関するお問い合わせはこちらからお願いします。 ※FAQ(よくある質問)もお読みください。

お名前
メールアドレス
件名
本文

アクセスカウンター