フォト
2018年1月
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      
無料ブログはココログ

2018年1月16日 (火)

豊四季Tiny BASIC for micro:bit をV0.05に更新しました

豊四季Tiny BASIC for micro:bit をV0.05に更新しました。

変更点
 ・Neopixel対応
 ・PCG(LEDマトリックス用フォント書き換え)対応
 ・RTC(時刻管理)対応(誤差は数分/日)
 ・2進数定数対応
 ・PWM暫定対応(Arduinoの制約により同時3チャンネル迄)
 ・CHR$()の複数キャラ指定対応(?CHR$(65,66,67) => "ABC")
 ・GRADE(値, 配列No,個数)関数の追加:等級判定関数

ダウンロード直リンク
https://github.com/Tama…/ttbasic_microbit/archive/master.zip

micro:bitで豊四季Tiny BASIC - 現在時刻の表示


プログラムソース

1 'トケイ
10 MATRIX ON
20 SETDATE 2018,1,16,12,0,0
30 IF !IN(BTNA) GOSUB "@ShowTime"
40 WAIT 200
50 GOTO 30
60 "@ShowTime"
70 GETTIME T1,T2,T3
80 MSG LEFT,80,#-2,T1;":";T2;":";T3;" "
90 RETURN

micro:bitで豊四季Tiny BASIC - Neopixelの制御



プログラムソース

10 'Neopixel(1)
20 NPBEGIN 0,16
30 NPCLS
40 FOR I=0 TO 7
50 NPRGB I,0,0,(2<<I)-1
60 NEXT I
70 NPSHIFT 1
80 WAIT 50
90 GOTO 70

2018年1月12日 (金)

micro:bitをArduino環境で使う (5) PPIを使ったLチカ

今回はPPI(Programmable Peripheral Interconnect)を使ったLチカを実装してみました。

micro:bitをArduino環境で使う (2)GPIOTEを使ったLチカ」では、
タイマー割り込みを使って、タスク(GPIOEを使って定義したLEDをトグルでON・OFF)を
実行していました。

今回はPPIを使って、イベント(カウンター値がコンパレーターと一致)発生時に
タスク(GPIOEを使って定義したLEDをトグルでON・OFF)を自動で実行させます。

この方法により、CPUが介在することなく、LEDを点滅させることが出来ます。

micro:bitをArduino環境で使う (2)GPIOTEを使ったLチカ」のスケッチの
割り込み処理部分をPPIに置き換えたスケッチを下記に示します。

スケッチ

//
// micro:bit PPIを使ったLチカ by たま吉さん
//

#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);        // 割り込み許可
*/  

  // PPIの設定(チャネル0を利用)
  //   TIMER2 コンパレータ0一致イベント と GPIOTE(ch0)LEDピン・トグルタスク を結び付ける
  NRF_PPI->CH[0].TEP  = (uint32_t)&NRF_GPIOTE->TASKS_OUT[0];       // PPI.ch0 にLEDピン・トグルタスク設定
  NRF_PPI->CH[0].EEP  = (uint32_t)&NRF_TIMER2->EVENTS_COMPARE[0];  // PPI ch0 にコンパレータ0一致イベント設定  
  NRF_PPI->CHENSET   |= PPI_CHENSET_CH0_Enabled;                   // PPI ch0 有効

  NRF_TIMER2->TASKS_START = 1;   // タイマスタート
  
}

void loop(){
    __SEV();
    __WFE();
    __WFE();
}


前回からの修正は、
・ 割り込み関数 TIMER2_IRQHandler(void) のコメントアウト
・ タイマー割り込み設定、割り込み関数登録のコメントアウト
・ PPI設定の追加
を行っています。

PPIの設定は簡単です(下記3行で設定)。
  // PPIの設定(チャネル0を利用)
  //   TIMER2 コンパレータ0一致イベント と GPIOTE(ch0)LEDピン・トグルタスク を結び付ける
  NRF_PPI->CH[0].TEP  = (uint32_t)&NRF_GPIOTE->TASKS_OUT[0];       // PPI.ch0 にLEDピン・トグルタスク設定
  NRF_PPI->CH[0].EEP  = (uint32_t)&NRF_TIMER2->EVENTS_COMPARE[0];  // PPI ch0 にコンパレータ0一致イベント設定  
  NRF_PPI->CHENSET   |= PPI_CHENSET_CH0_Enabled;                   // PPI ch0 有効

