アナログ風ゲージ
2023.05.15
YouTube でも紹介しています。画像をクリックすると再生できます。
12 Useful & Interesting ESP32 Projects for Beginners!
YouTube でスタイリッシュな計器を見つけました。
この動画では、ESP32ボードに240x135 ST7789 SPIディスプレイが搭載されているTTGO T-DISPLAYが使用されています。
ロータリー エンコーダーの回転度合いを表示するとともに PC ファンを制御しています。
注目したのはこの表示部分です。色々と活用できそうなので、gitHubにアップされていたソースコードを変更して動くようにしてみました。
ディスプレイとマイコンボード一体型は使い勝手がよくないので、動作環境にはマイコンボードとディスプレイを別々に用意しました。
表示に使用されているフォントは、ビルド時、SPI FLASHに保存されるので、Arduino UNOなどは使用できません。
4MBのSPI FLASHを実装しているESP8266ボードのWeMos D1 mini V3.0を使用しました。
●WeMos D1 Mini V3.0
送料込みで418円でした。Arduino NANO互換機よりもかなりお安いです。
A mini wifi(802.11) board with 4MB flash based on ESP-8266EX(80MHz).
LOLIN D1 mini v3.1.0
MCUに80MHzのESP-8266EX、4MBのSPI FLASH、80KBのRAM、オンボードWiFiと非常にコスパに優れていて、日本ではあまり知られていませんが海外では人気のボードです。
Pinout
Note. All of the IO pins run at 3.3V.
Getting Started with WeMos D1 Mini
ソースコードのビルドには、PlatformIOを使用しています。
Arduino開発環境構築 PlatformIO
ボード情報をみてみます。
$ pio boards 'WeMos D1'
Platform: espressif32
===============================================================
ID MCU Frequency Flash RAM Name
--------------- ----- --------- ----- ----- -------------------
wemos_d1_uno32 ESP32 240MHz 4MB 320KB WEMOS D1 R32
wemos_d1_mini32 ESP32 240MHz 4MB 320KB WeMos D1 MINI ESP32
Platform: espressif8266
===============================================================
ID MCU Frequency Flash RAM Name
------------ ------- --------- ----- ---- ---------------------
d1 ESP8266 80MHz 4MB 80KB WEMOS D1 R1
d1_wroom_02 ESP8266 80MHz 2MB 80KB WeMos D1 ESP-WROOM-02
d1_mini ESP8266 80MHz 4MB 80KB WeMos D1 R2 and mini
d1_mini_lite ESP8266 80MHz 1MB 80KB WeMos D1 mini Lite
d1_mini_pro ESP8266 80MHz 16MB 80KB WeMos D1 mini Pro
プロジェクトを作成します。
$ mkdir ~/WeMosD1Mini
$ cd ~/WeMosD1Mini
$ pio init -b d1_mini
ピン定義を確認しておきます。
$ cat ~/.platformio/packages/framework-arduinoespressif8266/variants/d1_mini/pins_arduino.h
#define PIN_WIRE_SDA (4)
#define PIN_WIRE_SCL (5)
static const uint8_t SDA = PIN_WIRE_SDA;
static const uint8_t SCL = PIN_WIRE_SCL;
#define LED_BUILTIN 2
static const uint8_t D0 = 16;
static const uint8_t D1 = 5;
static const uint8_t D2 = 4;
static const uint8_t D3 = 0;
static const uint8_t D4 = 2;
static const uint8_t D5 = 14;
static const uint8_t D6 = 12;
static const uint8_t D7 = 13;
static const uint8_t D8 = 15;
static const uint8_t RX = 3;
static const uint8_t TX = 1;
●定番Lチカプログラム
$ vi src/builtin.ino
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
delay(1000);
}
$ pio run -t upload
次に解像度240x135のST7789ドライバ使用のTFTディスプレイを用意します。
●Adafruit 1.14" 240x135 Color TFT Display + MicroSD Card Breakout - ST7789
The TFT driver (ST7789) is very similar to the popular ST7735, and our Arduino library supports it well. There was a little space so Adafruit placed a microSD card holder so you can easily load full color bitmaps from a FAT16/FAT32 formatted microSD card. (GREENTAB)
上記のAdafruit製ディスプレイも製造終了品のようなのですが、MOUSER.JPで大量に在庫があったのでストックしておきました。
●ロータリーエンコーダ
ロータリーエンコーダには、壊れたマウスから部品取りしてあったものをブレッドボード上に配線しやすいように加工しました。
●配線
ST7789 | - | D1 Mini | - | Encoder |
TFTCS | - | [D8]HCS | | |
DC | - | [D3] | | |
RST | - | [D4] | | |
LIT | - | [D0] | | |
SCK | - | [D5]HSCK | | |
MISO | - | [D6]HMISO | | |
MOSI | - | [D7]HMOSI | | |
Vin | - | 3.3V | | |
GND | - | GND | - | GND |
| | D1 | - | ENC_A |
| | D2 | - | ENC_B |
●EspGauge ソースコード
VolosR/EspGauge
取り合えず、ビルドだけ通したいのであれば、設定ファイルは下記のような感じです。
TFT_eSPI の設定で、User_Setup.h 内のピン番号を書き換えて使用する方法を見かけますが、お薦めできません。
$ vi platformio.ini
[env:d1_mini]
platform = espressif8266
board = d1_mini
framework = arduino
lib_deps =
adafruit/Adafruit GFX Library
bodmer/TFT_eSPI @ ^2.5.2
build_flags =
-fpermissive
-D SERIAL_BAUD=115200
-D USER_SETUP_LOADED
-D LOAD_GLCD
-D ST7789_DRIVER
-D TFT_WIDTH=135
-D TFT_HEIGHT=240
-D TFT_DC=D3
-D TFT_CS=-1
-D TFT_RST=D4
-D TFT_BL=-1
-D TFT_ROTATION=2
-D SPI_FREQUENCY=40000000
ビルドしてコードをマイコンにアップロードできますが、フォント情報を取り込めず不具合が発生してしまいました。
EspGauge.ino (抜粋)
void setup() {
........
img.setSwapBytes(true);
img.createSprite(220, 105);
img.setTextDatum(4);
........
}
void loop() {
........
img.fillSprite(TFT_BLACK);
img.fillCircle(sx,sy,124,color5);
img.setTextColor(TFT_WHITE,color5);
img.setFreeFont(&FreeSans9pt7b);
for(int i=0;i<10;i++)
if(start[i]+angle<360){
img.drawString(cc[i],x[start[i]+angle],y[start[i]+angle]);
........
img.pushSprite(10, 30);
ESPGaugeでは、Adafruit GFX ライブラリをコアとして、機能拡張された TFT_eSPIライブラリが使用されています。
制作者の意図を考えると、毎回再描画される決まりきった部分をテンプレート化するために、スプライト機能を用いたように思えるのですが、
そのテンプレート部分にも更新が発生しており、最適化されていないようです。
また、スプライト機能は小さなキャラクタを1つ描いておいて、それを複製させるのには有効ですが、画面の大半をスプライトしようとすると
膨大なRAMを消費するため、ESP32-S2,S3のような数MBのPSRAMを実装していないマイコンでは対応できません。
●ソースコードの変更点
・TFT_eSPIライブラリは使わないように変更
・ロータリーエンコーダの検出ロジック変更
【Arduino】マウスホイール(ロータリーエンコーダ)の回転量を取得する
・割り込み処理→loop()内処理に変更
ソースコードは変更点が多過ぎて説明する気になれません。
#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>
#include "FreeSans9pt7b.h"
#include "fonts.h"
#define TFT_CS D8
#define TFT_RST D4
#define TFT_DC D3
#define TFT_BL D0
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);
#define WHITE 0xFFFF
#define BLACK 0x0000
#define ORANGE 0xFBE0
#define SKYBLUE 0x8410
#define color4 0x15B3
#define color5 0x00A3
volatile int counter = 0;
float gauge;
double rad=0.01745;
float x[360];
float y[360];
float px[360];
float py[360];
float lx[360];
float ly[360];
int r = 100;
int sx = 110 + 10;
int sy = 116 + 30;
char *cc[10]={" 0","10","20","30","40","50","60","70","80","90"};
int start[10];
int startP[60];
#define ENC_A D1
#define ENC_B D2
bool debounce=true;
uint8_t prev = 0;
int angle = 270;
int lastAngle = 0;
void drawGauge()
{
char buf[16];
gauge = ((angle-270)/3.60)*-1;
if(gauge < 0) gauge = gauge + 100;
// tft.fillCircle(sx,sy,124,color5);
tft.fillCircle(sx,sy,112,color5);
// tft.setTextColor(color5);
tft.setFont(&FreeSans9pt7b);
tft.setTextColor(WHITE);
for(int i=0;i<10;i++) {
if(start[i]+angle<360){
drawString(cc[i],x[start[i]+angle]-10,y[start[i]+angle]+9);
tft.drawLine(px[start[i]+angle],py[start[i]+angle],lx[start[i]+angle],ly[start[i]+angle],WHITE);
} else {
drawString(cc[i],x[(start[i]+angle)-360]-10,y[(start[i]+angle)-360]+9);
tft.drawLine(px[(start[i]+angle)-360],py[(start[i]+angle)-360],lx[(start[i]+angle)-360],ly[(start[i]+angle)-360],WHITE);
}
}
tft.setFont(&DSEG7_Modern_Bold_20);
sprintf(buf, "%d", (uint8_t)gauge);
if (gauge < 10) {
drawString(buf,sx-4,sy-16);
} else {
drawString(buf,sx-20,sy-16);
}
for(int i=0;i<60;i++) {
if(startP[i]+angle<360)
tft.fillCircle(px[startP[i]+angle],py[startP[i]+angle],1,SKYBLUE);
else
tft.fillCircle(px[(startP[i]+angle)-360],py[(startP[i]+angle)-360],1,SKYBLUE);
}
tft.fillTriangle(sx-1,sy-70,sx-5,sy-56,sx+4,sy-56,ORANGE);
tft.setTextColor(WHITE);
tft.setFont();
drawString("POWER",104,96);
tft.setFont(&FreeSans9pt7b);
drawString("%",sx+16,sy-16);
}
void updateEncoder()
{
int value = 0;
uint8_t ab, encoded;
if (debounce) {
for (uint8_t i=0; i < 20; ++i) {
uint8_t a = digitalRead(ENC_A);
uint8_t b = digitalRead(ENC_B);
ab = (a << 1) | b;
encoded = (prev << 2) | ab;
if(encoded == 0b1101 || encoded == 0b0100 || encoded == 0b0010 || encoded == 0b1011){
value++;
} else if(encoded == 0b1110 || encoded == 0b0111 || encoded == 0b0001 || encoded == 0b1000) {
value--;
}
prev = ab;
delay(10);
}
if (value > 0) {
angle = angle + 6;
} else if (value < 0) {
angle = angle - 6;
}
if(angle>=360) angle=0;
if(angle< 0) angle=354;
// Serial.print("angle:");
// Serial.println(angle);
}
}
void drawOnOFF(bool onOff)
{
tft.fillRect(192,11,50,16,BLACK);
tft.drawCircle(202,18,7,WHITE);
tft.drawCircle(222,18,7,WHITE);
tft.drawLine(202,11,222,11,WHITE);
tft.drawLine(202,25,222,25,WHITE);
tft.fillRect(203,12,18,13,BLACK);
if (onOff) {
tft.fillCircle(202,18,4,ORANGE);
} else {
tft.fillCircle(222,18,4,ORANGE);
}
}
void drawString(char *str, uint8_t x, uint8_t y)
{
tft.setCursor(x, y);
tft.print(str);
}
void setup()
{
Serial.begin(9600);
pinMode(ENC_A, INPUT_PULLUP);
pinMode(ENC_B, INPUT_PULLUP);
/*
ledcSetup(pwmLedChannelTFT, 5000, 8);
ledcAttachPin(TFT_BL, 0);
ledcWrite(0, 90);
*/
pinMode(TFT_BL,OUTPUT);
analogWrite(TFT_BL, 64); // 0 - 255
tft.init(135, 240);
tft.setRotation(3);
tft.fillScreen(BLACK);
// tft.setFont(&FreeSans9pt7b);
drawString("ON/OFF",196,4);
drawString("CONTROL",20,20);
drawString("MOTOR",20,6);
tft.setTextColor(color4);
drawString("REVOLUTIONS PER MINUTE",60,4);
drawOnOFF(true);
int b=0;
int b2=0;
for(int i=0;i<360;i++) {
x[i]=(r*cos(rad*i))+sx;
y[i]=(r*sin(rad*i))+sy;
px[i]=((r-16)*cos(rad*i))+sx;
py[i]=((r-16)*sin(rad*i))+sy;
lx[i]=((r-24)*cos(rad*i))+sx;
ly[i]=((r-24)*sin(rad*i))+sy;
if(i%36==0) {
start[b]=i;
b++;
}
if(i%6==0) {
startP[b2]=i;
b2++;
}
}
tft.fillCircle(sx,sy,124,color5);
tft.setTextColor(ORANGE);
tft.setFont(&FreeSans9pt7b);
// tft.setFont(&Slackey_Regular_16);
drawString("32465",92,30);
drawGauge();
}
void loop()
{
static int lastCounter = 0;
updateEncoder();
debounce = false;
if(angle != lastCounter) lastCounter = angle;
if(angle!=lastAngle) {
lastAngle = angle;
drawGauge();
}
debounce=true;
}
言い訳:月2回の動画配信のために、手の空いたときに作業を行っているのですが、情報収集→テスト環境構築→ソースコード解析→システム設計→コーディング→検証→YouTube動画解説サイト編集(当サイト)→YouTube動画作成の工程をこなすには時間的にかなり無理があります。それで作成したコードは全然ブラッシュアップされていません。
●デフォルトフォントの変更
デフォルトフォントを変更します。
~/WeMosD1mini/ESP32Gauge/.pio/libdeps/d1_mini/'Adafruit GFX Library'/glcdfont.c
static const unsigned char font[] PROGMEM = {
・・・・・・・・
};
↓配列の中身を下記のデータに置き換えます
https://github.com/Bodmer/TFT_eSPI/blob/master/Fonts/glcdfont.c
static const unsigned char font[] PROGMEM = {
・・・・・・・・
};
デフォルトフォントを追加します。
https://github.com/Bodmer/TFT_eSPI/tree/master/Fonts/GFXFF/FreeSans9pt7b.h
をソースディレクトリにコピーします。
●検証
電源をいれた直後の状態です。
ロータリーエンコーダのローラーをくるくる回すとゲージも回転します。
今回はロータリーエンコーダーの数値表示に用いましたが、色々な用途への応用は容易です。
■参考文献
・Gauge for ESP32 and TFT (LilyGo T-Display)
・ロータリーエンコーダを使う(1)
|
Raspberry Pi(ラズベリー パイ)は、ARMプロセッサを搭載したシングルボードコンピュータ。イギリスのラズベリーパイ財団によって開発されている。
Arduinoで学ぶ組込みシステム入門(第2版)
●Arduinoを使って組込みシステム開発を理解する
・ハードウェアやソフトウェアなどの基礎知識/
・設計から実装までを系統的に説明するモデルベース開発/
・Arduinoを用いた実際の開発例
最新 使える! MATLAB 第3版
◆◆すぐに「使える!」 全ページフルカラー!◆◆
・MATLAB R2022bに対応し、解説もより詳しく!/
・コマンド・スクリプトの例が豊富で、動かして学べる!/
・超基本から解説。これから使いはじめる人にぴったり!/
・全編フルカラー、スクリーンショットも豊富!
Amazon Web Services基礎からのネットワーク&サーバー構築改訂4版
1.システム構築をインフラから始めるには/
2.ネットワークを構築する/
3.サーバーを構築する/
4.Webサーバーソフトをインストールする/
5.HTTPの動きを確認する/
6.プライベートサブネットを構築する/
7.NATを構築する/
8.DBを用いたブログシステムの構築/
9.TCP/IPによる通信の仕組みを理解する
C言語は第二の母国語: 独学学生時代から企業内IT職人時代に培った、独立のための技術とノウハウ 平田豊著
学生時代から独学でプログラミングをはじめ、企業内でデバイスドライバを開発し、そして独立後もたくさんのアプリケーション開発や技術書制作に携わってきた著者。その筆者が大事に使い続ける「C言語」の“昔と今”について、気づいたことや役立つ知識、使ってきたツールなどについて、これまで記してきたことを整理してまとめました。
本書では、現役プログラマーだけでなく、これからプログラミングを学ぶ学生などにも有益な情報やノウハウを、筆者の経験を元に紹介しています。
1冊ですべて身につくJavaScript入門講座
・最初の一歩が踏み出せる! 初心者に寄り添うやさしい解説
・最新の技術が身につく! 今のJavaScriptの書き方・使い方
・絶対に知っておきたい! アニメーションとイベントの知識
・プログラミングの基本から実装方法まですべて学べる
図解! Git & GitHubのツボとコツがゼッタイにわかる本
ソフトウェア開発では欠かすことのできないGit、GitHub。
これからGit、GitHubを使いたいという入門者の方でも、実際に手を動かしながら使い方を学べます。
C自作の鉄則!2023 (日経BPパソコンベストムック)
メーカー製のパソコンはスペックが中途半端で、自分が本当に欲しい機種がない――。そう思っている人には、ぜひ自作パソコンをお薦めします。自作パソコンのパーツは進化が速く、しかも驚くほど種類が豊富。価格も性能も、幅広く用意されているため、満足度100%の“自分だけの1台”を手に入れることができます。
Interface 2023年6月号
特集:第1部 フィルタ設計 基礎の基礎/
第2部 係数アプリや波形観測アプリで合点!FIR&IIRフィルタ作り/
第3部 配布プリント基板で体験!マイコンで動くフィルタ作り
日経Linux 2023年5月号
【特集 1】 AI時代の最強フリーソフト ~ 25のやりたいを実現!
【特集 2】 AWS、Azureのうまみを無料で体感!面倒なことはクラウドに任せよう
【特集 3】 新しいRaspberry Pi Cameraで遊んでみよう
【特集 4】 Linuxで旧型PCを復活! 1kg切るモバイルPCを「ChromeOS Flex」でChromebook化
ラズパイマガジン2022年秋号
特集:5大人気ボード 電子工作超入門
「半導体不足で在庫が不足し、電子工作のボードがなかなか買えない…」。そんな今にふさわしい特集を企画しました。5種の人気ボードにすべて対応した電子工作の入門特集です。「GPIO」や「I2C」を使った電子パーツの制御方法は、どのボードでも同じです。手に入れられたボードを使って、今こそ電子工作を始めましょう。
地方で稼ぐ! ITエンジニアのすすめ
学歴、理系の知識、専門スキル……全部なくてもITエンジニアになれる!
地方でも高収入でやりがいをもって働ける!ITエンジニアの魅力を一挙大公開
Raspberry Piのはじめ方2022
本書は、ラズパイやPicoの買い方やインストール、初期設定といった基本から、サーバー、電子工作、IoT、AIといったラズパイならではの活用方法まで、1冊でお届けします。
ラズパイをこれから始める方向けに、全36ページの入門マンガ「女子高生とラズベリーパイ」も巻末に掲載。これを読むだけでラズパイがどんなものなのか、すぐに分かって触れるようになります。
ハッカーの学校 IoTハッキングの教科書
生活にとけこみ、家電機器を便利にするIoT技術。
Webカメラなど、便利の裏側に潜むセキュリティの危険性をハッキングで検証。
専門家がパケットキャプチャからハードウェアハッキングまで、その攻撃と防御を徹底解説。
本書は2018年7月に刊行された「ハッカーの学校IoTハッキングの教科書」に一部修正を加えた第2版です。
攻撃手法を学んで防御せよ! 押さえておくべきIoTハッキング
本書は、経済産業省から2021年4月にリリースされた、IoTセキュリティを対象とした『機器のサイバーセキュリティ確保のためのセキュリティ検証の手引き』の『別冊2 機器メーカに向けた脅威分析及びセキュリティ検証の解説書』をもとに、IoT機器の開発者や品質保証の担当者が、攻撃者の視点に立ってセキュリティ検証を実践するための手法を、事例とともに詳細に解説しました。
ポチらせる文章術
販売サイト・ネット広告・メルマガ・ブログ・ホームページ・SNS…
全WEB媒体で効果バツグン!
カリスマコピーライターが教える「見てもらう」「買ってもらう」「共感してもらう」すべてに効くネット文章術
プログラマーは世界をどう見ているのか 西村博之著
イーロン・マスク(テスラ)、ジェフ・べゾス(Amazon)、ラリー・ペイジ(Google)…etc.
世界のトップはなぜプログラマーなのか?
ニーア オートマタ PLAY ARTS改 <ヨルハ 二号 B型 DX版> PVC製 塗装済み可動フィギュア
「NieR:Automata」より、ヨルハ二号B型こと2BがPLAY ARTS改に新たに登場!
高級感の感じられるコスチュームや髪の質感、洗練されたボディバランス、細かなデティールに至るまでこだわり抜かれた逸品。
DX版には通常版のラインナップに加え2Bの随行支援ユニット ポッド042などをはじめ“純白の美しい太刀"白の約定やエフェクトパーツ、自爆モードを再現できる換装用ボディパーツ、シーンに合わせて変えられる顔パーツ2種も付属する豪華な仕様に。
作中のあらゆるシーンを再現することが可能なファン必見の一品となっている。
Newtonライト2.0 ベイズ統計
ベイズ統計は,結果から原因を推定する統計学です。AIや医療などの幅広い分野で応用されています。その基礎となるのは18世紀に考えだされた「ベイズの定理」です。
この本では,ベイズ統計学のきほんをやさしく紹介していきます。
白光(HAKKO) ダイヤル式温度制御はんだ吸取器 ハンディタイプ FR301-81
無水エタノールP 500mlx2個パック(掃除)
ケイバ(KEIBA) マイクロニッパー MN-A04
サンハヤト SAD-101 ニューブレッドボード
白光(HAKKO) HEXSOL 巻はんだ 精密プリント基板用 150g FS402-02
[Amazon限定ブランド]【指定第2類医薬品】PHARMA CHOICE 解熱鎮痛薬 解熱鎮痛錠IP 100錠
|