工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Manufacturing Technology >> 製造プロセス

Arduino Nanoアナログ時計:DS3231 RTCと1mAアメーターで作る精密木製タイマー

必要な部品と材料

部品 数量 備考
Arduino Nano R3 1 制御用マイコン
DS3231M RTCモジュール(±5ppm、I2C) 1 高精度リアルタイムクロック
1mA アナログアメーター(パネルメーター) 3 時・分・秒表示用
5kΩ 抵抗 3 各メーターのPWM電流制限用(メーター特性に合わせて調整)
10kΩ 抵抗 2 プルアップ用等
タクトスイッチ 12mm 2 時刻合わせ用(アップ/ダウン)

使用ソフトウェア

プロジェクト概要

木製ケースに収めたアナログパネルメーターを用いた時計をArduino Nanoで製作しました。DS3231 RTCから時刻を取得し、3つの1mAアメーターをPWM制御で駆動して時・分・秒を針の代わりに表示します。メーターの個体差に合わせてPWM値をキャリブレーションする機能もコードに組み込んでいます。

元ネタはInstructablesの「Analog VU meter and Clock Arduino Powered」ですが、秒表示機能と起動時のフルスケールキャリブレーション動作を追加しました。使用するアメーターによって最適な5kΩ抵抗値やPWM値が異なるため、ご自身のメーターに合わせてコード内の定数を調整する必要があります。

配線図

Arduino Nanoアナログ時計:DS3231 RTCと1mAアメーターで作る精密木製タイマー
回路配線図(スケマティック)

主な接続

ソースコード

コードはDS1307ライブラリ互換のI2C通信でDS3231から時刻を読み取り、各メーターに適切なPWM値を出力します。メーターの非直線性を補正するため、時間ごと・分ごとに異なるPWM値をルックアップテーブル的に指定しています。秒メーターは分メーターとは別のスケーリング係数(4.25)を使用しています。

/* Analog Panel Meter - Clock ONLY Mode
   Instructables Link: https://www.instructables.com/id/Analog-VU-meter-and-Clock-Arduino-Powered/
   Credits: bildr - DS1307 RTC code https://bildr.org/2011/03/ds1307-arduino/
   _____________________
   Wiring goes as follows:
   - USB red wire (5v) to VCC
   - USB black wire to GND
   - Buttons
     - Left/Down to Digital 2
     - Right/Up to Digital 3
   - DS1307 RTC
     - SDA to Analog 4
     - SCL to Analog 5
   - Left Analog Meter to Digital 5 (PWM)
   - Right Analog Meter to Digital 6 (PWM)
   - Seconds Analog meter to Digital 9 (PWM)
   _____________________
   Note: Because all meters are slightly different, the PWM values need to be adjusted based on your design.
   Feel free to use my code, but you will have to change some values because it is set to work specifically with my meters.
*/
#include "Wire.h"
#define DS1307_ADDRESS 0x68
byte zero = 0x00;

int downButton = 2;
int upButton = 3;
int hours = 0;
int minutes = 0;
int seconds = 0;
int lastMinute = 0;
int lastSecond = 0;
int leftMeter = 5;
int rightMeter = 6;
int secMeter = 9;

void setup() {
  Wire.begin();
  Serial.begin(9600);
  pinMode(leftMeter, OUTPUT);
  pinMode(rightMeter, OUTPUT);
  pinMode(secMeter, OUTPUT);
  // 起動時テスト:全メーターをフルスケール振れさせる
  digitalWrite(leftMeter, HIGH);
  digitalWrite(rightMeter, HIGH);
  digitalWrite(secMeter, HIGH);
  digitalWrite(13, HIGH);
  delay(1000);
  digitalWrite(leftMeter, LOW);
  digitalWrite(rightMeter, LOW);
  digitalWrite(secMeter, LOW);
  digitalWrite(13, LOW);
  delay(1000);
}

void loop() {
  printDate();
  delay(75);

  // ボタンで時刻調整
  if (digitalRead(downButton) == HIGH) {
    // 時刻を1分戻す処理
    byte second = seconds;
    byte minute = minutes;
    byte hour = hours;
    if (minutes > 0) { --minute; }
    else { minute = 59; if (hours > 0) { --hour; } else { hour = 23; } }
    writeTimeToRTC(second, minute, hour);
  }
  if (digitalRead(upButton) == HIGH) {
    // 時刻を1分進める処理
    byte second = 0;
    byte minute = minutes;
    byte hour = hours;
    if (minutes < 59) { ++minute; }
    else { minute = 0; if (hours < 23) { ++hour; } else { hour = 0; } }
    writeTimeToRTC(second, minute, hour);
  }
}

