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

AVR

2024年9月15日 (日)

NeoPixel(WS2812B)の制御 その5

NeoPixel(WS2812B)の制御 その4」に関して質問がありました。
流通しているNeoPixelマトリックの配列には様々なタイプがあるようです。

そこで、前回のスケッチをもう少し見直して、 XYtoNo()関数の修正でレイアウトの差異を吸収できるよう、修正しました。
スクロール処理を行うNeoScroll()関数を、処理速度を少々犠牲にしてXYtoNo()を使って処理を行うようにしました。
試した感じでは、処理速度的には問題ないようです。

修正版 

■ 修正の補足
 NeoScroll()関数は、縦x横のドットデータを左に1ドットずらす処理を行っています。
 従来版は速度重視のためmemmove()、memset()を使っていたのですが縦並びのLEDに対応出来ません。
 そこで XYtoNo()を使てのデータ操作に修正しました。

 これにより、XYtoNo()関数にてパネルのレイアウトに対応するだけで差異を吸収できます。

 文字の縦の表示開始位置は、次の定数を変更することで調整出来ます。
  #define Y_OFFSET 0 // フォントの縦先頭位置  

ここで、「NeoPixel(WS2812B)の制御 その4」でZuhiさんがご質問されました、
横32ドットx縦8ドットで「パネルの左上起点に下上になっている」パネルについて対応してみましょう。
256個のLEDが数珠つなぎ(0~255)になっているのですが、並びは次の感じだと思われます。
左上が起点で↓向きでスタート、8個目で↑向きに折り返しで256個がつながっています。
Photo_20240914203101
上記において、任意の(x,y)の位置のLEDを操作するためには、そのLEDの先頭からの番号が必要となります。
計算式としては、次のようになります。

xが偶数の場合:
 no = x * 8 + y
xが偶数の場合:
 no = x * 8 -y + 8 -1

定数を踏まえると..
xが偶数の場合:
 no = x * PXCEL_H + y
xが偶数の場合:
 no = x * PXCEL_H -y + PXCEL_H - 1
となります。

修正版のスケッチをZuhiさんのパネルに対応する場合、以下の修正でいけると思います。
 ①定数の変更

  #define PXCEL_W 32 // 横ピクセル数
  #define PXCEL_H 8  // 縦ピクセル数


 ②XYtoNo()の変更
  noを参考にして修正すると、関数内のreturn文を下記のように修正します

  return x&1 ? x*PXCEL_H-y+PXCEL_H-1: x*PXCEL_H+y; // 左上起点下上方向並び


 (※修正版にコメント化して記述しています)

横32ドットx縦8ドットパネルは所有していないので、動作確認出来ないのですが、たぶん大丈夫でしょう(;^_^
(うまくいかない場合、連絡ください)

2018年10月30日 (火)

Arduino用SJIS漢字フォントライブラリ SDカード版を作成しました

以前作成した Arduino用のUTF-8版の漢字フォントライブラリ SDカード版をベースにして
シフトJIS版の漢字フォントライブラリ SDカード版を作成しました。

指定したシフトJISコードに対応する漢字フォントデータを取得するAPIを提供します。
漢字フォントは8、10、12、14、16、20、24ドットのサイズの利用が可能です。
フォントデータはSDカード上に配置して利用します。

公開ページ
・Arduino用SJIS漢字フォントライブラリ SDカード版
  https://github.com/Tamakichi/Arduino-SJISKanjiFont-Library-SD

ライブラリの利用にはSDカードが必要となります。

02_2

02

ライブラリに添付しているサンプルプログラム

// SJIS版フォントライブラリ利用サンプル
// 作成 2018/10/27  by Tamakichi
//

#include "SDSfonts.h"

// ビットパターン表示
// d: 8ビットパターンデータ
//
void bitdisp(uint8_t d) {
  for (uint8_t i=0; i<8;i++) {
    if (d & 0x80>>i) 
      Serial.print("#");
    else
      Serial.print(".");
  }
}

//
// フォントデータの表示
// buf(in) : フォント格納アドレス
//
void fontdisp2(uint8_t* buf) {
  uint8_t bn= SDSfonts.getRowLength();                // 1行当たりのバイト数取得
  Serial.print(SDSfonts.getWidth(),DEC);             // フォントの幅の取得
  Serial.print("x");      
  Serial.print(SDSfonts.getHeight(),DEC);            // フォントの高さの取得
  Serial.print(" ");      
  Serial.println((uint16_t)SDSfonts.getCode(), HEX); // 直前し処理したフォントのコード表示

  for (uint8_t i = 0; i < SDSfonts.getLength(); i += bn ) {
      for (uint8_t j = 0; j < bn; j++) {
        bitdisp(buf[i+j]);
      }
      Serial.println("");
  }
  Serial.println("");
} 

//
// 指定した文字列を指定したサイズで表示する
// pSJIS(in) SJIS文字列
// sz(in)    フォントサイズ(8,10,12,14,16,20,24)
//
void fontDump(char* pSJIS, uint8_t sz) {
  uint8_t buf[MAXFONTLEN]; // フォントデータ格納アドレス(最大24x24/8 = 72バイト)

  SDSfonts.open();                                   // フォントのオープン
  SDSfonts.setFontSize(sz);                          // フォントサイズの設定
  while ( pSJIS = SDSfonts.getFontData(buf, pSJIS) ) // フォントの取得
    fontdisp2(buf);                                 // フォントパターンの表示
  SDSfonts.close();                                  // フォントのクローズ
}

void setup() {
  Serial.begin(115200);                   // シリアル通信の初期化
  SDSfonts.init(10);                        // フォント管理の初期化
  Serial.println(F("sdfonts liblary"));
  char str[] = {0x7a,0x7b,0x7c,0x7d,0x7e,0xa2,0xb1,0xb2,0xb3,0};// z{|}~「アイウ
  fontDump(str,14);
  fontDump("\x82\xa0\x82\xa2\x82\xa4\x82\xa6\x82\xa8",16);//あいうえお
  fontDump("\x82\xa0\x82\xa2\x82\xa4\x82\xa6\x82\xa8",20);//あいうえお
  fontDump("\x8d\xe9\x8B\xCA\x81\x99\x82\xB3\x82\xA2\x82\xBD\x82\xDC", 24); // 埼玉☆さいたま
}

void loop() {
}

実行結果

01


このライブラリは豊四季Tiny BASIC for Arduino STM32に組み込むために作成しました。
TFT、NTSC、OLED画面に日本語文字列を表示したいと思っています。
BASICにてアドベンチャーゲーム的なものが作れないかなぁっと。

Arduino IDEでは、文字列にUTF-8を利用しているため、
このシフトJIS版でのフォントデータの扱いはちょっと面倒です。
通常は、UTF-8版を使った方が良いでしょう。

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

より以前の記事一覧