
現在、梱包上の問題でスイッチサイエンスでのHSES-LCD24の販売が停止されています。対策の目途は立っていますので、お盆明けぐらいには再開できると思います。
さて、HSES-LCD24に文字を表示させるプログラムですが、前回紹介したサンプルプログラムESP8266WebServer/HelloServerをベースに簡単に作ってみました。ソースは、この記事の最後に置いておきます。
拡張性を考え、
/printというパスに、文字表示のハンドラを設定しました。パラメータで表示にひつような情報を渡します。現在有効なパラメータを以下に示します。
[cpp]
text: // 表示する文字列
clear: // 画面クリアの有無、 1:全クリア、 2: x0,y0,x1,y1で指定した領域のみクリア
size: // 文字サイズ
rotation: // 描画座標の向き、デフォルト3
x,y: // 文字描画の位置
color: // 文字描画色、 #rrggbb または white, black, red, green, blueなど
bg: // クリアに使用する背景色
x0,y0,x1,y1: // 部分クリアの領域指定
[/cpp]
動作確認はブラウザで行えます。プログラムを書き込み、WiFiと接続できると、表示は次のようになります。

HSES-LCD24に割り当てられたIPアドレスが 192.168.0.104だったとして、ブラウザで
http://192.168.0.104/print?clear=1&size=3&text=Helloにアクセスすると、次の写真のように表示されます。

与えるパラメータの値を変えることで、表示をコントロールできます。
PC側のプログラムから表示を行うこともできます。
下のプログラムはPython3のプログラムで、1秒ごとに時刻を表示させています。
[python]
import urllib.request
import time
from datetime import datetime
ip_addr = '192.168.0.104'
url_date = "http://%s/print?clear=1&color=%%238080ff&x=21&y=80&size=3&text=%s"
url_time = 'http://%s/print?x=10&y=120&color=green&size=6&text=%s'
while(1):
s = datetime.now().strftime("%Y/%m/%d(%a)")
req = urllib.request.Request(url_date % (ip_addr,s));
the_page = urllib.request.urlopen(req).read()
s = datetime.now().strftime("%H:%M:%S")
req = urllib.request.Request(url_time % (ip_addr,s));
the_page = urllib.request.urlopen(req).read()
time.sleep(1)
[/python]
時刻を表示させる前に画面クリアをしていますので、多少ちらついて見えます。この辺は今後改良していきたいところです。
最後に、HSES-LCD24側のプログラムを以下に掲載します。
[cpp title="HSES_LCD24のプログラム"]
#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#define TFT_DC 15
#define TFT_CS 2
#define TFT_RST -1
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
const char* ssid = "ssid-name"; // 接続するWiFiのssidを設定
const char* password = "password"; // 接続するWiFiのパスワードを設定
ESP8266WebServer server(80);
typedef const struct {
const char *name;
uint16_t value;
} color_name_t;
color_name_t color_names[] = {
{"BLACK", ILI9341_BLACK},
{"LIGHTGREY", ILI9341_LIGHTGREY},
{"DARKGREY", ILI9341_DARKGREY},
{"BLUE", ILI9341_BLUE},
{"GREEN", ILI9341_GREEN},
{"RED", ILI9341_RED},
{"YELLOW", ILI9341_YELLOW},
{"WHITE", ILI9341_WHITE},
{"PINK", ILI9341_PINK},
{NULL, 0},
};
struct {
int16_t x0;
int16_t y0;
int16_t x1;
int16_t y1;
uint16_t bg_color;
} lcd_cont = { 0, 0, 320, 240, ILI9341_BLACK};
void handleRoot() {
server.send(200, "text/plain", "NetLCD server");
}
static boolean getHex(const char *s, int *pVal)
{
int i,vv=0;
for(i=0; i<2; i++){
int v;
if(!isxdigit(s[i]))
return false;
if(s[i] > 'f') return false;
else if(s[i] >= 'a') v = s[i] - 'a' + 10;
else if(s[i] > 'F') return false;
else if(s[i] >= 'A') v = s[i] - 'A' + 10;
else if(s[i] > '9') return false;
else if(s[i] >= '0') v = s[i] - '0';
else return false;
vv = vv * 16 + v;
}
*pVal = vv;
return true;
}
static boolean getColor( const char *str, uint16_t *pColor)
{
if(*str == '#'){
int r,g,b;
if(getHex(str+1, &r) && getHex(str+3, &g) && getHex(str+5, &b)) {
*pColor = tft.color565(r,g,b);
return true;
}
Serial.print("Bad color:\"");
Serial.print(str);
Serial.println("\" found.");
return false;
}
else {
color_name_t *p;
for(p=color_names; p->name; p++){
if(stricmp(str, p->name)==0){
*pColor = p->value;
return true;
}
}
Serial.print("Undefned color name:\"");
Serial.print(str);
Serial.println("\" found.");
return false;
}
}
void handlePrint() {
for(int i=0; i<server.args(); i++){
String name = server.argName(i);
String value = server.arg(i);
if(name == "text")
tft.print(value.c_str());
else if(name == "clear") {
if(value == "1"){
tft.fillScreen(lcd_cont.bg_color);
tft.setCursor(0,16);
}
else if(value == "2"){
tft.fillRect(lcd_cont.x0, lcd_cont.y0, lcd_cont.x1, lcd_cont.y1,
lcd_cont.bg_color);
}
}
else if(name == "size")
tft.setTextSize(value.toInt());
else if(name == "rotation")
tft.setRotation(value.toInt());
else if(name == "x")
tft.setCursor( value.toInt(), tft.getCursorY());
else if(name == "y")
tft.setCursor( tft.getCursorX(), value.toInt());
else if(name == "color") {
uint16_t color;
if(getColor(value.c_str(), &color))
tft.setTextColor(color);
}
else if(name == "bg") {
getColor(value.c_str(), &lcd_cont.bg_color );
}
else if(name == "x0")
lcd_cont.x0 = value.toInt();
else if(name == "y0")
lcd_cont.y0 = value.toInt();
else if(name == "x1")
lcd_cont.x1 = value.toInt();
else if(name == "y1")
lcd_cont.y1 = value.toInt();
else {
Serial.print("param:");
Serial.print(name.c_str());
Serial.print(" not defined.");
Serial.println();
}
}
server.send(200, "text/plain", "Ok");
}
void handleNotFound(){
String message = "File Not Found\n\n";
message += "URI: ";
message += server.uri();
message += "\nMethod: ";
message += (server.method() == HTTP_GET)?"GET":"POST";
message += "\nArguments: ";
message += server.args();
message += "\n";
for (uint8_t i=0; i<server.args(); i++){
message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
}
server.send(404, "text/plain", message);
}
void setup(void){
Serial.begin(115200);
tft.begin();
tft.setTextSize(2);
tft.setRotation(3);
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(2, 16);
tft.println("Initialize");
WiFi.begin(ssid, password);
Serial.println("");
tft.print("connecting");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
tft.print(".");
}
Serial.println();
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
tft.println();
tft.print("connected to ");
tft.setTextColor(ILI9341_GREEN);
tft.println(WiFi.localIP());
tft.setTextColor(ILI9341_WHITE);
server.on("/", handleRoot);
server.on("/print", handlePrint);
server.onNotFound(handleNotFound);
server.begin();
Serial.println("HTTP server started");
tft.println("start");
}
void loop(void){
server.handleClient();
}
[/cpp]
今後、このプログラムに、もう少し機能を追加していく予定です。