フォト
2019年6月
            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            
無料ブログはココログ

STM32

2019年6月 1日 (土)

Arduino STM32でキャラクタ液晶ディスプレイを使う

現在ちびちびと Arduino STM32 リファレンス 日本語版 を整備しているにですが、
今回、標準ライブラリの LiquidCrystalライブラリの部分を追記しました。

このライブラリはHD44780コントローラ(互換品含む)を使った
キャラクタ液晶ディスプレイ用のライブラリです。

動作確認として、実際にBluePillボードで制御してみました。

02_5  

利用したキャラクタ液晶ディスプレイ
1602A-V2aitendoでも販売されています)
   表示文字数 16桁×2行 、バックライト付きSTN液晶ディスプレイ
   Aliexpressでは、2ドル以下で購入出来ます。

久しぶりに、パラレル接続のキャラクタ液晶ディスプレイを使いました。
色々と忘れていて、コントラスト調整に戸惑ってしまいました。

今回はとりあえず、4ビットモードで利用しました。
動作電源が5Vのため、BluePillボードの5Vで利用可能なピンを利用しました。
下記がその結線です。

結線表

1602A-V2端子 接続先 備考
VSS BluePill - GND  
VDD BluePill - 5V  
V0 20kΩ半固定抵抗(GND接続) コントラスト調整用
RS BluePill - PA8 5Vトレラントピン利用
RW BluePill - GND LOW(GND)でWモード固定
E BluePill - PA9 5Vトレラントピン利用
D0 (未接続)  
D1 (未接続)  
D2 (未接続)  
D3 (未接続)  
D4 BluePill - PB6 5Vトレラントピン利用
D5 BluePill - PB7 5Vトレラントピン利用
D6 BluePill - PB8 5Vトレラントピン利用
D7 BluePill - PB9 5Vトレラントピン利用
A BluePill - 5V バックライトLED用
K BluePill - GND バックライトLED用


動作確認に利用したスケッチ

#include <LiquidCrystal.h>
#define LCD_RS  PA8
#define LCD_E   PA9
#define LCD_D4  PB6
#define LCD_D5  PB7
#define LCD_D6  PB8
#define LCD_D7  PB9
uint8_t font[]= {
  0b00001010,
  0b00001110,
  0b00011111,
  0b00010101,
  0b00011111,
  0b00011111,
  0b00001110,
 0b00000000,
};
LiquidCrystal lcd(LCD_RS,LCD_E, LCD_D4, LCD_D5, LCD_D6, LCD_D7);
void setup() {
  lcd.begin(16, 2);
  lcd.createChar(1,font);
  lcd.clear();
  lcd.cursor();
  lcd.blink();
  lcd.setCursor(0, 0);
  lcd.print("Hello, world!");
  lcd.setCursor(0, 1);
  lcd.print("\xc8\xba\x20\xc6\x20\xba\xdd\xca\xde\xdd\xdc\x01");
}
void loop() { }

スケッチは、LiquidCrystalクラスのインスタンス lcd をピン割り付けを指定して生成し、
begin()にて利用開始します。

4ビットモードだと結線数も少なく、割と簡単に制御出来ます。

LiquidCrystalライブラリ は、Printクラスの派生クラスのため、
Serialオブジェクトのような感じで、print()関数が利用出来ます。
数値等の出力も簡単に出来ます。

写真の 「ネコ ニ ホンバンワ」の半角カタカナ表示の部分は、
Arduino IDE環境の文字コードUTF-8コードのため、文字列をそのまま記述することはできません。
UTF-8で半角カタカナ1文字は、3バイトに置き換えられてしまい文字化けします。
ですので、文字コードを16進数表記で記述しています。

また、猫っぽいアイコンは、CGRAM領域にフォントデータを登録して表示しています。
CGRAM領域には、最大8文字(5x8ドット)登録することが出来ます。
lcd.createChar(1,font)にてその登録を行っています。
登録した文字は文字コード0~7にて指定出来ます。
(ただし、文字コード0は文字列終端子と被るのでwrite()で書く必要あり)

登録するフォントデータは8バイトですが、横5ドットは下位5ビットにて定義します。
縦は実際は7ドットのため、最後の8列目は0を設定します。

参考文献
 ・Adafruit Explore & Learn - Wiring a Character LCD
 ・HD44780U (LCD-II)

