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

AVR

2018年4月16日 (月)

ATtiny13AでI2C接続キャラクタLCDを利用する(4)

以前、挑戦ていた「ATtiny13AでI2C接続キャラクタLCDを利用する」を
Arduino 1.8.5 + MicroCore環境にてやってみました。

Dscn7826

キャラクタLCDは、秋月電子で購入したACM1602NI-FLW-FBW-M01を利用しています。
  ・I2C接続キャラクタLCD 16x2行白色バックライト付(ACM1602NI-FLW-FBW-M01)

以前コメントで頂いた、問題点の対応とRaulさんオリジナル版の
   Coding Laboratory - I2C on an AVR using bit banging

で指摘されている点の対応修正を行いました。
それと、可能な限り高速化をおこないました。

動いている様子

スケッチサイズは、MicroCoreのcore_settings.hにて利用しない機能を無効化することで
660バイトに抑えることが出来ました。

Ide

I2Cが使えると、電子工作の幅が広がりますね。

このスケッチは下記からダウンロードできます。
ダウンロード ATtiny13_I2CLCD.zip (4.7K)

2018年4月15日 (日)

ATtiny13Aで赤外線リモコン受信センサーを使う(2)

以前、「ATtiny13Aで赤外線リモコン受信センサーを使う」で行ったことを、
Arduino IDEATtiny13AMicroCoreパッケージの環境で動作確認しました。

以前のバージョンでは、micros() の精度が悪くて動作しなかったので、別パッケージを
利用していましたが、最新版では問題なく動作しました。

02

実行結果

01

ただしデフォルトでは、micros()は利用出来ないので、
core_settings.hの中のENABLE_MICROS の定義を有効にする修正が必要です。

スケッチ

//
// ATtiny13Aで赤外線リモコン受信
//
// ATMEL ATTINY13 / ARDUINO
// 利用パッケージ:https://github.com/MCUdude/MicroCore
// 注意: core_settings.h の#ENABLE_MICROS を有効にする必要あり
//
//                 +-V-+
// Reset      PB5 1|    |8 Vcc
// Tx         PB3 2|    |7 PB2 IR(IN)
// Rx         PB4 3|    |6 PB1
//            GND 4|    |5 PB0
//                 +----+
//

// シリアル通信定義
#define BAUD_RATE 38400
#include "BasicSerial3.h"
#define Tx      PB3 // (変更する場合、BasicSerial3.S修正が必要)
#define Rx      PB4 // (変更する場合、BasicSerial3.S修正が必要)

//IR受信定義
#define IR            PB2
#define IR_DDR        DDRB
#define IR_PORT       PORTB
#define IR_PININ      PINB
#define IRbitRead()   (IR_PININ&_BV(IR))
#define RC_RDH_TS     9000    // リーダコードOFF間隔  9ms判定用
#define RC_RDL_TS     3800    // リーダコードON間隔   4.5ms判定用
#define RC_BITLOW_TS  1000    // ビットデータON間隔   1.69ms判定用  
#define RC_TMOVER     8000    // タイムオバー

//
// 赤外線リモコンコード取得
// 4バイトのデータを返す
// CCCCDDdd
//    CCCC カスタムコード
//    DD   データコード
//    dd   データコードのビット反転(データチェック用)
// ただし、
//    リピートコードの場合  0
//    エラーの場合          0xFFFFFFFF
//  を返す.
//
uint32_t Read_IR() {
  uint8_t  repeat = 0;  // リピートコード検出フラグ
  uint32_t  dt    = 0;  // 赤外線リモコン読み取りデータ
  unsigned long t ;     // 信号長計測用

  // リード部の取得
  // 受信データはH/L反転で読まれる
  while(1) {
    while(IRbitRead());  // OFF検出受信待ち   
    t = micros();        // OFF検出時刻取得
    while(!IRbitRead()); // ON受信検出待ち 
    t = micros() -t;     // OFF->ONの時間間隔取得
    if (t > RC_RDH_TS) { // 9ms以上ならリーダコードとみなす
        t = micros();      // ON検出時刻取得
        while(IRbitRead());// OFF検出待ち
        t = micros() -t;   // ON->OFF時間間隔取得
        break;
    }
  }
  
  // データ部取得
  if (t < RC_RDL_TS) {
    // 0N->OFF がリピートコードの場合、データ取得はスキップ
    repeat = 1;          
  } else {
    // 0N->OFF がリダーコードの場合、データを取得
     for (uint8_t i = 0; i <32; i++) {  //32ビット分取得ループ
        // ビット開始待ち
        while(!IRbitRead());  // ON待ち
        t = micros();
        while(IRbitRead());  // OFF待ち
        t = micros() -t;
        if (t>RC_TMOVER)
          return 0xFFFFFFFF;  // エラー
        dt<<=1;
        dt |= (t>RC_BITLOW_TS) ? 1:0;     
    }
  }
  // ストップビットの待ち
  while(IRbitRead());  // OFF待ち  
  if (repeat)
    return 0;
  return dt;
}

