2018年8月30日木曜日

Nucleo DCO OLED表示(u8g2)と波形出力のテスト

u8g2-mbedを使ってSSD1306 OLED(I2C)に表示しつつ、内蔵DACから波形出力しました。Nucleoボードは、F446REだとサンプリング・レート100kHzではだめで50kHzぐらいまで下げないと追いつかなかったので、F767ZIを使用しました。


Nucleo_DCO_Test04 ピンアサイン


Arduino Nucleo Description
D15 PB_8 OLED/I2C/SCL
D14 PB_9 OLED/I2C/SDA
GND GND OLED/GND
D5 PE_11 CheckPin
D4 PF_14 CheckPin
- PA_4 WaveOut

テストプログラム(mbed-cli)
https://github.com/ryood/Nucleo_DCO/tree/master/mbed/Nucleo_DCO_Test04

u8g2-mbedを使ったプログラム作成の手順


プロジェクト作成

PS D:\Users\gizmo\Documents\mbed> mbed new Nucleo_DCO_Test04
[mbed] Creating new program "Nucleo_DCO_Test04" (git)
[mbed] Adding library "mbed-os" from "https://github.com/ARMmbed/mbed-os" at branch/tag "latest"
[mbed] Updating reference "mbed-os" -> "https://github.com/ARMmbed/mbed-os/#f8b140f8d7cb226e41486c5df66ac4f3ce699219"
The following paths are ignored by one of your .gitignore files:
mbed-os.lib
Use -f if you really want to add them.