2019年5月29日 (水)

Arduino STM32のWS2812Bライブラリ(NeoPixel制御ライブラリ) その1

Arduino STM32には、WS2812Bライブラリ(NeoPixel制御ライブラリ)が、
標準で(最初から)用意されています。

このライブラリを使いたいと思い、ドキュメントが無いので
プログラムソースから日本語ドキュメントを作成しました。

Arduino STM32 リファレンス 日本語版
 ┗  WS2812Bライブラリ(NeoPixel制御ライブラリ)

ドキュメントを作成し、ライブラリの仕様を理解した上で
さっそく、BluePillボードで動作確認してみました。

ダメです。このライブラリ、まともに動作しません。
LEDが全く点灯出来ません。
色々とソースを修正して現時点で、やっとLED点灯するももの、
意図したとおりに制御出来ません。

01_8

このライブラリはSPIを使ってパルスを生成しています。
システムクロック72MHzを1/32に分周した2.25MHzのパルス幅 0.444μSを使っています。
  パルス幅 0.444μSは許容範囲、
  1ビットのデータは3パルス幅、
  1つのLEDのRGBデータが24ビット、
  1つのLEDは3×24=72パルス、
   SPIは8パルス(8ビット)なので9バイト分、

これなら1個のLED単位でなんとか制御出来そうなのですが、リセット信号のがマズいようです。
ソースを見た限り、リセット信号の送信がされていないみたいなのですが..

更新
1ビット分の3パルスが0.444μS×3= 1.332 μS、
1.25 μS を超えているのがマズいようです。仕様では±0.6μSは許容範囲なのですが駄目っぽい。
24ビット分のデータの前半と後半部分がちゃんと受信されていないようです。
データはGRB(緑、赤、青)の順番で送信するのですが、
1点ルーレット表示は赤しかちゃんと点灯しません。

現在、ライブラリ修正中です。

2019年5月25日 (土)

Arduino STM32のADC(アナログ・デジタル コンバータ)周辺の調査(2)

前回の続きです。

Arduino STM32で手っ取り早くADCを使うには、analogRead()を利用します。
このanalogRead()を利用した場合、変換に要する時間はどれ程なのでしょうか?

疑問に思い、調べてみました。

STM32F1xでは、次のパラメタの設定値が変換時間を決定します。
1)ADCCLK
      ADCのベースとなるクロックです。次の設定が可能です。
      ・システムクロックの1/2
      ・システムクロックの1/4
      ・システムクロックの1/6
      ・システムクロックの1/8

      Arduino STM32では、デフォルトではシステムクロックを1/6 に分周したクロックが設定されています。

 2)サンプリングタイム 
      サンプリングタイムはADCCLKサイクルを単位として、次の設定が可能です。
      ・1.5 × ADCCLK サイクル
      ・7.5 × ADCCLK サイクル
      ・13.5 × ADCCLK サイクル
      ・28.5 × ADCCLK サイクル
      ・41.5 × ADCCLK サイクル
      ・55.5 × ADCCLK サイクル
      ・71.5 × ADCCLK サイクル
      ・239.5 × ADCCLK サイクル

 
変換に要する時間は次の式で求めることが出来ます。
   Tconv = サンプリングタイム + 12.5 サイクル (サイクル)

デフォルトでは 55.5 × ADCCLK サイクル が設定されています。 

Blue Pillボードをシステムクロック 72MHzで利用した場合、
   ADCCLK  = 72MHz / 6 = 12MHz
   Tconv(サイクル)  =  12.5 + 55.5 = 68 サイクル 
   Tconv(μ秒)         =  1/12e6 × 68 × 1e6 =  5.67 μ(マイクロ)秒

となります。

実際にBluePillボードで測定してみました。

テスト用スケッチ

void setup() {
  Serial.begin(115200);
  pinMode(PA0,INPUT_ANALOG);
}
void loop() {
  uint32_t t1,t2;
  uint16_t v;  
 t1 = micros();  
 v = analogRead(PA0);  t2 = micros();  Serial.print("v=");Serial.print(v);  Serial.print(" t=");Serial.println(t2-t1);  delay(1000); }

実行結果

01_7

測定結果としては、おおよそ7~8μ秒 でした。
呼び出しのオーバーヘッド等もあるので妥当な値でしょう。