byte decToBcd(byte val) { return ( (val/10*16) + (val%10) ); }
byte bcdToDec(byte val) { return ( (val/16*10) + (val%16) ); }

void writeTimeToRTC(byte second, byte minute, byte hour) {
  Wire.beginTransmission(DS1307_ADDRESS);
  Wire.write(zero);
  Wire.write(decToBcd(second));
  Wire.write(decToBcd(minute));
  Wire.write(decToBcd(hour));
  Wire.write(zero);
  Wire.endTransmission();
}

void printDate() {
  Wire.beginTransmission(DS1307_ADDRESS);
  Wire.write(zero);
  Wire.endTransmission();
  Wire.requestFrom(DS1307_ADDRESS, 7);
  seconds = bcdToDec(Wire.read());
  minutes = bcdToDec(Wire.read());
  hours = bcdToDec(Wire.read() & 0b111111); // 24時間制

  // Serial.print(hours); Serial.print(":"); Serial.println(minutes); // デバッグ用

  // 分の更新時にのみメーター駆動値を更新(チラつき防止)
  if (lastMinute != minutes) {
    // 時メーター:12時間制で0-11時を0-255にマッピング(要調整)
    if (hours == 1 || hours == 13) analogWrite(leftMeter, 0);
    else if (hours == 2 || hours == 14) analogWrite(leftMeter, 29);
    else if (hours == 3 || hours == 15) analogWrite(leftMeter, 52);
    else if (hours == 4 || hours == 16) analogWrite(leftMeter, 75);
    else if (hours == 5 || hours == 17) analogWrite(leftMeter, 98);
    else if (hours == 6 || hours == 18) analogWrite(leftMeter, 130);
    else if (hours == 7 || hours == 19) analogWrite(leftMeter, 152);
    else if (hours == 8 || hours == 20) analogWrite(leftMeter, 172);
    else if (hours == 9 || hours == 21) analogWrite(leftMeter, 192);
    else if (hours == 10 || hours == 22) analogWrite(leftMeter, 213);
    else if (hours == 11 || hours == 23) analogWrite(leftMeter, 234);
    else if (hours == 0 || hours == 12) analogWrite(leftMeter, 255);

    // 分メーター:0-59分を0-255に線形マッピング(係数4.75はメーター依存)
    if (minutes * 4.75 < 255) analogWrite(rightMeter, minutes * 4.75);
    else analogWrite(rightMeter, 255);

    // 秒メーター:0-59秒を0-255に線形マッピング(係数4.25)
    if (seconds * 4.25 < 255) analogWrite(secMeter, seconds * 4.25);
    else analogWrite(secMeter, 255);

    lastMinute = minutes;
    lastSecond = seconds;
  }
}

調整のポイント

製作のヒント

関連リソース

製造プロセス

  1. Arduino POVクロック:残像効果で浮かび上がるLED時計を自作する
  2. DIY Arduinoワードクロック – 文字で時刻を表示する洗練されたリアルタイムクロック
  3. Arduino で作るイスラム教礼拝時刻付きリアルタイムクロック
  4. 12メートル先から見える大型LEDマスタークロック(アラーム機能付き)を自作しよう
  5. Arduino Nanoで作るウェアラブル心拍ドレス:CrazyCircuitsとDFRobotセンサーで自信を持ってプロジェクトを構築
  6. アナログ風LED POVクロック – Arduino Nanoで作る残像時計
  7. FlightGear用アナログトリムタブホイールをArduino Nanoで自作 ─ Python経由でUDP連携
  8. Arduino Nanoとジョイスティックで2軸ステッピングモーターを制御:Visuinoで簡単プログラミング
  9. パネルメーター:機械インターフェースと制御のためのコスト効率の高いソリューション
  10. 適切なパネル選択:デジタルとアナログソリューションの比較
  11. パネルメーター徹底解説:産業機器の監視と制御の仕組み