Arduino MEGA 2560 Rev3と3.5インチ480×320液晶シールドにBME280をI2C接続して気圧・温湿度を表示、microSDカード記録

ILI9486を搭載した3.5インチ480×320液晶シールドをArduino MEGA 2560 Rev3(以下、MEGA)に接続して動作確認した際の作業メモです。シールド内蔵SDカードソケットのSPI接続ピンをMEGAのSPIに割り当てられているデジタルピンD51〜D53に変更して、I2C接続したBME280センサの測定データをSDカードに記録しました。

Arduino MEGA 2560 Rev3と3.5インチ480×320液晶シールド
SPI信号の変換シールド基板を挟んでArduino MEGA 2560 Rev3と3.5インチ480×320液晶シールドを直結
目次

内蔵SDカードスロットをMEGAで使えるようにSPI変換シールドを使ってICSPコネクタ経由で接続

3.5インチ480×320液晶シールドのSDカードスロットは、SPI信号がUno Rev3(以下、Uno)のデジタルピンD11〜D13を前提に作られているので、MEGAのSPIに割り当てられているデジタルピンD51〜D53に接続変更しました。

UnoとMEGA、3.5インチ480×320液晶シールドのピン配置

ジャンパー線でSPI信号とCS(chip select)信号の接続先をMEGAのデジタルピンD50〜D52、D53に変更することで、SDカードへの書き込み、読み出し、ファイル削除ができることを確認しました。

スケッチでは、if (!SD.begin(53)) {} で、CS信号線のピン番号として53を指定します。

MEGAのSPI
MEGAのSPI(D51〜D53)とCS(D53)に結線。写真手前に53、51、その裏側に52、50。

3.5インチ480×320液晶シールド基板の裏面には、5Vから3.3Vを生成する3端子レギュレータ(U3)、信号線のレベル変換チップ(U1、U2)が実装されています。

SDカードソケットは、小型のmicroSDカードです。FAT32でフォーマットしておきます。

3.5インチ480x320液晶シールドの端子
3.5インチ480×320液晶シールドの端子
#Uno
Rev3
MEGA
Rev3
3.5TFT
Pin Label
 3.5TFT
Pin Description
1A5<—F_CSA5 に接続なしでも動作
2A4<—LCD_RSTLCD bus reset signal, low level reset
3A3<—LCD_CSLCD bus chip select signal, low level enable
4A2<—LCD_RSLCD bus command / data selection signal,low level: command, high level: data
5A1<—LCD_WRLCD bus write signal
6A0<—LCD_RDLCD bus read signal
7GND<—GNDPower ground
8GND<—GNDPower ground
95V<—5V5V power input
103.3V<—3V33.3V power input, this pin can be disconnected
3.3Vに接続なしでも動作。シールド基板裏面の3端子レギュレータで5Vから3.3Vを生成
11D8<—LCD_D0LCD 8-bit data Bit0
12D9<—LCD_D1LCD 8-bit data Bit1
13D2<—LCD_D2LCD 8-bit data Bit2
14D3<—LCD_D3LCD 8-bit data Bit3
15D4<—LCD_D4LCD 8-bit data Bit4
16D5<—LCD_D5LCD 8-bit data Bit5
17D6<—LCD_D6LCD 8-bit data Bit6
18D7<—LCD_D7LCD 8-bit data Bit7
19D10D53SD_SSSD card SPI bus chip select signal, low level enable
20D11D51SD_DISD card SPI bus MOSI signal
21D12D50SD_DOSD card SPI bus MISO signal
22D13D52SD_SCKSD 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端子は、デジタルピンD51〜D53につながっています。

MEGAのICSP端子
MEGAのICSP端子(写真中央の2列X3ピン)。Unoと比べてMEGAのデジタル入出力ピンは14本から54本、アナログ入力ピンは6本から16本に、フラッシュメモリは32kBから256kBに増えているので使い勝手が良いです。
スイッチサイエンス マガジン
Uno用SPI接続シールドをMega・Leonardoで使えるようにする変換シールド Arduinoにはさまざまなシールド(機能拡張基板)が発売されています。しかしその中にはArduino Uno(あるいはDuemilanoveかそれ以前のバージョン)を対象に作られていて、A...

早速、スイッチサイエンスのAmazon店で販売されているArduino用バニラシールド基板ver.21を使って、Unoに合わせて作られた3.5インチ480×320液晶シールド基板のSPI端子(D11〜D13)をICSP端子に結線する変換シールド基板を作りました。

なお、ICSPにはCSピンの割り当てはないので、別途デジタルピンD53をつなぐ必要があります。今回、CSとして変換シールド基板のD10パターンからジャンパーワイヤで引き出し、D53ピンに挿しました。

MEGAでは使わない変換シールド基板のピン(D10~D13)の4本はカットします。

変換シールド基板
SPI端子(D11〜D13) と CS端子(D10)を結線した変換シールド基板。写真手前のピン4本(D10~D13)はカット
MEGA、変換シールド基板、3.5インチ液晶の3階建て
MEGA、変換シールド基板、3.5インチ480×320液晶シールドの3階建て

BME280センサとMEGAの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と直結できます。

MEGAのI2C
MEGAのI2C(写真左端の20:SDA、21:SCL)とMBE280を結線

気圧・温湿度を液晶表示して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桁です。

SDカードに書き込んだdatalog.txt
SDカードに書き込んだdatalog.txt
3.5インチ480x320液晶シールドに表示
3.5インチ480×320液晶シールドに表示

MEGAのフラッシュメモリはUnoの32kBから256kBに増えているのでFreeFONTを使っても余裕です。

最大253952バイトのフラッシュメモリのうち、スケッチが50904バイト(20%)を使っています。
最大8192バイトのRAMのうち、グローバル変数が1434バイト(17%)を使っていて、ローカル変数で6758バイト使うことができます。

スケッチを起動すると初期化ステータスを表示した後、測定データの表示画面に遷移します。SDカードやBME280との接続に失敗すると赤文字でエラー表示します。

正常起動
正常起動
BME280センサへの接続失敗
BME280センサへの接続失敗

millis()は「Arduino ボードが現在のプログラムを実行し始めてから経過したミリ秒数を返します。この数は、約 50 日後にオーバーフロー (ゼロに戻る) になります」とArduino Referenceに記載があります。
長期間の測定には、I2C接続のリアルタイムクロック(RTC)を設けて取得時刻を記録Tera Termのログに時刻(タイムスタンプ)を記録といった手段もあります。

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です。

SDカードのファイルをシリアルモニタに表示
SDカードのファイルをシリアルモニタに表示

スケッチ3:SDカードに記録したファイルを削除

SDカードに記録したファイル「datalog.txt」を削除するスケッチ3です。

SDカードに記録したファイルの削除
SDカードに記録したファイルの削除
よかったらシェアしてね!
  • URLをコピーしました!
目次