まごころせいじつ堂

浜町庄金 研究開発  マイコンで遊んでばっかりで

TI Stellaris LM4F120 LaunchPad メモ

TIから5米ドルを切るマイコン開発キット再び、今度はCortex-M4Fマイコンを搭載

TI storeからStellaris LM4F120 LaunchPad届いた。$4.99。桁間違えてるんじゃないのという安さ。
付属品はマイクロUSBケーブル。MSP430版に入っていたステッカーは残念入ってない。
基板はMSP430版とは違い水晶もコネクタも半田付け済み。左右のコネクタは少しずらしてあるがArduinoのシールドが使えるわけではない。
3色発光のRGB-LEDとユーザ用のタクトスイッチSW1,SW2がある。給電はデバッグ側のUSBポートとデバイス側のポート、スイッチで選択する。とりあえず接続してスイッチを長押ししたりするとLEDの色が変わったり点滅したりする。
2012LM4F120LaunchPad

Stellaris® LM4F120 LaunchPad Evaluation Kit EK-LM4F120XL

LM4F120H5QR

これによるとLM4F120H5QRはCortex-M4F(浮動小数点演算付き)、80MHz、Flash256KB/RAM32KB、シリアル/RTC/ADC/I2C/SPI付き。USBはデバイスモード。※共立エレショップではUSB-OTGとあるがたぶん間違い。 

EK-LM4F232 Firmware Development Package SW-EK-LM4F232

今のところ開発環境はWindowsのみ。

※日本語ページがあった
http://www.tij.co.jp/tool/jp/ek-lm4f120xl

温度センサLM35DZを複数Arduinoに繋いだ時のトラブル

※プログラムに誤りがありました。ADC0〜ADC5までなのにADC6相当を読んでいた。
続き↓
LM35DZを複数つないだ時の問題 お詫びとハードでの解決


環境:
Arduino UNO R3,Leonardo / IDE 1.0.1

 前回、LM35DZの動作確認をしたのでArduinoのアナログポートに複数個接続してみた所、測定値が時々跳ね上がる現象が発生。
LM35DZはA0〜A5に約50cmのケーブルで接続。パソコン筐体内の複数箇所の温度を測定するつもりで作った。

温度センサを同じ所にまとめて動作確認をした時に以下の現象が発生。

現象:時々、A0ポートに接続したLM35DZが6℃、A5ポートに接続したのが330℃を表示。測定間隔は約1分。
最初、Arduino Leonardo(ATmega 32U4)で確認したがArduino UNO R3(ATmega328)でも再現。こちらで調査開始。
アナログポートに接続したLM35DZを入れ替えても現象同じ。センサ個別についてまわる問題ではない。

 以前見かけたこの記事が詳しい。これに当たったようだ。これがなければわからなかっただろう。

// LM35DN x6 Thermal Logger

// http://arduino.cc/en/Reference/AnalogReference

unsigned int t,c;
float sc;
unsigned long time;
#define NUM_LM35 6
int LM35[NUM_LM35];
int Shuffle[NUM_LM35] ; // shuffle LM35 port 0-5 

// initialize the library with the numbers of the interface pins
///LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

float temp5v(int ain) {  // analog 0-1023 10mV/Celsius ,5V*100/1024
  return ain*5.0*100/1024;
}

float temp3v3(int ain) {  // analog 0-1023 10mV/Celsius,3.3V*100/1024
  return ain*3.3*100/1024;
}

float temp2v56(int ain) {  // analog 0-1023 10mV/Celsius,2.56V*100/1024
  return ain*2.56*100/1024;
}

float temp1v1(int ain) {  // analog 0-1023 10mV/Celsius,1.1V*100/1024
  return ain*1.1*100/1024;
}

