microbitのエディタをブログに表示するテスト
micro:bitのエディタをブログに表示するテストです。
ココログでもできるみたいです。
追記
2019/3/19のココログシステムのリニューアルで、表示出来なくなってしまいました。
« 2017年10月 | トップページ | 2017年12月 »
micro:bitのエディタをブログに表示するテストです。
ココログでもできるみたいです。
追記
2019/3/19のココログシステムのリニューアルで、表示出来なくなってしまいました。
今後色々と利用するために、nRF51822のリファレンス・マニュアルをちびちびと読解しています。
今日はGPIOTE(GPIO tasks and events)を使ってLチカをやってみました。
GPIOTEは、GPIOのピンの入力に対するイベント、または出力に対するタスクを定義することが出来ます。
GPIOTEは便利なのですが、4チャンネル(4つしか定義出来ない)です。
Arduino IDE環境では、GPIOピンのピン入力割り込みに利用されています。
具体的には、attachInterrupt()、detachInterrupt()です。
4チャンネル(4つしか定義出来ない)の制約から、attachInterrupt()は同時に4つまで
の利用となります。
とりえず、GPIOTEの利用の練習として、前回のLチカで利用してみました。
GPIOTEの0チャンネルを利用してLEDのポートをトグルでHIGH、LOW出力するタスクを
定義して、割り込み関数でタスクを実行します。
スケッチ
#include "nrf.h" const int COL1 = 3; // Column #1 control const int LED = 26; // 'row 1' led uint8_t sw =0; extern "C" void TIMER2_IRQHandler(void) { NRF_TIMER2->EVENTS_COMPARE[0] = 0; // 割り込みイベントクリア NRF_GPIOTE->TASKS_OUT[0] = 1; // タスク実行 //sw =!sw; //digitalWrite(LED, sw); } void setup() { uint32_t ulPin; Serial.begin(115200); Serial.println("microbit is ready!"); // GPIOピンの設定 pinMode(COL1, OUTPUT); digitalWrite(COL1, LOW); // COL1ピンの設定 //pinMode(LED, OUTPUT); // LEDピンの設定 // GPIOTEの設定:LEDピン・トグルタスクを定義する ulPin = g_ADigitalPinMap[LED]; // LEDの実ピン番号の取得 NRF_GPIOTE->CONFIG[0] = // チャネル0に機能設定 (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) | // タスクモード (ulPin << GPIOTE_CONFIG_PSEL_Pos) | // ピン番号設定 (GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos) | // 動作指定:トグル (GPIOTE_CONFIG_OUTINIT_Low << GPIOTE_CONFIG_OUTINIT_Pos); // ピン出力初期値 NRF_GPIOTE->POWER = 1; // GPIOTE有効 //タイマ設定 NRF_TIMER2->TASKS_STOP = 1; // タイマストップ NRF_TIMER2->TASKS_CLEAR = 1; // カウンタクリア NRF_TIMER2->MODE = TIMER_MODE_MODE_Timer; // モード設定:タイマモード NRF_TIMER2->PRESCALER = 8; // プリスケーラ設定:128分周(125KHz) NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_16Bit; // カウンタ長設定:16ビット長指定 NRF_TIMER2->CC[0] = 62500/2; // コンパレータ0の設定:0.5秒周期 NRF_TIMER2->INTENSET = // 割り込み設定:コンパレータ0と比較 (TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos); NRF_TIMER2->SHORTS = // ショートカット設定:クリアタスク指定 (TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos); // タイマ割り込み設定 NVIC_SetPriority(TIMER2_IRQn, 3); // 割り込み優先度設定 NVIC_ClearPendingIRQ(TIMER2_IRQn); // 保留割り込みクリア NVIC_EnableIRQ(TIMER2_IRQn); // 割り込み許可 NRF_TIMER2->TASKS_START = 1; // タイマスタート } void loop(){ __SEV(); __WFE(); __WFE(); }
割り込み関数内で、前回のLED用のポート出力をdigitalWrite()で制御をコメントアウトして、
代わりにNRF_GPIOTE->TASKS_OUT[0] = 1 でチャネル0のタスクを実行しています。
そのタスクの定義は、下記で行っています。
// GPIOTEの設定:LEDピン・トグルタスクを定義する ulPin = g_ADigitalPinMap[LED]; // LEDの実ピン番号の取得 NRF_GPIOTE->CONFIG[0] = // チャネル0に機能設定 (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) | // タスクモード (ulPin << GPIOTE_CONFIG_PSEL_Pos) | // ピン番号設定 (GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos) | // 動作指定:トグル (GPIOTE_CONFIG_OUTINIT_Low << GPIOTE_CONFIG_OUTINIT_Pos); // ピン出力初期値 NRF_GPIOTE->POWER = 1; // GPIOTE有効
NRF_GPIOTE->TASKS_OUT[0] = 1によるタスク実行指示で、
動作指定をトグルにし、初期設定状態はLOWとしています。
この定義を行った場合、pinMode()によるピン機能の設定は不要となります。
割り込み関数で、NRF_GPIOTE->TASKS_OUT[0] = 1実行される度に
タスクが実行され、LEDピンの出力がトグルでHIGH,LOWと変化します。
次は、PPI(Programmable Peripheral Interconnect)を使って、
割り込みを利用せずにLチカをやってみます。
PPIは、イベントに対して実行するタスクを割り当てることが出来ます。
タイマ(TIMER2)のコンパレータとの一致イベントNRF_TIMER2->EVENTS_COMPARE[0]と
LEDの点滅タスクNRF_GPIOTE->TASKS_OUT[0] を結び付けてれば、Lチカするはずです。
前回のLチカスケッチでは、loop()で無駄に無限ループをしていました。
省電力対策を調べたところ、
void loop(){ __SEV(); __WFE(); __WFE(); }
でスリープモードになり、割り込み発生時にウェイクして処理を実行してくれるようです。
参考にしたサイト
How do you put the nrf51822 chip to sleep? [closed]
前回の「micro:bitはじめました」では、microbitをArduino IDE環境で利用出来るようにしました。
今回はそのArduinoIDEを使ってタイマー割り込みを使ってLチカをやってみました。
microbitに搭載されているARM Cortex-M0 nRF51822でタイマ割り込みを行う場合、
タイマかRTCを使って実現できるようです。
今回はタイマを使って5x5マトリックス左上LEDを0.5秒間隔で点滅させてみました。
スケッチ
#include "nrf.h" const int COL1 = 3; // Column #1 control const int LED = 26; // 'row 1' led uint8_t sw =0; extern "C" void TIMER2_IRQHandler(void) { NRF_TIMER2->EVENTS_COMPARE[0] = 0; // 割り込みイベントクリア sw =!sw; digitalWrite(LED, sw); } void setup() { Serial.begin(115200); Serial.println("microbit is ready!"); pinMode(COL1, OUTPUT); digitalWrite(COL1, LOW); pinMode(LED, OUTPUT); //タイマ設定 NRF_TIMER2->TASKS_STOP = 1; // タイマストップ NRF_TIMER2->TASKS_CLEAR = 1; // カウンタクリア NRF_TIMER2->MODE = TIMER_MODE_MODE_Timer; // モード設定:タイマモード NRF_TIMER2->PRESCALER = 8; // プリスケーラ設定:256分周(62.5kHz) NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_16Bit; // カウンタ長設定:16ビット長指定 NRF_TIMER2->CC[0] = 62500/2; // コンパレータ0の設定:0.5秒周期 NRF_TIMER2->INTENSET = // 割り込み設定:コンパレータ0と比較 (TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos); NRF_TIMER2->SHORTS = // ショートカット設定:クリアタスク指定 (TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos); // タイマ割り込み設定 NVIC_SetPriority(TIMER2_IRQn, 3); // 割り込み優先度設定 NVIC_ClearPendingIRQ(TIMER2_IRQn); // 保留割り込みクリア NVIC_EnableIRQ(TIMER2_IRQn); // 割り込み許可 NRF_TIMER2->TASKS_START = 1; // タイマスタート } void loop(){ }
解説
タイマー割り込みはTIMER2のレジスタを直接操作して実装しています。
(TIMER1は、PWM出力で利用されているため使わない方がよいでしょう)
まず、割り込みで呼び出される関数が、TIMER2_IRQHandler(void)です。
この関数名は固定で、extern "C"を付けてC言語互換にする必要があります。
呼び出された割り込み関数内では、割り込みイベントをクリアする必要があります。
NRF_TIMER2->EVENTS_COMPARE[0] = 0;
にてそれを行っています。コンパレータ0を使った割り込みのため、対応するイベントを
クリアしています。
次に、タイマ設定についてすが、最初の2行はコメントの通りで、タイマをストップして
カウンタをクリアしてます。
NRF_TIMER2->TASKS_STOP = 1; // タイマストップ
NRF_TIMER2->TASKS_CLEAR = 1; // カウンタクリア
次の2行は、タイマのモード設定とプリスケーラ(分周)を設定しています。
NRF_TIMER2->MODE = TIMER_MODE_MODE_Timer; // モード設定:タイマモード
NRF_TIMER2->PRESCALER = 8; // プリスケーラ設定:128分周(125KHz)
最後に、タイマをスタートさせます。
NRF_TIMER2->TASKS_START = 1; // タイマスタート
タイマについては、PPI(Programmable Peripheral Interconnect)との連携方法がまだわかりません。
PPIを使えば、割り込みを使わずにLチカ出来ると思っているのですが。
=> 2018/06/22 PPIの使い方がわかりました。下記の記事を参考願います。
micro:bitをArduino環境で使う (5) PPIを使ったLチカ
このあたりのレジスタマップ定義はArduino IDEのnRF51環境にnRF51 SDKが
組み込まれているために利用出来ているようです。
まとまったドキュメントを探しているのですが、見つからないので
Arduino IDEのnRF51環境周りをdoxygenにかけてドキュメント化して利用しています。
2017/11/25 追記
Arduino IDEのnRF51環境周りのファイルを調べると、nRF5_SDKのうち、
ヘッダファイルの一部しか入っていないことが判明。SDKは実質レジスタ等の定義のみです。
関連記事
micro:bitをArduino環境で使う (2)GPIOTEを使ったLチカ
micro:bitをArduino環境で使う (5) PPIを使ったLチカ
以前、Arduino用でやってみた「Arduino - TV出力(TVoutLibrary使用)で漢字表示」を
Arduino STM32でやってみました。
マイコンボードは、STM32F103C8T6搭載のBlack Pillボードを利用しています。
(Blue Pillボードでも動きます)
自作フォントライブラリを利用しています。
Arduino用漢字フォントライブラリ SPIフラッシュメモリ版
https://github.com/Tamakichi/Arduino_exfonts
動いている様子
結線
スケッチ
// // TTVOutでマルチフォント表示 by たま吉さん 2017/11/18 // #include <SPI.h> #include <W25Q64.h> #include <exfonts.h> #include <TTVout.h> TTVout TV; exfonts ft; // フォント管理オブジェクト // 指定位置に1文字表示 void mputc(uint16_t x, uint16_t y, uint16_t code) { byte buf[MAXFONTLEN]; ft.getFontData(buf,code); // フォントデータの取得 TV.bitmap(x,y, buf ,0,ft.getWidth(), ft.getHeight()); } // 指定位置に文字列表示 void mprint(uint16_t x, uint16_t y, char* str) { uint16_t wstr[1024]; int16_t len; len = exfonts::Utf8ToUtf16(wstr, str); // UTF8からUTF16に変換する for (uint16_t i=0; i <len; i++) { mputc(x, y, wstr[i]); if (x + ft.getWidth()*2 < TV.hres()) { x += ft.getWidth(); } else { x = 0; if (y+ft.getHeight()*2 < TV.vres()) { y+=ft.getHeight(); } else { break; } } } } void setup () { static const char* text= "吾輩わがはいは猫である。名前はまだ無い。" "どこで生れたかとんと見当けんとうがつかぬ。何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。" "吾輩はここで始めて人間というものを見た。しかもあとで聞くとそれは書生という人間中で一番獰悪どうあくな種族であったそうだ。" "というのは時々我々を捕つかまえて煮にて食うという話である。しかしその当時は何という考もなかったから別段恐しいとも思わなかった。" "ただ彼の掌てのひらに載せられてスーと持ち上げられた時何だかフワフワした感じがあったばかりである。" "掌の上で少し落ちついて書生の顔を見たのがいわゆる人間というものの見始みはじめであろう。"; TV.begin(SC_448x216,2); // 第2引数でSPI 1,2を指定(デフォルト 1)) TV.adjust(2); // 垂直同期信号補正(デフォルト 0) ft.init(PA4); // フォント管理の初期化 //7種類のフォントサイズで文字列表示 while(1) for (uint8_t i =0 ; i <7; i++) { TV.fill(0); ft.setFontSize(i); mprint(0,0,(char*)text); delay(1000*3); } } void loop () { }
Arduinoと比べると、SRAMが20kバイトあるため画面解像度448x216ドットを確保出来ました。 表示も速いです。
豊四季 Tiny BASIC for Arduino STM32のファームウェア書込み手順を下記サイトにまとめました。
ブートローダ付きファームウェアのインストール手順
マイクロソフトの統合開発環境 「Visual Studio 2017 Community 2017」で
Arduino向けプログラムの開発が出来ると聞き、試してみました。
最近のVsual Studioは個人レベルの利用であれば、無償版の範囲でも
かなりの機能が利用できるようです。
プラグイン的な「Arduino IDE for Visual Studio」をインストールすると、
Arduinoのプラグイン的に利用していたArduino STM32もコンパイルと書き込みまで出来ました。
他に、Androidアプリ開発、マークダウンドキュメント対応と充実しています。
最近のマイクロソフトは個人開発・オープンソース開発者に優しくなった感があります^^
豊四季Tiny BASIC for Arduino STM32で
超音波距離センサHC-SR04を使った距離計測を試してみました。
HC-SR04は、秋月電子でも販売されていますが、amazonで探すと、200円程度で入手出来るようです。
プログラム
1 'キョリケイソク 10 CLS 20 P1=PB8:P2=PB3:T=180 30 K=(3315+T*6)/20 40 GPIO P1,OUTPUT 50 GPIO P2,INPUT_FL 60 "loop" 70 OUT P1,LOW 80 OUT P1,HIGH 90 OUT P1,LOW 100 D=PULSEIN(P2,HIGH,200,1) 110 ?DMP$(D/100*K,2) 120 WAIT 300 130 GOTO "loop"
PULSEIN()関数を使って、超音波が反射して帰ってくるパスル幅を調べ、
その時間から距離を求めています。
小数が使えないため、DMP$()という、指定位置に小数点を挿入する文字列関数で
見かけ上、小数表示しています。
動作の様子
正確な計測値とは言えませんが、そこそこ目安となる数字はでていますね。
参考にしたサイト
【Arduino】超音波距離センサ(HC-SR04)の測定精度を向上(気温考慮)
こちらのサイトにもまとめました
超音波距離センサ(HC-SR04)を使った距離計測
Aliexpressでシリアル接続で利用出来る赤外線送受信モジュールを見つけ、入手しました。
製品はこんな感じです。
いつものAliexpressクオリティでマニュアルが無いので、
裏のシルク印刷「YS-IRTM」で情報を探すと ズバリの情報がありました。
・Arduino フォーラム Topic: Infrared interface
https://forum.arduino.cc/index.php?topic=359707.0
上記の情報から、通販サイト「UCTronics Store」の商品情報のページに詳しい情報があります。
・Infrared Remote IR Decoder Encoding Transmitter & receiver Wireless Module NEC
このページにマニュアルのリンクがあります。
http://www.uctronics.com/download/U3107_Infrared_decoding_module.zip
マニュアルは中国語ですが、使い方が分かりました。
(以下、使い方のメモ)
結線
シリアル(UART)はクロス接続です。電源は3.3Vでは動きません。5Vを供給します。
3.3Vマイコンを使う場合は、5Vトレラント対応を確認して利用します。
IchigoJamやSTM32(Blue Pillボード)のSerial1は、5Vトレラントなので直結出来ます。
シリアル通信条件
デフォルトでは、9600bpsで、8ビット長、パリティなし、ストップビット1、フロー制御無し
とりあえず、データの受信はこれで出来ます。
NECフォーマットなので、赤外線リモコンを押したときに、受信するデータは
次の3バイトとなります。
[カスタマーコード上位] [カスタマーコード下位] [ボタンコード]
試しに、豊四季Tiny BASICを使って、受信してみます。
プログラムソース
10 CLS
20 SOPEN "9600"
30 D=SREAD()
40 IF D>=0 ?HEX$(D,2)
50 GOTO 30
プログラムは、シリアルをオープンして、データを受信したら16進数で表示します。
ボタンを押すと3バイト受信出来ました。
3バイトのうち、最初の2バイトがカスタマーコードで、どの赤外線リモコンから送信されたか識別できます。
3バイト目が押されるボタン毎に異なる値となります。
こういった実験は、単独稼働できるボードだとお手軽に出来ますね。
インタープリターでコンパイル不要なのも良いです。
モジュールには幾つかのコマンドが利用出来ます。
コマンドは次の5バイト構成となっています(16進コード)。
[アドレス] [コマンド] [引数1] [引数2] [引数3]
アドレス:送信先モジュールを指定するアドレス
0xA1(デフォルトアドレス、変更可能)
0xFA(ユニバーサルアドレス、変更不可)
コマンド: モジュールに対する指示
0xF1 赤外線信号送信
引数1~引数3に送信するデータを指定します。
引数 1: カスタマーコード上位
引数 2: カスタマーコード下位
引数 3: データ(ボタン識別コード)
0xF2 アドレスの変更
引数1~引数3に送信するデータを指定します。
引数 1: 新しいアドレス
引数 2: 0x00
引数 3: 0x00
0xF3 シリアル通信速度の設定
引数1~引数3に送信するデータを指定します。
引数 1: 0x01~0x04(0x01:4800、0x02:9600、0x03:19200、0x04:57600bps)
引数 2: 0x00
引数 3: 0x00
ここで、アドレスとはモジュールを個体識別するコードのようです。
やろうと思えばシリアル通信でも1対多送信出来るので、同時に複数のモジュールを
接続してる場合にでも利用するのかもしれません。
上記のコマンドを送信し、正しく処理が行われた場合は、コマンドのコード1バイトが
応答として送られてきます。
0xF1 送信に成功した
0xF2 シリアルポートアドレスが正常に変更されました
0xF3 ボーレートが正常に設定されました
応答が帰ってこない場合、エラーを意味します。
資料を読むと、アドレス、通信速度のリセット方法の説明があるので、
アドレス、通信速度の変更は保持さるっぽいです(試していません)。
モジュールをもう一つ使って送信も試してみました。
もう一方はUSB-シリアル変換にてパソコン(Windows 10)に接続しています。
Real Time Serial Captureというソフトを使って、データ送信コマンドとして
0xA1 0xF1 0x12 0x34 0x56 をモジュールに送信します。
相手側にて受信され、画面に 12、34、56が表示されました。
パソコン側は応答としてF1を受信しています。
2、3メートル離して送信を試してみましたが、問題なく送信出来ました。
NECフォーマットの都合上、一度に3バイトしか送れませんが、色々と使えそうです。
さて、このモジュール、回路図を見るとこのモジュールにはSTC11F02Eというマイコンが
使われているようです。STCは中国で良く使われているマイコンのようです。
ちょっと消費電力が気になり、測定してみると15mA(5V)でした。
まあこの程度なら利用には問題ないでしょう。
豊四季Tiny BASIC for Arduino STM32 のTFT版で簡単な画像ビュアーを作成してみました。
SDカード内の24ビット ビットマップファイルを表示しています。
プログラムソース
1 'BMPローダー
10 CLS
20 FOR I=1 TO 8
30 DWBMP "cat/cat";I;".bmp",0,0
40 WAIT 1000
50 NEXT I
60 GOTO 20
micro:bitは、子供向けのスクラッチみたいなプログラム環境と思い込んで様子見だった
のですが、MicroPython、mbed、Arduinoも利用可能とうことを知り、入手しました。
まずは、ハードウェアスペック
MPU:Nordic nRF51822 ARM Cortex-M0 16MHz RAM 16kバイト Flash 256kバイト
BLE搭載、5x5ドットマトリックスLED、ユーザー利用可能ボタン 2個
加速度センサ、磁気センサ
これだけあれば、そこそこのサイズのプログラムが作成できます。
利用可能開発環境
下記は、公式サポートしている開発環境です。
ブラウザ(クラウド)で利用出来ます。
・Javascript(JavaScriptブロックエディターでスクラッチのようにプログラミング可能)
・MicroPython(Pythonエディターでプログラム開発)
次が本命の利用したい環境
・mbed(BBC micro:bit )
・Arduoino
早速、Arduinoの開発環境を利用してみました。
開発環境の構築は、adafruit - Micro:bit with Arduinoを参考にしました。
BLE、加速度センサ、磁気センサ、5x5ドットマトリックスLED用ライブラリは、
上記解説サイトの内容に従って別途インストールしました。
試しに、豊四季Tiny BASICのターミナルスクリーン版を動かしてみました。
Arduino対応版は取りあえず、無修正で動きました。
開発環境周りのドキュメントを調べていくと、
micro:bit runtimeという解説を見つけました。
・micro:bit runtime https://lancaster-university.github.io/microbit-docs/
このサイトのconseptの解説に次の階層図があります。
(画像は、https://lancaster-university.github.io/microbit-docs/concepts/ より引用)
プログラム環境はmbedベースであることが分かります。
NordicのSDKがベースになっていて、その上にmbed、 runtimeが乗っています。
ランタイムはmicro:bit DALという名称のようです。
このmicro:bit DALは、mbedの他に、Yotta という環境で利用可能なようです。
Arduinoよりも、mbed、Yottaに手を出した方が良さそうです。
micro:bit DALにはmessageBusというイベント駆動をサポートしているようです。
かなり洗練されたデザイン(設計)がなされています。
#include "MicroBit.h" MicroBit uBit; void onButtonA(MicroBitEvent e) { if (e.value == MICROBIT_BUTTON_EVT_CLICK) uBit.display.scroll("CLICK"); if (e.value == MICROBIT_BUTTON_EVT_DOWN) uBit.display.scroll("DOWN"); } int main() { uBit.init(); uBit.messageBus.listen(MICROBIT_ID_BUTTON_A, MICROBIT_EVT_ANY, onButtonA); // We don't want to drop out of main! while(1) uBit.sleep(100); }
最近のコメント