LoginSignup
1
0

More than 3 years have passed since last update.

LEDマトリックスを使ってデジタル時計+温湿度計を作ってみた

Last updated at Posted at 2020-10-06

今回製作したもの

LEDマトリクスモジュールを使いた、温度・湿度計付きのデジタル時計
Digital Clock
画像クリックにより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

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0