次に、変換時間が最短になるよう、ADCCLKとサンプリングタイムを変更してみました。
次の設定に変更します。
  ADCCLK                : システムクロックの1/2
  サンプリングタイム  : 1.5 × ADCCLK サイクル

この設定の場合、変換に要する時間は、
   ADCCLK  = 72MHz / 2 = 36MHz
   Tconv(サイクル)  =  12.5 + 1.5 = 14 サイクル 
   Tconv(μ秒)         =  1/36e6 × 14 × 1e6 =  0.38 μ(マイクロ)秒

変更したスケッチ

#include <libmaple/adc.h>
void setup() {
  Serial.begin(115200);
  adc_set_prescaler(ADC_PRE_PCLK2_DIV_2);
  adc_set_sample_rate(PIN_MAP[PA0].adc_device,ADC_SMPR_1_5);
  pinMode(PA0,INPUT_ANALOG);
}
void loop() {
  uint32_t t1,t2;
  uint16_t v;  
 t1 = micros();  
 v = analogRead(PA0);  t2 = micros();  Serial.print("v=");Serial.print(v);  Serial.print(" t=");Serial.println(t2-t1);  delay(1000); }

実行結果

02_4

測定結果としては、おおよそ2~3μ秒 でした。
デフォルト設定の実測値 7~8μ秒より、約5μ秒短縮出来ました。
計算値上でも5.3μ秒の短縮(5.67⇒0.38)ですので、オーバヘッドが2μ秒程度であることがわかります。
ですので、高速化時の測定結果 2~3μ秒(うちオーバヘッドが2μ程度)は妥当な値でしょう。

高速化のスケッチのADCCLK、サンプリングタイムの変更は、前回 ちょっこと触れた
 ・アナログ - デジタル変換(ADC)のサポート Analog to Digital Conversion (ADC) support(adc.h)
のAPI関数を利用しています。

analogRead() を使って、簡単なADCを行う分においては、
デフォルト設定と高速化でそれほど大きな差はないので、デフォルトのまま利用して問題ないと思います。
ただし、DMAを使って多チャンネルのADCを行う場合は、このパラメタの変更はかなり有効になってきます。

2019年5月24日 (金)

Arduino STM32のADC(アナログ・デジタル コンバータ)周辺の調査(1)

BluePillボード(STM32F103C8T6搭載) + Arduino STM32 の環境で、
ADC(アナログ・デジタル コンバータ)を使うためのライブラリを調べています。

STM32のADC機能はArduino Unoと比べるとかなり高機能・高性能なのですがその分、複雑です。
下図は「中容量及び大容量 STM32F101xx 及び STM32F103xx 高性能 ARM ベース32bit MCU(RM0008)」
の「10.3 ADC の機能詳細」からの引用です。雰囲気的に高機能だとわかると思います。

01_6
図を簡単に解説すると、
  ・最大16チャンネルをグループ化して不定期 or 周期的サンプリングが出来る(レギュラー・グループ)
     ADCx_IN0~ADCx_IN15(ただし、ADCコンバータは2機or3機なので同時にではなく各チャンネルを順次変換)
  ・上記のグループに割り込んでADCして最大4つのデータが別途保持できる(インジェクト・グループ)
  ・AD変換開始の様々なトリガーの設定が出来る
  ・サンプルレートの設定が出来る(ADCCLK×選択サイクル数、ADCCLKはシステムクロックの分周選択)
  ・AD変換完了の割り込みが利用可能(レギュラー・グループ 変換完了、インジェクト・グループ完了、アナログ閾値監視ウオッチドック)
  ・DMAを使って、CPUが介在しないマルチチャンネルサンプリングが出来る
  ・マルチチャンネルサンプリング において、各チャンネルに異なるサンプリング周期の指定が出来る 

ADCを使うにあたり、次のライブラリ or APIが用意されています。
1)analogRead()関数       ・・・  Arduino互換関数(ただし分解能は12ビット)
2)STM32ADCライブラリ  ・・・  多チャンネルサンプリング、DMA利用等の機能が利用できる
3)Analog to Digital Conversion (ADC) support(adc.h)  ・・・下位ライブラリ