void setup() {
  // set up the LCD's number of columns and rows: 
  // lcd.begin(16, 2);
  Serial.begin(9600);
  // External Aref(3.3V)
  // analogReference(EXTERNAL);//3.3V
  // Internal Aref(1.1V) ATmega328 ???
  analogReference(INTERNAL);
/*
  Shuffle[0]=A0;
  Shuffle[1]=A1;
  Shuffle[2]=A2;
  Shuffle[3]=A3;
  Shuffle[4]=A4;
  Shuffle[5]=A5;
*/
/*
  Shuffle[0]=A4;
  Shuffle[1]=A2;
  Shuffle[2]=A5;
  Shuffle[3]=A0;
  Shuffle[4]=A3;
  Shuffle[5]=A1;
*/
//  for (int i=0; i<=NUM_LM35;i++) LM35[i]=Shuffle[i] ;
/*
  LM35[0]=A0;
  LM35[1]=A1;
  LM35[2]=A2;
  LM35[3]=A3;
  LM35[4]=A4;
  LM35[5]=A5;
*/
  LM35[0]=A4;
  LM35[1]=A2;
  LM35[2]=A5;
  LM35[3]=A0;
  LM35[4]=A3;
  LM35[5]=A1;
}

void loop() {
    time=millis();Serial.print(time);Serial.print(" ");

    for(int i=0;i<=NUM_LM35;i++) {
      t=analogRead(LM35[i]); // (0...1023)
      sc=temp3v3(t); // Selcius
      // Serial.print(sc);
      // Serial.print(":");
      Serial.print(t);
      if (i<NUM_LM35) Serial.print(" ");
      delay(100);
    }
    Serial.println("");
    delay(60000); // 1000
} 
(1)A/Dコンバータ(ADC)のリファレンス電圧による違い→ 3.3Vより1.1Vの方が発生頻度が上がる
analogReference(EXTERNAL); // 3.3VをAREF端子に接続
analogReference(INTERNAL); // 1.1V内部リファレンス

(2)測定間隔による違い→1分間隔よりも1秒間隔の方が頻度が下がる(が発生)

(3)チャネルによる違い
A0,A1,A2,A3,A4,A5の順にリード→ A0で少し下がり、A5で大きく跳ね上がる
A4,A2,A5,A0,A3,A1の順にリード→ A4で少し下がり、A1で大きく跳ね上がる
つまり、ポートに関係なく読み出し順の最初と最後で異常。

(4)チャネルによる違いその2
  Shuffle[0]=A4;
  Shuffle[1]=A2;
  Shuffle[2]=A5;
  Shuffle[3]=A0;
  Shuffle[4]=A3;
  Shuffle[5]=A1;
  for (int i=0; i<=NUM_LM35;i++) LM35[i]=Shuffle[i] ;

として analogRead(LM35[i]);とやってみたら再現しなくなった。Shuffle[i]に代入するポート番号をA0〜A5に整列させても発生しない。

ATmega32U4のデータシートを見てみると、ADCの実体は1つで入力ポートを切り替えている。

きょうはここまで。

LM35DZによる温度測定とanalogReference()

LM35DZという三端子の温度センサを使ってみた。
高精度IC温度センサ LM35DZ 0~100℃ [秋月電子]
【LM35DZ-N】高精度・摂氏直読温度センサーIC [マルツ]
 1℃あたり10mVの出力で、外付け部品なしの測定範囲は+2℃〜。Arduinoだとアナログ入力が使える。
作例はたくさんあるのでLCDに表示してみた。つかったのはLCDシールド
2012LM35DZ

ソースはこちら。https://gist.github.com/3724141 
→ https://gist.github.com/3725477

※A/D入力を℃に変換する箇所:ain*330/1024を修正。(ドライヤーで温めたらマイナス表示になってしまった)
float temp3v3(int ain) { // analog 0-1023 10mV/Celsius,3.3V*100/1024
  return ain*3.3*100/1024;
}



 今回使用したのはArduino UNO R3とArduino IDE1.0.1。A/Dコンバータの基準電圧に外部3.3Vを使用している。AREFピンと3V3ピンを接続し、スケッチ内でanalogReference(EXTERNAL); と指定した。

 ここでちょっと引っかかったのがanalogReference(INTERNAL)の指定。
