LCD KEY SHIELDをuno ESP32-S3で動かしてみた。
WEB経由でなくスタンドアロンでSPI MINITORを動かせる余地が欲しかったので、LCDとキーが合体しているSHIELDを買ってみた。Uno用だったので、ESP32に当てはめないと動かないので、改造が必要でちょっと面倒かなと思った。今回買ったLCD KEY SHIEILDは下記の物。それに合わせてESP32-S3のUnoに合わせるボードも大した値段ではなかったので一緒に買った。
Arduino用LCDキー付きキーボードカバー,青色のディスプレイ,1602モジュール,lcd1602 – AliExpress 502
Bluetooth互換フラッシュボードモジュール,ワイヤレス開発モジュール,ch340,n8r2,n16r8,UNOESP-32,d1,r3,ESP32-S3 – AliExpress 502
LCD KEY SHILEDはLCDはパラネル出力で、KEYはアナログ入力であることが分かった。
それに対応するuno EPS32-S3のピン配置は下記の通りになる。
仕様書から見比べた使用は下記のようで、I2C接続よりいろいろPINを使っているなあというのが印象。
とりあえず、ピンレイアウトが分かったので、まずはLCDに文字を出そうと思った。しかし、うまく行かなった。正確には問題なかっただけど、KEYSHIELDにある、LCDの明度をいじる半固定抵抗が細かくて、かなりねじ込まないと文字が出てこなかった。20X4行は一周しないで出来たので、半固定抵抗はあまり触らない様にしたいので、触らなかったのが敗因だった。これは、とりあえず、ネジがくるくる回るので、閉め切るまで回すのがよいかと。今回は、uno ESP32-S3の使い方がよくなかったのかと思って、実績のあるESP32でも同様だったのでわかった。
ピンレイアウトを間違えなくて、LCDの半固定抵抗の調整がちゃんとできれば文字は表示できる。
次に、問題が発生したのは、KEY入力だった。作ってみたけどSELECTキーが認識できなかった。LCD KEY SHIELDはIO2へアナログ電圧で入力して、ESP32のA/Dコンバーターで認識する形態をとるだけど、LCD KEY SHIELDが5Vで作られているようで、ESP32にはオーバー電圧だった。何も押さないと、4V弱がIO2に入力されている。
SELECTを選択すると、3.4Vにわかる。しかし、ESP32のA/Dコンバーターは3.3V仕様なので、何も入れない状態とSELECTの選択ができないことが分かった。
それなら、SPI MONITERでやった通り、抵抗を使って分圧させればよい。まずは、IO2とkeyの間をパターンカットする
抵抗2本を追加して、分圧させる。
未入力で2V弱になったので、これで、3.3V以内になったので判別できるようになる。
SELECTを押して1.5Vになったので、判別が可能になった。
合わせて、これはI2C接続に変えたLCD KEY SHILD接続が簡単なので、これも合わせて作ってみた。ボタンを押しているのが、こっちの写真しかなかったので、こっちを利用させてもらった。パラレル接続もいいけど、I2C接続なら2つのGPIOでいろいろなデバイスをつなげられるので便利だ。
今回動作確認したスケッチは下記の通り、
#include <LiquidCrystal.h>
#define KEYRIGHT 0
#define KEYUP 1
#define KEYDOWN 2
#define KEYLEFT 3
#define KEYSELECT 4
#define KEYNONE 5
#define KEYERR 6
#define KEY_AD 2 // analog input oprt
// A/D input Threshold
#define THRIGHT 100
#define THUP 500
#define THDOWN 1000
#define THLEFT 1500
#define THSELECT 2000
#define THNONE 2300
/* LCD Assign ESP32 */
//#define LCD_RS 19
//#define LCD_RW // GND
//#define LCD_EN 14
//#define LCD_D4 18
//#define LCD_D5 5
//#define LCD_D6 17
//#define LCD_D7 16
/* LCD Assign ESP32-S3 UNO */
#define LCD_RS 21
//#define LCD_RW // GND
#define LCD_EN 46
#define LCD_D4 19
#define LCD_D5 20
#define LCD_D6 3
#define LCD_D7 14
LiquidCrystal lcd(LCD_RS, LCD_EN, LCD_D4, LCD_D5, LCD_D6, LCD_D7);
void setup()
{
Serial.begin(115200);
delay(100);
lcd.begin(16, 2);//LCDの初期化
delay(100);
lcd.clear();
}
/*********************/
/* Keypad 入力処理 */
/*********************/
const struct {
short dat; // A/D入力閾値
int ret; // 戻り値
} t_key[5] = {
{ THRIGHT , KEYRIGHT },
{ THUP , KEYUP },
{ THDOWN , KEYDOWN },
{ THLEFT , KEYLEFT },
{ THSELECT,KEYSELECT }
};
int red_key()
{
int i;
int r;
int key;
r = KEYERR;
key = analogRead(KEY_AD);
if( key > THNONE ) r = KEYNONE;
else {
for( i = 0; i < 5; i++ ) {
if( key < t_key[i].dat ) {
r = t_key[i].ret;
break;
}
}
}
return( r );
}
/*********************/
/* 入力Key表示 */
/*********************/
void prn_key(int key)
{
lcd.setCursor(0,1); //カーソルの移動
switch (key) {
case KEYRIGHT:
lcd.print("RIGHT ");
break;
case KEYLEFT:
lcd.print("LEFT ");
break;
case KEYUP:
lcd.print("UP ");
break;
case KEYDOWN:
lcd.print("DOWN ");
break;
case KEYSELECT:
lcd.print("SELECT ");
break;
case KEYNONE:
lcd.print("NONE ");
break;
case KEYERR:
lcd.print("ERROR ");
break;
default:
break;
}
}
/*********************/
/* メインLoop */
/*********************/
void loop()
{
int key1, key2;
Serial.print("MAIN LOOP\n");
lcd.setCursor(0,0); //カーソルの移動
lcd.print("www.misago.com");
key2 = 0;
while( 1 ) {
do {
key1 = red_key();
delay(100);
Serial.printf("KEY %d\n", key1 );
} while( key1 == key2 );// 入力に変化あり?
prn_key( key1 );
key2 = key1;// 現入力キーを保存
delay(1000);
}
}
最近のコメント