まごころせいじつ堂

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

Arduino

メモ PIC/PIC32MX/ビデオ出力

ビデオ出力の原理。D/Aコンバータ
Wayne and Layne

Arduinoでの作例
Arduino Uno output to VGA monitor


【紹介】PIC32MXマイコンでカラーコンポジット出力を試す&ビデオゲームもできる!

PIC32MX,HC08,MSP430用BASIC
CPUStick and StickOS

PICのクラスタ
PIC cluster

Arduino Online Compiler
Arduino Online Compiler


ArduinoライクなPIC32MX開発環境
Pinguino X4 IDE 簡単インストール

PIC32MXについて(概要)

AVR VGA Generation

PIC32MX USB

Arduinoで4×4キーマトリックス

キーマトリックスのスキャンをやってみた。Arduinoのシールドにタクトスイッチを16個取り付け、4×4で扱う。
2013keyscan0

D9,D10,D11,D12は出力で、どれか1つをLOWにする。これをD5,D6,D7,D8で読み取り、キーが押されている位置を判定する。
2013keyscan

D9,D10,D11,D12の出力には2.2KΩの抵抗を入れている。これは複数のキーを押した時に出力のLOW-HIGHが直接繋がってしまうのを避けるため。
Arduinoのリファレンスによると、INPUTに指定したピンにHIGHを出力するとプルアップが有効になり、LOWで無効になるとあるので、この抵抗はいらなかったかも。 

スケッチはこちら。押したキーの番号を0〜15で返す。-1は何も押されていない。シリアルに出力する。
https://gist.github.com/houmei/4735235


int KO[4]={5,6,7,8};
int KI[4]={9,10,11,12};

void setup() {
  pinMode(KI[0],INPUT_PULLUP);
  pinMode(KI[1],INPUT_PULLUP);
  pinMode(KI[2],INPUT_PULLUP);
  pinMode(KI[3],INPUT_PULLUP);
  pinMode(KO[0],OUTPUT);
  pinMode(KO[1],OUTPUT);
  pinMode(KO[2],OUTPUT);
  pinMode(KO[3],OUTPUT);
  Serial.begin(9600);
  keyscan_init();
}

void loop() {
  int a;
  a=keyscan();
  if (a>=0) Serial.println(a);
}


void keyscan_init() {
  digitalWrite(KO[0],HIGH);
  digitalWrite(KO[1],HIGH);
  digitalWrite(KO[2],HIGH);
  digitalWrite(KO[3],HIGH);
}

int keyscan() { // pressed 0-15 , not pressed -1
  int i,j;
  int n=-1;
  for(i=0;i<4;i++) {
    for(j=0;j<4;j++) {
       if (i==j) {
          digitalWrite(KO[j],LOW);
       } else {
         digitalWrite(KO[j],HIGH);
       }
    }
    for(j=0;j<4;j++) {
      if (n<0 && digitalRead(KI[j])==LOW) {
        n=i+j*4;
      }
      delay(1); // wait for 1ms
    }
  }
  keyscan_init();
  return n;
}


Adafruit 1.8インチTFTシールド

スイッチサイエンスで扱っているAdafruit 1.8インチTFTシールドをとりあえず使ってみた。

Adafruit 1.8インチTFTシールド
(スイッチサイエンス)

Adafruit 1.8" 18-bit Color TFT Shield w/microSD and Joystick(Adafruit)

 ST7735R 128×160ドット 18bit色のディスプレイ、おおよそ33mm×40mmの大きさで、ウォークマンW用の液晶保護シートがぴったり貼れる。microSDカードスロット付き。上下左右と押しこむ操作のスティック付き。あと、バックライトを制御できそうなことが書いてあった(何もしないとON)。
 使用ピンはSPI接続でpin13,11,10,8。microSDカードを使う場合は加えて12と4。スティックはアナログ出力でA4。このシールドは3.3V/5V対応なのでGR-SAKURAに使えるかもしれん。

#define sclk  13  
#define mosi  11
#define sd_cs  4
#define lcd_cs 10
#define dc     8
#define rst    0  


 ライブラリはAdafruit-ST7735-LibraryとAdafruit-GFX-Libraryが必要。Adafruit-GFX-Libraryは同社のOLEDでも使われている。

https://github.com/adafruit/Adafruit-ST7735-Library

https://github.com/adafruit/Adafruit-GFX-Library

 これらをgithubのzipでダウンロードするボタンを押して、Arduino IDEのライブラリに展開すればいいんだけどそのままのフォルダ名だと半角英数字以外使えんといったエラーメッセージが出るので、-masterは削除しハイフン(-)はアンダースコア(_)に変えた。

 以下、ArduinoIDE1.0.3、MacOSX、Arduino UNO R3で確認。