// 文字列出力
void serOut(const char* str) {
   while (*str) TxByte (*str++);
}

// 整数を16進数で出力
void serOutHex(uint16_t h) {
  uint8_t c;
  for (int8_t i=12; i>=0; i-=4) {
    c = h>>i & 0xf; 
    c = c >9 ? c+'A'-10: c+'0';
    TxByte ((uint8_t)c);
  }
}

void setup() {
  IR_DDR &= ~_BV(IR);  // IRピンのみ入力設定する
}

void loop() {
  uint32_t rc =  Read_IR();  // IR受信
  if (rc) {
    if (rc != 0xFFFFFFFF) {
      serOut("custom="); serOutHex(rc>>16);serOut(" ");
      serOut("data=");serOutHex(rc>>8&0xff);serOut("\n\r");
    }
  } else {
    //serOut("Repeat\n\r");
  }
}

2018年4月14日 (土)

ATtiny13AでHC-SR04を使った距離計測

Arduino IDE 1.8.5の環境で、ATtiny13Aの開発が出来るようになったので、
試しに、HC-SR04を使った距離計測を実装してみました。

スケッチは、アルゴリズム雑記さんの下記の記事を参考にさせていただきました。
・【Arduino】超音波距離センサ(HC-SR04)の測定精度を向上(気温考慮)
  https://algorithm.joho.info/arduino/ultrasonic-distance-sensor-hcsr04-temp/

実装

09

実行結果

08

測定結果は、シリアルコンソールに出力します。
とりあえず、それらしく動いています。

スケッチサイズは、ジャスト1024バイト、ぎりぎり書き込めました。

09_2

スケッチ

(修正) 2018/04/14 ライブラリBasicSerial3をlibraliesに配置するように修正しました。

//
// 超音波距離センサHC-SR04を使った距離計測  
//
// ATMEL ATTINY13 / ARDUINO
// 利用パッケージ:https://github.com/MCUdude/MicroCore
//
//                 +-V-+
// Reset      PB5 1|    |8 Vcc
// Tx         PB3 2|    |7 PB2 
// Rx         PB4 3|    |6 PB1 ECHO
//            GND 4|    |5 PB0 TRIG
//                 +----+
//

// シリアル通信ライブラリ
//   AVR half-duplex software UART supporting single pin operation
//   http://nerdralph.blogspot.jp/2014/01/avr-half-duplex-software-uart.html
//
#define BAUD_RATE 38400
#include "BasicSerial3.h"

#define Tx    PB3 // (変更する場合、BasicSerial3.S修正が必要)
#define Rx    PB4 // (変更する場合、BasicSerial3.S修正が必要)

// HC-SR04
#define TRIG  PB0 // 出力ピン
#define ECHO  PB1 // 入力ピン
#define TEMP  180 // 温度補正 気温(℃)*10

// 整数を10進数で出力
void OutDEC(uint16_t d) {
int8_t n =-1;
  uint16_t v = 10000;
  for (uint8_t i=0; i<5; i++) {
    if (d >= v) {
      TxByte(d/v + '0');
      d %= v;
      n=i;
    } else {
      if (n!=-1||i==4) TxByte ('0');
    }
    v/=10;
  }
}
void setup() {
  pinMode(TRIG, OUTPUT);
  pinMode(ECHO, INPUT);
}

void loop() {
  // 超音波の出力終了
  digitalWrite(TRIG,LOW);
  delayMicroseconds(1);

  // 超音波を出力
  digitalWrite(TRIG,HIGH);
  delayMicroseconds(11);
 
  // 超音波を出力終了
  digitalWrite(TRIG, LOW);

  // 出力した超音波が返って来る時間を計測
  uint16_t d = (uint16_t)pulseIn(ECHO, HIGH, 200000);

  // 計測した時間と音速(気温を考慮)から反射物までの距離を計算
  uint16_t k=(3315+TEMP*6)/20; // 係数
  uint16_t v=d/100*k;
  uint16_t h=v/100;
  uint16_t l=v%100;

  // 計算結果をシリアル通信で出力
  OutDEC(h); TxByte('.'); OutDEC(l);
  TxByte('\n');
  delay(250);
}