http://arduino.cc/en/Reference/AnalogReference
これによるとATmega328でINTERNAL指定すると基準電圧は2.56V1.1Vになるらしいのだが、指定してみたらどうも3.3Vみたい。AREFピンに3V3を接続していたが、これを外すと値がおかしくなる。INTERNAL指定のままでAREFを5Vに接続したらそれが基準電圧みたいな動作をする。
Arduino UNO R3/Arduino IDE1.0.1ではINTERNAL指定もEXTERNAL指定も同じみたいだ。 

追記:MacOSXのArduino IDE1.0 と 0023でも同じだった。
解決:INTERNAL指定の時はAREFをつないじゃいけない。

ATmega328Pのデータシート、p.251 Figure 23-1. Analog to Digital Converter Block Schematic OperationをみるとA/Dコンバータの基準電圧はAREF端子に直に出ているので、INTERNALで1.1V指定していてもここに3.3Vをつなぐとそっちが勝つ。
 

ブレッドボード用電源治具

ブレッドボードで工作していると、電源を上下に渡すのが面倒と感じることがあるのでちょっと作った。
2012pow1

 こうやって2x5=10Pのピンヘッダを二個用意。奥の方はプラスとマイナスになる端子を少し引き伸ばしておく。

2012pow2


  ACアダプタのジャックとコネクタがあらかじめ配線されている製品があるので、これをつける。
あとは使用したい電源電圧にあったACアダプタを繋ぐだけ。今はACアダプタがスイッチング電源になって期待通りの電圧が得られるのでこれでOK。

Seeeduino用DCジャック〜2ピンコネクタ変換ケーブル [スイッチサイエンス]
※2mm間隔のコネクタのものは使えないので注意

ほんとはこれが欲しかった
Adjustable breadboard power supply kit - v1.0

PS/2キーボード変換器の製作(15) US配列→JP配列の問題点

US配列から日本語配列に変換する部分を作成した。
Arduino用のスケッチは以下のとおり。これはUSB HIDキーボードに文字を出力すると共にシリアルポートにデバッグ情報を流す。
https://gist.github.com/3464019
ライブラリ(ps2kybd.h、ps2kybd.cpp)は前回から修正なし。
https://gist.github.com/ab100bfb33a78ddf067d



記号の置き換えは、以下のパターンで行う。
(1)SHIFTを押していない状態でSHIFTを押したような入力……右シフトキーpress、置き換えコード、右シフトキーrelease
(2)SHIFTを押していない状態で記号の置き換え……置き換えコード
(3)SHIFTを押した状態でSHIFTを押したような入力……置き換えコード
(4)SHIFTを押した状態でSHIFTを押さないような入力……左右のシフトキーをrelease、置き換えコード、元のシフトキーをpress