これらは下記にてリファレンスマニュアルとまとめ中です。

 Arduino STM32 リファレンス 日本語版
    ┣ 1) analogRead()関数
    ┣ 2) STM32ADC 高機能アナログ - デジタル変換(ADC)ライブラリ
    ┗ 3) Analog to Digital Conversion (ADC) support(adc.h) アナログ - デジタル変換(ADC)のサポート

現在、2)STM32ADCライブラリを詳しく調査しています。
このライブラリは、ADCブログ図のかなりの部分をカバーしているライブラリで、
DMAを利用した高速多チャンネルサンプリング等をサポートしています。
中々、強力なライブラリです。

ただし、調査そ進めていくと、いくつかの不具合を見つけました。

現時点で見つけた不具合
 (1)コンパイル時、一部の関数のリンクに失敗する。
     その関数を呼び出すと、暴走(フリーズ?)する。
 (2)readVcc()、readTemp()で取得する値が正しくない。

このライブラリの実装、イージーミスが多く、テスト不十分のようです。

Blue PillボードではADCは2個、ADC接続端子は外部端子として10チャンネル、
内部端子は2チャンネル(内部温度センサ用、内部基準電圧測定用)があります。
このあたりの機能について、上記のライブラリと合わせてもう少し調べてまとめて行きたいと思います。


2019年4月 9日 (火)

豊四季Tiny BASIC for Arduino STM32用基板を頂きました

Facebookのお友達から、豊四季Tiny BASIC for Arduino STM32用の基板を頂きました (^_^)

Dscn9939

早速、手持ちのパーツをかき集めて組み立てみました。

Dscn9940

完成しました。
やはり専用基板があると、組み立てが楽ちんです。

Dscn9956

GROVE端子にてCardKeyBoard(PS/2インタフェース改造版)が直接接続可能です。
まずは、NTSC版のファームウェアを書き込んでの動作確認。
問題なく動作しました。

Dscn9951

次に、TFT版のファームウェアを書き込んでの動作確認。

裏面には3.2インチのTFT液晶の取り付けが可能です。
ひっくり返して、TFT版として利用出来ます。

Dscn9963

こちらも問題なく動作く動作しました。
TFTモジュール側のSDカードスロットでのSDカードの利用も可能です。
漢字フォントを読み込んで、日本語表示も問題無しです。

だだしこのキーボード、やはりちょっと入力しにくいです。
そこで以前製作した USB・PS/2 変換モジュール を思い出し、試しに使ってみました。

Dscn9959

Bluetoothドングルを使ってポケモンキーボードを接続して利用、
いい感じで文字入力出来ました。
USB・PS/2 変換モジュール  を活用することにします。
このケースを3Dプリンターで作ればもう少し小型化も出来ると思います。

う~ん、やはり自分で基板を製作したいですね。
いずれ、チャレンジしたいと思います。
頂いた基板、レイアウトやマルチに使える機能、大変参考になりました^^

2019年4月 1日 (月)

Arduino用 MML文演奏ライブラリの作成 その1

Arduino および Arduino STM32環境で利用できる
MML(Music Macro :ミュージック・マクロ・ランゲージ) 演奏ライブラリを作成中です。
ゲームなんかでも利用できるよう、バックグラウンド演奏にも対応予定です。

01

ハードウェア依存部分を切り離して利用できるようにと、
音を出す処理(実際は関数)をアタッチして利用する形式にしています。
これにより、Arduino、Arduino STM32やMIDI出力等に柔軟に対応できると思います。
02_1

ほぼ完成で、マニュアル作成および動作確認を残すのみです。
ArduinoTVoutとの併用も出来るか等、動作確認をやろうと思っています。

サンプルプログラム
Arduino STM32環境にてBluePillボードを使った単音演奏のサンプルプログラムです。

とりあえず、こんな感じです。
ココログのシステムリニューアルで、不具合が続出で<pre>での
プログラムソースの表示がおかしくなります。

<pre></pre>の中に<br>が追加されたりと、分断されたりと
<pre></pre>ブロックを認識出来ないようです。
システム不具合が改善されてから、改めて修正します。

直接挿入は諦めて、GitHubのgistを使ったソース挿入に変更しました。

2019年3月21日 (木)

BluePillボードで4桁7セグLEDの制御

先日のArduino STM32用タイマー割り込みライブラリを使って、
BluePillボードを使って、4桁7セグLEDをダイナミック点灯にて制御してみました。

Dscn9818