PPIのチャネル0~15のうち、今回はチャネル0を利用しています。
CH[0].TEPにタスク、CH[0].EEPにイベントのレジスタのアドレスを登録しています。
これにより、タスクとイベントを結び付けることが出来ます。

タイマーのカウンターが指定した値になったら、指定したタスクを実行します。

PPIは、周辺機器の様々なイベント(状態変化)発生のタイミングで、指定したタスクを
実行することが出来る機構です。

micro:bitに採用されているMCU: Nordic nRF51822 ARM Cortex-M0 は、
ハードウェアによる直接PWMを生成する機能は無いのですが
PPIを使うことで、同様のことを行うことが出来ます(たぶん)。
(PWMのHIGH期間、LOW期間の調整はコンパレータを2つ用いて出来ると思います)

2018年1月11日 (木)

ルミちゃんの毛づくろい

最近、=^_^= 成分が少ないというご指摘が各方面からある今日このごろ...

ということで、我が家の愛猫 ルミちゃん(♀)の毛づくろいの様子をご堪能下さい。



ちょっとセクシーかも...

2018年1月10日 (水)

micro:bit用Arduino環境にてrtcの精度が悪い - その対策

micro:bit をArduino環境で利用しています。
時計を実装したいと思い、mbed用の下記のライブラリを参考にしてやってみました。

参考にしたサイト
・Francis Schumacher /  nrf51_rtc
https://os.mbed.com/users/fxschumacher/code/nrf51_rtc/
・Francis Schumacher /  nRF51_rtc_example
https://os.mbed.com/users/fxschumacher/code/nRF51_rtc_example/file/c1f06d0a5e11/main.cpp/

一見、ちゃんと動作していると思いつつ、放置すると徐々に時間が進んでしまいます。
誤差を測定すると私のmicro:bitでは5%も速く時間を刻みます。
(誤差はmicro:bitの個体ごとに異なると思います)

Photo

原因を調べるとArduinoのrtc(リアルタイムクロック)に供給されているクロックソース
LFCLKSRC32.768 kHz RC oscillatorに設定されていました。

micros()、millis()、delay()ではrtc1が利用されており、これらも5%進んでしまいます。
このズレは、micros()、millis()、delay()でパルス幅の生成や測定を行っている場合には
影響を受けるかもしれません。

改善方法として、LFCLKSRCに指定するクロックソースを
16MHz crystal oscillatorをベースにしている LFCLK synthesizerに設定します。
RCオシレータよりクリスタル・オシレータの方が当然精度が良いですね。

具体的には、setup()の頭でLFCLKSRCのクロックソースを次のように設定します。

