今回製作したもの
LEDマトリクスモジュールを使いた、温度・湿度計付きのデジタル時計
画像クリックによりYoutube再生します
仕様
- 温湿度表示
- デジタル時計表示
- 日付表示 曜日・月は英語表記
- ワンクリックで秒を0に補正 (追加:2020/10/17)
- Arduino UNO -> NANO に変更 (変更:2020/10/25)
主なパーツと入手先
- Arduino Uno (Kyoritsu)または Arduino nano(Kyoritsu)
- MAX7219 Arduino用ドットマトリクスモジュール (Amazon)
- リアルタイム・クロック PCF8523(Amazon)
- 温湿度センサーモジュール DHT-22(Amazon)
- USB 電源アダプタ DC5V 2A (Kyoritsu)
- ゴムブッシュ (Kyoritsu)
- 抵抗 10KΩ (Kyoritsu)
- DC 5V 25mm 冷却ファン (Yahoo)
- プシュスイッチ (Kyoritsu) 秒補正用
- 冷却ファン用ねじ 2.6mm × 15mm
- ブレッドボード、ジャンパーワイヤー
- 電動ドライバー+ドリル (手で穴をあけるのは少し大変)
- 瞬間接着剤
配線
Arduino | MaxtriModule |
---|---|
5V | VCC |
13 | CLK_PIN |
11 | DATA_PIN |
10 | CS_PIN |
GND | GND |
Arduino | PCF8523 |
---|---|
5V | VCC |
SDA | SDA i2c data pin |
SCL | SCL i2c clock pin |
GND | GND |
左端にあるのが温湿度センサー 、右端が空冷ファンです。
今回、リアルタイムクロックのみ、端子4カ所のハンダ付けが必要でした。
それ以外はブレッドボードを使用しています。
温湿度センサー DHT-22
DHT-22をブレッドボードに差してみたのですが、LED自身が発熱するため温度が上がってしまいました。ケースを密閉していたのが良くなかったようです。そこで両端をドリルで穴をいくつか開け、ファンと温度センサーをケースの両端に取り付けました。温湿度センサーは、緩衝材を軽くかぶせて、テープで固定しています。
これでファンが吸い込んだ外気と直接触れるので、室温が正しく表示されるようになりました。
日付表示・温湿度表示
温湿度は2分ごとに表示、曜日、日付は10分おきに表示するように設定しています。好みによってタイミングを変えれば良いと思います。初期の設定は、時刻、温湿度、カレンダーのデータが、連続で右から左に流れるようにしていました。しかし、通常は時計で、時おり温湿度とカレンダーを表示する方が、飽きずに長く使えそうです。
ケース
小物入れ(プルアウトボックス)(Amazon)
本体がポリプロピレン、フタがポリエチレンのため、加工がしやすく取り扱いが容易です。100均でも購入出来ます。
フロントパネル
・パネルは100均で購入した黒色半透明の下敷きを使用しています。アロンアルフアのような瞬間接着剤で、コーナーと各辺の中心を目立たないよう接着しました。樹脂切削用カッター(Amazon)を使うと綺麗に切れます。
・LED基板は発泡スチロールを両面テープでパネル裏に貼り、これにはさみこんでいます。
プログラム
コード (クリックで詳細表示)
#include "DHT.h"
#include <Wire.h>
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include <RTClib.h>
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
#define PAUSE_TIME 1000
#define SCROLL_SPEED 100
#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321
#define DHTPIN 2 // Digital pin connected to the DHT sensor
#define MAX_MESG 20
const int BUTTON = 7; //pin of push botton
int val = 0; // pin
int old_val = 0; // former pin
// Global variables
char szTime[9]; // mm:ss\0
char szMesg[MAX_MESG+1] = "";
char *mon2str(uint8_t mon, char *psz, uint8_t len)
// Get a label from PROGMEM into a char array
{
static const __FlashStringHelper* str[] =
{
F("Jan"), F("Feb"), F("Mar"), F("Apr"),
F("May"), F("Jun"), F("Jul"), F("Aug"),
F("Sep"), F("Oct"), F("Nov"), F("Dec")
};
strncpy_P(psz, (const char PROGMEM *)str[mon-1], len);
psz[len] = '\0';
return(psz);
}
char *dow2str(uint8_t code, char *psz, uint8_t len)
{
static const __FlashStringHelper* str[] =
{
F("Sunday"), F("Monday"), F("Tuesday"),
F("Wednesday"), F("Thursday"), F("Friday"),
F("Saturday"), F("Sunday")
};
strncpy_P(psz, (const char PROGMEM *)str[code-1], len);
psz[len] = '\0';
return(psz);
}
RTC_PCF8523 rtc;
DHT dht(DHTPIN, DHTTYPE);
MD_Parola P = MD_Parola (HARDWARE_TYPE,CS_PIN, MAX_DEVICES);
MD_MAX72XX matrix = MD_MAX72XX(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
void setup ()
{
pinMode(BUTTON, INPUT); // BUTTON is for input
dht.begin();
Wire.begin();
P.begin();
Serial.begin(57600);
P.setIntensity(1);
if(!rtc.begin())
{
Serial.println("Couldn't find RTC");
while (1);
}
if(!rtc.isrunning())
{
Serial.println("RTC is NOT running!");
// following line sets the RTC to the date & time this sketch was compiled
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
}
void loop ()
{
static uint32_t tmpTime = 0; // millis() memory
static uint32_t lastTime = 0; // millis() memory
static uint32_t pastTime = 0; // millis() memory
static bool flasher = false; // seconds passing flasher
char humdStamp[5];
char tempStamp[5];
char szMesg[7];
char timeStamp[20];
char dateStamp[15];
matrix.control(MD_MAX72XX::INTENSITY, 0);; // Use a value between 0 and 15 for brightness
// check the state of botton
val = digitalRead(BUTTON);
if (val == HIGH) // Check if there is a change
{
delay(10);
val = 0;
//Reset second
DateTime now = rtc.now();
rtc.adjust(DateTime(now.year(),now.month(),now.day(),now.hour(),now.minute(),00));
sprintf(timeStamp, "%2d:%02d:%02d",now.hour(),now.minute(),0);
P.displayClear();
delay(100);
for (uint8_t i=0; i<ARRAY_SIZE(timeStamp); i++)
{
P.displayText(timeStamp, PA_CENTER, SCROLL_SPEED,0, PA_PRINT,PA_SCROLL_LEFT);
P.setTextEffect(0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
P.displayAnimate();
while (!P.displayAnimate())
;
break;
}
delay(10);
}
// Show Temparature, Humidity every 2 minute
if (millis() - tmpTime >= 120000)
{
tmpTime = millis();
float h = dht.readHumidity();
float f = dht.readTemperature();
f = f - 1;
// Humidity
dtostrf(h, 3, 1, szMesg);
strcat(szMesg, "%");
sprintf(humdStamp, "%05",szMesg);
P.displayText(szMesg, PA_CENTER, SCROLL_SPEED, PAUSE_TIME, PA_PRINT,PA_SCROLL_DOWN);
P.displayAnimate();
while (!P.displayAnimate())
;
// Temp
delay(1000);
dtostrf(f, 3, 1, szMesg);
strcat(szMesg, "c");
sprintf(tempStamp, "%05",szMesg);
P.displayText(szMesg, PA_CENTER, SCROLL_SPEED, PAUSE_TIME, PA_PRINT, PA_SCROLL_DOWN);
P.displayAnimate();
while (!P.displayAnimate())
;
delay(1000);
}
// Time
//char timeStamp[15];
if (millis() - lastTime >= 500)
{
lastTime = millis();
DateTime now = rtc.now();
sprintf(timeStamp, "%2d%c%02d",now.twelveHour() , (flasher ? ':' : ' '),now.minute());
Serial.println(timeStamp);
sprintf(dateStamp, "%s%s%02d",mon2str(now.month(), szMesg, MAX_MESG)," ",now.day());
Serial.println(dateStamp);
delay(100);
for (uint8_t i=0; i<ARRAY_SIZE(timeStamp); i++)
{
P.displayText(timeStamp, PA_CENTER, SCROLL_SPEED,PAUSE_TIME, PA_PRINT);
P.displayAnimate();
while (!P.displayAnimate())
;
break;
}
flasher = !flasher;
}
if (millis() - pastTime >= 600000) //every 10 minute
{
pastTime = millis();
// day of week
delay(1000);
for (uint8_t q=0; q<ARRAY_SIZE(timeStamp); q++)
{
DateTime now = rtc.now();
P.displayClear();
dow2str(now.dayOfTheWeek()+1, szMesg, MAX_MESG); // Added +1 to get correct DoW
P.displayText(szMesg, PA_CENTER, SCROLL_SPEED, 0, PA_PRINT, PA_SCROLL_LEFT);
P.setTextEffect(0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
P.displayAnimate();
while (!P.displayAnimate())
;
break;
}
// day of year
delay(1000);
for (uint8_t j=0; j<ARRAY_SIZE(dateStamp); j++)
{
P.displayText(dateStamp, PA_CENTER, SCROLL_SPEED, PAUSE_TIME, PA_PRINT, PA_SCROLL_DOWN);
P.setTextEffect(0, PA_SCROLL_DOWN, PA_SCROLL_DOWN);
P.displayAnimate();
while (!P.displayAnimate())
;
break;
}
// year
delay(1000);
for (uint8_t k=0; k<ARRAY_SIZE(dateStamp); k++)
{
DateTime now = rtc.now();
int iVarToCast = now.year();
char buffer[4];
dtostrf(iVarToCast, 4, 0, buffer);
P.displayText(buffer, PA_CENTER, SCROLL_SPEED,PAUSE_TIME, PA_PRINT, PA_SCROLL_DOWN);
P.setTextEffect(0, PA_SCROLL_DOWN, PA_SCROLL_DOWN);
P.displayAnimate();
while (!P.displayAnimate())
;
break;
}
}
}
参考:
MAX72xx Library
MD_Parola Libraries
PCF8523 Libraries
DHT22 Library