動いている様子



以前、秋月電子で入手して放置していた 4桁7セグLEDはOSL40562-IG を利用しました。
このOSL40562-IGアノードコモンでVFが3.3Vと高く 少々使いにくです。

  ダイナミック接続4桁高輝度緑色7セグメントLED表示器 アノードコモン アノード共通接続 OSL40562-IG

  01


03

とりあえず、次のような回路で駆動させてみました。

02

BluePillボードの5Vトレラント対応のピンを使って駆動させます。
各LEDに流れる電流は5mA程度にしています。
I = (5[V] - Vf[V] ) / 330[Ω]  = (5 - 3.3) /330 = 0.00515[A] ≒ 5[mA]

各桁セグメントDIG1 ~ DIG4は、LED8個分の40mAが流れます。 
BluePillボードでは20mAまでしか流せないため、PNPトランジスタ 2SA1015を使って
駆動させるようにしました。

スケッチ
//
// 4桁高輝度緑色7セグメントLED表示器(アノードコモン) OSL40562-IG の制御
// 2019/03/17 たま吉さん 
// 利用パーツ
//  BluePillボード
//  4桁7セグメントLED  OSL40562-IG x 1
//  桁制御用トランジスタ    2SA1015L-GR x 4
//  LED電流制御用抵抗       330Ω x 8
//  トランジスタベース抵抗  10kΩ x 4
//

#include "TimerEvent.h"

// タイマー割り込み管理
TimerEvent ticker;     
#define REFTIME 4

// デジタルピンの定義
#define DIG1  PB12
#define DIG2  PB13
#define DIG3  PB14
#define DIG4  PB15
#define SEGA  PB3
#define SEGB  PB4
#define SEGC  PB6
#define SEGD  PB7
#define SEGE  PB8
#define SEGF  PB9
#define SEGG  PB10
#define SEGP  PB11

// 桁表示ON・OFF
#define DIG_ON   0
#define DIG_OFF  1

// セグメント表示ON・OFF
#define SEG_ON   0
#define SEG_OFF  1

// セグメントビット定義
#define BIT_A 0b10000000
#define BIT_B 0b01000000
#define BIT_C 0b00100000
#define BIT_D 0b00010000
#define BIT_E 0b00001000
#define BIT_F 0b00000100
#define BIT_G 0b00000010
#define BIT_P 0b00000001

// フォントの定義
const uint8_t font[12] = {
  BIT_A|BIT_B|BIT_C|BIT_D|BIT_E|BIT_F,       // 0
  BIT_B|BIT_C,                               // 1
  BIT_A|BIT_B|BIT_G|BIT_E|BIT_D,             // 2
  BIT_A|BIT_B|BIT_G|BIT_C|BIT_D,             // 3
  BIT_F|BIT_B|BIT_G|BIT_C,                   // 4
  BIT_A|BIT_F|BIT_G|BIT_C|BIT_D,             // 5
  BIT_A|BIT_F|BIT_E|BIT_D|BIT_C|BIT_G,       // 6
  BIT_A|BIT_B|BIT_C,                         // 7
  BIT_A|BIT_B|BIT_C|BIT_D|BIT_E|BIT_F|BIT_G, // 8
  BIT_A|BIT_B|BIT_C|BIT_D|BIT_F|BIT_G,       // 9
  0,                                         // ブランク
  BIT_G,                                     // -
};

// 桁制御ピン
const uint8_t pin_dig[4] = {
  DIG1, DIG2, DIG3, DIG4,
};

// セグメント制御ピン
const uint8_t pin_seg[8] = {
  SEGA, SEGB, SEGC, SEGD, SEGE, SEGF, SEGG, SEGP,
};

// 表示用データ
volatile uint8_t digit[4];

// タイマー割り込み呼び出し関数
void dinamic_update() {
  static uint8_t cnt = 0;
  for (uint8_t i = 0; i < 4; i++)
    digitalWrite(pin_dig[i], DIG_OFF); 
  for (uint8_t i = 0; i < 8; i++)  
     digitalWrite(pin_seg[i], digit[cnt] & (0x80>>i) ? SEG_ON:SEG_OFF);
  digitalWrite(pin_dig[cnt], DIG_ON); 
  cnt++; if (cnt == 4) cnt = 0;
}