void setup() {
  NRF_CLOCK->TASKS_LFCLKSTOP = 1;
  NRF_CLOCK->LFCLKSRC = 
    (uint32_t)((CLOCK_LFCLKSRC_SRC_Synth << CLOCK_LFCLKSRC_SRC_Pos) &
    CLOCK_LFCLKSRC_SRC_Msk);
  NRF_CLOCK->TASKS_LFCLKSTART = 1;
   ・・・・

実際に試したところ、当初の5%よりもかなり改善されました。
一晩放置して誤差を調べてみます。

別の方法として、コンパイルオプション -DUSE_LFSYNTを付けることでも対応出来ます。
Arduinoのローカル設定ファイル platform.local.txtを
AppData\Local\Arduino15\packages\sandeepmistry\hardware\nRF5\0.4.0\に作成して
  compiler.c.extra_flags=-DUSE_LFSYNT
  compiler.cpp.extra_flags=-DUSE_LFSYNT

を定義で対応でいけると思います。

2018/01/11 追記


改善を施した場合の誤差は0.6%でした。
24時間で8分ずれます。思ったほど精度が改善できませんでしたが、
まあ、効果はあるのでこれで良しとします。

2018年1月 9日 (火)

豊四季Tiny BASIC for micro:bit をV0.04に更新しました

豊四季Tiny BASIC for micro:bit をV0.04に更新しました。
MSGコマンドでテキストメッセージ表示、加速度センサーの値取得等に対応しました。

豊四季Tiny Basic for micro:bit V0.04
https://github.com/Tamakichi/ttbasic_microbit




動画は下記のプログラムを動かしている様子です。

10 CLS 1
20 MSG LEFT,200,"コンニチハ"
30 FOR I=O TO 30
40 MSG DOWN,50,I/10
50 WAIT 50
60 MSG LEFT,100,I%10
70 NEXT I
80 WAIT 500
90 GOTO 20

プログラムはシリアルコンソール上にて作成し、即実行することが出来ます。

01


2018年1月 2日 (火)

Aliexpressで見つけたSTM32F407VGT6ボードを購入

こりもせず、Aliexpressで見つけた良さそうなマイコンボードを購入しました。

STM32F4discovery STM32F407VGT6 ARM Cortex-M4 32bit MCU Core Development Board 02

到着したマイコンボード

BluePillボードの2倍くらいの大きさです。STM32F4が乗っている割には非常にシンプルなボードです。

Dscn7437

使い勝手は良さそうなのですが、資料なし。
色々探してみると、このボードを評価しているサイトがありました(感謝!)。

Visuariddim - DIY More STM32F407VGT6 ボード
http://dubstylee.net/v/diy-more-stm32f407vgt6/

上記サイトの情報により、ユーザー利用可能LED、ボタン利用のポート番号や、
USBの問題点を知ることが出来ました。

とりあえず、Arduino STM32環境にてLチカを行うことが出来ました。
書込みはST-Linkを利用しました。

Dscn7442

USBシリアルの利用は上記サイトで指摘のある通り、問題ありです。
D+、D-がプルアップ抵抗、ダンピング抵抗がなくポートに直結の状態。
とりあず1.5kΩの抵抗でプルアップすることで、USBシリアルを使った通信を行うことが出来ましたが、
USBを認識したり、しなかったりと不安定です。

USB経由でDFUを使った書き込みは、DfuSeDemoでは出来ましたが、Arduino IDEからは
出来ませんでした。

(2018/01/05 補足 Arduino IDE for STM32にてF4ボードでUSB経由(.dfu形式イメージ対応)で
  書き込みを行うには、下記のリンク先のカスタマイズ設定が必要です。
  alternative way to use STM DFU in Arduino 1.8.3 on Black F407VET6
  ただし、このボードでは書き込みは出来ても、動作しませんでした。
)

Dscn7443

ボードとしては、シンプルで好きなタイプなのですが...
とりあえず、実験用に使ていこうとは思います。

2018/01/03 追記

端子名が分かるよう、ラベルを貼り付けました。
これでちょっと使いやすくなりました。

Dscn7455

2018/01/10 追記
Arduino for STM32のフォーラムにこのボードに関する投稿記事を見つけました。
[Solved] Anybody using this F4 board and got the USB working?

結論としては、「外部プルアップ抵抗付けなくてもUSB CDCは利用できる~よん」
とのことです。内部でプルアップ処理を施す対応のようです。

2018年1月 1日 (月)

新年あけまして、おめでこうございます!

明けましておめでとうございます。
今年もマイペースでブログやっていきます。

「正月的な何か」をと思い、そのへんに飾ってあった餅を無理やり猫にあてがいました。
(以前もこんなのやった気が ...)

ルミちゃん、ますます太った感じです。

Dscn7429

たまちゃん(たま吉さん)は、一見スリムなのですが、お腹がすごいことになっています。

Dscn7435

今年も例年通り、家族で墓参りに行ってきました。天気も良く一年の始めに日としては申し分のない1日でした。

2017年12月28日 (木)

micro:bitをArduino環境で使う(4)豊四季Tiny BASICを動かしてみる

Tetsuya Suzukiさんが開発・公開している「豊四季タイニーBASIC」をmicro:bitに移植しました。
まだまだ機能不十分ですが、下記のサイトにて公開しました。
先日作成した、内部フラッシュメモリへの保存機能も組み込みました。

豊四季Tiny Basic for micro:bit V0.03
https://github.com/Tamakichi/ttbasic_microbit

ダウンロードの直リンク
https://github.com/Tamakichi/ttbasic_microbit/archive/master.zip

シリアル接続したターミナル上でプログラムを作成することが出来ます。
フルスクリーンエディタ対応で、操作は8ビットマイコン時代のBASIC風です。

02

上記のプログラムを動かした様子

01

機能的には、現時点で
  ・シリアルコンソール上でのPRINT、INPUT等の一般的なコマンドの利用
  ・プログラムの保存・読み込み・保存一覧表示:SAVE n、LOAD n、FILES
 ・LEDマトリックスの描画:PSET、LINE、RECT、CIRCLE
 ・GPIOを使ったデジタル入出力、アナログ入力:OUT、IN()、ANA()

に対応しています。

ファームウェアの書込みは、通常のプログラム書き込みと同様です。
公開サイトからダウンロードした圧縮ファイルを解凍し、
binフォルダ内のhexファイルをmicro:bitのフォルダに書き込みます。

マニュアル等はこれから整備していきます。

グラフィカルなインタフェースも良いのですが、修正の都度コンパイルと書き込みに
ちょっとフラストレーションがたまります。
その点、即実行できるインタープリタ言語のBASICは思ったら直ぐ実行できるので良いです。

2017年12月25日 (月)

micro:bitをArduino環境で使う (3)内部フラッシュへのデータ書き込み

256kバイトもあるフラッシュメモリにプログラムから自由にデータを書き込みたいと思い、ライブラリを作成しまた。

2017/12/27 更新
書込みの*addr++ = *ptr++;の両アドレスが4バイト境界でないとフォルトを起こしてしまうようです。
その防止のためのエラー処理を追加しました。

ライブラリ

//
// フラッシュメモリ書き込みライブラリ
// 2017/12/25 by たま吉さん
// 参考文献
//  nRF51 Series Reference Manual Version 3.0 「6 Non-Volatile Memory Controller (NVMC)」
//

#include <Arduino.h>
#include "nrf.h"

//
// フラッシュメモリ指定ページ消去
// フラッシュメモリアドレスは、0x00000000 ~ 0x0003FFFFの範囲とする
// 1ページのサイズは1024バイトとし、アドレスは
//
// 引数
//   addr 消去対象ページ先頭アドレス
// 戻り値
//   0:正常終了
//   1:異常終了(指定アドレスが正しくない)
//
uint8_t  flashPageErase(uint32_t addr) {
  if ( addr >= 0x00040000 )
    return 1;  // フラッシュメモリ領域外
  if ( addr % 1024 )
    return 1;  // ページ先頭アドレスでない
  
  // 書込みアンロック
  NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Een;
  while (NRF_NVMC->READY == NVMC_READY_READY_Busy);

  // 指定ページの消去
  NRF_NVMC->ERASEPAGE = addr;
  while (NRF_NVMC->READY == NVMC_READY_READY_Busy);

  // 書込みロック
  NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
  while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
  return 0;
}

// フラッシュメモリ32ビットワードデータ書き込み
// 引数
//  addr: 書込みアドレス(4バイト境界アドレスであること)
//  ptr : 書込みデータ格納アドレス(4バイト境界アドレスであること)
//  len : 書込みデータ長さ
// 戻り値
//   0:正常終了
//   1:異常終了(指定アドレスが正しくない)
//
uint8_t flashWriteData(uint32_t* addr, uint32_t *ptr, uint16_t len) {

  if ( ((uint32_t)addr) >= 0x00040000 )
    return 1;  // フラッシュメモリ領域外
  if ( ((uint32_t)addr) % 1024 )
    return 1;  // ページ先頭アドレスでない
  if (((uint32_t)ptr)%4)
    return 1;  // 4バイト境界アドレスでない
    
  // 書込み有効設定
  NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen;
  while (NRF_NVMC->READY == NVMC_READY_READY_Busy);

  // データ書き込みループ
  for (uint32_t i = 0; i<len; i++) {
    *addr++ = *ptr++;
    //Serial.println(i,DEC); 
    while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
  }

  // 書込み無効設定
  NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
  while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
  return 0;
}


利用サンプルスケッチ
//
// micro:bit フラッシュメモリ書込みテスト 2017/12/25 by たま吉さん
//

uint8_t  flashPageErase(uint32_t addr);
void flashWriteData(uint32_t* addr, uint32_t *ptr, uint16_t len);

#define FLASH_PAGESIZE    1024         // ページサイズ
#define FLASH_PAGENUM     256          // 総ページ数
#define FLASH_TOPADR      0x00000000   // フレッシュメモリ先頭アドレス
#define FLASH_SAVESIZE    4096         // 保存データサイズ(ttbasicを想定)
#define FLASH_SAVEPAGENUM 4            // 
#define FLASH_SAVENUM     1
#define FLASH_SAVEPOP  ((FLASH_TOPADR+FLASH_PAGESIZE*256)-FLASH_SAVESIZE*FLASH_SAVENUM)

uint8_t buf[FLASH_SAVESIZE];
void setup() {
  uint8_t c;
  
  Serial.begin(115200);
  Serial.print("Save top adr=");
  Serial.println(FLASH_SAVEPOP,HEX);

  // テスト用ダミーデータ
  for (uint16_t i=0; i < FLASH_SAVESIZE; i++) {
    buf[i] = i%256;
  }

  Serial.print("Write(y/n)? ");
  while(!Serial.available());
  c = Serial.read();
  Serial.write(c);
  Serial.println();
  if (c == 'y') {
  
    // ページの消去
    Serial.println("ERASE PAGE");
    for (uint8_t i=0; i<FLASH_SAVEPAGENUM; i++) {
       flashPageErase(FLASH_SAVEPOP+FLASH_PAGESIZE*i);
    }
  
    // データの書込み
    Serial.println("Write Data");
    //for (uint8_t i=0; i<FLASH_SAVEPAGENUM; i++) {
      flashWriteData((uint32_t*)FLASH_SAVEPOP, (uint32_t*)buf, FLASH_SAVESIZE/4);
    //}
  }
  
  // データの確認
  Serial.println("Read Data");
  for (uint32_t i=0; i <FLASH_SAVESIZE; i++) {
    if (i%16 == 0) {
      Serial.print(FLASH_SAVEPOP+i,HEX);
      Serial.print(":");
    }
 
    c = *((uint8_t*)FLASH_SAVEPOP+i);
    if (c<0x10){
      Serial.print("0");Serial.print(c,HEX);
    } else {
      Serial.print(c,HEX);
    }
    if (i%16 == 15) 
      Serial.println();
    else
      Serial.print(" ");
   }
}

void loop() {
  // put your main code here, to run repeatedly:

}

実行結果

03

フラッシュメモリの書込みは、ページ単位(1024バイト)で行います。
データの書込みはワード単位(4バイト)で行います。

フラッシュメモリの256kバイト領域のアドレス範囲は、
   0x00000000 ~ 0x0003FFFF
です。

テストプログラムでは、ブートローダやプログラムを破壊しないよう、後半部に4kバイトを書き込んでいます。

このライブラリは、豊四季TinyBASICの移植時に利用する予定です。

2017年12月22日 (金)

STM32関連 「STM32HAL&SW4入門 Kindle版」を読んでみると..

STM32開発環境として最近 SW4STM32を使い始めました。
何か参考になる書籍をと思い、電子書籍「STM32HAL&SW4入門 Kindle版」購入しました。
(実際には、Kindle Unlimited: 読み放題対象の書籍なので、そのサービスにて購入)

03

内容的には、参考になる書籍なのですが、確実に間違っている内容もあります。
ケチをつけるつもりは無いのですが(う~ん、でも有料なので文句も言いたいなぁ..)、
間違った手順が広まると困るので、その点について記載します。

以下、インストールに関しての電子書籍「STM32HAL&SW4入門 Kindle版」 からの引用です。

2-2. 統合開発環境 インストール

 今回 は Windows 7 マシン に インストール する 場合 について 説明 し ます。

2-2-1. JavaSE インストール

  SW 4 STM 32 は Eclipse ベース の 開発環境 の ため、 JavaSE の インストール が 必須 です。 既に JavaSE が インストール さ れ て いる 場合 は 次項 へ 進ん で ください。 先 ほど、 ダウンロード し た SW 4 STM 32 の インストール を 開始 する と、 JavaSE が インストール さ れ て い ない 場合 は 自動的 に インストール が 中止 さ れ、 JavaSE の インストール が 促さ れ ます が、 今回 は 先 に JavaSE を インストール し ます。

実際には、JavaSEの事前インストールは不要ですし、インストールは中止されません。
実際に試してみると、途中でjavaのインストール確認画面が表示され、javaがインストール
されます。

02

インストール後は問題なくSW4STM32が起動出来ました。
インストールしたSW4STM32のフォルダを調べてみると、jreがインストールされてる
ことが分かります。

05

利用しているSW4STM32のEclipdeインストール情報を見てみると、
どのjava環境を利用しているかが分かります。

04_3

公式サイトのインストール手順にjavaを事前にインストールする記載は
ないので、素直に公式サイトの手順に従えばインストールでOKですね。

情報が正確かどうかは、改めて「一次ソース(公式サイト)」の確認が大事ですね。


«電子書籍「Mastering STM32」で勉強中 。。。。