頂戴した LCD シールドで暫定的に遊んでみた
結果的に随分放置することになってしまったが、ある意味、正解だったのかもしれない。
話は少し長くなるが、まとめておいて(公益的な意味でも)損はないと思うので少々お付き合い下さい。「付き合いきれん!」という方はこれの次のエントリへ。(Coming Soon …たぶん)
…
っていうのを(長編覚悟で)書こうと思っていたのだけれども、こうして書いているあいだにも Twitter 経由で基板がガンガン改良されており、私の考えたこと・試したことが瞬時に陳腐化してゆく。私の浅慮など秒殺状態。なんか虚しくなってきたので、とりあえず昔書いたスケッチだけ上げておしまいにする。
因みにここで使用している「LCD シールド」はプロトタイプ。ユーザーテストという形で試作基板を分けていただいたものに(概ね)自前でパーツ実装している。できるだけ変態「シェフの気紛れパーツ」を使用することに腐心した(なんでだ)
- LED:http://akizukidenshi.com/catalog/g/gP-00282/
- digital 13 番用の LED 。
- タクトSW:http://akizukidenshi.com/catalog/g/gP-02532/
- Arduino リセット用。
- 普通のリードタイプのタクトSW推奨。
敢えて面実装を使用するのは激烈無意味。
今回はなんとなくやってみたかったので。
- CRD:http://akizukidenshi.com/catalog/g/gI-03084/
- R1 。本来は抵抗(1kΩ程度)を取付。
LED 差替式にする場合は CRD が好都合。
- R1 。本来は抵抗(1kΩ程度)を取付。
- ソケット:(千石:丸ピンソケット ピンのみ ¥360/100pcs)
- 丸ピン ICソケットのピンだけ売り品。結構重宝。
- 100Ω:拾った(ぉぃ)
- R2 。輝度調整用半固定不使用の場合、若しくはいっぱいまで回した場合のリミッタ。
- LCD 内蔵バックライト不使用の場合は不要。
- スライドSW:http://akizukidenshi.com/catalog/g/gP-02627/
- 6P 2位置 2回路 2接点。LCD 制御信号に使用するピンを切り替える。
- ピンヘッダを立ててもよい。(→ジャンパピン使用)
- 半固定:http://www.marutsu.co.jp/user/shohin.php?p=76910
- Pot1(Contrast):5k 〜 10kΩ程度。
- こちらの可変抵抗は必須。
- :http://www.marutsu.co.jp/user/shohin.php?p=37953
- Pot2(Brightness):500 〜 1kΩ程度。
- バックライト不使用、若しくは輝度固定の場合は、不要。
輝度固定とする場合は裏面の半田ジャンパを埋める。
- 連結ソケット:http://akizukidenshi.com/catalog/g/gC-04045/
- :http://akizukidenshi.com/catalog/g/gC-04046/
- 普通はピンヘッダでも充分。
- ピンソケット:http://akizukidenshi.com/catalog/g/gC-03077/
- ピンヘッダ:http://akizukidenshi.com/catalog/g/gC-00167
あ、あと勿論、CLCD モジュール(これ とか このへん )が必要。秋月の以外を使用する場合は電源ピンのレイアウトが異なる可能性があるので、要注意。
液晶モジュールを固定するためにスペーサなりなんなりも要る。勿論なくても平気ではある。このへんもいろいろと(ノウハウ的なものを含めて)あるのだが、書くのが面倒になったので割愛。
時期は不明だが、今後ネット通販等を通じて市販もされるようななるであろう量産版の LCD シールドには PWM 用の配線が標準搭載されるなど、まだまだ改良が加えられてゆくことになりそうな雰囲気なので、まあ、参考程度に。
…と思っていたのだが、どうやら量産型は(すみません量産型って言いたいだけです)シリパラ変換の CMOS IC を使って占有ポートを節約するタイプになる模様…。つまり、ここで紹介しているものはスケッチも流用できないし、あんまり参考にならないです。すみません m(_ _)m
/* OKAERINASA"I" 2010/06/14 2010/08/15 By OkibiWorksLabo. */ #include <LiquidCrystal.h> LiquidCrystal lcd(12, 11, 5, 4, 3, 2); const int ledPin = 13; const int lcdContPin = 6; const int sensPin = 5; const int pseudoVCC = 17; const int pseudoGND = 18; int pos = 3; byte lcdChar[3][8] = { {16, 8, 4, 6, 5, 4, 4, 0}, // Reverse HIRAKAGANA "i" {31, 21, 31, 21, 31, 21, 31, 0}, // HAYABUSA SOLAR PANEL {14, 4, 31, 14, 14, 4, 0, 0}, // HAYABUSA BODY }; int sensRead() { int lcdOn; int sens; int thresh = 900; // 900 の場合 4.4V ぐらい sens = analogRead(sensPin); lcd.setCursor(12,0); lcd.print(sens); lcd.print(" "); if (sens > thresh) { lcdOn = 1; } else { lcdOn = 0; } // lcdOn = sens / thresh; // 正の相関の場合これでもいい return lcdOn; } void lcd_bright(int dly) { int dStep = 50; float vUpper = 3.5; // 電圧の上限 float vLower = 0.2; // 電圧の下限 float volt; for(int i = 0; i <= dStep / 2; i++) { volt = vLower + (i * (vUpper - vLower) / dStep); analogWrite(lcdContPin, volt / 5 * 256 * sensRead()); delay(dly / dStep); } digitalWrite(ledPin, HIGH); for(int i = dStep / 2; i >= 0; i--) { volt = vLower + (i * (vUpper - vLower) / dStep); analogWrite(lcdContPin, volt / 5 * 256 * sensRead()); delay(dly / dStep); } digitalWrite(ledPin, LOW); } void setup() { // Serial.begin(9600); pinMode(ledPin, OUTPUT); pinMode(lcdContPin, OUTPUT); pinMode(pseudoVCC, OUTPUT); pinMode(pseudoGND, OUTPUT); digitalWrite(pseudoVCC, HIGH); digitalWrite(pseudoGND, LOW); for(int i = 0; i<=2; i++) { lcd.createChar(i, lcdChar[i]); } lcd.begin(16, 2); // lcd.begin( 8, 2); lcd.clear(); lcd.write(0xB5); lcd.write(0xB6); lcd.write(0xB4); lcd.write(0xD8); lcd.write(0xC5); lcd.write(0xBB); lcd.write(0); // for(int i = 0; i<=23; i++){ // lcd.scrollDisplayRight(); // delay(50); // } randomSeed(analogRead(0)); } void loop() { lcd.setCursor(pos, 1); lcd.write(32); lcd.write(1); lcd.write(2); lcd.write(1); lcd.write(32); // delay(1000); lcd_bright(3000); pos = pos + random(3) - 1; if(pos < 1) { pos = 2;} if(pos > 11) { pos = 10;} }
「…なんで SMD …?」とかそのへんは気にしてはいけないポイントであります*1。
これが右下隅にくっついてる。LCD シールドは、こういう単体のセンサのテストなどにも非常に便利。
/* temperture003 for LM35D, 60, 61 for LCD panel 2009/11/21 2009/11/22 2009/11/23 2010/08/13 *bugfix By OkibiLabo. */ #include <LiquidCrystal.h> LiquidCrystal lcd(12, 11, 5, 4, 3, 2); // Enable -> GND const int ledPin = 13; const int thmPin = 5; // const int pseudoGND = 6; // const int pseudoVCC = 7; const int pseudoGND = 18; const int pseudoVCC = 17; // const byte deg = B11011111; byte lcdChar[8][8] = { {12, 18, 18, 12, 0, 0, 0, 0}, // Degree Mark { 9, 5, 1, 12, 1, 5, 11, 0}, // following means {31, 1, 31, 0, 31, 21, 31, 0}, // thermometer ("Ondokei") { 0, 3, 2, 3, 2, 4, 21, 0}, // by Japanese KANJI. {14, 31, 17, 31, 17, 14, 29, 0}, { 1, 23, 3, 17, 7, 4, 23, 0}, { 1, 25, 7, 17, 25, 9, 25, 0}, { 0, 0, 24, 0, 0, 0, 0, 0}, }; // const float thmPitch = 0.01; // for LM35D , LM61 const float thmPitch = 0.00625; // for LM60 *bugfix // const float thmOffset = 0; // for LM35D const float thmOffset = 0.424; // for LM60 // const float thmOffset = 0.6; // for LM61 int aValue = 0; float temp = 0; float aRef ; float gain ; void ondokei_LCD() { for(int i = 1; i<=7; i++) { lcd.createChar(i, lcdChar[i]); } lcd.begin(16, 2); // lcd.begin( 8, 2); lcd.clear(); lcd.print("Hello!"); lcd.setCursor(0, 1); for(int i = 1; i<=7; i++) { lcd.write(i); } delay(2000); for(int i = 0; i<=23; i++){ lcd.scrollDisplayRight(); delay(50); } } int pickDecimal(float a, int digit) { float d = pow(10, -1 - digit); return int((abs(a * d) - abs(int(a * d))) * 10); } void setup() { Serial.begin(9600); pinMode(ledPin, OUTPUT); pinMode(pseudoGND, OUTPUT); pinMode(pseudoVCC, OUTPUT); analogReference(INTERNAL); aRef = 1.1; // analogReference(EXTERNAL); // 基準電圧外部化には問題ありとの噂 // aRef = 2.5; // analogReference(DEFAULT); // aRef = 5; gain = 1.0; digitalWrite(pseudoVCC, HIGH); digitalWrite(pseudoGND, LOW); lcd.createChar(0, lcdChar[0]); ondokei_LCD(); } void loop() { digitalWrite(ledPin, HIGH); delay(200); aValue = analogRead(thmPin); temp = ((float)aValue / gain / 1024 * aRef - thmOffset) / thmPitch; digitalWrite(ledPin, LOW); delay(800); /* */ Serial.print (aValue); /* */ Serial.print (" "); /* */ Serial.println(temp); lcd.clear(); lcd.print("Temp:"); lcd.setCursor(1, 1); lcd.print((long)temp); lcd.print("."); lcd.print(pickDecimal(temp + 0.05 * temp / abs(temp), -1)); // lcd.print(deg, BYTE); lcd.write(0); lcd.print("C"); lcd.setCursor(8, 0); lcd.print("Gain"); lcd.print(gain); lcd.setCursor(8, 1); lcd.print("Ref"); lcd.print(aRef); lcd.print("V"); }
スケッチの説明その他は、気力が戻ってきたら、ぼちぼちやるかもしれません。
基本的にそんな面倒くさいことはしていないので(下手過ぎて(というか行き当たりばったりにもほどがある)読むに耐えないコードではありますが)解説も何も不要だとは思いますけども。
因みに、LM35 にしても LM60 , 61 にしても、どうも若干温度が高めに計測されるという傾向が私のところでは、あります。データシートに示されている仕様の誤差範囲内には充分収まって入るようですが、気になるところではあります。(そもそもこの手の温度センサは相対値で読み取ることでより正確な運用ができるものだという認識ですが。)実用上は 2℃程度リニアにマイナス補正をかけてやると、なんとなくそのあたりの空気温度と比較してちょうどいい感じになりそうな気がします。
Arduino 側の analogRead() 関数による読み値はさほど悪くない気がしました。基準電圧を INTERNAL に設定した際の誤差も気になるところではありますが、系統誤差があるというよりはブレが大きいということなのではないかという気がします。(ブレは相当ひどい様子*2。)
*1:無論、TO-92 パッケージもございます。
http://akizukidenshi.com/catalog/g/gI-02490/