// データのクリア
void cls() {
  digit[0] = 0; digit[1] = 0; digit[2] = 0; digit[3] = 0;
}

// 数値の設定
void setNumber(uint16_t n, uint8_t dt = 0) {
  if (n>9999)
    return;

  cls();
  uint8_t dec = 0;
  // 4桁目
  if (n >= 1000) {
    digit[0] =font[ n / 1000]; n = n % 1000; dec = 1;
  }
  // 3桁目
  if (n >= 100) {
    digit[1] = font[n / 100]; n = n % 100; dec = 1;
  } else if (dec) {
    digit[1] = font[0];
  }
  // 2桁目
  if (n >= 10) {
    digit[2] = font[n / 10]; n = n % 10; dec = 1;
  } else if(dec) {
    digit[2] = font[0];
  }
  // 1桁目
  digit[3] = font[n];

  // 小数点
  if(dt && dt <=4) {
    digit[4-dt] |= BIT_P;
  }
}

void setup() { 
  //  桁ピンの初期化
  for (uint8_t i = 0; i < 4; i++) {
    pinMode(pin_dig[i], OUTPUT_OPEN_DRAIN);
    digitalWrite(pin_dig[i], DIG_OFF);
  }

  //  セグメントピンの初期化
  for (uint8_t i = 0; i < 8; i++) {
    pinMode(pin_seg[i], OUTPUT_OPEN_DRAIN);
    digitalWrite(pin_seg[i], SEG_OFF);
  }

  // 表示データの初期化
  for (uint8_t i = 0; i < 4; i++) {
    digit[i] = 0;
  }

  // LEDダイナミック点灯用割り込み設定
  ticker.set(REFTIME, dinamic_update);  // REFTIME間隔で dinamic_update()を呼び出す
  ticker.start();                       // タイマー割り込み実行開始
}

void loop() {
  static uint16_t n = 0;
  setNumber (n,millis()%1000>500?1:0);
  delay(100);
  n++; if (n>9999) n = 0;
}

タイマー割り込みは4m秒間隔で実行させています。
一回の割り込みで4桁のうちの1つを表示させています。
全桁更新周期は 4m秒 x 4 = 16m秒 ≒ 1/60秒 です。
これは、人間の目がちらつきを感じない周期です。
これ以上遅くすると、ちらついて見えます。

電圧を5Vではなく、3.3Vにしても問題なく点灯出来ました。
VF 3.3Vとありますが、実際はもっと低い値のようです。

2019年3月17日 (日)

Arduino STM32用タイマー割り込みライブラリを作成しました

Arduino STM32用のタイマー割り込みライブラリを作成しました。

・Arduino STM32用 簡易タイマー割り込みライブラリ (Tamakichi/STM32_TimerEvent)
  https://github.com/Tamakichi/STM32_TimerEvent

Arduino STM32では、最初から強力なタイマー割り込みライブラリがあるのですが、
少々設定が面倒なので、もう少しお手軽に使えるライブラリを作成しました。
(正確には、ラッパークラスライブラリですね)

次のような感じで使います。
BluePillボード上にあるLEDを0.5秒間隔で点滅するスケッチです。
#include "TimerEvent.h"

#define LED_PIN  PC13 // LEDピン

// タイマー割り込み管理
TimerEvent ticker;     

// タイマー割り込み呼び出し関数
void handle_timer() {
  static uint8_t sw = LOW;
  sw = !sw;
  digitalWrite(LED_PIN, sw);      // LEDの制御
}
 
void setup() {
  pinMode(LED_PIN, OUTPUT);
  ticker.set(500, handle_timer);  // 0.5秒間隔で handle_timer()を呼び出す
  ticker.start();                 // タイマー割り込み実行開始
}

void loop() {

}
 

設定できる割り込み間隔は 1ミリ秒 ~ としています。
利用するハードウェアタイマを明示的に指定することが出来ます。

次のような感じで複数のタイマー割り込みを同時実装することも出来ます。
また、割り込み優先度を指定することが出来ます。

// タイマー割り込み管理
TimerEvent ticker1(Timer1);
TimerEvent ticker2(Timer2);
TimerEvent ticker3(Timer3);
TimerEvent ticker4(Timer4);
・・・

ticker1.set(100, handle_timer1); ticker1.setPriority(14);
ticker2.set(200, handle_timer2);
ticker3.set(400, handle_timer3);
ticker4.set(800, handle_timer4);
・・・

