ILI9486を搭載した3.5インチ480×320液晶シールドをArduino MEGA 2560 Rev3(以下、MEGA)に接続して動作確認した際の作業メモです。
シールド内蔵SDカードソケットのSPI接続ピンをMEGAのSPIに割り当てられているデジタルピンD51〜D53に変更して、I2C接続したBME280センサの測定データをSDカードに記録しました。
内蔵SDカードスロットをMEGAで使えるようにSPI変換シールドを使ってICSPコネクタ経由で接続
3.5インチ480×320液晶シールドのSDカードスロットは、SPI信号がUno Rev3(以下、Uno)のデジタルピンD11〜D13を前提に作られているので、MEGAのSPIに割り当てられているデジタルピンD50〜D52に接続変更しました。
UnoとMEGA、3.5インチ480×320液晶シールドのピン配置
ジャンパー線でSPI信号とCS(chip select)信号の接続先をMEGAのデジタルピンD50〜D52、D53に変更することで、SDカードへの書き込み、読み出し、ファイル削除ができることを確認しました。
スケッチでは、if (!SD.begin(53)) {} で、CS信号線のピン番号として53を指定しています。
3.5インチ480×320液晶シールド基板の裏面には、5Vから3.3Vを生成する3端子レギュレータ(U3)、信号線のレベル変換チップ(U1、U2)が実装されています。
SDカードソケットは、小型のmicroSDカードです。FAT32でフォーマットしておきます。
# | Uno Rev3 | MEGA Rev3 | 3.5TFT Pin Label | 3.5TFT Pin Description |
1 | A5 | <— | F_CS | A5 に接続なしでも動作 |
2 | A4 | <— | LCD_RST | LCD bus reset signal, low level reset |
3 | A3 | <— | LCD_CS | LCD bus chip select signal, low level enable |
4 | A2 | <— | LCD_RS | LCD bus command / data selection signal,low level: command, high level: data |
5 | A1 | <— | LCD_WR | LCD bus write signal |
6 | A0 | <— | LCD_RD | LCD bus read signal |
7 | GND | <— | GND | Power ground |
8 | GND | <— | GND | Power ground |
9 | 5V | <— | 5V | 5V power input |
10 | 3.3V | <— | 3V3 | 3.3V power input, this pin can be disconnected 3.3Vに接続なしでも動作。シールド基板裏面の3端子レギュレータで5Vから3.3Vを生成 |
11 | D8 | <— | LCD_D0 | LCD 8-bit data Bit0 |
12 | D9 | <— | LCD_D1 | LCD 8-bit data Bit1 |
13 | D2 | <— | LCD_D2 | LCD 8-bit data Bit2 |
14 | D3 | <— | LCD_D3 | LCD 8-bit data Bit3 |
15 | D4 | <— | LCD_D4 | LCD 8-bit data Bit4 |
16 | D5 | <— | LCD_D5 | LCD 8-bit data Bit5 |
17 | D6 | <— | LCD_D6 | LCD 8-bit data Bit6 |
18 | D7 | <— | LCD_D7 | LCD 8-bit data Bit7 |
19 | D10 | D53 | SD_SS | SD card SPI bus chip select signal, low level enable |
20 | D11 | D51 | SD_DI | SD card SPI bus MOSI signal |
21 | D12 | D50 | SD_DO | SD card SPI bus MISO signal |
22 | D13 | D52 | SD_SCK | SD card SPI bus clock signal |
ICSP端子を使って変換シールド基板経由でMEGAと3.5インチ480×320液晶シールドを直結
せっかくジャンパーワイヤ無しでAruduinoと直結できるシールドですので、MEGAと3.5インチ480×320液晶シールドを直結できないか調べていると、スイッチサイエンスのサイトにICSP(In Circuit Serial Programming)端子を使って変換シールド基板経由でつなぐ方法の記事がありました。
Uno R3とMEGA 2560 R3のSPI信号線は、基板中央にあるICSP端子で共通化されています。MEGAのICSP端子は、デジタルピンD50〜D52につながっています。
早速、スイッチサイエンスのAmazon店で販売されているArduino用バニラシールド基板ver.21を使って、Unoに合わせて作られた3.5インチ480×320液晶シールド基板側のSPI端子(D11〜D13)をMEGAのICSP端子に結線する変換シールド基板を作りました。
SPI変換シールド基板のICSPパターンには6Pソケットをはんだ付けします。6Pソケットは手持ちがなかったので1列x42ピンを切って使っています。
ICSP端子にはCSピンの割り当てはないので、別途MEGAのデジタルピンD53をつなぐ必要があります。今回、CSとしてSPI変換シールド基板のD10パターンからジャンパーワイヤで引き出してD53ピンに挿します。
MEGAでは使わない変換シールド基板のピン(D10~D13)の4本はカットします。
MEGAとのBME280センサをI2C接続(20:SDA、21:SCL)
MEGAの基板コネクタ端に、I2C(20:SDA、21:SCL)があります。この場所には3.5インチ480×320液晶シールド基板のピンは無いのでジャンパーワイヤで引き出せます。
SCL、SDA、5VとGNDの4線をBME280センサ基板と結線します。
BME280センサ自体の電源電圧とI2C信号レベルは3.3V系ですが、今回使ったBME280センサ基板には、Vin電源とI2C信号のレベル変換チップが内蔵されているので5V系のArduinoと直結できます。
気圧・温湿度を液晶表示してSDカードに記録するスケッチ
BME280センサで測った温度、湿度、気圧データを3.5インチグラフィック液晶モジュールへの表示とファイル名「logdata.txt」でSDカードに書き込むスケッチ1。SDカードを取り出してカードリーダ経由でPCに接続するのも手間なので、シリアルモニタでSDカードのデータを読み出して確認するスケッチ2、ファイルを削除するスケッチ3を作りました。
スケッチ1:MCUFRIEND_kbvライブラリで3.5インチ液晶シールドに表示、SDカードに書き込み
ILI9486を搭載した液晶モジュールのライブラリとしてMCUFRIEND_kbv.h(MCUFRIEND_kbv-master.zip)を、文字表示用にAdafruit_GFX.h(Adafruit-GFX-Library-master.zip)を、Adafruit_Sensor.h(Adafruit_Sensor-master.zip)とAdafruit_BME280.h(Adafruit_BME280_Library-master.zip)はBME280センサの取り込み用に使っています。
GitHubサイトからzipファイルをPCにダウンロードして保存(「Code」ボタンをクリックして「Download ZIP」)。Arduino IDEのメニューの「スケッチ」→「ライブラリをインクルード」→「.ZIP形式の ライブラリを インストール」で ダウンロードしたZIPファイルを追加します。
Adafruit-GFX-Libraryのフォント「FreeMonoBold24pt7b」や「FreeMonoBold12pt7b」で描画したフォントは拡大しても見やすいです。
℃は、2倍に拡大したグレイ色のドット「.」にスクリーン色と同じ黒色の1倍の「.」を座標をずらして重ねて丸孔を描画しています。
tft.setTextColorの背景色指定が効かなくて、測定データの数字表示が重ね文字になりました。測定値が変わったら前の表示データをtft.fillRectでスクリーン色と同じ黒四角で消してから最新値を表示する処理を入れています。黒四角で消す領域が気圧、温度、湿度の行単位なのでレトロなパタパタ時計のような表示遅れが残ってます。桁単位にすれば多少改善すると思います。
測定データの表示スペースは、気圧は4桁、温湿度は整数部2桁、少数点以下1桁です。
MEGAのフラッシュメモリはUnoの32kBから256kBに増えているのでFreeFONTを使っても余裕があります。
最大253952バイトのフラッシュメモリのうち、スケッチが50904バイト(20%)を使っています。
最大8192バイトのRAMのうち、グローバル変数が1434バイト(17%)を使っていて、ローカル変数で6758バイト使うことができます。
スケッチを起動すると全画面の白から数秒後に各モジュールの初期化ステータスを表示した後、測定データの表示画面に遷移します。SDカードやBME280との接続に失敗すると赤文字でエラー表示します。
BME280センサで測った温度、湿度、気圧データを3.5インチグラフィック液晶モジュールへの表示とファイル名「logdata.txt」でSDカードに書き込むスケッチ1です。
MEGA_MCUFRIEND_kbv_BME280_SD-card.ino
※ここをクリックするとコード表示を開閉できます。
//3.5 INCH TFT Display Shield with Arduino MEGA 2560 Rev3
#include <Adafruit_GFX.h> // Core graphics library
#include <MCUFRIEND_kbv.h> // Hardware-specific library
MCUFRIEND_kbv tft;
#include <Fonts/FreeMonoBold24pt7b.h>
#include <Fonts/FreeMonoBold12pt7b.h>
#define BLACK 0x0000
#define RED 0xF800
#define GREEN 0x07E0
#define WHITE 0xFFFF
#define GREY 0x8410
#define YELLOW 0xFFE0
#include <SPI.h>
#include <SD.h>
File dataFile;
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h> // BME280_Library
Adafruit_BME280 bme; // 気圧・温湿度センサ
float pres;
float temp;
float humi;
String op;
String ot;
String oh;
String np;
String nt;
String nh;
void setup(void){
Serial.begin(9600);
// TFTライブラリ初期化
tft.reset();
uint16_t ID = tft.readID();
if (ID == 0xD3D3) ID = 0x9486; //force ID if write-only display
tft.begin(ID);
tft.setRotation(1);
tft.fillScreen(BLACK);
tft.setFont(&FreeMonoBold12pt7b);
tft.setTextSize(1);
tft.setCursor(0, 40);
tft.setTextColor(WHITE,BLACK);
tft.print("TFT ID...");
tft.setTextColor(GREEN,BLACK);
tft.print(ID,HEX);
delay(1000);
// SDカードマウント確認
tft.setCursor(0, 80);
tft.setTextColor(WHITE,BLACK);
tft.print("Initializing SD card...");
if (!SD.begin(53)) { // CS - pin 53
tft.setTextColor(RED,BLACK);
tft.print("failed!");
while (1);
}
tft.setTextColor(GREEN,BLACK);
tft.print("done.");
delay(1000);
// SDカードファイル書き込み
tft.setCursor(0, 120);
tft.setTextColor(WHITE,BLACK);
tft.print("File written...");
dataFile = SD.open("/datalog.txt", FILE_WRITE);
dataFile.println("datalog.txt");
dataFile.close();
tft.setTextColor(GREEN,BLACK);
tft.print("datalog.txt");
delay(1000);
// Wireライブラリ初期化
Wire.begin();
// BME280初期化
tft.setCursor(0, 160);
tft.setTextColor(WHITE,BLACK);
tft.print("BME280...");
if (!bme.begin(0x76)) {
tft.setTextColor(RED,BLACK);
tft.print("connection failed");
while (1);
}
tft.setTextColor(GREEN,BLACK);
tft.print("connected");
delay(1000);
// 項目名の表示
tft.fillScreen(BLACK);
tft.setFont(&FreeMonoBold24pt7b);
tft.setTextSize(1);
tft.setTextColor(WHITE,BLACK);
tft.setCursor(0, 40);
tft.print("Pres:");
tft.setTextColor(GREY,BLACK);
tft.setCursor(0, 85);
tft.print("(hPa)");
tft.setTextColor(WHITE,BLACK);
tft.setCursor(0, 150);
tft.print("Temp:");
tft.setTextColor(GREY,BLACK);
tft.setCursor(20, 195);
tft.print("( ");
tft.setCursor(65, 195);
tft.print("C)");
tft.setTextSize(2);
tft.setCursor(29, 175);
tft.print(".");
tft.setTextColor(BLACK,BLACK);
tft.setTextSize(1);
tft.setCursor(44, 174);
tft.print(".");
tft.setTextColor(WHITE,BLACK);
tft.setCursor(0, 260);
tft.print("Humi:");
tft.setTextColor(GREY,BLACK);
tft.setCursor(20, 305);
tft.print("(%)");
}
void loop(void){
// ----- BME280センサからデータ取得 -----
pres=bme.readPressure() / 100.0F;
temp=bme.readTemperature();
humi=bme.readHumidity();
tft.setFont(&FreeMonoBold24pt7b);
tft.setTextSize(3);
tft.setTextColor(GREEN,BLACK); // FreeFONTでは背景色指定は無効
// ----- 液晶画面に気圧、温度、湿度の測定値を表示 -----
// 気圧表示(前後で測定値が変わったら黒背景で前の文字消去)
np = String(pres, 0);
if( np != op ) {
tft.fillRect(150,0,329,105,BLACK);
}
tft.setCursor(150, 95);
tft.print(np); // 気圧
op = np;
// 気温表示(前後で測定値が変わったら黒背景で前の文字消去)
nt = String(temp, 1);
if( nt != ot ) {
tft.fillRect(150,105,329,110,BLACK);
}
tft.setCursor(150, 205);
tft.print(nt); // 気温
ot = nt;
// 湿度表示(前後で測定値が変わったら黒背景で前の文字消去)
nh = String(humi, 1);
if( nh != oh ) {
tft.fillRect(150,215,329,105,BLACK);
}
tft.setCursor(150, 315);
tft.print(nh); // 湿度
oh = nh;
// ----- SDカードへの書き込み用データファイルの生成 -----
// 経過時間millis()を秒に変換
String dataString = "";
dataString += String(millis() / 1000);
// 測定データ1:BME280の気圧
dataString += ","; // カンマセパレータ
if(!isnan(pres)){
dataString += String(pres);
}else{
dataString += " ";
}
// 測定データ2:BME280の温度
dataString += ","; // カンマセパレータ
if(!isnan(temp)){
dataString += String(temp);
}else{
dataString += " ";
}
// 測定データ3:BME280の湿度
dataString += ","; // カンマセパレータ
if(!isnan(humi)){
dataString += String(humi);
}else{
dataString += " ";
}
// ----- SDカードのdatalog.txtにdataStringを追加 -----
dataFile = SD.open("/datalog.txt", FILE_WRITE);
dataFile.println(dataString);
dataFile.close();
// 測定間隔を調整
delay(2000);
}
スケッチ2:SDカードに記録されたデータを読み込んでシリアルモニタ表示
SDカードに記録された「datalog.txt」ファイルのデータを読み出してシリアルモニタに表示するスケッチ2です。
MEGA_SD_dataFile-read.ino
※ここをクリックするとコード表示を開閉できます。
//3.5 INCH TFT Display Shield with Arduino MEGA 2560 Rev3
#include <SPI.h>
#include <SD.h>
File dataFile;
void setup() {
Serial.begin(9600);
// SDカードマウント確認
if (!SD.begin(53)) { // CS - pin 53
Serial.println("card failed.");
return;
}
Serial.println("card connected.");
//ファイルを読み込み
dataFile = SD.open("/datalog.txt");
if (dataFile) {
while (dataFile.available()) {
Serial.write(dataFile.read());
}
dataFile.close();
} else {
Serial.println("File not found.");
}
}
void loop() {
}
スケッチ3:SDカードに記録したファイルを削除
SDカードに記録したファイル「datalog.txt」を削除するスケッチ3です。
MEGA_SD_dataFile-removed.ino
※ここをクリックするとコード表示を開閉できます。
//3.5 INCH TFT Display Shield with Arduino MEGA 2560 Rev3
#include <SPI.h>
#include <SD.h>
File dataFile;
void setup(){
Serial.begin(9600);
// SDカードマウント確認
if (!SD.begin(53)) { // CS - pin 53
Serial.println("Card failed.");
return;}
Serial.println("card connected.");
//ファイルを削除
if (SD.exists("datalog.txt")) {
SD.remove("datalog.txt");
}
Serial.println("File removed.");
//ファイルを読み込み確認
dataFile = SD.open("/datalog.txt");
if (dataFile) {
while (dataFile.available()) {
Serial.write(dataFile.read());
}
dataFile.close();
} else {
Serial.println("File not found.");
}
}
void loop(){
}
CO2濃度センサSCD30と気圧・温湿度センサBME280、RTCモジュールDS3231をI2C接続
MEGAと気圧・温湿度センサBME280、CO2濃度センサSCD30、RTCモジュールDS3231をI2C接続した本サイト内の記事です。
リアルタイムクロック(RTC)を使うことで、正確なタイムスタンプで測定データをSDカードに記録できます。