2013tft1

 サンプルでついてくるshieldtestを開いて実行。スティックを動かすと画面に向きを表示。押しこむとmicroSDカードにあるparrot.bmpを開いて表示するらしいのだが、手元にないので適当に用意する。サンプルのparott.bmpを適当にリネームし、用意した128x160サイズのBMP画像のファイル名に合わせる(実際には128x171サイズ)。この時ファイル名は8+3文字の制限があるみたい。シリアルには以下の様に出力され、画像が液晶画面に表示される。

Button read analog = 3.34
Button read analog = 3.34
Button read analog = 0.59
Button read analog = 0.59
Button read analog = 3.34
Button read analog = 3.34
Button read analog = 3.34
Button read analog = 1.05
Initializing SD card...
Loading image 'sakura.bmp'
File size: 65718
Image Offset: 54
Header size: 40
Bit Depth: 24
Image size: 128x171
Loaded in 1111 ms

2013tft2


こんな感じです。

lcd.write(0)でerror: call of overloaded 'write(int)' is ambiguousと言われる

キャラクタ液晶を扱うライブラリLiquidCrystalには、ユーザ定義文字を設定するcreateChar(num,data)という関数がある。これを試したらなぜかエラーになった。

createChar(num,data) Arduino日本語リファレンス
createChar() (原文)

Arduino1.0.3で以下のメッセージ。(MacOSX) Windowsでも同様

sketch_jan04b.ino: In function 'void setup()':
sketch_jan04b:18: error: call of overloaded 'write(int)' is ambiguous
/Applications/Arduino1.0.3.app/Contents/Resources/Java/libraries/LiquidCrystal/LiquidCrystal.h:82: note: candidates are: virtual size_t LiquidCrystal::write(uint8_t)
/Applications/Arduino1.0.3.app/Contents/Resources/Java/hardware/arduino/cores/arduino/Print.h:49: note:                 size_t Print::write(const char*)

??サンプルがそのまま動かないのナンデ? 0x00に書き換えても同様。

調べたら定数0を指定した時だけの問題。lcdに限らない。
call of overloaded 'write(int) is ambigous?

lcd.write(0); を lcd.write((byte)0);にして解決。1〜の定数を指定した時はエラーが発生しない。
もちろん、変数で指定した場合は問題ない。
サンプルのコピペでちょっとハマッてしまった。
 2013smile

ArduinoIDE1.0.3 USB-HID特に変わらず

やっと今日Arduino1.0.3のソースがダウンロードできたので、USB0-HIDのキーボード部分をチェックした。

// Keyboard
    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)	// 47
    0x09, 0x06,                    // USAGE (Keyboard)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x85, 0x02,                    //   REPORT_ID (2)
    0x05, 0x07,                    //   USAGE_PAGE (Keyboard)
   
	0x19, 0xe0,                    //   USAGE_MINIMUM (Keyboard LeftControl)
    0x29, 0xe7,                    //   USAGE_MAXIMUM (Keyboard Right GUI)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
    0x75, 0x01,                    //   REPORT_SIZE (1)
    
	0x95, 0x08,                    //   REPORT_COUNT (8)
    0x81, 0x02,                    //   INPUT (Data,Var,Abs)
    0x95, 0x01,                    //   REPORT_COUNT (1)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x81, 0x03,                    //   INPUT (Cnst,Var,Abs)
    
	0x95, 0x06,                    //   REPORT_COUNT (6)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x25, 0x65,                    //   LOGICAL_MAXIMUM (101)
    0x05, 0x07,                    //   USAGE_PAGE (Keyboard)
    
	0x19, 0x00,                    //   USAGE_MINIMUM (Reserved (no event indicated))
    0x29, 0x65,                    //   USAGE_MAXIMUM (Keyboard Application)
    0x81, 0x00,                    //   INPUT (Data,Ary,Abs)
    0xc0,                          // END_COLLECTION

そんなわけで LOGICAL_MAXIMUM(101) 、USAGE_MAXIMUM(101) →0x65 で変わらず。
なんで毎回制限してんだろ?日本語キーボードなど国際化無視?
 

LM35DZを複数繋いだ温度ロガーと誤差

温度センサLM35DZを複数個繋いだロガーやっとできた。

これまでの記事:
LM35DZを複数つないだ時の問題 お詫びとハードでの解決
温度センサLM35DZを複数Arduinoに繋いだ時のトラブル
LM35DZによる温度測定とanalogReference()

マイコン風雲録さんのanalogReadEx()関数で解決しました。ありがとうございました。
Arduino:温度センサー Processing + Firmata LM61BIZとLM35DZとDS18B20のメモ[マイコン風雲録]