ticker1.start();
ticker2.start();
ticker3.start();
ticker4.start();

上記では、ticker1の優先度をticker2 ~ ticker4 よりも上げています。
ticker1は、ticker2 ~ ticker4の割り込み処理実行中に更に割り込んで実行できます。
ticker1の割り込み実行中は、ticker2 ~ ticker4の割り込み実行は保留されます。

割り込み優先度の設定については、シリアル通信、I2C、ピン変化等の割り込み優先度も
考慮して設定する必要があります。

割り込み優先度は0~15の16レベルがあり、
デフォルトでは、すべての割り込み優先度は最低の15が設定(0が最優先)されています。
ただし、同一の優先度の場合は、割り込みベクター番号が小さいほど優先度が高いです。

このたりの詳細については、Arduino STM32の低レベルAPI nvic.h が参考になると思います。
Nested Vector Interrupt Controller (NVIC) support(nvic.h)


元祖 AVR版Arduinoでも割り込み機能はあるのですが、
優先度が固定のため、特定の割り込み処理中でI2C通信が出来ない等、
(I2Cの割り込み優先度は最低レベルに近い)
多重割り込みを使う場合、場合によっては色々と難儀しました。

その点、ARM cortex M3 の割り込み機構 NVIC はかなり強力で自由度があり
使いやすいです。

2019年3月 6日 (水)

I2Cインタフェースの小型キーボードを試してみる

AliexpressにてM5Stack用のI2Cインタフェースのキーボードを見つけ、入手しました。

  M5Stack Official CardKB Mini Keyboard Unit MEGA328P GROVE I2C

  02

CardKBに関する情報
  ・M5Stack - docs CardKB
  ・Github M5-ProductExampleCodes/Unit/CARDKB/
  ・frame and key-top for M5Stack CardKB


送料がちょっと高めで、1個だけ購入すると割高のため2個購入しました。
M5Stack公式製品なので、そのうちスイッチサイエンスでも販売されるかもしれません。


到着した製品

Dscn9721

ボード

Dscn9722

ATmega328Pが乗っています。ボードの左下にISP用の端子用のランドがあります。

公開されているファームウェアのソースを見ると、Arduinoでベースのようです。
水晶振動子が無いので、内部RC発信8MHzっぽいです。

とりあえず、豊四季Tiny BASIC for STM32環境でI2C接続で使ってみました。

Dscn9729

コネクタがGROVE仕様のため、長足のシングルピンソケットを加工して、
ブレッドボードでつかえるようにしました。
2mmピッチなので、微妙にピンを曲げています。

Dscn9726 Dscn9727

とりあえず、動作しました。
ただし、豊四季Tiny BASICのI2CR()関数に不具合を見つけ、豊四季Tiny BASICを
少々、修正しました。

01

3.3Vで動作しました。
I2Cのバスクロックは100kHz、400kHzとも試してみましたが動作しました。

ボード上にNeoPixel(LED)が乗っているのですが、
シフトキーのロック、シンボルキーのロック等の状態を、色や点滅で状態を教えてくれます。
文字入力は意外とストレスを感じないですが、タクトスイッチのボタンが固いのが残念です。

ファームウェアがArduinoなので、改造してPS/2インタフェースに変更できるかもしれません。


追記

IchigoJamでもI2Cインタフェースで利用出来ました。

Dscn9733

2019年2月18日 (月)

入手したボード用 Arduino STM32用ブートローダの作成

AliexpressにてSTM32F103RCT6搭載miniボード(写真の上のボード)を
入手したのですが、Arduino STM32環境で使うためのブートローダが
用意されていないため、ソースからビルドして用意しました。

その時のまとめメモです。

ブートローダの作成はWindows 10環境にて行いました。

Dscn9600


ボードの調査


ボート別にたくさんのブートローダが用意されていますが、基本的な相違は、
  1) ボード上のLEDの制御用ポート番号
  2) 永続モード設定用のボタン用のポート番号

です。この修正版を用意すれば良いわけです。

今回入手したボードは、2つのLEDがPC0、PC1に接続、1つのボタンがPC2に接続しています。

 

02

 

ボタンは、押すとLOWになるタイプです。

03

 