シリアル出力はNerd Ralphさんが公開しているライブラリ、BasicSerial3 を利用しています。
  ・Nerd Ralph - AVR half-duplex software UART supporting single pin operation
   http://nerdralph.blogspot.jp/2014/01/avr-half-duplex-software-uart.html

   ライブラリをダウンロードし、BasicSerial3を\librariesに配置する必要があります。
   さらに、BasicSerial3.Sのピン指定を修正しています。
     #define UART_Tx 3
     #define UART_Rx 4   

スケッチの全ソースは、下記のサイトに置いています。
https://github.com/Tamakichi/Arduino_ATtiny13_HC_SR04

50円マイコン、容量の制約が厳しいですが、それなりに実装でき、十分楽しめますね。

Arduino 1.8.5環境でATtiny13Aを利用する

Arduino IDEのATtiny13A用MicroCoreパッケージを久しぶりにチェックしたところ、
いい感じになっているので、最新版1.03を利用してみました。

パッケージ公開サイト

  MicroCore - An optimized Arduino hardware package for ATtiny13

以前はmicros()等の精度が悪く、タイミングをとるプロトコル実装に使えず難儀したのですが、
更新履歴をみると改善されたみたいです。

早速Arduino 1.8.5にインストールしてみました。
インストールは公開サイトの「How to install」に従ってインストールしました。
ボードマネージャのURL追加の方法で行いました。
下記の1行を環境設定追加のボードマネージャのURLに登録し、

  https://mcudude.github.io/MicroCore/package_MCUdude_MicroCore_index.json

URL

ボーマネージャにて、最新版をインストールします。

01


インストール後の書込み確認

とりあえず、Lチカですね。
ATtiny13Aへのスケッチの書込みには、書き込み装置が必要です。
安価な書込み装置としては、次のものが利用されることが多いようです。
  ・USBasp
  ・USBtinyISP
  ・Arduino as ISP(Arduino Unoを使う方法)

今回はUSBtinyISPを利用しました。
USBaspも安くて良いのですが、Windows 10対応の署名付きのドライバーがないようで、
開発とサポートが止まっている感があります。

一方、USBtinyISPはAdafruit製もあり、ドライバー等もそこから入手出来ます。
  Adafruit - USBtinyISP :AVR programmer & SPI interface
  https://learn.adafruit.com/usbtinyisp/


書込みのための結線はUSBtinyISPMicroCoreのHPのMinimal setupを参考にしてしました。
Lチカ用の出力ピンは書込みに利用していないPB3を利用しました。

Dscn7818

スケッチ

void setup() {
  pinMode(PB3, OUTPUT);
}

void loop() {
  digitalWrite(PB3, HIGH);
  delay(500);
  digitalWrite(PB3, LOW);
  delay(500);
}
 

ピン指定は、ピン名称のPB0PB5がそのまま利用出来るようです。

04_2

ボード指定と書き込み装置を設定し、スケッチをコンパイル&書き込み実施。
とりあえず、上記の設定では問題なくLチカ出来ました。
ヒューズビットの設定も同時に行われているようです。


128kHzでのLチカで問題発生

次にクロックを落としての利用。
低速書込みでは過去の経験から色々と問題が発生するのですが、やはり問題発生。

スケッチの書込みは出来るのですが、ヒューズビットの設定が出来ていないようです。
本来ならスケッチの書込みと同時に、ヒューズビットの設定もおこなわれるはずです。

公式サイトを見ると、書込み装置として「USBtinyISP(slow)」を設定しないといけないようです。

試して見ると、書込み時に下記のエラーが発生しました。
  avrdude: Can't find programmer id "{upload.protocol}"

05

これのエラーは、"upload.protocol"が未定義ということです。

MicroCore
の設定ファイル
  C:\Users\ユーザー\AppData\Local\Arduino15\packages\MicroCore\hardware\avr\1.0.3\

を調べてみるとプロトコルの設定をprogrammers.txtでは"protocol"のidを使っているのに
platform.txtの定義では"upload.protocol"のidを参照しています。
idがミスマッチのようです。

このエラーの対応として、
  platform.txt内の"upload.protocol"を"protocol"に変換
idのエラーは解決できました。


しかし、新たなエラーが発生

06

このエラーはSCKのクロックタイミングがマズイようです。
USBtinyISPのSCKのクロックパルス速度ではATtiny13が応答出来ないようです。

対応としてprogrammers.txt-B32をところを-B64 -Fに修正