Arduino UNOのA0〜A5ポートにLM35DZを接続。信号線は10KΩでGNDに。

 ログ時刻はRTCをつないで頑張るつもりだったが、Arduino UNOではI2Cの端子がアナログポートとかぶるのであきらめた。Arduino Microだとアナログポートはたくさんあるし次はこれ使おう。
で、肝心のタイムスタンプはTeraTermに任せた。ログを取るときに□タイムスタンプのチェックボックス入れるか、teraterm.ini内のLogTimestamp=onにする。
参考:
TeraTermログの行毎に自動的にタイムスタンプを付与する

※追記:@maris_HYさんにSPI接続のRTC教えてもらいました。
DS3234搭載のリアルタイムクロック・モジュール

以下を追加・修正した。
・Setup()内で5秒の待ち。シリアルモニタ(TeraTerm等)を立ち上げる時間を待つため
・別のセンサを付けることを考慮して、A0〜A5ポートの入れ替えを最初のほうで定義した。
・温度測定の結果は先頭に連番を付けるようにした
・Arduinoが生きているかどうか分かるようLEDを点滅させる処理を追加
・LM35DZセンサの誤差を補正できるようにした(Adj[]で定義)

さて、これで安定して測定できるようになったが、温度センサを一箇所にまとめても数℃の誤差が出る。これはセンサについてまわるので素子のばらつきと思われる(安いグレードだし)が、ADCの基準電圧が内部リファレンス1.1Vと外部リファレンス3.3Vではどう違うだろうか。

ADCの基準電圧1.1Vと3.3Vについて200回測定し、平均を求めた。
$ gawk -f 20121130.awk lm35dz1v1.txt
AVG1= 188.02
AVG2= 190.65
AVG3= 193.33
AVG4= 191.77
AVG5= 192.27
AVG6= 194.555

1.1V÷1024で分解能は1.07mV
6.54ステップのゆらぎ 約7.00mV

$ gawk -f 20121130.awk lm35dz3v3.txt
AVG1= 60.2977
AVG2= 61.1395
AVG3= 61.4512
AVG4= 61.214
AVG5= 60.9488
AVG6= 61.8791

3.3V÷1024で分解能は3.22mV
1.58ステップのゆらぎ 約5.10mV

 ということで、ATmega328の内部1.1Vよりも外部の定電圧レギュレータによる3.3Vの方がより正確。外部5Vも使えるが、USBから給電して使う場合はそちらに影響されるので3.3V参照のほうがよさそう。
 または、基準1.1Vの方がセンサの誤差に対してより敏感なのかも。ちょっとこの辺はLM35DZの良いグレードの品で比較しないといけないんだろうけど資本切れです。


プログラムはこちら。
※analogReference()の箇所がINTERNALになってますが3.3V参照ではEXTERNALでした。ただしINTERNAL設定でもAREFにかかっている電圧が優先になるようです。

https://gist.github.com/4176111


20121201terrmal

一晩測ってExcelに持っていった。おおよそ期待通り。上がったりしている箇所はストーブを使った時間。

Arduino MicroとLED付き押ボタンスイッチ

秋月電子のLED付き押ボタンスイッチが以前から気になっていた。今回入手してこれまた最近発売されたArduino Microと組み合わせてブレッドボード上で組み立ててみた。

LED付き押しボタンスイッチ(白・正方形・赤色LED)ST12-401FCG (秋月電子)

Arduino Micro 5V 16MHz (ATmega32u4 - ピンヘッダ付き) (スイッチサイエンス)
まだスイッチサイエンスが扱う前だったのでAdafruitから買った。Arduino Leonardoの時みたいに品薄になるんじゃないかなあと思ってたらそんなことはなかった。



 Arduino MicroはATmega32U4を使ったブレッドボード上で使える小さなArduinoで、Arduino Leonardo相当の機能。Arduino IDE 1.0.2から使える。([ツール]→[マイコンボード]で指定) 通電するとmicroUSBコネクタ下にある青LEDが光る。

2012micro1

 Arduino IDE 1.0.2では、Leonardoでtone()を使った時の問題が修正されたらしいので圧電ブザーも繋いでみた。これで電子ゲームっぽくなる。
 Arduino Microのピンアウトはこちらを参照。
Arduino Micro

 電源はArduino MicroのUSB経由でもらっている。
タクトスイッチ部分はA0,A1,A2,A3を使用。analog入力で読んでいる。A0〜A3はINPUT_PULLUPでプルアップ指定し、スイッチはONでGNDに接続。
LED部分はタクトスイッチとは独立して制御できる。12(PWM),11(PWM),10(PWM),9(PWM)で明るさを変化させている。アノード(+)側を端子に接続し、カソード(-)は330Ωの抵抗を通してGNDへ。
圧電ブザーは4(PWM)へ、隣のSCL,SDA端子をまたいでGNDに接続。
 2012micro2

 LED付き押ボタンスイッチは普通のブレッドボードに5個まで並べて挿せるようだ。LEDの(+)、(-)端子は細くて接触不良を起こしやすいので、挿す前に少し広げておく。
 ブレッドボード2枚で作れた。