そこで、ブートローダで利用するLEDをPC0、ボタンをPC2として利用することにします。

ブートローダの作成には、下記の情報が大変参考になりました。

ただし、参考にした情報はLinux環境でのビルドのため若干方法が異なります。

参考サイト
   ・Visuariddim - STM32Duino Bootloaderの自前ビルドとか


ブートローダのビルドに必要なものの用意

1)Arduino STM32ブートローダのソースファイル

  STM32duino-bootloader
  https://github.com/rogerclarkmelbourne/STM32duino-bootloader

上記からダウンロードまたは、gitコマンドでcloneを作成します。
ここでは、解凍したフォルダを D:\work\STM32duino-bootloader とします。

2)makeコマンド

  Cygwinのmake.exeを利用しました。
  ※Cygwinのインストール時にmakeパッケージのインストール指定が必要です。   

04

インストールしたCygwin環境のコマンドパスを調べておきます。
ここでは、C:\cygwin64\bin とします。


3)arm-none-eabi-gcc 4.8.x

  Arduino IDEの環境のものを利用しました。   

  arm-none-eabi-gccの絶対パスの調査

05

Arduino IDEの環境設定画面下の赤枠部分のパスをクリックすると、
エクスプローラーが起動します。
そこから、フォルダpackagesに下記のパスがあることを確認します。
\packages\arduino\tools\arm-none-eabi-gcc\4.8.3-2014q1\bin\

エクスプローラーのアドレスバーの絶対パスをコピペして、
D:\work\STM32duino-bootloader\ の下に
環境設定用のバッチコマンド makeenv.bat をメモ帳で作成します。

makeコマンドへのパスが通っていない場合、
一緒にmakeコマンドのパスの設定します。

makeenv.bat の中身

PATH=%PATH%;C:\Users\Owner\AppData\Local\Arduino15\packages\arduino\tools\arm-none-eabi-gcc\4.8.3-2014q1\bin;C:\cygwin64\bin; 

※ アップデート等により、4.8.x以降のパス名称は異なる可能性があります。

ファイルの修正

新しいボード用のブートローダ作成にために、
D:\work\STM32duino-bootloader\にあるMakefile、config.h を修正します。

追加は面倒なので、既存のgeneric-pg15 用の定義をgeneric-pc0に変更します。

1)Makefileの修正
  メモ帳で開いて、置換機能でpg15 ⇒ pc0、PG15 ⇒ PC0に置換して保存します。

06_2

07

2)config.hの修正

メモ帳でconfig.hを開き、PG15で検索して該当する定義を参照します。

08

次に、下記の修正をします。
ターゲット
  PG15 ⇒ PC0
LED
  GPIOG ⇒ GPIOC
  15 ⇒ 0
Button
  14 ⇒ 2
  1 ⇒ 0

この修正は、LEDがPC0(1でON)、ボタンにPC2(0でON)を割り当てるためです。

09

保存してメモ帳を閉じます。


ブートローダのビルド

コマンドプロンプトを起動し、 D:\work\STM32duino-bootloader  フォルダに移動し、
作成しておいた環境設定バッチコマンドを実行します。

さらに、makeコマンドを実行します。
ターゲットは generic-pc0 を指定します。

> make generic-pc0

12

ビルド処理が実行されて、程なく genenic_boot20_pc0.bin が
D:\work\STM32duino-bootloader\bootloader_only_binaries\ に
作成されます。

13

 

 

 


ボードへのブートローダの書き込み

 

ST-Linkを使って書き込みを行いました。

 

 

 

 

 

Dscn9661

ボードを接続し、STM32 ST-Link Utilityにて、genenic_boot20_pc0.bin を読み込んで
書き込みを行いました。

 

14

ブートローダの書き込み後は、USB経由でのスケッチ書き込みです。

ボードを永続モード(スケッチ書き込み待ち状態)にて、最初のスケッチを書き込ます。
永続モードの設定は、ユーザーボタンを押したまま、リセットボタンを押します。
LEDが点滅して永続モードの状態を示します。

 

16

スケッチも問題なく書き込めました。

 

Dscn9662

スケッチ書き込み後は、COMポートも認識出来ました。

以後、このボードはArduino IDE環境でUSB経由でスケッチが書き込めます。
ブートローダのコンパイルはLinux環境の方が楽ですね。

 

より以前の記事一覧