2017年6月25日日曜日

POTx16 PizzaBox MDFで木枠を作った。

ダイソーで売っている6mm厚のMDFで木枠を作ってみた。


いきなり切り出しで失敗




MDFはやわらかいのでカッターで軽く溝を掘ってノコギリで切断したが、ずれてしまって切断面がガッタガタ。


使ったノコギリは細工用というやつで、薄刃で細かい作業に便利だが、刃渡りが12cmしかなくて切り出しはかなり疲れた。翌日あちこちが筋肉痛になってしまった(@@;

板材があまっているので新たに切り出そうかと思ったが、ミスったところは組み上げたときに外からあまりわからない感じで使うことにした。←疲れてやる気がでない(^q^;

接着



木工用ボンドで接着して、木ねじで固定。ついでにパンツのゴム(ダイソー)で(かなり弱いが)圧をかけた。


しばらく放置して補強用に隅に三角材(これもダイソーで売ってた)を接着してさらに丸一日放置。

組み立て



底板はクリップボードを切り出したプラ板。新しいのがもう売ってなかったので使いまわしです。

見栄えを良くするために別に側板を作って、木ネジで固定。


6mm厚のMDFに2.1mmの木ネジを使ってみたが木端(?)だと板がわれてしまいました。

もう少し厚ければ大丈夫なんだろうか。この辺は経験を積むしかなさそう。


見栄えを良くするために、前面に天板と同じプラ板を切り出して両面テープで貼り付けてみた。最初は考えていなかったので、側板とずれていてイマイチ。

とはいえ、ダンボール枠より外観、強度は良くなったと思う。

Nucleo用テストプログラム
https://developer.mbed.org/users/ryood/code/Nucleo_MCP3008_Ticker_Test/ Revision3

メモ:


ベースマシンの筐体用の木枠も作ってみたい。

加工しやすいMDFでも手作業でノコギリで精度良く切断するのは難しい&かなりの重労働。

もう少し切り出しやすいサイズのノコギリを買ってみる?いっそのこと電動ノコとか。

ホムセンの切断サービスを利用する?

平ネジ用のザグリの入れ方ももう少し考える。太めのドリルでザグってるが、収まりが悪い。太さを2~3段階に分けて円錐状になるようにしてみる?

2017年6月23日金曜日

Nucleo F303K8(mbed)の内蔵DACとSPI DACのMCP4922の速度を比較する

サイズの小さいNucleo F303K8でも内蔵DACとMCP4922の処理時間を比較してみた。

ブレッドボード配線図


プログラムはNucleoF446REの場合と同じです。

SPIクロックに16MHzを指定した場合



ch1:D2 ch2:SPI_SCK

MCP4922に出力完了するまで、21.04usかかっている。


ch1:SPI_MOSI ch2:SPI_SCK

SPIクロックに16MHz指定した場合、SCKの周波数は表示では15.98MHzとなっているが測定誤差で16MHzだと思う。

SPIクロックの指定を変えて測定


SPIクロック設定値 SPIクロック実測値 D2(MCP4922の処理時間) D3(内蔵DACの処理時間)
1MHz 1.0MHz 34.8us 2.8us
2MHz 2.0MHz 27.3us 2.8us
4MHz 4.0MHz 23.5us 2.8us
8MHz 8.0MHz 21.04us 2.8us
16MHz 16.0MHz 21.04us 2.8us
32MHz 32.0MHz 19.8us 2.8us
64MHz 32.0MHz 19.8us 2.8us

32MHzまでは設定値通りのSPIクロックが出力される。やはりNucleo F303は64MHz駆動で、SPIクロックはマスタークロックの1/2まで設定できるんだと思う。

MCP4922の仕様ではSPIクロックは20MHzまでだが、32MHzでも動作した。

NucleoF446REと比べると、SPIクロックを上げてもSPI通信の処理時間はあまり短縮されない。

2017年6月22日木曜日

Nucleo F446RE(mbed)の内蔵DACとSPI DACのMCP4922の速度を比較する

結論から言うと、内蔵DACの方が圧倒的に速かった。

mbedでプログラムを書いて、SPI DACのMCP4922とNucleo F446RE内蔵DACの処理時間を比較してみた。

どちらも12bit。

/*
 * 内蔵DACとMCP4922に出力するテスト
 *
 * 2017.06.21
 *
 */

#include "mbed.h"
#include "rtos.h"

#define SPI_CLOCK   (24000000)

SPI SpiM(SPI_MOSI, SPI_MISO, SPI_SCK);  // mosi, miso, sclk
DigitalOut Cs(D10, 1);

AnalogOut InternalDac(PA_4);

DigitalOut CheckPinD2(D2);
DigitalOut CheckPinD3(D3);

// v: 0..0x0fff
void OutMCP4922(uint16_t v)
{
    //v &= 0x0fff;

    // Channel A
    Cs = 0;
    SpiM.write(v >> 8 | 0x30);    // 0x30: DAC_A(0) | Vref Unbuffered(0) | Vout 1x(1) | !SHDN(1)
    SpiM.write(v & 0xff);
    Cs = 1;
}


// v: 0..0xffff
void OutInternalDac(uint16_t v)
{
    InternalDac.write_u16(v);
}

int main()
{
    SpiM.format(8, 0);
    SpiM.frequency(SPI_CLOCK);

    uint16_t count = 0;
    for (;;) {
        uint16_t v12 = count >> 4;
        uint16_t v16 = count;
        
        CheckPinD2 = 1;
        OutMCP4922(v12);
        CheckPinD2 = 0;

        CheckPinD3 = 1;
        OutInternalDac(v16);
        CheckPinD3 = 0;
        
        count += 0x100;

        Thread::wait(1);
    }
}

Nucleoをmbedで使って、SPIの周波数設定をするとちょうどの周波数にはならない。おそらくマスタークロックの分周比なのだと思う。

こういうハードウェア寄りの使い勝手はmbedの弱点ではあります。

SPI::frequency()でSPIクロックの周波数を変えて測定してみた。

ブレッドボード配線図


MCP4922にはLDAC pinがあって、これをH→LするとA ChannelとB Channelが同期して
同時に電圧が出力されるが、LDACをL(GND)に落としておくと、CSのアクティブ/インアクティブで制御できるようだ。配線や処理時間のコストがシビアな場合は役に立つと思う。(A Channelだけしか試してないです)

1MHz

ch1:MCP4922 ch2:内蔵DAC

MCP4922から出力すると、27.3usかかる。一方内蔵DACは700ns(0.7us)で済む。


ch1:MCP4922 ch2:SPI_SCK

1MHzを設定した場合はMCP4922との通信に使っているSPIのクロック周波数は643kHz

24MHz

ch1:MCP4922 ch2:内蔵DAC

SPIのクロック周波数を上げるとMCP4922でも6.8us(≒147kHz)で済む。


ch1:MCP4922 ch2:SPI_SCK

SPIのクロック周波数は22.44MHz。クロックが高周波数になるとダンピング抵抗を入れていても波形が怪しくなる。

MCP4922の最大周波数は20MHzなので仕様外だが、VOUTAから波形は出力される。

Zoom Out

ch1:MCP4922 ch2:SPI_SCK

高クロックになると、8bitずつのSPI通信の間隔が開くようだ。

<追記:2017.06.25>
間隔が開くと言うより、SPI::write()のオーバーヘッドが2~3us程度ある?
</追記>

設定値と出力周波数


設定値 SPIクロック 処理時間
1MHz 643.8kHz 27.3us
2MHz 1.154MHz 16.76us
4MHz 2.810MHz 11.32us
6MHz 5.762MHz 8.76us
12MHz 11.29MHz 7.36us
24MHz 22.44MHz 6.74us

2017年6月21日水曜日

キックマシン KIK01 POTをMCP3008で読み取り

Nucleo F446RE(mbed)でA/DコンバーターのMCP3008を使ってPOTの値を読み取るようにしてみた。


出力は内蔵12bitDACから、A/DコンバーターとのSPI通信はSCK、MOSI、CSに33Ωのダンピング抵抗を入れた。MISOは1kΩのRでプルダウンした。

オーディオ出力波形は前回と変わらない。(参考:「キックマシン KIK01 Nucleo(mbed)でプロトタイピング」)

mbed repository:
https://developer.mbed.org/users/ryood/code/KIK01_Proto02/ Revision:13

SPI通信のようす


MOSI

ch1:MOSI ch2:SCK

MISO

ch1:MISO ch2:SCK

CS1(D11)

ch1:CS1 ch2:SCK

CS2(D10)

ch1:CS2 ch2:SCK

SPIクロック(SCK)が419.7kHzとなっているが、MCP3008クラスがSPIオブジェクトをコピーして持つ仕様になっているようで、MCP3008クラスのコンストラクタを呼び出す前にSPI.frequecy()を呼び出さないとクロックの設定が反映されないようだ。なので、デフォルトの周波数になっている。

SPIオブジェクトの周波数をローカルで設定をしないとダメなので、しばし保留。参照かポインタでSPIオブジェクトを持つように変更する予定です。

処理時間の計測


DigitalOutをH/Lさせて、

D2: サンプリング周期ごとの割り込み中の処理時間(エンベロープ生成+波形出力)
D3: エンベロープ生成時間
D4: MCP3008/16chの読み取り時間

がわかるようにしてみた。

D2: サンプリング周期ごとの割り込み中の処理時間

ch1:D2 ch2:SPI_SCK

50kHzの割り込み中の処理時間は5us。プログラムで48kHzに設定しているのでちょっと速い。

割り込み処理中のch1がHiになっている間も、ch2のA/Dコンバーター読み取り用のSPIの SCK(クロック)が出力されているのでSPI通信は非同期で行われているようだ。

普通、SPI用ハードウェアはレジスタに値を設定してやれば、CPUと独立して勝手に通信を行ってくれる。mbedでもこの仕組が効いているんだと思う。ありがたいことです(^q^/

D3: エンベロープ生成時間

ch1:D3 ch2:SPI_SCK

エンベロープ生成には3usかかっている。

D2:D3

ch1:D2 ch2:D3

わかりやすいようにD2とD3を同時に測定。48kHzのサンプリングレートだと周期の1/4を処理に使っているので、まだ余裕がありそう。

D4: MCP3008/16chの読み取り時間

c1:D4 ch2:SPI_SCK

MCP3008の16ch分の読み取りに0.732msかかっていて、その間SCKが出力されている。A/Dコンバーターの読み取りはメイン・ループ内で行っているのでエンベロープ生成、波形出力の割り込みが優先される。(←はず)

2017年6月19日月曜日

POTx16 PizzaBox ダンボールver.でけた


枠は、ダンボールの作ったもの。すでに崩壊寸前で見た目も残念な感じなので近いうちに木材で枠を作り直すつもりです。

Moog
や、MPC

っぽくしてみたいところですが、枠の塗装はのちのち。

A/Dコンバーター基板 回路図

A/Dコンバーター基板 基板図

A/Dコンバーター基板 部品面

A/Dコンバーター基板 ハンダ面

MCP3008が2個の16チャンネルのADC基板。12bit A/DコンバーターのMCP3208もピンコンパチなので差し替えられる。ADCにつなぐマスター側のプログラムの変更で対応できると思う。

また、PINOUT_0、PINOUT_1のピンヘッダで、可変抵抗で分圧した電圧を直接取れる。

POTパネル 表面

POTパネル 裏面

パネルはダイソーで売っていたクリップボードを切り出して使った。最近プラ製ではなく紙製のクリップボードしか売ってなくて困っている。ホムセンのアクリ板は結構お高いので気軽に試しにくいです(^q^;

配線は去年の正月買った共立の福袋に入っていたBELDENの8503というケーブルを使ってみた。このケーブルは線材が固めでパネル取付型のPOTなど空中配線するときには使いやすいと思う。線材にクセをつけられるので手で押さえていなくてもはんだ付けしやすい。

どっちにしろ、はんだ付け箇所が多いのでめんどくさいです。量産する場合はプリント基板に基板取り付け型の可変抵抗でしょうか。

POTは40円、つまみは30円のものを秋月で仕入れたので、パネルだけだと材料費は1200円ぐらいです。

2017年6月15日木曜日

POTx16 PizzaBoxの構想

可変抵抗をただ16個並べただけ+A/Dコンバーターを使ってマイコンとのやりとりの線数減らす構想。

PizzaBoxといっても宅配ピザのSサイズより小さいと思う。たぶん。(17cm×17cm)

モックアップを作ってみた。


中は、


スッカスカ

枠は現状のダンボールでもいいが、木工の練習のためにダイソーで売っているMDFで組んでみるつもりです。

課題は、木材をきちんと裁断できるか、接合ははうまくできるかなど。


中の基板のパーツを並べた。

まずは基板をつくって、パネルにPOTを並べてダンボールのモックアップでどうなるか見てみます。

2017年6月14日水曜日

NucleoF303K8を買ってみた。


(左)Nucleo F401RE、(右上)Arduino Pro Mini、(右下)Nucleo F303K8

画像の通りかなりコンパクトで、USBシリアル変換基板も不要。基板は両面実装でメインMPUのSTM32F303のほかに裏面にSTM32F103が載っている。

STMF303はCorete-M4ベースでDACも2つ(3ch)搭載されている。

内蔵DAC


mbedでプログラムを書いてDACの出力を見てみた。

main.cpp

#include "mbed.h"

AnalogOut my_output1(PA_4);
//AnalogOut my_output2(PA_5);
//AnalogOut my_output3(PA_6);

#define PI        (3.141592653589793238462)
#define AMPLITUDE (1.0)    // x * 3.3V
#define PHASE     (PI * 1) // 2*pi is one period
#define RANGE     (0x7FFF)
#define OFFSET    (0x7FFF)

// Configuration for sinewave output
#define BUFFER_SIZE (360)
uint16_t buffer[BUFFER_SIZE];

void calculate_sinewave(void);

int main() {
    printf("Sinewave example\n");
    calculate_sinewave();
    while(1) {      
        // sinewave output
        for (int i = 0; i < BUFFER_SIZE; i++) {
            my_output1.write_u16(buffer[i]);
            //my_output2.write_u16(buffer[i]);
            //my_output3.write_u16(buffer[i]);
        }
    }
}

// Create the sinewave buffer
void calculate_sinewave(void){
  for (int i = 0; i < BUFFER_SIZE; i++) {
     double rads = (PI * i)/180.0; // Convert degree in radian
     buffer[i] = (uint16_t)(AMPLITUDE * (RANGE * (cos(rads + PHASE))) + OFFSET);
  }
}

mbed repository:
https://developer.mbed.org/users/ryood/code/Nucleo_sinewave_output/ revision:0

3chあるということで、3つAnalgOutを作ってみたがmbedでは同時に2つ以上使えないようだ。いろいろ組み合わせてみたがうまくいかなかった。それぞれ1chだけなら利用可能。

出力波形

PA_4

F:922.5Hz

PA_5

F:932.8Hz

PA_6

F:924.2Hz

各chで出力された周波数が若干異なる。

PA_4では922.5Hzのサイン波が出力された。以前Nucleo F446REでテストした時は、6.4kHzのサイン波が出力されたので、比較するとかなり遅い。

1周期のサンプル数(BUFF_SIZE)が360なので、サンプリング周波数は約332kHz(3u秒)となる。

F446REの時に見られた波形のつぶれはなく、フルレンジできれいなサイン波が出力されている。

単精度浮動小数点数点演算


駆動クロックははっきりしないが、回路図と基板を見比べてみるとF303用の外付けのクリスタル(X1)が実装されていない。内蔵RCで動作しているとすると、PLLで逓倍して最大64MHzとなっているので、64MHzとして比較してみた。

No Device No2 Op time(us) clock(MHz) period(us) clock:op
3 Nucleo F303K8 1 div 0.357 64 0.015625 22.848
3 Nucleo F303K8 2 sinf 2.011 64 0.015625 128.704
3 Nucleo F303K8 3 cosf 1.922 64 0.015625 123.008
3 Nucleo F303K8 4 expf 3.202 64 0.015625 204.928
3 Nucleo F303K8 5 logf 2.506 64 0.015625 160.384
3 Nucleo F303K8 6 sqrtf 0.739 64 0.015625 47.296

単精度浮動小数点数の割り算


1処理あたりの実行時間

1処理あたりのクロック数

単精度浮動小数点数のsinf()


1処理あたりの実行時間

1処理あたりのクロック数

FPUが載っているので単精度浮動小数点演算は十分速いと思う。

メモ:


NucleoF303K8の駆動クロックはわからないが、STM F4もSTM F3もFPUの割り算の性能が変わらないとすると64MHzなのかも?

2017年6月11日日曜日

SPI ADCのMCP3008をNucleo(mbed)で使ってみる。

MicroChipのADCの10bitバージョンのMCP3008をNucelo F401REで使ってみた。MCP3008はMCP3208より解像度は低いが、SPIの最大クロック数が3.6MHzまで対応している。

mbedのライブラリ


MCP3208用のライブラリをMCP3008用に書き換えてみた。

mbed repository:
Library:
https://developer.mbed.org/users/ryood/code/mcp3008/

Test Program:
https://developer.mbed.org/users/ryood/code/Nucleo_MCP3008_Test/

ライブラリのA/Dコンバーターの差動入力はテストしていないのでコメントアウトしている。

ブレッドボード配線図


MCP3008に送る電源は5Vでも3.3Vでもよい。

5V電源のほうがSPIのクロックを上げられるが、Nucleoに載っているMPUが3.3V駆動なので、Nucleo→MCP3008のSPI信号が3.3Vになり、一応はMCP3008の仕様外になる。Nucleoの方は3.3V駆動だが、5VトレラントなのでMCP3008→Nucleoの信号レベルが5Vでも問題はない。

3.3V電源だとSPIのクロックの最大値が低くなる(1.35MHz@2.7V)が、3.3V系同士なので信号レベル的には安心。

UART出力


ダンピング抵抗を入れてみる。


出力の近くにダンピング抵抗を入れるとオーバーシュートや振動が抑えられるので入れてみた。

mbed repository:
https://developer.mbed.org/users/ryood/code/Nucleo_MCP3008_Ticker_Test/

配線図


NucleoにArduino互換のシールドを載せている。(参考:「ベースマシン UI Controller ダンピング抵抗用シールドの製作」)シールド上でピンソケットを使ってダンピング抵抗を入れられるようにしている。SCK、MOSI、CSに33Ωの抵抗を挿入、MISOはジャンパでショート。

また、SPI通信用のケーブルは、30cm程度のものを2本コネクタでつないでわざと状態を悪くしている。


ダンピング抵抗なし

MOSI

ch1:MOSI ch2:SCK

MISO

ch1:MISO ch2:SCK

SCK、MOSIはNucleoが出力している信号で、オーバーシュートや振動がかなり出ている。MOSIはMCP3008が出力している信号で立ち上がり/立ち下がりが遅い。

33Ωダンピング抵抗あり


MOSI

ch1:MOSI ch2:SCK

MISO

ch1:MISO ch2:SCK

33Ωだと多少整形されている感じ。ようすを見ながら差し替えられるようにしておいた方が良さそう。