2012micro3

確認用のソースは以下。動作開始時にブザーが鳴り、LEDが点滅する。ボタンを押すとその場所のLEDが消え、ブザーが鳴る。

☆toneのサンプルスケッチではpatches.hをincludeしているのだが、単体のソースで動くようにコピペして貼り付けました。

気になる点:いちばん左端のLED (A0ポート)が消灯する割合が高いような。
あと、以下の行間違い(というより当初の意図どおりではなかった)。点滅の具合が変わります。
int t=random(0,16)*16;
アナログポートA0〜はデジタルポートとしても使えるはずなのだが、上手くいかなかったのでアナログ入力で誤魔化しています(100以下でボタンが押されていると判定)。私の勘違いで上手く使えなかったのかもしれないし、なんかあるのかもしれない。

// LED tactswitch+Arduino Micro
// 20121124 K.Takesita
//

// copy from pitches.h
/*************************************************
 * Public Constants
 *************************************************/

#define NOTE_B0  31
#define NOTE_C1  33
#define NOTE_CS1 35
#define NOTE_D1  37
#define NOTE_DS1 39
#define NOTE_E1  41
#define NOTE_F1  44
#define NOTE_FS1 46
#define NOTE_G1  49
#define NOTE_GS1 52
#define NOTE_A1  55
#define NOTE_AS1 58
#define NOTE_B1  62
#define NOTE_C2  65
#define NOTE_CS2 69
#define NOTE_D2  73
#define NOTE_DS2 78
#define NOTE_E2  82
#define NOTE_F2  87
#define NOTE_FS2 93
#define NOTE_G2  98
#define NOTE_GS2 104
#define NOTE_A2  110
#define NOTE_AS2 117
#define NOTE_B2  123
#define NOTE_C3  131
#define NOTE_CS3 139
#define NOTE_D3  147
#define NOTE_DS3 156
#define NOTE_E3  165
#define NOTE_F3  175
#define NOTE_FS3 185
#define NOTE_G3  196
#define NOTE_GS3 208
#define NOTE_A3  220
#define NOTE_AS3 233
#define NOTE_B3  247
#define NOTE_C4  262
#define NOTE_CS4 277
#define NOTE_D4  294
#define NOTE_DS4 311
#define NOTE_E4  330
#define NOTE_F4  349
#define NOTE_FS4 370
#define NOTE_G4  392
#define NOTE_GS4 415
#define NOTE_A4  440
#define NOTE_AS4 466
#define NOTE_B4  494
#define NOTE_C5  523
#define NOTE_CS5 554
#define NOTE_D5  587
#define NOTE_DS5 622
#define NOTE_E5  659
#define NOTE_F5  698
#define NOTE_FS5 740
#define NOTE_G5  784
#define NOTE_GS5 831
#define NOTE_A5  880
#define NOTE_AS5 932
#define NOTE_B5  988
#define NOTE_C6  1047
#define NOTE_CS6 1109
#define NOTE_D6  1175
#define NOTE_DS6 1245
#define NOTE_E6  1319
#define NOTE_F6  1397
#define NOTE_FS6 1480
#define NOTE_G6  1568
#define NOTE_GS6 1661
#define NOTE_A6  1760
#define NOTE_AS6 1865
#define NOTE_B6  1976
#define NOTE_C7  2093
#define NOTE_CS7 2217
#define NOTE_D7  2349
#define NOTE_DS7 2489
#define NOTE_E7  2637
#define NOTE_F7  2794
#define NOTE_FS7 2960
#define NOTE_G7  3136
#define NOTE_GS7 3322
#define NOTE_A7  3520
#define NOTE_AS7 3729
#define NOTE_B7  3951
#define NOTE_C8  4186
#define NOTE_CS8 4435
#define NOTE_D8  4699
#define NOTE_DS8 4978


const int SW0 = A0; //A0
const int SW1 = A1; //A1
const int SW2 = A2; //A2
const int SW3 = A3; //A3

const int LED0 = 12;
const int LED1 = 11;
const int LED2 = 10;
const int LED3 = 9;