usbtinyisp.name=USBtinyISP (slow)
usbtinyisp.protocol=usbtiny
usbtinyisp.program.tool=avrdude
#usbtinyisp.program.extra_params=-B32
usbtinyisp.program.extra_params=-B64 -F

ついでに、platform.txt-B32設定の箇所を-B64に修正
下記はヒューズビットの書込みに関連する設定です。

tools.avrdude.erase.params.verbose=-v
tools.avrdude.erase.params.quiet=-q -q
tools.avrdude.erase.pattern="{cmd.path}" "-C{config.path}" -v -p{build.mcu} -c{protocol} -B64 {program.extra_params} -e -Ulock:w:{bootloader.unlock_bits}:m -Uhfuse:w:{bootloader.high_fuses}:m -Ulfuse:w:{bootloader.low_fuses}:m

tools.avrdude.bootloader.params.verbose=-v
tools.avrdude.bootloader.params.quiet=-q -q
tools.avrdude.bootloader.pattern="{cmd.path}" "-C{config.path}" {bootloader.verbose} -p{build.mcu} -c{protocol} -B64 -Ulock:w:{bootloader.lock_bits}:m

    (備考)
     programmers.txt、platform.txtはサクラエディタで開くとUTF-7と誤判断され、
    上書き保存すると、Arduino IDEで正しく読めなくなりました。
    明示的にUTF-8指定して保存する必要があります。

修正後、Arduino IDEを再起動して動作確認すると、問題無く書き込めるようになりました。

07



まとめ

・Arduino 1.8.5でMicroCoreパッケージを使うと、ATtiny13Aのアプリ開発が出来る
・書き込み装置は、USBtinyISPがおススメ
・9.6MHzのクロックを利用する場合は、デフォルトのままで利用しても問題ない
・クロックを変更して利用する場合、現段階では定義ファイルの修正が必要っぽい

問題はあるようですが、Arduino 1.8.5でATtiny13Aのアプリが開発できるのは有難いですね。
開発者さんに感謝です。


2018年4月 3日 (火)

Arduinoのブートローダーの有無による起動時間の違いについて

SNSにて、「Arduinoを電源を入れてからスケッチが実行するまでの時間を早くしたい」という
旨の話題があり、ブートローダーが無ければ早くなるのではと思い、調べてみました。