u8g2-mbedから以下のファイルをプロジェクトディレクトリにコピー
u8g2.lib
.mbedignore
src/*
src/main.cppはu8g2-mbedを使ったプログラムの雛形として使えます。

.mbedignoreの中身は

PS D:\Users\gizmo\Documents\Develop\Nucleo_DCO\mbed\Nucleo_DCO_Test04> cat .mbedignore
u8g2/cppsrc/*
u8g2/doc/*
u8g2/sys/*
u8g2/tools/*

となっていて、mbedのBUILD対象外とするファイルを指定するようです。

参考「Ignoring files from mbed build

続いてプロジェクトディレクトリに移動して、デプロイ

> mbed deploy

コンパイルです。

> mbed compile -t GCC_ARM -m NUCLEO_F767ZI

Nucleo_DCO_Test04ではOLEDに
fps | 経過時間
表示更新回数
を表示しています。fpsはおおよそ10.9になりました。OLEDの表示はメイン・ループ内で行っていて1秒間に10.9回のループです。操作子からの入力もメイン・ループ内で行うと思うので、fpsはもっと下がると思います。

出力波形

ch1:PA_4

Ticker割り込みの処理時間

ch2:D4

Hになっている時間(PW)が波形出力の割り込み処理に要した時間で、1.2マイクロ秒です。

mbedのオンラインコンパイラ(mbed OS 2)でやったときは(参考「Nucleo DCOの構想 ~ いわゆるプロダクト・アウト」)720ナノ秒だったので、処理時間が増えました。

これはOLED表示のためというよりは、OS 2 → OS 5に移行したためなんじゃなかな~と思います。

F767でもいろいろやろうと思うと48kHzのサンプリング・レートがキープできるかどうかちょっと心配です。

ToDo:

・3オシレーターの波形合成(ミキシング)
・入力系の処理のテスト

2018年8月28日火曜日

NucleoF446RE(mbed-cli)でu8g2を使う。


Arduinoの汎用モノクロディスプレイ用ライブラリのu8g2をmbedにPortしたライブラリが公開されています。

u8g2-mbed https://github.com/domantascibas/u8g2-mbed

mbed-cliで使うようになっています。mbed-cliのインストール、使い方は前回の「NucleoF446REでmbed-cliを使う。(メモ)」にあります。

Github:u8g2-mbed」からZipファイルを入手して作業ディレクトリに展開します。

作業ディレクトリ
D:\Users\gizmo\Documents\mbed\u8g2-mbed-master
展開したディレクトリに移動してmbedプロジェクトを作成。

PS D:\Users\gizmo\Documents\mbed\u8g2-mbed-master> mbed new .
[mbed] WARNING: Directory "D:\Users\gizmo\Documents\mbed\u8g2-mbed-master" is not empty.
---
[mbed] Creating new program "u8g2-mbed-master" (git)
[mbed] Adding library "mbed-os" from "https://github.com/ARMmbed/mbed-os" at branch/tag "latest"
[mbed] Updating reference "mbed-os" -> "https://github.com/ARMmbed/mbed-os/#f8b140f8d7cb226e41486c5df66ac4f3ce699219"
The following paths are ignored by one of your .gitignore files:
mbed-os.lib
Use -f if you really want to add them..

続いてデプロイします。

PS D:\Users\gizmo\Documents\mbed\u8g2-mbed-master> mbed deploy
[mbed] Updating library "mbed-os" to rev #f8b140f8d7cb (tags: latest, mbed-os-5.9.5)
[mbed] Adding library "u8g2" from "https://github.com/olikraus/u8g2" at rev #eb1b12fde776

ディレクトリの確認

PS D:\Users\gizmo\Documents\mbed\u8g2-mbed-master> ls


    ディレクトリ: D:\Users\gizmo\Documents\mbed\u8g2-mbed-master


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----       2018/08/26     17:11                .vscode
d-----       2018/08/26     17:11                fonts
d-----       2018/08/26     17:21                mbed-os
d-----       2018/08/26     17:11                src
d-----       2018/08/26     17:23                u8g2
-a----       2017/11/27      5:42             71 .gitignore
-a----       2018/08/26     17:23              8 .mbed
-a----       2017/11/27      5:42             48 .mbedignore
-a----       2017/11/27      5:42           1067 LICENSE
-a----       2018/08/26     17:21             78 mbed-os.lib
-a----       2018/08/26     17:21           1469 mbed_settings.py
-a----       2017/11/27      5:42           1508 README.md
-a----       2017/11/27      5:42             75 u8g2.lib

手持ちのI2C接続のSSD1306 OLED 128x32でテストしました。

ブレッドボード配線図

src/main.cppを以下のように書き換えました。

#include "mbed.h"
#include "u8g2.h"

DigitalOut led(D13);

uint8_t u8x8_gpio_and_delay_mbed(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
u8g2_t myScreen;

extern const uint8_t XLargeFont[] U8G2_FONT_SECTION("XLargeFont");
extern const uint8_t LargeFont[] U8G2_FONT_SECTION("LargeFont");

void setup() {
  //u8g2_Setup_ssd1306_i2c_128x64_noname_f(&myScreen, U8G2_R0, u8x8_byte_sw_i2c, u8x8_gpio_and_delay_mbed);
  u8g2_Setup_ssd1306_i2c_128x32_univision_f(&myScreen, U8G2_R0, u8x8_byte_sw_i2c, u8x8_gpio_and_delay_mbed);
  u8g2_InitDisplay(&myScreen);
  u8g2_SetPowerSave(&myScreen, 0);
  u8g2_ClearBuffer(&myScreen);

  // u8g2_SetFont(&myScreen, XLargeFont);
  // u8g2_DrawUTF8(&myScreen, 0, 32, "53");
  // u8g2_SetFont(&myScreen, LargeFont);
  // u8g2_DrawUTF8(&myScreen, 0, 32, "Hello world");
  u8g2_SetFont(&myScreen, u8g2_font_f16_t_japanese1);
  u8g2_DrawUTF8(&myScreen, 0, 20, "こんにちは世界");
  // u8g2_SetFont(&myScreen, u8g2_font_unifont_t_chinese2);
  // u8g2_DrawUTF8(&myScreen, 0, 62, "你好世界");

  u8g2_SendBuffer(&myScreen);
}

int main() {
  led = 0;
  // printf("Hello world");
  setup();
  
  while(1) {
    led = !led;
    wait(1.0);
  }
  return 0;
}

mbed-cliにMakefileみたいなものがあるのかわかりませんが、mbed compileするとfonts/以下の*.cファイル(フォント・データ)はコンパイルされるようです。

PS D:\Users\gizmo\Documents\mbed\u8g2-mbed-master> ls .\BUILD\NUCLEO_F446RE\GCC_ARM\fonts


    ディレクトリ: D:\Users\gizmo\Documents\mbed\u8g2-mbed-master\BUILD\NUCLEO_F446RE\GCC_ARM\fonts


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       2018/08/28     12:29            150 LargeFont.d
-a----       2018/08/28     12:29           9880 LargeFont.o
-a----       2018/08/28     12:29            152 MediumFont.d
-a----       2018/08/28     12:29           8588 MediumFont.o
-a----       2018/08/28     12:29            150 SmallFont.d
-a----       2018/08/28     12:29           6084 SmallFont.o
-a----       2018/08/28     12:29            152 XLargeFont.d
-a----       2018/08/28     12:29           2464 XLargeFont.o

オブジェクトファイルは生成されますが、「XLargeFont」や「LargeFont」はmain.cppで宣言されていなくてコンパイル・エラーになるのでexternで宣言しました。

extern const uint8_t XLargeFont[] U8G2_FONT_SECTION("XLargeFont");
extern const uint8_t LargeFont[] U8G2_FONT_SECTION("LargeFont");

変数名のあとに付いている「U8G2_FONT_SECTION()」はメモリ空間を指定するマクロのようです。

I2C接続のSSD1306 128x64を使うようになっているのでI2C接続のSSD1306 128x32のものを使うように初期化関数を変更。

  //u8g2_Setup_ssd1306_i2c_128x64_noname_f(&myScreen, U8G2_R0, u8x8_byte_sw_i2c, u8x8_gpio_and_delay_mbed);
  u8g2_Setup_ssd1306_i2c_128x32_univision_f(&myScreen, U8G2_R0, u8x8_byte_sw_i2c, u8x8_gpio_and_delay_mbed);

「u8g2_font_f16_t_japanese1」というフォントはu8g2.hで宣言されています。一覧は「olikraus/u8g2」の「fntlistall」にあります。

コンパイル

PS D:\Users\gizmo\Documents\mbed\u8g2-mbed-master> mbed compile -t GCC_ARM -m NUCLEO_F446RE
Building project u8g2-mbed-master (NUCLEO_F446RE, GCC_ARM)
Scan: .
Scan: env
Scan: mbed
Compile [100.0%]: main.cpp
Link: u8g2-mbed-master
Elf2Bin: u8g2-mbed-master
+------------------+--------+-------+------+
| Module           |  .text | .data | .bss |
+------------------+--------+-------+------+
| [fill]           |    115 |     4 |   14 |
| [lib]\c.a        |  24641 |  2472 |   56 |
| [lib]\gcc.a      |   3168 |     0 |    0 |
| [lib]\misc       |    252 |    16 |   28 |
| mbed-os\drivers  |    192 |     4 |  100 |
| mbed-os\hal      |   1697 |     4 |   68 |
| mbed-os\platform |   2764 |   260 |  133 |
| mbed-os\rtos     |   8498 |   168 | 6073 |
| mbed-os\targets  |   8583 |     4 |  552 |
| src\delay.o      |      4 |     0 |    0 |
| src\main.o       |    194 |     4 |  156 |
| src\u8g2_mbed.o  |    204 |     4 |   56 |
| u8g2\csrc        |  50114 |     0 |  512 |
| Subtotals        | 100426 |  2940 | 7748 |
+------------------+--------+-------+------+
Total Static RAM memory (data + bss): 10688 bytes
Total Flash memory (text + data): 103366 bytes

Image: .\BUILD\NUCLEO_F446RE\GCC_ARM\u8g2-mbed-master.bin

ピンをアサイン


ピン名はPinNames.hで定義されています。Nucleo F446REの場合は

https://github.com/ARMmbed/mbed-os/blob/master/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F446xE/TARGET_NUCLEO_F446RE/PinNames.h

I2C_SCL     = PB_8,
I2C_SDA     = PB_9,

と定義されています。

u8g2のピンアサインはu8g2-mbed-master\u8g2\cppsrc\U8g2lib.hで定義されています。


class U8G2_SSD1306_128X32_UNIVISION_1_SW_I2C : public U8G2 {
  public: U8G2_SSD1306_128X32_UNIVISION_1_SW_I2C(const u8g2_cb_t *rotation, uint8_t clock, uint8_t data, uint8_t reset = U8X8_PIN_NONE) : U8G2() {
    u8g2_Setup_ssd1306_i2c_128x32_univision_1(&u8g2, rotation, u8x8_byte_sw_i2c, u8x8_gpio_and_delay_arduino);
    u8x8_SetPin_SW_I2C(getU8x8(), clock,  data,  reset);
  }
};

「u8g2-mbed-master\u8g2\cppsrc\」下はArduino用のラッパーで、そのままではmbedで使えません。

I2Cで信号線がSCL/SDAの2本だけのものならピン固定で使えそうですが、SPIだとRESETやDS線が必要なのでピンアサインできるようにしないとダメですがちょっとしんどそう(@@;;;

<追記:2018.09.01>

ピンアサインについてですが、u8g2-mbedのsrc/u8g2_mbed.cppを見てみると

DigitalInOut i2c_scl(PB_8);
DigitalInOut i2c_sda(PB_9);

とI2Cに使うピン名がハードコーディングされていました。(しかもSTM32のピン名)

u8g2-mbedは、u8g2の全体を移植したものではなく、STM32でI2CのSSD1306を使うためのものと考えたほうが良さそうです。

</追記>

2018年8月26日日曜日

NucleoF446REでmbed-cliを使う。(メモ)

だいぶ前になりますが、以下のサイトを参考にしてmbed-cliの環境を構築しました。(Windows10)

オフィシャルのドキュメント
「Github: Arm Mbed Command Line Interface https://github.com/ARMmbed/mbed-cli
「arm MBED https://os.mbed.com/docs/v5.9/tools/installation-and-setup.html

日本語の解説
「Toyomasa Watarai」さんの「mbed オフラインの開発環境
「Yoshihiro TSUBOI」さんの「[lang:ja] mbed CLIをWindowsで使ってみる(環境構築編)
@matsujirushiさんの「Arm Mbed CLIの環境構築 for Windows

WindowsまたはMac OS Xの場合は専用のインストーラーがあるようですが、もろもろのツールを手動インストールしていました。

以下、PowerShellで作業しました。

手動でインストールしたプログラムの確認


Python


PS D:\> python --version
Python 2.7.14

Git

PS D:\> git --version
git version 2.16.2.windows.1

Mercurial

PS D:\> hg --version
Mercurial - 分散構成管理ツール(バージョン 4.6.1)
(詳細は https://mercurial-scm.org を参照)

Copyright (C) 2005-2018 Matt Mackall and others
本製品はフリーソフトウェアです。
頒布条件に関しては同梱されるライセンス条項をお読みください。
市場適合性や特定用途への可否を含め、 本製品は無保証です。

GCC

PS D:\> arm-none-eabi-gcc --version
arm-none-eabi-gcc.exe (GNU Tools for Arm Embedded Processors 7-2018-q2-update) 7.3.1 20180622 (release) [ARM/embedded-7-branch revision 261907]
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

GCCはGCC 7をインストールしてPATHを通していますが、mbed-cliでcompileするとエラーが出たので、別にインストールしているGCC 6をmbed-cliの環境設定で指定して使用しました(後述)。

エラーメッセージ

PS D:\Users\gizmo\Documents\mbed\mbed-os-example-blinky>  mbed compile -t GCC_ARM -m NUCLEO_F446RE
[Error] @,: Compiler version mismatch: Have 7.3.1; expected version >= 6.0.0 and < 7.0.0

mbed-cliのアップデート

PS D:\Users\gizmo\Documents\mbed> pip install -U mbed-cli
Collecting mbed-cli
  Downloading https://files.pythonhosted.org/packages/dc/42/8c4d0ac81a063074a62143aeb136035c9d80517bdaf611603fefe2b67856/mbed_cli-1.7.5-py2-none-any.whl (47kB)
    100% |################################| 51kB 1.2MB/s
Installing collected packages: mbed-cli
  Found existing installation: mbed-cli 1.7.3
    Uninstalling mbed-cli-1.7.3:
      Successfully uninstalled mbed-cli-1.7.3
Successfully installed mbed-cli-1.7.5
You are using pip version 9.0.1, however version 18.0 is available.
You should consider upgrading via the 'python -m pip install --upgrade pip' command.

mbed-cliを新規インストールする場合は
pip install mbed-cli
とUpdateするオプションの「-U」を省いてやればだいじょうぶだと思います。

念の為ですが、パスの「gizmo」はWindowsのUser名で「D:\Users\gizmo\Documents\mbed\」をmbedの作業フォルダとしています。

mbed-cliはPythonスクリプトでPythonのインストール・フォルダ下にあります。
C:\Python27\Scripts

Exampleのインポート


まずはLチカです。mbed-os-example-blinkyをインポートしました。

インポートにまずまず時間はかかりますが、インポート完了時に反応がないので適当にEnterキーを押します。

PS D:\Users\gizmo\Documents\mbed> mbed import mbed-os-example-blinky
[mbed] Importing program "mbed-os-example-blinky" from "https://github.com/ARMmbed/mbed-os-example-blinky" at latest revision in the current branch
[mbed] Adding library "mbed-os" from "https://github.com/ARMmbed/mbed-os" at rev #f8b140f8d7cb

インポートしたフォルダのサイズ:695MB

環境変数の設定

前述の通り、mbed-cliの環境設定でGCC 6のパスを指定します。

PS D:\Users\gizmo\Documents\mbed\mbed-os-example-blinky> mbed config -G GCC_ARM_PATH "D:\GNU Tools ARM Embedded\6.2 2016q4\bin"
[mbed] D:\GNU Tools ARM Embedded\6.2 2016q4\bin now set as global GCC_ARM_PATH

mbed-cliの設定の確認

PS D:\Users\gizmo\Documents\mbed\mbed-os-example-blinky> mbed config --list
[mbed] Global config:
GCC_ARM_PATH=D:\GNU Tools ARM Embedded\6.2 2016q4\bin

[mbed] Local config (D:\Users\gizmo\Documents\mbed\mbed-os-example-blinky):
No local configuration is set

パソコンに繋がっているmbedボードの検出

mbedボード(今回はNucleo F446RE)をUSBでパソコンに繋ぎ、確認します。

PS D:\Users\gizmo\Documents\mbed\mbed-os-example-blinky> mbed detect

[mbed] Detected NUCLEO_F446RE, port COM4, mounted I:, interface version 0221:
[mbed] Supported toolchains for NUCLEO_F446RE
+---------------+-----------+-----------+-----------+-----------+-----------+
| Target        | mbed OS 2 | mbed OS 5 |    ARM    |  GCC_ARM  |    IAR    |
+---------------+-----------+-----------+-----------+-----------+-----------+
| NUCLEO_F446RE | Supported | Supported | Supported | Supported | Supported |
+---------------+-----------+-----------+-----------+-----------+-----------+
Supported targets: 1
Supported toolchains: 3

コンパイル


PS D:\Users\gizmo\Documents\mbed\mbed-os-example-blinky> mbed compile -t GCC_ARM -m NUCLEO_F446RE
Building project mbed-os-example-blinky (NUCLEO_F446RE, GCC_ARM)
Scan: .
Scan: mbed
Scan: env
Compile [  0.2%]: mbed_tz_context.c
<中略>
Compile [100.0%]: test_env.cpp
Link: mbed-os-example-blinky
Elf2Bin: mbed-os-example-blinky
+------------------+-------+-------+------+
| Module           | .text | .data | .bss |
+------------------+-------+-------+------+
| [fill]           |   119 |     4 |   14 |
| [lib]\c.a        | 24641 |  2472 |   56 |
| [lib]\gcc.a      |  3168 |     0 |    0 |
| [lib]\misc       |   252 |    16 |   28 |
| main.o           |    68 |     4 |   28 |
| mbed-os\drivers  |   192 |     4 |  100 |
| mbed-os\hal      |  1653 |     4 |   68 |
| mbed-os\platform |  2764 |   260 |  133 |
| mbed-os\rtos     |  8498 |   168 | 6073 |
| mbed-os\targets  |  8583 |     4 |  552 |
| Subtotals        | 49938 |  2936 | 7052 |
+------------------+-------+-------+------+
Total Static RAM memory (data + bss): 9988 bytes
Total Flash memory (text + data): 52874 bytes

Image: .\BUILD\NUCLEO_F446RE\GCC_ARM\mbed-os-example-blinky.bin

出来上がった「.\BUILD\NUCLEO_F446RE\GCC_ARM\mbed-os-example-blinky.bin」をオンラインコンパイラと同じようにNucleoF446REのフォルダにDrag&Dropすれば実行されます。

<追記:2018.09.20>

コマンドラインに「-f」オプションを付けると、compile後、自動的にパソコンにつないでいるTarget Boardにバイナリが書き込まれます。


> mbed compile -t GCC_ARM -m NUCLEO_F446RE -f

</追記>

プロジェクトの新規作成

Lチカ・プログラムを新規作成します。プログラム名はblink2としてExampleより素早くチカチカするようにしました。

空のプロジェクトを作成します。

PS D:\Users\gizmo\Documents\mbed> mbed new blink2
[mbed] Creating new program "blink2" (git)
[mbed] Adding library "mbed-os" from "https://github.com/ARMmbed/mbed-os" at branch/tag "latest"
[mbed] Updating reference "mbed-os" -> "https://github.com/ARMmbed/mbed-os/#f8b140f8d7cb226e41486c5df66ac4f3ce699219"
The following paths are ignored by one of your .gitignore files:
mbed-os.lib
Use -f if you really want to add them.

環境の確認

作成したプロジェクト・ディレクトリに移動して環境を確認。

PS D:\Users\gizmo\Documents\mbed> cd blink2

PS D:\Users\gizmo\Documents\mbed\blink2> mbed config --list
[mbed] Global config:
GCC_ARM_PATH=D:\GNU Tools ARM Embedded\6.2 2016q4\bin

[mbed] Local config (D:\Users\gizmo\Documents\mbed\blink2):
No local configuration is set

main.cppを作成

#include "mbed.h"

DigitalOut led1(LED1);

// main() runs in its own thread in the OS
int main() {
    while (true) {
        led1 = !led1;
        wait(0.1);
        led1 = !led1;
  wait(0.1);
    }
}

ファイルの確認

PS D:\Users\gizmo\Documents\mbed\blink2> ls


    ディレクトリ: D:\Users\gizmo\Documents\mbed\blink2


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----       2018/08/26     14:58                mbed-os
-a----       2018/08/26     14:59              8 .mbed
-a----       2018/08/26     15:00            215 main.cpp
-a----       2018/08/26     14:59             78 mbed-os.lib
-a----       2018/08/26     14:59           1469 mbed_settings.py

コンパイル

PS D:\Users\gizmo\Documents\mbed\blink2> mbed compile -t GCC_ARM -m NUCLEO_F446RE
Building project blink2 (NUCLEO_F446RE, GCC_ARM)
Scan: .
Scan: mbed
Scan: env
Compile [  0.2%]: mbed_tz_context.c
<中略>
Compile [100.0%]: test_env.cpp
Link: blink2
Elf2Bin: blink2
+------------------+-------+-------+------+
| Module           | .text | .data | .bss |
+------------------+-------+-------+------+
| [fill]           |    87 |     4 |   14 |
| [lib]\c.a        | 24641 |  2472 |   56 |
| [lib]\gcc.a      |  3168 |     0 |    0 |
| [lib]\misc       |   252 |    16 |   28 |
| main.o           |   100 |     4 |   28 |
| mbed-os\drivers  |   192 |     4 |  100 |
| mbed-os\hal      |  1653 |     4 |   68 |
| mbed-os\platform |  2764 |   260 |  133 |
| mbed-os\rtos     |  8498 |   168 | 6073 |
| mbed-os\targets  |  8583 |     4 |  552 |
| Subtotals        | 49938 |  2936 | 7052 |
+------------------+-------+-------+------+
Total Static RAM memory (data + bss): 9988 bytes
Total Flash memory (text + data): 52874 bytes

Image: .\BUILD\NUCLEO_F446RE\GCC_ARM\blink2.bin

出来上がった「.\BUILD\NUCLEO_F446RE\GCC_ARM\blink2.bin」をDrag&Dropです。

複数のプロジェクトを管理

下記のドキュメントを参考にすれば、mbed-osをダウンロードする時間とディスクスペースを節約できそうです。

Managing multiple Mbed projects

2018年8月23日木曜日

Nucleo DCO 表示器を考える(メモ)

中華製のOLEDのSSD1306はArduinoだとうまく表示できましたが、Nucleo(mbed)で簡単に試すと動作が怪しくなりました。

mbedで、ライブラリにAdafruit_GFXを移植したものを使ってSPI版のSSD1306 OLEDを動作テスト


Adafruit_GFXのライブラリの中をいじったり、まじめにやるのも辛いので表示器をどうするか考えます。

1)OLED SSD1306


視認性が良くてサイズがコンパクト。Arduinoではu8glib / u8g2で動作確認済みです。

SSD1306をArduinoで使用
HiLetogo 0.9" I2C OLED 128X32が届いたのでFast Mode(400kHz)で動作させてみた。
HiLetogo 0.9" I2C OLED 128X32をu8g2で使ってみる。
u8g2のFull BufferとPage Buffer
温度・湿度・気圧センサーのBME280をArduino Pro Miniで使う。
ESP WROOM 02(ESP8266)でBME280とSSD1308 OLED(I2C)を使う。

u8g2(https://github.com/domantascibas/u8g2-mbed

ローカルのmbed-cliでやらなければだめそう。フォント生成にLinux環境が必要とかなんとかで、ちょっとめんどい。

Adafruit_GFX(https://os.mbed.com/users/nkhorman/code/Adafruit_GFX/

Nucleo(mbed) + Adafruit_GFXでは動作不良。SPIだと表示が乱れるようです。I2Cならだいじょうぶか?フォントも用意する必要があります。

参考「Lifelog」さんの「128×64ピクセルのOLEDをmbed (Nucleo)から制御

2)SPI Graphic LCD


ST7565はベースマシンのBSM02のNucleo(mbed)で使っていて実績あり。

aitendoのFSTN液晶モジュール(SPI) [CH12864F-SPI]をNucleo F401RE(mbed)で動かす。
Nucleo F401REのMorpho HeaderでaitendoのSPI Graphic LCDのCH12864F-SPIを使ってみる。

一回り小さいUC1701のLCDも簡単にテストしたことがあります。
aitendoのSPI LCD(F12864G25412P1701)をArduinoのUC1701ライブラリで動作させてみる。


3)I2C Char LCD


aitendoのSPLC792-I2C、秋月のAQM1602、AQM0802はコマンドコンパチで使用経験あり。mbedでは使ったことはなかったと思いますが、コマンドを生書きしているので移植は可能だと思います。

SPLC792-I2C

4)HD44780互換のChar LCDとかLEDとかUARTとか


これは動くだろうと思います(^q^;

mbedはオンラインコンパイラが手軽すぎて今まで使っていなかったmbed-cliの環境を整えるあたりから手をつけようかなと思います。

2018年8月19日日曜日

Nucleo DCOの構想 ~ いわゆるプロダクト・アウト

需要ははあまりなさそうなテーマですが、Arduino LFOと同じような仕組みでハイスペックなNucleoF767でDCOを試作したいと思います。

OTAを使ったVCAのDual OTA VCA、トランジスターラダーLPFのTLF01とアナログ回路で組んできたので、VCOもアナログ回路で組みたいところですが、一度、音源として汎用的に使えそうなデジタル・オシレーターを作ってみようと思います。

Arduino + MCP4922ではいいとこLFO程度が上限でしたが、Nucleo F767なら12bit DACを内蔵、動作クロック216MHz、double型のFPU内蔵、メモリも潤沢(Flash 2MB/RAM 512kB)、mbedでプログラミング可ということでNucleo F767をコアとして試作することにしました。

仕様案


1) 内蔵12bit DAC 1ch出力

Nucleo F767は2ch分のDACが内蔵されていますが、1つはオンボードのLEDと接続されていて出力波形が汚いので1chのみとします。

参考「Nucleo F446RE 内蔵DACのテスト

2) サンプリング・レート 48kHz以上

最低でも48kHzとします。12bit/48kHzなので20年ぐらい前のサンプラー相当です。

I2Sならオーディオ品質のDACを使えますが、とりあえず楽をする方向で考えます。I2SはPSoC 5LPで使ったことがありますが、NucleoやESP32で使ったことがないので後々。

参考「オーディオ用DACを使ったファンクションジェネレータ まとめ

3) 出力波形

SQR、SAWUP、SAWDOWN、TRI、SIN、NOISE。Arduino LFOでは計算時間が足りなくてNoiseは出力できませんでしたがNucleoならできそうです。

4) 3オシレーター

1オシレーターだと音が薄いので、3オシレーターをプログラム上でMIXして出力します。サンプリングレートを下げていけばできそうな気がしますが、問題は操作子が増えることです。1オシレーターで妥協するかもしれません。1~2オクターブ下の周波数を出力するサブオシレーターにするかも?出音を比較しつつ。

5) 出力周波数

ピアノの音階の27.5Hz~4,186Hzより広くするつもりです。POTの解像度が10bit(1024)程度しかないので、レンジ切り替えで対応すると思います。

6) 出力電圧

最低、-∞ ~ ±2.5V程度で考えています。DC成分のない両電源波形です。

1オシレーターの場合のブロック図

ほとんどArduino LFOと同じ構成ですが、両電源波形にするためDAC出力をACカップリングしています。プッシュスイッチを使ってレンジ、波形を切り替えると、フィードバックが必要になるので表示器としてLCDかOLEDを使うつもりです。

ロータリースイッチを使えば表示器は不要ですが、線数が増えまくります。

Phase POTは位相を可変するもので、1オシレーターだとあまり意味はがないんですが、複数あればオシレーターごとに位相をずらしてうねりをつくれます。

外観案


1オシレーターならこれぐらいのサイズで収まりそうです。3オシレーターにしようと思うとPOTx16 PizzaBoxぐらいの規模になりそうです。

内蔵DACからの出力波形


1kHzのサイン波を出力するプログラムを書いて出力波形を見てみました。サンプリングレートはとりあえず100kHzにしました。

DDSにつかうWaveテーブルは32,768要素にしました。簡単に出力テストしてみると、これ以上要素数を増やしてもあんまり効果はなさそうでしたが、メモリーが潤沢なので要素数は増やせます。

mbed Repository
https://os.mbed.com/users/ryood/code/Nucleo-F767_DCO_Test01/

処理時間の計測

ch1:D4 ch2:D5

ch1:D4はメインループ内で1マイクロ秒のWaitをかけてH/Lしていて、ch2:D5はサンプリング周期毎の割り込み処理の最初と最後でH/Lしています。

サンプリングレートが100kHzなのでch2の周波数は100kHzになっています。Hになっている時間(PW)は720.0nsでまずまず計算する時間の余裕はありそうです。

オシロで見ると、ch2の波形が多少ブルブル震えています。←ジッターあり。

ch1は、ch2の割り込みのタイミングで1マイクロ秒より引き伸ばされる場合があります。

以下、電源ノイズを避けるために、NucleoのUSB電源を電池使用の安定化電源にして測定しました。


出力波形

普通に内蔵DACで出力すると波形の上下でクリップするので、ファームウェアで小細工して3Vp-p弱の振幅にしました。ファームウェアの以下の部分です。

    //uint16_t v = val << 4;
    // avoid distortion of the built-in DAC
    uint16_t v = (val + 256) * 14;

出力波形(拡大)

ガタガタの幅は10usで、逆数は100kHzなのでサンプリングレートと合致します。

FFT

横軸は25kHz/DIVで100kHzと200kHz付近にエイリアスが現れています。

WaveSpectra

Audio Interface: TASCAM US-144II、MIC/LINE入力、24bit/96kHz
窓関数: Flat Top

THD: 0.03635%
THD+N: 0.19748%

出力にLPFをかけるにしても可聴帯域の20kHzあたり以下の帯域は通過域です。

メモ:


Nucleo F767のZIOヘッダは、Arduinoのシールドを使うと内側の穴が隠れてしまって使いづらい。

サンプリングレートを決めてからLPFを設計する。

MIDI対応できるように考えておく。

SyncIn必要?