int button[4] = { SW0,SW1,SW2,SW3 };
int light[4] = { LED0,LED1,LED2,LED3 };
int bright[4] = { 128,128,128,128 } ;
void setup() {
  pinMode(SW0,INPUT_PULLUP);
  pinMode(SW1,INPUT_PULLUP);
  pinMode(SW2,INPUT_PULLUP);
  pinMode(SW3,INPUT_PULLUP);
  
  pinMode(LED0,OUTPUT);
  pinMode(LED1,OUTPUT);
  pinMode(LED2,OUTPUT);
  pinMode(LED3,OUTPUT);
  
  tone(4,NOTE_C4,100);
}
void loop(){

  for(int i=0; i<4; i++) {
    if (analogRead(button[i])<100) {
      tone(4,NOTE_A4,10);
      analogWrite(light[i],0);
    } else {
      int t=random(0,16*16);
      analogWrite(light[i],t);
    }
  }

  delay(100);
}


シリアル接続7セグメント4桁LEDとUSB-TTLシリアルコンバータケーブル

 Sparkfunの7-Segment Serial Displayというのを使ってみた。最近改版されたらしい。

7-Segment Serial Display - Blue(Sparkfun)
※Sparkfunの写真は上下逆。

スイッチサイエンスから購入できる。
シリアル接続7セグメント4桁LED(青) (スイッチサイエンス)

シリアル、I2C、SPIでマイコンと接続、0〜Fの表示だけでなく任意のセグメントも表示可能で輝度も調整できるらしい。ATmega328で制御していて、Arduinoブートローダもあるので単独でも動作できるようだ。
2012led1
2012led2

 が、いきなりマイコンに接続して使うのもなんなのでUSB-TTLシリアルコンバータケーブルというのでPCから直接いじってみた。ストロベリーリナックスからUSBケーブルの様なシリアル変換器が出ている。5V品と3.3V品がある。

USB-TTLシリアルコンバータ(5V) (ストロベリーリナックス)
FTDI USB TTL Serial Cables (FTDIchip)

2012led4

黒 ー GND
茶 ← *CTS
赤 → Vcc電源出力 Max75mA
橙 → TXD
黄 ← RXD
緑 → *RTS

MacOSXだと/dev/tty.usbserial-なんとか という風に見える。

 では7セグLEDの実験。端子の取り付けはちょっと悩んだが、上にある10個はLEDの見える側にメス、右側のI2Cと電源はブレッドボードに載せられるようオスのピンヘッダを半田付け。I2Cと電源は左側にも配置してある。
 2012led3
 USB-TTLシリアルコンバータケーブルからの電力供給は弱そうで保護もないので、5V電源は別に取っている。ここではUSBミニコネクタ経由で5Vを給電。
7セグLEDの+、ー端子に電源接続、上の10個ある端子の右端にUSB-TTLシリアルコンバータの4番ピン(橙)、USB-TTLシリアルコンバータの1番ピン(黒)をGNDに接続。これだけ。
電源を接続しただけでは何も表示されない。Arduino IDEのシリアルモニタ経由で
cdef
と入力すると写真の様に表示される。
2012led5

キー入力順に左から右に出力され、4文字目を表示した次は1文字目の位置から出力される。cdefと入力した時とCDEFと入力した時は表示されるフォント(と言っていいのか)が若干異なる。

 ということでえらい簡単に動作確認できた。

メモ:秋月電子で買えるRTC(RealTimeClock)

データロガーを作ろうとしてるけど、タイムスタンプも欲しいよねということで調べた。秋月電子ではDIP基板に載せてモジュール化したものが2種類ある。

リアルタイムクロック(RTC)モジュール RTC-8564NB 
RTC-4543SA使用32kHz出力シリアルRTC基板モジュール RTC-4543SA

大きな違いは、RTC-8564NBがI2C、RTC-4543SAは独自シリアルI/Fでマイコンと通信する点。