ALTキーを押した状態では、[`~]キーは変換せずにそのまま出力することで[ALT]+[漢字]と同じ操作になる。

 これで記号の置き換え、漢字入力のON/OFFができた。

 残った問題点。
(1)CapsLockの扱い。CapsLockはUSキーではSHIFT併用だが、日本語キーではそのまま。
→Capsフラグはライブラリ側にまかせているが、これをスケッチ側で対処
(2)[¥_]が入力できない →Arduino LeonardoはいったんASCIIコードで受けて内部で変換しUSB HIDコードを送っている。USキーのレイアウトを前提にしているため、日本語配列の[¥_]は対応するものがない。
(3)このアダプタをWindowsXPに接続するたびにデバイスドライバの確認ダイアログが登場する。

(2)、(3)は非常に大きな問題。

(2)はUSB HIDを直接送出する方法を調べなければならない。
(3)はArduinoのブートローダを置き換えなければならない。

うーん、これはけっこう難しいぞ……

鳥人間Harpy nano/H2A nanoは3V3と5Vが入れ替わっている

株式会社鳥人間の小型Arduino互換ボード Harpy nanoと、Arduino用シールドを取り付けるためのアダプタH2A nanoだけど、3.3V動作の回路を工作してて気付いた。H2A nanoの3.3Vと5Vが入れ替わっている。
2012harpy
H2A nano。

左から RESET,3V3,5V,GNDの順だけど、H2A nanoの端子をテスタで確認したら 3V3と5Vが入れ替わっていた。
H2A nano 回路図によるとRESET,5V,3V3の順になっている。シルクは通常のArduinoと同じ。

 持ってる方はご注意を。製造元には連絡済みなので次の版からは直るかもしれません。

追記:次の版は修正済で、旧版を持ってる方は交換対応してくれるとのことです。

GR-SAKURAのイーサポートがシールドと干渉する

2012grsakura1

 見たまんま。シールドによってはショートする危険性もある。

2012grsakura2

 まあこうするしかないよね。

 Netduino plusという、同じようにイーサの口を持ったボードはこうなってる。

2012netduino1

 プラスチック製で絶縁されており、基板の下に逃がしてあるので背が低い。
 2012netduino2


スイッチサイエンス32U4ブレークアウトボードとAVRISPmkII

スイッチサイエンスの32U4ブレークアウトボードをArduino Leonardo化した。

SWITCH SCIENCE 32U4ブレークアウトボード

AVR ISPmkIIでArduinoブートローダを書き込むための端子は以下。

SCK (2).B1
MOSI (3).B2
MISO (4).B3
RST (5)
Vcc (6)
GND (21)

ACR ISPmkIIのICSP端子を上から見た図
AVRISPmkIIcon

ブレッドボード上で書き込み用の接続。32U4ブレークアウトボードはひっくり返して載せてる。また、AVR ISPmkIIのICSPコネクタは写真では上を向けているのでVccが左上に見える(赤い線)。
AVRISPmkII-32U4
 
 Arduino IDEから[ツール]→[書込装置]でAVRISPmkIIを選択し、[ツール]→[ブートローダを書き込む]でしばらく待つと青いLEDが点滅するようになる。これでOK。

参考:
AVRC Programming-Programmer

GR-SAKURA がじぇるねボード

RSコンポーネンツで注文したGR-SAKURA がじぇるねボードが届いた。ルネサスのRX63Nマイコンを搭載し、Arduinoのシールドが使える。単体でもEther、USB、SDカードなど機能豊富。

 2012sakura1

 USBコネクタが部品で付属している。必要なら半田付け。

2012sakura

 USBケーブルを接続して赤いリセットボタンを押すと、GR-SAKURAがドライブとして認識される。これにwebコンパイラでコンパイルしたバイナリをコピーするとそれを実行する。えらい簡単。

 MacOSXで動作確認した。/Volumes/GR-SAKURAとして見える。

がじぇっとるねさす
SAKURA BOARD 

 浮動小数点演算のハードを内蔵しているということで、whetstoneでも試してみようかと思い動かしてみた。

元ネタ:Benchmark Programs and Reports

/*GR-SAKURA Sketch Template Version: V1.00*/
#include <rxduino.h>

#define INTERVAL 100


#define ITERATIONS    10000 /* 1 Million Whetstone instructions */

#include "math.h"

#define PREC float

PREC        x1, x2, x3, x4, x, y, z, t, t1, t2;
PREC         e1[4];
int        i, j, k, l, n1, n2, n3, n4, n6, n7, n8, n9, n10, n11;


void setup()
{
    Serial.begin(9600); 
    pinMode(PIN_LED0,OUTPUT);
    pinMode(PIN_LED1,OUTPUT);
    pinMode(PIN_LED2,OUTPUT);
    pinMode(PIN_LED3,OUTPUT);
}

void pa(PREC *e)
{
    register int j;

    j = 0;
     lab:
    e[0] = (  e[0] + e[1] + e[2] - e[3] ) * t;
    e[1] = (  e[0] + e[1] - e[2] + e[3] ) * t;
    e[2] = (  e[0] - e[1] + e[2] + e[3] ) * t;
    e[3] = ( -e[0] + e[1] + e[2] + e[3] ) / t2;
    j += 1;
    if (j < 6)
        goto lab;
    return;
}


void p3(PREC x, PREC y, PREC *z)
{
    x  = t * (x + y);
    y  = t * (x + y);
    *z = (x + y) /t2;
    return;
}


void p0()
{
    e1[j] = e1[k];
    e1[k] = e1[l];
    e1[l] = e1[j];
    return;
}

#ifdef POUT
pout(int n, int j, int k, PREC x1, PREC x2, PREC x3, PREC x4)
{
    printf("%6d%6d%6d  %5e  %5e  %5e  %5e\n",
        n, j, k, x1, x2, x3, x4);
}
#endif

void testfloat() {

    /* initialize constants */

    t   =   0.499975;
    t1  =   0.50025;
    t2  =   2.0;

    /* set values of module weights */

    n1  =   0 * ITERATIONS;
    n2  =  12 * ITERATIONS;
    n3  =  14 * ITERATIONS;
    n4  = 345 * ITERATIONS;
    n6  = 210 * ITERATIONS;
    n7  =  32 * ITERATIONS;
    n8  = 899 * ITERATIONS;
    n9  = 616 * ITERATIONS;
    n10 =   0 * ITERATIONS;
    n11 =  93 * ITERATIONS;

/* MODULE 1:  simple identifiers */
    digitalWrite(PIN_LED0, 1);

    x1 =  1.0;
    x2 = x3 = x4 = -1.0;

    for(i = 1; i <= n1; i += 1) {
        x1 = ( x1 + x2 + x3 - x4 ) * t;
        x2 = ( x1 + x2 - x3 - x4 ) * t;
        x3 = ( x1 - x2 + x3 + x4 ) * t;
        x4 = (-x1 + x2 + x3 + x4 ) * t;
    }
#ifdef POUT
    pout(n1, n1, n1, x1, x2, x3, x4);
#endif


/* MODULE 2:  array elements */
    digitalWrite(PIN_LED1, 1);

    e1[0] =  1.0;
    e1[1] = e1[2] = e1[3] = -1.0;

    for (i = 1; i <= n2; i +=1) {
        e1[0] = ( e1[0] + e1[1] + e1[2] - e1[3] ) * t;
        e1[1] = ( e1[0] + e1[1] - e1[2] + e1[3] ) * t;
        e1[2] = ( e1[0] - e1[1] + e1[2] + e1[3] ) * t;
        e1[3] = (-e1[0] + e1[1] + e1[2] + e1[3] ) * t;
    }
#ifdef POUT
    pout(n2, n3, n2, e1[0], e1[1], e1[2], e1[3]);
#endif

/* MODULE 3:  array as parameter */
    digitalWrite(PIN_LED2, 1);

    for (i = 1; i <= n3; i += 1)
        pa(e1);
#ifdef POUT
    pout(n3, n2, n2, e1[0], e1[1], e1[2], e1[3]);
#endif

/* MODULE 4:  conditional jumps */
    digitalWrite(PIN_LED3, 1);

    j = 1;
    for (i = 1; i <= n4; i += 1) {
        if (j == 1)
            j = 2;
        else
            j = 3;

        if (j > 2)
            j = 0;
        else
            j = 1;

        if (j < 1 )
            j = 1;
        else
            j = 0;
    }
#ifdef POUT
    pout(n4, j, j, x1, x2, x3, x4);
#endif

/* MODULE 5:  omitted */

/* MODULE 6:  integer arithmetic */
    digitalWrite(PIN_LED0, 0);

    j = 1;
    k = 2;
    l = 3;

    for (i = 1; i <= n6; i += 1) {
        j = j * (k - j) * (l -k);
        k = l * k - (l - j) * k;
        l = (l - k) * (k + j);

        e1[l - 2] = j + k + l;        /* C arrays are zero based */
        e1[k - 2] = j * k * l;
    }
#ifdef POUT
    pout(n6, j, k, e1[0], e1[1], e1[2], e1[3]);
#endif

/* MODULE 7:  trig. functions */
    digitalWrite(PIN_LED1, 0);

    x = y = 0.5;

    for(i = 1; i <= n7; i +=1) {
        x = t * atan(t2*sin(x)*cos(x)/(cos(x+y)+cos(x-y)-1.0));
        y = t * atan(t2*sin(y)*cos(y)/(cos(x+y)+cos(x-y)-1.0));
        // x = x * 2;
        // y = y * 2;
}
#ifdef POUT
    pout(n7, j, k, x, x, y, y);
#endif

/* MODULE 8:  procedure calls */
    digitalWrite(PIN_LED2, 0);

    x = y = z = 1.0;

    for (i = 1; i <= n8; i +=1)
        p3(x, y, &z);
#ifdef POUT
    pout(n8, j, k, x, y, z, z);
#endif

/* MODULE9:  array references */
    digitalWrite(PIN_LED3, 0);

    j = 1;
    k = 2;
    l = 3;

    e1[0] = 1.0;
    e1[1] = 2.0;
    e1[2] = 3.0;

    for(i = 1; i <= n9; i += 1)
        p0();
#ifdef POUT
    pout(n9, j, k, e1[0], e1[1], e1[2], e1[3]);
#endif

/* MODULE10:  integer arithmetic */
    digitalWrite(PIN_LED0, 1);
    digitalWrite(PIN_LED1, 1);

    j = 2;
    k = 3;

    for(i = 1; i <= n10; i +=1) {
        j = j + k;
        k = j + k;
        j = k - j;
        k = k - j - j;
    }
#ifdef POUT
    pout(n10, j, k, x1, x2, x3, x4);
#endif

/* MODULE11:  standard functions */
    digitalWrite(PIN_LED2, 1);
    digitalWrite(PIN_LED3, 1);

    x = 0.75;
    for(i = 1; i <= n11; i +=1)
        x = sqrt( exp( log(x) / t1));
        // x = x / 2;
#ifdef POUT
    pout(n11, j, k, x, x, x, x);
#endif

// -----------------------------

}

void loop() {
    digitalWrite(PIN_LED0, 0);
    digitalWrite(PIN_LED1, 0);
    digitalWrite(PIN_LED2, 0);
    digitalWrite(PIN_LED3, 0);
    Serial.println(millis());
    testfloat();
}


 ITERATIONSを1000倍にして15秒だったので、1000÷15=約66.7MWIPSかな?目安程度に。

 当初、doubleとfloatの実行速度が変わらなくて「?」だったのだが、Arduino互換ということでfloatもdoubleも単精度となる。実際にdouble版とfloat版でコンパイルしてバイナリを比較したら一致した。

 LEDが4個載っているのでprintfデバッグも楽、web上でコンパイルできるため開発環境をインストールしなくて済む。フラッシュ1MB/RAM 128KBで入出力も豊富。これはたのしい。

POS端末用PS/2キーボード FTP-CKB11の解析

 昔ジャンク屋で入手したPOS用のPS/2接続キーボード。テンキー以外はラベルを入れることができる。鍵付き。
2011pos01

 裏面はツメで嵌めこまれているだけなので簡単に外れる。キーボードのくせに基板が複雑。16bitマイコンが載っていた。
F2MC-16L MB90610A Series[pdf]

2012pos02

 これは磁気カードリーダーにも対応しているためだろう。フラッシュメモリも搭載されていたのでログを取るのかもしれない。

2012pos03

解析結果

pos_scancode
 
記事検索
プロフィール

hardyboy

カテゴリ別アーカイブ
月別アーカイブ
QRコード
QRコード
  • ライブドアブログ