まずArduino Unoで採用しているブートローダー optibootのソースを見てみると、
(参考:Optiboot/optiboot https://github.com/Optiboot/optiboot

ホストからのスケッチ書き込み要求のためのシリアル通信の監視を1.5秒間行った後、
書き込まれているスケッチの実行を行っていることが分かりました。
(この監視する待ち時間をタイムアウト時間と呼ぶことにします)

実際に、次のようなスケッチを実行してリセットからD2ピンにLOW・HIGHが出力されるまでの
時間を計測してみました。

void setup() {
  pinMode(2,OUTPUT);
  digitalWrite(2,0);
  digitalWrite(2,1);
}

void loop() {
}

ブートローダーありの場合
ロジックアナライザでリセットピンD2ピンの出力を調べてみると次のような感じになりました。

Boot
(クリックすると拡大表示します)

リセットボタンを押して、離した後からD2ピンがLOW・HIGHのエッジ間は1.579秒でした。
まあ、だいたい予想通りの時間でした。


ブートローダー無しの場合
次に、同じスケッチをプログラマを使って直接書き込み、測定していました。
スケッチをブートローダー経由ではなく、プログラマで直接書き込む場合は、
Arduino IDEのメニュー [スケッチ]  - [書込み装置を使って書き込む]にて書き込みます。
この際、事前にメニュー [ツール] - [書込み装置]にて利用する書込み装置を指定しておきます。

リセットボタンを押して、離した後からD2ピンがLOW・HIGHのエッジ間は67ミリ秒でした。
ブートローダーのタイムアウト時間ない分、早く起動できていることがわかりました。

Noboot
(クリックすると拡大表示します)


1.5秒が長いか、短いかは微妙ですがブートローダーを利用しない場合は、
リセット後のスケッチの起動がタイムアウト時間を待たない分、早く起動できます。

ただし、スケッチを直接書き込んだ場合、ブートローダーは無くなってしまうため、
Arduinoとしてのお手軽さが無くなってしまいます。
とりあえず、1.5秒の待ちは我慢して利用したほうが良いですね。

ちなみに、スケッチの直接書込みはこんな感じで行っています。

aitendoのATTiny ISPシールドきっと [K-TINY-SLD]を利用しました。

Writing

上が書込み装置(スケッチ Arduino ISPを書込み)のArduino Uno互換機です。
下が書き込み対象のArduino Uno互換機です。




2018年3月18日 (日)

豊四季タイニーBASIC for Arduino機能拡張版 作成しました

取り組んでした「豊四季タイニーBASIC for MW25616L実験用表示モジュール」の作成を
もう少し汎用化して、Arduino Uno用にしました。

MW25616L実験用表示モジュールの対応はオプション機能としました。
(ttconfig.hの機能選択を修正すること対応)

01

  公開サイト
    豊四季タイニーBASIC for Arduino機能拡張版(+ VFD MW25616L対応)
    https://github.com/Tamakichi/ttbasic_MW25616L

  このプログラムはTetsuya Suzuki氏の   豊四季タイニーBASICをベースにしています。

   オリジナル版
     配布サイト https://github.com/vintagechips/ttbasic_arduino

  オリジナル版からの主な機能強化
    ・プログラム領域を256バイトから1024に拡張
    ・プログラムのセーブ・ロードに対応(内部EEPROM、I2C EEPROM)
    ・スクリーン制御(LOCATE、COLOR、ATTR、CLS)
    ・全角文字対応(シフトJISコード)
    ・ラインエディタ機能強化(カーソル移動、指定行の内容表示等)
    ・2進数、16進数表記サポート(`10101111、$ABCD)
    ・演算子の追加(ビットシフト演算や論理積・和など)
    ・IF文でELSEが利用出来る
    ・GOTO、GOSUBでラベルが使える(GOTO "LOOP")
    ・GPIO対応(デジタル入出力、アナログ入力、PWM、I2C、SHIFTIN、SHIFTOUT、PULSEIN)
    ・プログラム編集コマンドの追加(RENUM、DELETE)
    ・リセット時プログラム自動起動対応
    ・I2C RTC DS3231対応(DATE、DETDATE、GETDATE、SETDATE)

  BASIC言語のプログラム開発はターミナル上で行います。
  雰囲気的には、次の動画のような感じです。

   8チャンネルアナログ入力サンプルプログラム 
   

ターミナル上でもちょっとした、動きのある表示も可能ですね。

性能評価
さて、8ビットマイコン AVRでのTiny BASIC、性能的にはどうなんでしょう?
下記の3万回ループ処理を32ビット ARMマイコン搭載のイチゴジャムと比較してみました。

10 ?TICK()
20 FOR A=1 TO 30000
30 V=V+1
40 NEXT A
50 ?V
60 ?TICK()
測定結果 
  ・豊四季 Tiny BASIC Arduino(8ビット AVR)機能拡張版
    2.262秒
  ・イチゴジャム 1.2b56 最新版 (32ビット ARM)
   81.333秒 (ビデオ出力停止時 44.31秒)
  ・イチゴジャム ラズベリーパイ版 (BASIC RPi1.2.5 ラズパイ 2 900MHz)
   2.517秒
なんと、予測外の結果!  イチゴジャムの約36倍の処理能力でした。

イチゴジャム36台分の処理を1台でこなせる性能です。
ラズパイ2版 よりも早い!

追記 2018/03/23
  イチゴジャムをビデオ停止(VIDEO 0)した場合も測定してみました。
  それでも約20倍の処理能力でした。
「え、測定ミス? プログラムミス?」と思い何回も見直してしまいました。
AVRマイコンは確かに高性能ですが、同クロック 16MHz LPC1114(ARM cortex-M0)
よりは劣ると思います。


訂正(上記消し線の部分) 2018/03/20
  てっきりイチゴジャムは16MHzで稼働していると思っていたのですが、
  48MHzで動作しているようです。
  となると、16MHz Atmega328の3倍以上の処理能力があるはずでは..

豊四季タイニーBASIC for Arduinoは、ソース公開、分かり易さ重視です。
結構、無駄な処理をしています。
コマンドの処理を行う処理関数の検索を単純検索で行っており、コマンドの実行の都度、
最悪100回以上比較処理を行う等、特にパフォーマンス重視の作りではないです。
それでもイチゴジャムの約36倍..
非常に謎です..

追記

PLAY文による演奏デモ

演奏データは、下記のサイトに公開されているのもを流用させて頂きました。

・主体性の無いページ http://astr.me.land.to
   ねこふんじゃった! http://astr.me.land.to/tool/mabi/mml/nekof.htm
10 '猫ふんじゃった
20 PLAY "L16D+C+R8F+RF+RD+C+R8F+RF+RD+C+L8RF+RF+R"
30 PLAY "L16FRFRD+C+R8FRFRD+C+R8FRFRD+C+"
40 PLAY "L8RFRFRL16F+RF+RD+C+R8F+RF+RD+C+R8F+RF+RD+C+"
50 PLAY "L8RF+RF+RL16FRFRD+C+R8FRFRD+C+R8FR"
60 PLAY "L16FRD+C+L8RFRFRL16F+RF+RD+C+L8RF+RF+RF+RF+RF+RF+R"
70 PLAY "L16FRFRD+C+L8RFRFRFRFRFRFR"
80 PLAY "L16F+RF+RD+C+R8F+RF+RD+C+R8F+RF+RD+C+"
90 PLAY "L8RF+RF+RL16FRFRD+C+R8FRFRD+C+R8FRFRD+C+"
100 PLAY "L8RFRFRL16F+RF+R8.F+RC+C+D8C+8.FRF+"

2018年3月16日 (金)

中華製Arduino NanoのArduino Uno化を行う

中華製 Arduino Nano(実際はPro Mini+USBシリアル)をArduino Uno化するお話です。

次の写真は、USB-シリアル変換にCH340を採用している、中華製 Arduino Uno(左)のNano(右)です。

Dscn7718

Nanoの方は裏にCH340が搭載されています。

Dscn7719

さてこの2つ、実装形状は異なるものの、スペック的に同じです。
(3.3VレギュレータはCH340が内蔵しています)
しかし、サンプルのLチカスケッチ Blinkを書き込むと、利用出来るフラッシュメモリサイズが異なります。

中華版Arduino Unoの場合

Blink_uno

中華版Arduino Nano(実質 Pro mini + USBシリアルモジュール)の場合

Blink_nano

スケッチサイズは同じなのですが、Unoの方が1526バイト多く利用出来ます。

公式サイトの基本スペックでこの違いを確認すると、

Arduino Unoは、フラッシュメモリのうち512バイトがブートローダに利用されています。
03_2

Arduino NanoやMiniは2048バイトがブートローダに利用されています。
04

この違いが腑に落ちないので、ちょっと調べてみると、次のスレッドにヒントがありました。
Arduino Forum>Using Arduino>Microcontrollers>Optiboot on arduino Nan
Topic: Optiboot on arduino Nano

Arduino NanoやPro miniは製品的にはArduino Unoよりも古く、
Arduino Unoの前のバージョンのArduino Duemilanoveのベースになっています。
ブートローダもArduino Duemilanoveのものを利用しいます。

一方後発のUnoは、ブートローダがOptibootに変更されました。
NanoやPro miniもOptibootの利用が可能なのですが、Arduino Duemilanoveの
ブートローダが採用されたままになっています。
(このあたりは、Arduino ccの怠慢では..)

試しに、Namo(中身はPro mini)のブートローダーをArduino UnoのOptibootに
変更してみました。

ブートローダの書込みはArduino Unoを使ったArduinoISPを使用して行いました。
参考サイト:Arduino as ISP and Arduino Bootloaders

Dscn7715

結線はaitendoのATTiny ISPシールドきっと [K-TINY-SLD]を利用しました。
Arduino Unoにブートローダ書き込み用のスケッチ ArduinoISPを書き込み、
書込み装置に"Arduino as ISP"を選択して、
ボードをArduino/Genuino Unoを選択し、「ブートローダを書き込む」で書き込みます。

02

問題無く書き込めました。

ブートローダ書き込み後、ボード選択をArduino UnoとしてLチカのblinkスケッチを
書き込みます。

Dscn7716

これも問題無く、Lチカ出来ました。
これで、スケッチのサイズの上限を1536バイト増やすことが出来ました。

Arduino Uno用のスケッチの中には、スケッチが31,000バイトを超えて
NanoやPro Miniに書き込めないものがあります。
というか、私が今取り組んでいるArduino用のTiny BASICなのですが..OTz
このブートローダ変更でNanoに31,300のスケッチを書き込むことが出来ました。

05

折角なので、手持ちのNano strongという変則タイプのボードをArduino Uno化してみました。

Dscn7721_2

これで、ちっちゃいArduino Unoとして利用出来ます。

Dscn7722




2018年2月17日 (土)

Arduino Unoの内部EEPROMの利用(書込みの高速化)に関するメモ

Arduino Unoの内部EEPROMへのデータ書き込みに関するメモです。


先日「豊四季タイニーBASIC for MW25616L実験用表示モジュール」の実装で、
プログラムを内部EEPROMに保存しています。

方法としては、Arduino標準クラスライブラリEEPROM を使っています。
(Arduino リファレンス - EEPROM Library

  #include <EEPROM.h>

  // 内部EEPROMメモリへの保存
  topAddr = EEPROM_PAGE_SIZE*prgno;
  for (uint16_t i=0; i < SIZE_LIST; i++) {
    EEPROM.write(topAddr+i,listbuf[i]); 
  }

512バイトのデータ書き込みは、上のような感じでやっています。
クラスライブラリEEPROM は1バイト単位でしか書き込みが出来ないためか、
書込みに時間がかかります(感覚的に2,3秒くらい?)。

改善策はないかと、EEPROM.h のソースを読むと、
#include <avr/eeprom.h> を読み込んでおり、内部EEPROM用のAPIが存在することが
分かりました。

eeprom.hのソースを読むと、ブロック単位の書込みが行えるAPI等色々と用意されています。
内部EEPROM用のAPIを使う方法に修正しました。

  #include <avr/eeprom.h>

  // 内部EEPROMメモリへの保存
  topAddr = EEPROM_PAGE_SIZE*prgno;
  eeprom_update_block(listbuf,topAddr,SIZE_LIST);

書込みには下記のAPIを使っています。

  void eeprom_update_block (const void *__src, void *__dst, size_t __n);

試してみると、ほぼ瞬時に書き込みを行うことが出来ました。
コードも短くなり、フラッシュメモリの消費量も減りました。
内部EEPROM用のAPIは、#include <avr/eeprom.h> でヘッダーファイルをインクルード
することで利用出来ます。

クラスライブラリEEPROM を使うよりも、APIを使った方がお手軽に利用できます。

用意されているAPIはeeprom.hを直接覗いてみれば確認できます。
arduino-1.8.5\hardware\tools\avr\avr\include\avr\eeprom.h

2018年2月11日 (日)

豊四季Tiny BASIC for ArduinoのSRAM消費軽減対応

豊四季Tiny BASIC for Arduino(オリジナル版)のSRAM消費を軽減する修正を行ってみました。

Arduino UNOでは、SRAMが2kバイトしかありません。
オリジナル版のまま利用した場合、グローバル変数が1481バイト(72%)を利用しており、
残りが567バイトです。機能拡張するにはちょっと辛いです。

そこで、キーワード、エラーメッセージ等のグローバルな固定データをフラッシュメモリ上に
配置する修正をおこない、SRAMの消費を少々押さえました。

参考にしたサイト

・Arduinoで遊ぶページ - Arduino Uno編 - メモリの種類
・武蔵野電波 - Arduino 日本語リファレンス - PROGMEMとFマクロ
・Arduino - PROGMEM

良く知られているテクニックですが、
Arduino(AVRマイコン)でPROGMEMキーワードを使って変数の宣言を行うことで、
SRAMではなく、フラッシュメモリ上にデータを配置することが出来ます。

ただし、データの参照がちょっと面倒で、専用の参照を行う関数を利用する必要があります。
データ構造にも制約があり、キーワードテーブル等で使う2次元配列は対応されていません。
入れ子になる1次元配列を定義してから、その一次元配列のアドレスを配列として宣言して
2次元配列っぽい構造を作成します。

修正前のキーワードテーブル(オリジナル版よりソースを引用しています)

// Keyword table
const char *kwtbl[] = {
  "GOTO", "GOSUB", "RETURN",
  "FOR", "TO", "STEP", "NEXT",
  "IF", "REM", "STOP",
  "INPUT", "PRINT", "LET",
  ",", ";",
  "-", "+", "*", "/", "(", ")",
  ">=", "#", ">", "=", "<=", "<",
  "@", "RND", "ABS", "SIZE",
  "LIST", "RUN", "NEW"
};

修正したキーワードテーブル

// Keyword table
#define KW(k,s) const char k[] PROGMEM=s  // キーワード定義マクロ
KW(k000,"GOTO"); KW(k001,"GOSUB"); KW(k002,"RETURN");
KW(k003,"FOR"); KW(k004,"TO"); KW(k005,"STEP"); KW(k006,"NEXT");
KW(k007,"IF"); KW(k008,"REM"); KW(k009,"STOP");
KW(k010,"INPUT"); KW(k011,"PRINT"); KW(k012,"LET");
KW(k013,","); KW(k014,";");
KW(k015,"-"); KW(k016,"+"); KW(k017,"*"); KW(k018,"/"); KW(k019,"("); KW(k020,")");
KW(k021,">=");KW(k022,"#"); KW(k023,">"); KW(k024,"="); KW(k025,"<="); KW(k026,"<");
KW(k027,"@"); KW(k028,"RND"); KW(k029,"ABS"); KW(k030,"SIZE");
KW(k031,"LIST"); KW(k032,"RUN"); KW(k033,"NEW");

const char*  const kwtbl[] PROGMEM = {
 k000,k001,k002,
 k003,k004,k005,k006,
 k007,k008,k009,
 k010,k011,k012,
 k013,k014,
 k015,k016,k017,k018,k019,k020,
 k021,k022,k023,k024,k025,k026, 
 k027,k028,k029,k030,
 k031,k032,k033,
};

KW()マクロは、

const char k000[] PROGMEM="GOTO";
const char k001[] PROGMEM="GOSUB";

と定義するのを省略するのに利用しています。
テーブルの参照はちょっと面倒です。
キーワード比較を行う部分は、一旦、SRAM上のメモリーにコピーして利用しています。

char* pkw = 0; //ひとつのキーワードの内部を指すポインタ
char kwtbl_str[16]; // コマンド比較用

// オリジナル
pkw = (char *)kwtbl[i]; //キーワードの先頭を指す

// 修正版
pkw = strcpy_P(kwtbl_str, (char*)pgm_read_word(&(kwtbl[i])));

ARM cortex-M系のgccでは、constキーワードを付ければ、
フラッシュメモリ上に配置してくれて、かつ参照はSRAMと同等に行えるのと比べると
ちょっと面倒ですね。

とりあえず、この修正によりSRAM消費量を712バイト抑えることが出来ました。
SRAMは1279バイトほど余っているので、ちょっとした機能追加は出来ると思います。

もしかしたら、もっと効率の良いやり方があるかもしれませんが、これで良しとします。

Arduino IDE 1.8.15

ちょっといじった感じでは、オリジナル版と同じ感じで動いています。

ttbasic

この修正版は、下記にて公開いたいます。
https://github.com/Tamakichi/ttbasic_arduino_uno


2017年12月 9日 (土)

Arduino IDEのgccのバージョンの再認識

Arduino IDE 1.8.5の環境は、「C++11対応しているの?」とちょっと疑問に思い、試してみました。


サンプルスケッチ

//
// C++11対応の確認
//

void setup() {
  Serial.begin(9600);

  int x       {3};           // 新しい初期化形式
  int d[]     {0,1,2,3,4,5}; // 新しい初期化形式(配列)
  char *ptr   {nullptr};     // 新しい初期化形式、NULLの新しい形式
  uint16_t b  {0b11110001};  // 2進数対応

  Serial.print("x=");
  Serial.println(x,DEC);
  Serial.print("b=");
  Serial.println(b,BIN);
      
  for (auto a:d) {         // 新しい範囲指定形式 
    Serial.println(a,DEC);
  }
}

void loop() {

}

コンパイルは問題なく出来ました。実行結果も期待通りに動作しています。
う~ん、これは積極的に使っていった方がコーディング量も減り、不具合も回避できるかも..

01


裏付けを取るために、Arduinoのgccの環境周りを調べてみました。
まずは、利用しているgccのバージョンですが、
C:\Users\ユーザー\AppData\Local\Arduino15\staging\packagesの下には、
avr-gcc-4.9.2-atmel3.5.4-arduino2-i686-mingw32.zip
があります。

確認のため、インストールされているフォルダ \arduino-1.8.5\hardware\tools\avr\bin
のgcc++のバージョンを調べると4.9.2でした。

02

次にコンパイルオプション
\arduino-1.8.5\hardware\arduino\avr\platform.txt に定義されているコンパイルオプション
を調べると次の設定になっています。

compiler.c.cmd=avr-gcc
compiler.c.flags=-c -g -Os {compiler.warning_flags} -std=gnu11 -ffunction-sections -fdata-sections -MMD -flto -fno-fat-lto-objects


compiler.cpp.cmd=avr-g++

compiler.cpp.flags=-c -g -Os {compiler.warning_flags} -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threads

gcc4.9.2では機能的にc++11は完全対応であり、
cコンパイラはC11対応、C++コンパイラはC++11対応の指定が設定されています。

これでc++11の記述が堂々と利用出来ます。

(注意)
同じArduino IDE を利用していても、Arduino M0、DueのARMや、別のアーキテクチャのボードは、
利用しているコンパイラが異なります。この設定はAVRマイコン限定です。
他の環境については、別途調べる必要があります。

より以前の記事一覧