RTC-4543SAはまだ実験してないのでメモ:
■[電子工作][プログラミング]RTC-4543(RTC-4543SA/SB)を使う(後編) (99円のへたれ日記!) 
シリアル出力リアルタイムクロック(RTC-4543SA)を使ってみた (明日から本気だす(´・ω・`))

RTC-8564NBはArduinoで実験してみた。
2012RTC

RTCモジュール上の端子にハンダを盛ってSDA,SCL信号はモジュール内でプルアップする。
スケッチについてはエレキジャックの記事を参照した。
リアルタイムクロックの最近のブログ記事 (エレキジャック・フィジカルコンピューティング)
RTC-8564NBモジュール(1)
RTC-8564NBモジュール(2)

Arduino1.0.2では以下のソースを一部修正。
ardsens090010.txt

Wire.send()はWire.write()に、Wire.receive()はWire.read()に書き換えが必要。
実行するとシリアルに時刻が出力される。そのままでは値がおかしいので
t213000[enter]
d121113[enter]
と入力すれば 2012年11月13日 21時30分00秒と設定される。

ところで、Arduino UNOではSCL,SDA端子がAnalog A5,A4の端子と一緒なので同時には使えない(@maris_HYさんありがとうございました)。
[SCL=A5,SDA=A4]
Arduino LeonardoではAREF端子の上のほうにSDA,SCL端子が増えている。Arduino UNO R3では互換のためにSDA,SCL端子はあるけどA4,A5の端子がそのまま引き出してあるだけ。ということでアナログ6ポートと同時に使うためにはLeonardoが必要。
が、手持ちのバニラシールドはこの増設部分が半分ずれてるのよね。ということでR3対応のものを取り寄せ中。
Arduino用バニラシールド基板ver.2(白) (スイッチサイエンス) 

Arduino IDE1.0.2 1.0.1との違い調査

Arduino IDE 1.0.2がリリースされた。
Download the Arduino Software

 リリースノートが和訳されている。
2012/11/5 Arduino-1.0.2リリース

 Arduino IDE 1.0.1でいじって気付いたLeonardo周りについて変化がないか確認した。

(1)USB HIDキーボードの送出可能コード範囲
ソースのHID.cppから該当箇所を確認。送出可能なコードの指定部分は0x65(101)で以前と変わらない。

(2)割込み
Arduino Leonardoの外部割り込み番号とピンの割り当てが異なる

これも変わらなかった。
PIN2かPIN3にスイッチを付けてGNDに落とし、割込みがかかるか調べる。

Arduino UNO R3:
INTNUM=0,INTPIN=2でPIN2○ PIN3×
INTNUM=0,INTPIN=3でPIN2○ PIN3△ (保証外動作)
INTNUM=1,INTPIN=2でPIN2× PIN3○ (保証外動作)
INTNUM=1,INTPIN=3でPIN2× PIN3○ 

Arduino Leonardo:
INTNUM=0,INTPIN=2でPIN2× PIN3△
INTNUM=0,INTPIN=3でPIN2× PIN3○
INTNUM=1,INTPIN=2でPIN2○ PIN3×
INTNUM=1,INTPIN=3でPIN2△ PIN3△ (不安定)

今後の実験はArduino IDE 1.0.2に移行する。

LM35DZを複数つないだ時の問題 お詫びとハードでの解決

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

こちらの方がADCの動作を考慮した読み捨ての回数を記事にされていた。
Arduino:温度センサー Processing + Firmata LM61BIZとLM35DZとDS18B20のメモ[マイコン風雲録]

ログを分析しようとしててあっと気付いた。
 for(int i=0;i<=NUM_LM35;i++) {
 だめだ……チャネルは6個しかないのに7個目読んでる……

 というわけでADC読み取りの最後が順番によらず跳ね上がるのは私のプログラムが原因でした。未定義のチャネル読んでる。申し訳ありません。

 ところで、チャネル読み込みの初回が順序に関わらず少し上がる現象は間違いなく起こっている。これを改善できるかどうか、以前も参考にした
■AVR(Arduino)にLM35温度センサをつなげた場合に正しくA/D変換出来ないトラブル(2012年2月15日)[SIESTA HOMEPAGE]
を参考に、LM35DZの出力に10KΩをぶら下げた。テスタでちゃんと信号-GND間が10KΩ程度か確認。
2012_10Kohm

 これで一晩ランニング。
比較のため前回とまったく同じヘボいコード(ADC0〜6まで読んでしまうもの)で実施。
この結果、最初に読んだチャネルが跳ね上がるという現象はなくなった。

□前回の生ログ(Arduino Leonardo、3V3リファレンス版) ※間違ったADCの7番目は除去
60702 72 73 74 74 73 74
121405 72 73 74 73 73 74
182107 72 73 73 73 73 73
242809 72 73 74 73 73 73
303512 72 73 73 73 73 73
364215 72 73 73 73 73 73
424918 72 73 73 72 73 73
485620 105 73 73 73 72 73
546323 71 73 73 73 72 73
607026 128 73 73 73 73 73
667727 72 73 73 73 73 74
728430 72 73 73 73 72 73
789133 72 73 73 73 72 73
849836 71 72 73 72 73 73

□今回の生ログ(Arduino Uno R3、1V1リファレンス版)
1759184 135 127 136 122 124 125 
1760387 135 128 136 122 124 124 
1761589 134 128 136 121 125 124 
1762791 135 127 136 122 125 124 
1763994 135 127 136 121 124 124 
1765196 134 127 135 122 125 123 
1766398 134 128 136 121 124 124 
1767602 135 127 136 122 125 124 
1768804 135 128 136 122 124 124 
1770006 134 127 135 122 124 124 
1771209 135 128 136 122 124 124 
1772411 135 128 136 122 125 124 
1773614 134 127 136 122 125 124 
1774816 135 128 136 122 125 124 

 LM35DZ直結の時は最初のADC読み取りで跳ね上がる現象が見られたが、10KΩをぶら下げることによりなくなった。しかし、各センサの値にむらがあるように見える。ADC0とADC2が値が大きい。

・今後の調査方針
(1)温度センサを束ねて同じ条件に
(2)ログをしっかり取ってawkで分析
(3) マイコン風雲録さんのanalogReadEx()で確認
 
 うう、デジタル温度センサに逃げたくなった……

PS/2キーボード変換器の製作(19) HEXファイルにパッチを当てる

前回、Arduino LeonardoではUSBキーボードに関するHID Report Descriptorではふつうの日本語キーボード等とは違い、キーの上限を101に制限していることがわかった。これが原因で日本語キーボードの[¥]や[ろ]に対応するコードを送っても無視されていた。
 このHID Report Descriptorの記述はArduino IDE1.0.1のソースにあるHID.cppの中で定義されてある。これはコンパイル済みなのでいじれない。そこでArduino IDEが生成する、マイコンに書き込むイメージファイルである.HEXファイルにパッチを当てることにした。

 Arduino IDE1.0.1でコンパイル時に生成される.hexファイルの所在は以下の方法で知ることが出来る。
Arduino開発環境が使えなくなってハマった件

例えばこのようなディレクトリの中に生成される。(MacOSX)
/var/folders/r5/h8nsfjps4kzdltsm9t4p0qr00000gn/T/build2978712088924621678.tmp/sketch_oct06a.cpp.hex

.hexファイルはひとつしかないので、これをコピーして以下のパッチを当てる。
25行目、
:100180008103950675081500256505071900296581
 ↓
:10018000810395067508150025FE0507190029FE4F

 パッチ当て後はチェックサムも変更しなければならないのでawkで作ったツールで確認した。
[awk]インテルHEXフォーマットのチェッカ

 こうやって作った.hexファイルを書き込む。色々試行錯誤して、結局AVRISPmkIIを使った。
 
$ /Applications/Arduino1.0.1.app/Contents/Resources/Java/hardware/tools/avr/bin/avrdude -C/Applications/Arduino1.0.1.app/Contents/Resources/Java/hardware/tools/avr/etc/avrdude.conf -v -patmega32u4 -cavrispmkII -Pusb -b57600 -e -Uflash:w:ok.hex:i

書き込み用ツールavrdudeはArduinoIDE内のものを、confファイルも同様。ここでは-eでフラッシュメモリを消去してから書き込んでいる。-Uオプションで消去をスキップしたらverifyでエラーが出たため。

以下、ログ
avrdude: Version 5.11, compiled on Sep  2 2011 at 18:52:52
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2009 Joerg Wunsch

         System wide configuration file is "/Applications/Arduino1.0.1.app/Contents/Resources/Java/hardware/tools/avr/etc/avrdude.conf"
         User configuration file is "/Users/takesita/.avrduderc"
         User configuration file does not exist or is not a regular file, skipping

         Using Port                    : usb
         Using Programmer              : avrispmkII
         Overriding Baud Rate          : 57600
avrdude: usbdev_open(): Found AVRISP mkII, serno: 000200081404
         AVR Part                      : ATmega32U4
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PA0
         RESET disposition             : dedicated
         RETRY pulse                   : SCK
         serial program mode           : yes
         parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         ByteDelay                     : 0
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :

                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom        65    10     8    0 no       1024    8      0  9000  9000 0x00 0x00
           flash         65     6   128    0 yes     32768  128    256  4500  4500 0x00 0x00
           lfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           lock           0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

         Programmer Type : STK500V2
         Description     : Atmel AVR ISP mkII
         Programmer Model: AVRISP mkII
         Hardware Version: 1
         Firmware Version Master : 1.10
         Vtarget         : 5.0 V
         SCK period      : 8.00 us

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01s

avrdude: Device signature = 0x1e9587
avrdude: safemode: lfuse reads as FF
avrdude: safemode: hfuse reads as D8
avrdude: safemode: efuse reads as CB
avrdude: erasing chip
avrdude: reading input file "ok.hex"
avrdude: writing flash (6676 bytes):

Writing | ################################################## | 100% 2.75s

avrdude: 6676 bytes of flash written
avrdude: verifying flash memory against ok.hex:
avrdude: load data flash data from input file ok.hex:
avrdude: input file ok.hex contains 6676 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 2.01s

avrdude: verifying ...
avrdude: 6676 bytes of flash verified

avrdude: safemode: lfuse reads as FF
avrdude: safemode: hfuse reads as D8
avrdude: safemode: efuse reads as CB
avrdude: safemode: Fuses OK

avrdude done.  Thank you.


 これで書き込んだLeonardo(Davinci)をPCに接続し、前回のキー入力テストを行うと、ちゃんと¥マークが入力できた。成功!

 なお、Arduino IDEのソース中ではLEDの状態を受信する部分は定義されていないので、USB経由の指示で、接続したPS/2キーボードのLEDを制御することができないようだ。

PS/2キーボード変換器の製作(18) USBキーボードの無視されるキーについて

正確にはArduino Leonardoで送信するキーのコードの一部が無視される現象について。

 WindowsXPで日本語キーボードが使える状態にして[¥]、[ろ]キーに対応するUsageコード0x89,0x87を送信する。普通の日本語キーボードでは期待通りの表示。だがArduino Leonardoから対応するコード0x89,0x87を送信しても無視される。この動作はUbuntu12.04をインストールした日本語キーボード接続のPCでも同様。
 USBlyzer というのを使ってパケットを監視してみた。これは有料だがお試し期間がある。
すると、日本語キーボードを接続したときは0x89を含むパケットにInternational3、0x87を含むパケットにInternational1の注釈がはいる。 しかしArduino Leonardoの場合は0x89、0x87とも注釈がApplicationとなっている。おなじキーボードデバイスなのに違う扱いを受けているようだ。どこかに違いがあるはずだが、ディスクリプタをよく理解していないので時間がかかりそう。キーボードに種別があるような記述は見つけていないし、ディスクリプタ中に現れるbCountrycodeは日本語キーボードでも0だったため、使われる地域の指定は無関係だった。他にあるのか。

 なお、調査中にわかったのだが、日本語キーボードの全角/半角キーはUsage 0x94にコードが割り当てられているが、実際に全角/半角の動作に切り替わるのは0x35[`]だった。

追記:なんとなくわかってきた。

https://gist.github.com/3854088

普通の日本語キーボードのHID Report Descriptorでは

Logical Minimum 0
Logical Maxmum 255
Usage Minimum (Undefined)
Usage Maximum 255

だけど、Arduino Leonardoは

Logical Minimum 0
Logical Maxmum 101
Usage Minimum (Undefined)
Usage Maximum 101 (アプリケーションキーまで)

となっている。0x89や0x87のコードを送っても無視されるのは多分このせい。

これらの記述はHID.cppの最初の方にある。これは……パッチを当てるしかないのか?


以下、資料: 
USB Descriptor
マウス付きUSBキーボードのディスクリプタ構成を調べる
HIDクラス
http://linux.die.net/Mobile-Guide/mobile-guide-p2c1s6-keyboard.html
USBキーボードのキーコード
アーカイブ: HID デバイスのハードウェア ID
Device Class Definition for Human Interface Devices (HID) [pdf]
HID Usage Tables[pdf]HID Usage Tables

PS/2キーボード変換器の製作(17) USBキーボードの任意コードの送出

Arduino Leonardo+IDE1.0.1ではKeyboard.press() / release()でUSB HIDキーボードのキーを押したような動作ができるが、引数としてアルファベットはASCIIコードを受け付け、HID Usage IDに変換してから送出しているので送れないキーがある。できれば余計な変換なしでHID Usage IDをそのまま送りたい。
 キーボードのコードを送信している部分 HID.cpp内のKeyboard_::sendReport(KeyReport* keys)はUSBAPI.hではprivateで宣言されている。USBAPI.hをコピーしてここだけpublic宣言にすればダマせるかなとやってみたがそんなのは通用しなかった。ここはコンパイル済で提供されているのでいじると大げさだしそんな実力はない。ということで、sendReport()内で呼び出してるHID_SendReport()は隠されてないのでこれを呼び出すArduinoライブラリを作ってみた。

https://gist.github.com/2ad9f7a713f46149e72f

ほぼHID.cppからのコピペですよ。

PS/2キーボード変換器の製作(16) ArduinoIDE1.0.1

Bootloaderメモ:
ArduinoのブートローダをいじってHIDのみホストに認識させることはできないだろうか?
dfu-programmer

ATmega 32u4 bootloader without ISP connection

USBメモ:
Arduino Leonardoを使ってUSBキーボード相当を実現しようとすると日本語キーボードの一部(¥、_)に対応するコードが送信できない。keyboard.press()を実現している部分をArduinoIDE1.0.1のソースから持ってきてそのままのコードを送れるように書き換えた。
ただしコンパイルが通った程度&汚いのでとりあえず置いとく。今週ちゃんと書きなおす。

https://gist.github.com/3827425

温度センサ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をつなぐとそっちが勝つ。
 

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


記事検索
プロフィール

hardyboy

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