2017年振り返り
今年も残り僅かになりましたので、例年通り今年の振り返りをやってみたいと思います。さて振り返りることなんてあるのかな?・・・(汗)
無線運用の停滞
condx低下と去年に10万QSO突破してしまったことも相まって、無線を運用すること自体がだいぶ減ってしまいました。モチベーションが低下してしまったということです。家からではDXを手軽に楽しむことができなくなってしまったし、国内の移動おっかけは飽きてしまったし、これまでマメに参加していたローカルコンテストもパスすることが多くなってしまいました。正しくカウントしていませんが、個人コールで運用したのは、2,000〜3,000QSOくらいだと思います。以前は10〜15kだったのに。
去年は海外運用をたっぷり楽しんだのですが、今年は結局いけず(全く運用せずにパラオの免許の期限(1年)を切らしてしましました)。まぁ、condxとともにモチベーションが上昇すると思います。
仕事が忙しくなってきた
今年度に上級の経営基幹職になってしまったせいで、仕事の密度が上がってしまい、休暇を自由に取れないなど、趣味に少し影響を受けたと思います。仕事の方は割りと充実しているので、このことがストレスになっているわけではないので、さほどマイナスではないのですが、昔のように勝手なことができなくなってしまったのは確かですね・・・
地元の無線クラブの運営
JQ1ZQQという地元の無線クラブの役員をやっています。このクラブの運営に従事することが今年は多かったと思います。おかげさまで、構成員も順調に増えて、これからやらなければならないことが山積みですが、以前よりは活発なクラブになってきたと思います。
体調すぐれず
気管支の炎症と一年中、咳が止まらない症状に悩みました。いろいろ調べてみると重度のアレルギーとのこと。特にスギ花粉、ハウスダスト、イヌ?ダストに過剰に反応する体質になっているとのこと。原因が分かりホッとしているのですが、アレルギーの薬が手放せなくなりました。また、アレルギーが原因か分かりませんが、免疫力が低下し、ちょっとダイエットするとすぐに風邪を引いてしまうことが多くなりました。体調悪くてコンテストの参加を辞退、というのも多かったです。
自作派復活
無線運用の方が不活発になってきた反面、自作・電子工作のほうが活発になった年だと思います。JL1VNQさん設計のVN-4002に出会ったせいで自作熱が復活。ついでにARM系マイコンいじりも復活。秋葉原では無線屋よりもパーツ屋に行く機会が増えました。まだ作ってないVNシリーズがあるのでこの冬休みで作ってみたと思います(汗)。
記念局8J1C70Yの開設・運営
今年は何と言っても記念局の開設・運営をやったことでしょうか。実質的にほぼ私一人が開設から運営管理までやったのですが、やはり一人ではどうしてもできないことがあり、各方面にはご面倒をおかけしたと思います。また地元茅ヶ崎市やJARLにもいろいろお世話になりました。記念局の開設や運営については改めて別の記事で語りたいと思います。
というわけで、今年はいろいろお世話になりました。来年も引き続きよろしくお願いします。
NucleoにMicroPython入れてみた
以前、Pyboradという最初からMicroPythonが実装されているボードを使ってみました。MicroPythonはSTM32系を中心にどんどんポートされているようです(PyboardのマイクロコントローラもSTM32F405RGです)、安くて入手しやすいNucleoでも動かせるようなので、早速やってみました。実装の仕方はいろいろありますが、Windows上で一番簡単と思われる方法をご紹介します。
まずチップに適合したMicroPythonのバイナリをダウンロード
ソースから自分でビルドしてみるのもよいのですが、バイナリをダウンロードしてくるのが一番早いです。ダウンロードページはココです。すべてのNucleoボードのバイナリが用意されているわけではありません。運良く手持ちのNucleo F411REのバイナリがあったのでそれをダウンロードしました。ここではDFU形式のファイルとなっています。
DfuSeDemoをインストール、DFUからhexファイルへ変換
次に、STmicroが用意しているツール、DfuSeDemoをダウンロードしインストールします。このツールを使って、NucleoをDFUモードで起動して書き込むことができるのですが、ジャンパーを用意したり、うまくいかないことがあったので、本体のDfuSeDemoではなく、DfuSeDemoと同じディレクトリにあるDFU File Managerを使いました。このツールでダウンロードしてきたDFUファイルをhexファイルへ変換しておきます。
hexファイルをST LinkでNucleoへ書き込む
PCとNucleoをUSB接続すると、PCのストレージ扱いになりかつSTLinkでつながっているで(デバイスマネージャで確認できます)ST-Link Utilityを使って書き込むことができます。Nucleoと接続した状態でST-Link Utilityを立ち上げます。Target→Connectで認識させ、File→File Openで上で変換したhexファイルを開き、Target→Programでhexファイルを書き込みます。
TeratermでMicroPythonを起動
ST-Linkと同時にシリアル接続にもなっているので、Teratermなどのターミナルソフトで接続し(ボーレートを115200に設定)、NucleoのRESETボタンを押すと、MicroPythonが起動します。これで完了です。また、uPyCraftというツールを使っても動かすことができます。
例によってLチカプログラムを打ち込むとすぐさま動作しました。
自分でビルド
チップに適合したバイナリがない場合は、自力でビルドするしかありません(すべてのチップ対応しているわけではありません)。ソースはGitHubやココにあります。tarを展開したディレクトリを~/micropython/とすると、~/micropython/stmhal/boardsに対応しているチップ(ボード)のディレクトリがあるので、そのボード名をmake時のBOARDに指定して(例えばNUCLEO_F767ZIならば)、
$ cd ~/micropython/stmhal $ make BOARD=NUCLEO_F767ZI
とし、成功するとbin, hex, dfuファイルが生成されます。hexファイルを上の方法でST Linkで書き込めばOKです。なおビルドにはARM GCCツールチェーンが必要なので最新のものをインストールして下さい。その方法はmbed CLIを紹介したページをご覧下さい。
Mbed OS 2をMbed OS 5 CLIで動かす
前回の記事で、Mbed OS 5のCLIをインストールし実際にARMを動かすのをお見せしました。Mbed OS 5に対応していないボードをtargetにすると、そのままではコンパイルできないのでイマイチ使い物にならないと思い込んでましたが、実は(まぁ当たり前ですが)そんなことはありませんでした。GitHubのMbed CLIのページを見るとMbed OS 2を動かせるとあります。引用すると、
$ mbed new mbed-classic-program --mbedlib [mbed] Creating new program "mbed-classic-program" (git) [mbed] Adding library "mbed" from "https://mbed.org/users/mbed_official/code/mbed/builds" at latest revision in the current branch [mbed] Downloading mbed library build "f9eeca106725" (might take a minute) [mbed] Unpacking mbed library build "f9eeca106725" in "D:\Work\examples\mbed-classic-program\mbed" [mbed] Updating reference "mbed" -> "https://mbed.org/users/mbed_official/code/mbed/builds/f9eeca106725" [mbed] Couldn't find build tools in your program. Downloading the mbed 2.0 SDK tools...
とこれはWidowsでの動作例ですが、--mbedlibオプションで昔のmbedライブラリまるごとごっそりとgitで引っ張ってくることができるようです。しかし、実際にやってみると、
$ mbed new mbed-classic-program --mbedlib [mbed] Creating new program "classic-test" (git) [mbed] Adding library "mbed" from "https://mbed.org/users/mbed_official/code/mbed/builds" at latest revision in the current branch [mbed] Updating reference "mbed" -> "https://mbed.org/users/mbed_official/code/mbed/builds/tip" [mbed] Couldn't find build tools in your program. Downloading the mbed 2.0 SDK tools...
となり、mbedライブラリをダウンロードしません。mbed-classic-program/mbedのディレクトリが空っぽです。
ならばマニュアルで強引にライブラリをダウンロードしようと、ブラウザでhttps://os.mbed.com/users/mbed_official/code/mbed/にアクセスし、ダウンロードレポジトリのzipファイルをクリックしてダウンロードしてきました。unzipしてできたファイルを丸ごと、先のmbed-classic-program/mbedにコピーしてしまうと、一応、プロジェクト内のファイル構成がおなじになるはずです。
ターゲットをLPC11U35のQuickStart Board互換(秋月で売ってる互換ボード)として、Lチカのmain.cppを適当にこしらえ、コンパイルしてみます。
$ cat main.cpp #include "mbed.h" DigitalOut led(P0_8); int main() { led = 0; while(1) { led = !led; wait(0.5); } } $ mbed compile -m lpc11u35_401 Building project mbed-classic-program (LPC11U35_401, GCC_ARM) Scan: . Scan: env Scan: mbed Compile [100.0%]: main.cpp Link: mbed-classic-program Elf2Bin: mbed-classic-program +--------------------------+-------+-------+------+ | Module | .text | .data | .bss | +--------------------------+-------+-------+------+ | BUILD/lpc11u35_401 | 228 | 4 | 24 | | [fill] | 281 | 0 | 6 | | [lib]/c_nano.a | 2391 | 100 | 12 | | [lib]/gcc.a | 1044 | 0 | 0 | | [lib]/mbed.a | 1368 | 0 | 30 | | [lib]/misc | 244 | 8 | 28 | | mbed/TARGET_LPC11U35_401 | 2928 | 8 | 24 | | Subtotals | 8484 | 120 | 124 | +--------------------------+-------+-------+------+ Total Static RAM memory (data + bss): 244 bytes Total Flash memory (text + data): 8604 bytes Image: ./BUILD/lpc11u35_401/GCC_ARM/mbed-classic-program.bin
はい。これでMbed OS 2のボードでも無事にMbed CLIでビルドすることができました。やれやれ。
爆安Black Pillをmbedで動かしてみた
またまたマイコンネタですが・・・・世の中にARMの石であるSTM32F103C8T6のボードがありまして、これをArduinoにするという「STM32duino」プロジェクトがあるそうです。ここを見るとこの石の評価ボードにはいろいろ亜流があるらしく、Blue PillやらBlack Pillといわれる中華コピー版が100円台と超格安で売られているとのことで、Aliexpressで10枚くらい購入しましまた。で、忘れた頃に届きました。Arduinoではなくもちろんmbedで動かしてみたのですが、実に簡単です。これがおそらく最安値のmbedハードでしょう。Cortex-M3がこんな安く手に入り手軽に使えるなんてさすがARMでありSTであります。
ピンのはんだ付け
ピンとジャンパスイッチが付いていないので自分ではんだ付けします。変な油が基板にべっとり付いていたので、アセトンを浸した綿棒でよく拭ってからはんだ付けしましょう。ピン名のシルク印刷が非常に不鮮明、基板の切断位置がズレたりして、さすがは中華クオリティです。
基板上のジャンパスイッチは、ISPモードにするか動作モードにするかのスイッチらしく、ISPモード起動はB0+/B1-のようです。
mbedでコンパイル
STM32F103C8T6はmbedに非対応ですが、これに似ているNUCLEO F103RBをmbedのプラットフォームにしてしまえば、出来上がったプログラムはバイナリ互換です。しかもmbed OS 5対応。オンラインコンパイラもしくはmbed CLIでLチカプログラムをコンパイルします。
#include "mbed.h" DigitalOut myled(PB_12); int main() { while(1) { myled = 1; wait(0.1); myled = 0; wait(0.1); } }
UARTでプログラムを転送
USB-シリアル変換のTXをボードのRX(A10)、RXをボードのTX(A9)に接続し(なおピン配置はBlue Pillの基板であるがココを参考にしました)、stm32flashというツールをダウンロードして入手します。なおLinux版のファイルは"stm32flash-0.5.tar.gz"です。以下Linuxでの操作を示します。
$tar xvfz stm32flash-0.5.tar.gz $cd stm32flash $sudo make install
USB-シリアル変換のUSBをPCに挿して、dmsegコマンドで、シリアルポートを確認。
$dmseg | grep 'USB Serial' [850126.770536] usb 2-1.7: FTDI USB Serial Device converter now attached to ttyUSB0
ここでは/dev/ttyUSB0がシリアルポートでした。Fチカのプログラムをそのポートへ転送します。
$sudo stm32flash -w F103test.bin -v -g 0x0 /dev/ttyUSB0 stm32flash 0.5 http://stm32flash.sourceforge.net/ Using Parser : Raw BINARY Interface serial_posix: 57600 8E1 Version : 0x22 Option 1 : 0x00 Option 2 : 0x00 Device ID : 0x0410 (STM32F10xxx Medium-density) - RAM : 20KiB (512b reserved by bootloader) - Flash : 128KiB (size first sector: 4x1024) - Option RAM : 16b - System RAM : 2KiB Write to memory Erasing memory Wrote and verified address 0x08004d84 (100.00%) Done. Starting execution at address 0x08000000... done.
これで書き込みできました。プログラム起動するには、ジャンパをB0-/B1-にして電源を入れます。
秋月のLPC11U35 QuickStart互換ボードも安いですが、Black Pillはmbed OS 5に対応しているSTM32F103なのでmbed CLIで開発するにはとてもFBで使いやすそうです。
【追記】Windows上でbinファイルの転送
リクエストがありましたので、Windows上での方法を記してみます。ここにstm32flashのWindows版があるので、これをダウンロードして適当なフォルダに展開します。実行ファイルの"stm32flash.exe"はCLIプログラムなので、このフォルダにパスを通すか、Windows PowerShellもしくはDOSプロンプトを実行しこのフォルダに移動します。さらにmbedコンパイラでビルドしたBinファイルをこのフォルダへ移動しておきます。
次にデバイスマネージャーを開いて、「ポート(COMとLPT)」を開いてUSB Serial Portのポート番号を確認してます。例えば、COM9だとします。Black PillをISP起動モードにしてUSBをつなぎ直して、プロンプトから、
> .\stm32flash.exe -w '.\F103test.bin' -v -g 0x0 COM9
とすると、Black Pillへ書き込まれます。エラーが出る場合は、ISP起動モードになっているか、COMポートが正しく指定されているか、Black Pillへの配線が正しいか、USBバスパワーが足りているか確認して下さい。
mbed cliをlinuxで構築してみた
これまで書いてきたマイコン記事の通り、ふだんの工作に使っているマイコンはARM mbedです。世の中で最も出回っているマイコンであり、安価で手に入りやすく、それでいてクラウドmbed環境はとても使いやすいからです。しかし日本ではPICやAVR(Arduino)に負けるらしく、日本語で情報を入手できにくい感があります。
今回オフラインコンパイラであるmbed OS 5のmbed CLI(コマンドラインインターフェイス)をLinux上に環境構築してみたので、備忘録代わりにブログに記してみます。STの安価なmbedボードであるNUCLEOシリーズをCLIでビルドする際、ハマってしまった点がいくつかあったのでその解決法も記してみます。
まずは、こちらのシステム環境です。
Ubuntu 16.04.3 LTS
Linux kernel 4.4.0-92-generic 64bit
GCC 5.4.0 20160609
Python 2.7.12
usbmountのインストール
USBをマウントして実行権付きで読み書きするパッケージをインストールします。
$sudo apt-get install usbmount
mbedボードをUSBポートに差し込んでUSBストレージとして認識させ、dfコマンドで見ると、/media/usb0などが見えるはずです。しかしこのままではファイルのユーザーがrootなので多少使いにくいです。そこで/etc/usbmount/usbmount.confを編集してみます。
MOUNTOPTIONS="sync,nodev,noatime,nodiratime" FS_MOUNTOPTIONS="-fstype=vfat,uid=yuji,gid=yuji"
この2箇所を書き換えると実行権が自分のものになるので使いやすくなります(あくまで個人環境で使う場合の設定です)。
Python 2.7を入れる
mbedはpythonのスクリプトを多用するので入ってなければPythonを入れておきます。デフォルトでpython3が動く環境だとエラーになるので注意して下さい。Pythonのモジュールインストーラーであるpipも使うので、
$sudo apt-get install python2.7 python-pip
としておきます。続いてmbed cliをpipでインストール。
$sudo pip install mbed-cli
ARM GCC, mercurial, gitをインストール
ツールチェーンであるARM GCC、レポジトリ管理のMercuialと必要ならばGitも入れておきます。
$sudo apt-get install gcc-arm-none-eabi mercurial git
Lチカのプロジェクトを作ってコンパイル
定番テストプログラムである「Lチカ」を動かしてみましょう。オンラインのmbed IDEと同様プロジェクトとしてディレクトリを用意しておきます。
$mkdir mbed-test $cd mbed-test $mbed new .
ここでmbed-osのすべてのライブラリをgithubからダウンロードしてくるので結構時間がかかります。
次に、ここのフォルダでUSBにマウントされているmbedボードを認識させます。ここではSTのNucleo F411REをつなげてみた例です。
$mbed detect [mbed] Detected NUCLEO_F411RE, port /dev/ttyACM0, mounted /media/usb0 [mbed] Supported toolchains for NUCLEO_F411RE +---------------+-----------+-----------+-----------+-----------+-----------+-----------+ | Target | mbed OS 2 | mbed OS 5 | ARM | GCC_ARM | IAR | ARMC6 | +---------------+-----------+-----------+-----------+-----------+-----------+-----------+ | NUCLEO_F411RE | Supported | Supported | Supported | Supported | Supported | Supported | +---------------+-----------+-----------+-----------+-----------+-----------+-----------+ Supported targets: 1 Supported toolchains: 4
もしNucleo 4xxを使っていて正しく認識されないようならば、ST-LINKをファームアップしてみて下さい。mbedのページあります。Windows機でST-LINKで接続し(場合によって最新のデバイスドライバが必要かも。場所は先のリンクにあります)、Windows上のファームアップソフトを立ち上げてファームアップできます。
また、この時点で、
[mbed] Auto-installing missing Python modules...
と表示されたら、足りないPythonモジュールがあるようなので、追加で入れておきます。
$sudo pip install -r mbed-os/requirements.txt
まだプロジェクトにプログラムの中身が無いので、Lチカのmain.cppを作っておきます。
#include <mbed.h> DigitalOut led1(D13); int main() { led1 = 1; while(1) { led1 = !led1; wait(0.1); } }
D13ピンにLEDのアノードを接続、GNDにカソードを接続しておきます。モジュールとツールチェインの設定を済ませて、ようやくビルドへ。
$mbed target NUCLEO_F411RE $mbed toochain -G GCC_ARM $mbed compile
設定とソースに誤りがなければ、
Building project mbed-test (NUCLEO_F411RE, GCC_ARM) Scan: . Scan: mbed Scan: env Compile [ 5.8%]: TimerEvent.cpp Compile [ 6.1%]: Timeout.cpp Compile [ 6.4%]: Timer.cpp ・ ・ ・ Compile [ 99.7%]: stm_spi_api.c Compile [100.0%]: test_env.cpp Link: mbed-test Elf2Bin: mbed-test +------------------+-------+-------+------+ | Module | .text | .data | .bss | +------------------+-------+-------+------+ | [fill] | 115 | 4 | 11 | | [lib]/c.a | 17219 | 2472 | 89 | | [lib]/gcc.a | 3120 | 0 | 0 | | [lib]/misc | 252 | 16 | 28 | | main.o | 80 | 4 | 28 | | mbed-os/drivers | 136 | 4 | 100 | | mbed-os/hal | 863 | 0 | 26 | | mbed-os/platform | 1246 | 4 | 270 | | mbed-os/rtos | 8539 | 180 | 5988 | | mbed-os/targets | 6102 | 4 | 820 | | Subtotals | 37672 | 2688 | 7360 | +------------------+-------+-------+------+ Total Static RAM memory (data + bss): 10048 bytes Total Flash memory (text + data): 40360 bytes Image: ./BUILD/NUCLEO_F411RE/GCC_ARM/mbed-test.bin
と表示されbinファイルが生成されます。このファイルをmbedにコピーすれば完了。
$cp ./BUILD/NUCLEO_F411RE/GCC_ARM/mbed-test.bin /media/usb0
無事にLチカが動くはずです。
NUCLEO F746ZGでは最新のtoolchainが必要!
別のmbedボードにつなぎ直して動作するか確かめていたところ、mbed OS 5に対応のSTMのNucleo F746ZGでは、うまくコンパイルできませんでした。
$mbed target NUCLEO_F746ZG $mbed compile ・ ・ ・ /usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/bin/ld: error: /usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a(lib_a-setjmp.o): Conflicting CPU architectures 13/1 /usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/bin/ld: failed to merge target specific data of file /usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a(lib_a-setjmp.o) collect2: error: ld returned 1 exit status [ERROR] /usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/bin/ld: error: /usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a(lib_a-setjmp.o): Conflicting CPU architectures 13/1 /usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/bin/ld: failed to merge target specific data of file /usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a(lib_a-setjmp.o) collect2: error: ld returned 1 exit status
リンカの設定がおかしいの?pythonもモジュールがおかしいのか?いろいろ悩んだり調べてみた挙句、最新のGCC Toolchainを使えば治るっぽいことがわかりました。早速、GNU ARM Embedded Toolchainのページへ行ってLinux版のライブラリをダウンロードしてきました。
これをbunzip2+tarで展開し、展開場所が/usr/localだとすると、そこにパスを通しておくのを忘れずに。
$mbed config -G GCC_ARM_PATH="/usr/local/gcc-arm-none-eabi-6-2017-q2-update/bin"
とし、compileをかけると、
$mbed compile ・ ・ ・ Compile [100.0%]: test_env.cpp Link: mbed-test Elf2Bin: mbed-test +------------------+-------+-------+-------+ | Module | .text | .data | .bss | +------------------+-------+-------+-------+ | [fill] | 104 | 4 | 19 | | [lib]/c.a | 17219 | 2472 | 89 | | [lib]/gcc.a | 3120 | 0 | 0 | | [lib]/misc | 252 | 16 | 28 | | main.o | 80 | 4 | 28 | | mbed-os/drivers | 136 | 4 | 100 | | mbed-os/features | 44 | 0 | 12556 | | mbed-os/hal | 863 | 0 | 26 | | mbed-os/platform | 1246 | 4 | 270 | | mbed-os/rtos | 8809 | 180 | 5988 | | mbed-os/targets | 9727 | 4 | 1084 | | Subtotals | 41600 | 2688 | 20188 | +------------------+-------+-------+-------+ Total Static RAM memory (data + bss): 22876 bytes Total Flash memory (text + data): 44288 bytes Image: ./BUILD/NUCLEO_F746ZG/GCC_ARM/mbed-test.bin
mbed CLIを使ってみて
mbed OS 5に対応していないとダメなのが残念ですが、使い慣れたLinux上のCエディタ(Emacs)でサクサクとコードが書けるのが快適です。mbed OS 5に対応しているNucleoのようなボードでソースのトライアンドエラーを済ませて、またオンラインコンパイラに戻って古いmbedボードを動かす、というのも悪くないと思っています。しかし、mbed-osを一々ダウンロードしてくるのには閉口しました・・・^^;まだまだ洗練度が足りない感じですね。
Windowsにもオフラインコンパイラがほしいですが、CLIではなくWindowsらしくEclipseで動かしてみたいと思います。
ドットマトリックスLED LTP-305を動かしてみた
部品箱を整理していると買い込んでみたものの買ったことすら忘れられている部品ってありますよね。この連休に整理していたら、ドットマトリックスタイプのLEDディスプレイ LTP-305HRが大量に出てきました(汗)。ちょうどmbedをいじっていたところなので光らせてみました。
LEDエレメントは5列7行のマトリクスでピン配置はこのとおり。
列のアノードと行のカソードがつながるとその交点のLEDが光るという仕組みで、デコーダーのようなものは内蔵されていません。文字を表示させるには各列(または各行)をダイナミック点灯していく必要があります。多桁表示し接続ピン数を節約するためには、行を並列接続し、列をスキャンさせていくのが良さそうです。
どこか探せばライブラリが見つかりそうですが、とりあえず数字「0」〜「9」を光らせることくらいなら自力で作ってみました。各文字のドットパターンを決めて、各列のパターン(一次元)をビットデータに置き換えて(行は7つなので先頭ビットを0に固定)1バイト表現してみました。つまり、各文字を5バイトを割り当てました。例えば、「0」は、{0x3e, 0x45, 0x49, 0x51, 0x3e}となります。各列ごと各行ごとに、ビットシフトして光らせるデータを取り出し、高速に列をスキャンしていき、チラ付かない程度のウェイトでループさせてみました。
マイコンはLPC11U35の互換ボードを使ってみました。GPIOがたくさんあるので、3桁くらい光らせることができそうです。実際に動かしてみた動画がこちらです。
少し明るいところでは視認性が悪く、各点の明るさにバラツキがあるのが気になりますね。ディスプレイの上に曇りガラスやスモークを乗せると少し見やすくなりますが・・・。
デモのプログラムはこちらです。後日、mbedのレポジトリに登録したいと思います。
// Dot matrix led display LTP-305 demo using mbed LPC11U35 // copyright 2017 Oct, JF1DIR // LTP-305 http://akizukidenshi.com/catalog/g/gI-07440/ // #include "mbed.h" Ticker sec_timer; DigitalOut col[5]={P0_7, P0_8, P0_9, P0_10, P0_22}; // connected anodes DigitalOut row[7]={P0_6, P0_21, P0_5, P0_4, P0_3, P0_2, P0_20}; // connected cathodes unsigned char numdata[10][5] = { {0x3e, 0x45, 0x49, 0x51, 0x3e}, // "0" {0x00, 0x21, 0x7f, 0x01, 0x00}, // "1" {0x21, 0x43, 0x45, 0x49, 0x31}, // "2" {0x42, 0x41, 0x51, 0x69, 0x46}, // "3" {0x0c, 0x14, 0x24, 0x7f, 0x04}, // "4" {0x72, 0x51, 0x51, 0x51, 0x4e}, // "5" {0x1e, 0x29, 0x49, 0x49, 0x06}, // "6" {0x40, 0x47, 0x48, 0x50, 0x60}, // "7" {0x36, 0x49, 0x49, 0x49, 0x36}, // "8" {0x30, 0x49, 0x49, 0x4a, 0x3c} // "9" }; int sec = 0; void countup() { sec++; if (sec > 9) sec = 0; } int main() { unsigned char x; int k = 0; // number of col sec_timer.attach(&countup, 0.3); while(1) { for(int i = 0; i < 5; i++) col[i] = 0; // all segments turn off for(int i = 0; i < 7; i++) row[i] = 1; // all segments turn off x = numdata[sec][k]; col[k] = 1; for(int i = 0; i < 7; i++) { if ((x & 0x40) == 0x40) row[i] = 0; x <<= 1; } k++; if (k > 5) k = 0; wait(0.002); } }
※2017/10/10 追記
3桁バージョンも作ってみました。並列化の配線が大変だったのと、GPIOを22本も使ってしまったので利用価値が微妙です(苦笑)。waitを1ms以下にしないとちらつきが目立ちます。消費電流が大きいのでドライバを使うべきです。
mbedによるGPS同期時計の製作
久々のブログ更新・・・しかも、電子工作の記事が少ないぞ、と言われ続けようやくの工作ネタで更新になりました(汗)。
お空のcondxもイマイチだし無線運用も飽きてきたなと思い、チョット気分を変えるために、購入したけど手を付けられず放置されていた電子工作キット(いわゆる「積みキット」)を消化しておりました。その中にあった秋月電子から出ている時計のキット2種を作ってみました。なんだかんだ時計が一番実用的ですからね(汗)。
下がNTP同期時計で上がGPS同期時計です。この通り、1秒以下できっちり同期しており時刻のズレなど心配せず使えるのですが、このLCD表示では字が小さくて見えないし(寝室に置きたいのでメガネがない状態でも読めないと困る)、バックライトが妙に明るいなど不満が多いものでした。一応シリアルの他桁7セグLEDに接続できる仕様となっているのですが、LEDが選べないのが不満(汗)。どちらも1万円近いお値段で、これならマイコン使って数千円程度で自分で作ってみようと考えました。太陽誘電製GPSモジュールGYSFDMAXBが安価で部屋の中でも衛星が常に受信できるという高性能なので使いこなしたいとも思いました。
表示機はLCDよりは7セグLEDがFBです。しかも最近の眩しい高輝度タイプではなくぼんやりと光る古いタイプを使ってみたいと部品箱を漁ると、古い東芝のTLR324が多数出てきました。2桁の赤LEDでカソードコモンタイプのものです。これを3つ並べて6桁にすればOK。TLR324のピン配置はこちら。古い部品なのでデーターシートを見つけるのに苦労しました。ちなみにコレの緑も在庫があるので2台目は緑にしたいです。
6桁のLEDをダイナミック点灯するので、信号線は8+6で14本。他にGPSモジュールから出ている1PPSの信号とLED点滅を同期させるために2本、合計16本のGPIOと1つのUSART(シリアル)が必要となります。設計当初はRaspberry Pi3でPythonを使って設計したのですが、たかが時計のためにRPiを組み込んでしまうのはもったいないので、普通のマイコンにすることにしました。mbedで安価のLPC1114を使ってみたいところだったのですが、ピン数がギリギリ足りないのでNG。手持ちのSTmicroから出ているNucleoが安価なのでこれを使うことにしました。ここ最近Pythonばかりだったので、C++はかなり抵抗があります・・・だけどだんだん慣れてきました(笑)。
ピン数が多くて組みやすいNucleo F746ZGを使ってで試作。ARM32-bitのCortex-M7が搭載されておりEthernetもなんでもあり最大クロック216MHzというバケモノクラスのボードですね(汗)。GPSのNMEAパーサーとしてTinyGPSというライブラリを利用しました。
全体のプログラムはごく簡単で、mainループ内でtime(NULL)関数で現在時刻を得ながら、GPSからの受信を割り込みで時刻を取得し、一定時間間隔でset_time関数を使って現在時刻をGPSの時刻に設定(補正)していくだけのものです。GPSモジュールの1PPS出力を立ち下がり・立ち上がり割り込みでLEDを点滅させたりなどもしています。一つ注意点としては、LEDのダイナミック点灯の素早いループがmainで走っているのですが、waitを掛けないとLEDが完全に消灯しないうちに点灯するので、全桁「8」の字に見えてしまいます。これもTLR324のような古いLEDを使っているせいでしょうか、2〜5msくらいのwaitで塩梅よくLEDが点いてくれました。それと、ピンあたりの電流量が不足しがちなので、GPIOに直接LEDを繋げるのではなく、アノード側にソースドライバTD62783AP、カソード側にシンクドライバTD62083AFNPを使いました。これでアノード側もカソード側も正論理でスイッチすることができるので、ソースコードのロジックが気持ち悪くなくなります(苦笑)。
ここまでは順調に行ったのですが、次に安価なNucleo F401REに載せ替えようとしたところ、急に動かなくなりました。mainループでハングアップ。どうやらシリアル割り込みするとハングアップするようです。F401REには2つのUSARTポートがあり、USART2(tx:D1, rx:D0)であったところを(ちなみにD0, D1ピンは裏面のハンダブリッジをしないと使えないので注意。これもしばらくハマった)。USART1(tx:D10, rx:D2)にすると、mainが動き出しました。しかしLEDの表示がヘンです。そこで割り込みの優先度を上げるためのおまじないとして、"NVIC_SetPriority(USART1_IRQn, 0);"を記述したり、ダイナミック点灯のwaitを微調整しました。それでも安定しません。最後に、GPSからの受信割り込みのコードを一番最初に書くと、完璧に治りました。この正解にたどり着くまで2日費やしまった(大汗)。mbedでもボードを変えるといろいろ不具合が出るものなんですね。Nucleo F401REでの試作の様子がコレ。
後はユニバ基板に取り付けケーシングし、視認性がよい安価なGPS同期時計が完成です。
以下にソースコードを示しますが、上記のようにmbedプラットフォームによってそのままでは動かないことがあるので注意して下さい。
/* GPS同期時計 mbed版 by JF1DIR 2017 * Nucleo F401RE */ #include "mbed.h" #include "TinyGPS.h" DigitalOut led[8]={D1, D3, D4, D5, D6, D7, D8, D9}; // nucleo F401RE DigitalOut digit[6]={D14, D15, D12, D13, D0, D11}; DigitalOut pps(PC_0); InterruptIn pps_in(PC_1); Ticker ticker_set_time; int number[11][8]={ {1,1,1,1,1,1,0,0}, //zero {0,1,1,0,0,0,0,0}, //one {1,1,0,1,1,0,1,0}, //two {1,1,1,1,0,0,1,0}, //three {0,1,1,0,0,1,1,0}, //four {1,0,1,1,0,1,1,0}, //five {0,0,1,1,1,1,1,0}, //six {1,1,1,0,0,0,0,0}, //seven {1,1,1,1,1,1,1,0}, //eight {1,1,1,1,0,1,1,0}, //nine {0,0,0,0,0,0,0,1} //dot }; Serial serial_gps(D10, D2); // UART1: tx, rx なぜかF401REのUART2では割り込み不能 TinyGPS gpsr; int year; byte month, day, hour, minute, second; void led_off() { pps = 0; } void led_on() { pps = 1; } void setup() { pps = 0; serial_gps.baud(9600); NVIC_SetPriority(USART1_IRQn, 0); } void getgps() { if (serial_gps.readable()) { char c = serial_gps.getc(); bool gps_avairable = gpsr.encode(c); if (gps_avairable) { (void)gpsr.crack_datetime(&year, &month, &day, &hour, &minute, &second); } } } void gps_to_nowtime() { struct tm t; t.tm_sec = (int)second; t.tm_min = (int)minute; t.tm_hour = (int)((hour + 9) % 24); t.tm_mday = 1; t.tm_mon = 1; t.tm_year = 100; time_t sec2 = mktime(&t); set_time(sec2); } int main() { int h, m, s, v, j, k = 0; int x[6] = {0, 0, 0, 0, 0, 0}; time_t seconds; struct tm *ts; setup(); serial_gps.attach(getgps, Serial::RxIrq); ticker_set_time.attach(&gps_to_nowtime, 10.0); pps_in.fall(&led_on); pps_in.rise(&led_off); while (1) { seconds = time(NULL); ts = localtime(&seconds); h = ts->tm_hour; m = ts->tm_min; s = ts->tm_sec; x[0] = (int)(h / 10); x[1] = (int)(h - x[0] * 10); x[2] = (int)(m / 10); x[3] = (int)(m - x[2] * 10); x[4] = (int)(s / 10); x[5] = (int)(s - x[4] * 10); for (v = 0; v < 8; v++) { led[v] = 0; } for (v = 0; v < 6; v++) { digit[v] = 0; } digit[k] = 1; j = x[k]; if ((k == 1) or (k == 3)) { for (v = 0; v < 7; v++) { led[v] = number[j][v]; } led[7] = 1; } else { for (v = 0; v < 8; v++) { led[v] = number[j][v]; } } wait(0.005); k++; if (k > 5) { k = 0; } } }