寝室用に明るさを抑えた壁掛けデジタル時計を作りました。
ESP8266(ESPr Developer)でRTCから時刻を読んで、7セグメント表示器風にフルカラーLEDを28個配置して時刻を表示します。せっかくのフルカラーLEDなのでランダムに表示の色を変更します。1日1回NTPサーバーにアクセスして時刻を校正します。照度センサーで室内の明るさをモニターして暗くなったらLEDも暗くします。
ESP8266は時分の表示が終わると、電力削減のため50秒間Deepsleepします。NTPサーバーにアクセスする直前はWiFi ONで起動し、それ以外はWiFi OFFで起動します。
LEDの信号線は15ピン、照度センサーは20kΩと10kΩで分圧してTOUTピン、RTC(DS1302)は3ワイヤーという通信なので CLKを12ピン、DATを13ピン、RSTを14ピンに接続しました。Deepsleep後の起動用に16ピンをRESETに接続します。
筐体は5mm厚のMDFをレーザーカッターで切り抜きます。セグメントの中央にLEDを配置して表面に経木(紙のように薄い板)を貼りました。セグメント内での光の均一性にもう一工夫必要です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
//Deepsleep後の起動時は先頭から実行 // #include <NTPClient.h> #include <ESP8266WiFi.h> #include <WiFiUdp.h> const char *ssid = "your SSID"; const char *password = "your password"; WiFiUDP ntpUDP; NTPClient timeClient(ntpUDP, "ntp.nict.jp", 32400, 86400000); String NTPstring; //18:02:24 #include <DS1302.h> DS1302 rtc(14, 13, 12); #include <Adafruit_NeoPixel.h> #define PIN 15 #define NUMPIXELS 28 Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800); String StringHHMM, pStringHHMM="", StringDisp; String WiFiHHMM="1800";//NTPにアクセスする1分前はWiFi_ONで起動する String NTPHHMM="1801";//NTPにアクセスする時刻 boolean Awaked=HIGH; int r,g,b; void setup() { delay(100); Serial.begin(9600); Serial.println("Wakeup&Setup"); rtc.halt(false); rtc.writeProtect(false); pixels.begin(); // This initializes the NeoPixel library. } void loop() { int lum=analogRead(A0); StringHHMM=rtc.getTimeStr(FORMAT_SHORT); StringHHMM.remove(2,1); Serial.println(StringHHMM); Serial.println(lum); if(StringHHMM!=pStringHHMM){ Serial.println("WriteLED"); if(lum<275){ r=5, g=10, b=10; //Night mode //r=1, g=2, b=2; //Night mode } else{ r=random(190,255), g=random(190,255), b=random(190,255); //Demo mode } for(int i=0;i<4;i++){ StringDisp=StringHHMM.substring(i,i+1); Seven_seg(3-i,StringDisp.toInt()); } pixels.show(); Awaked=LOW; if(StringHHMM==NTPHHMM){ Serial.println("NTP"); ntpAdjust(); //Awaked=HIGH; } } else if(Awaked==LOW){ Serial.println("Deepsleep"); Awaked=HIGH; if(StringHHMM!=WiFiHHMM){ ESP.deepSleep(50 * 1000 * 1000 , WAKE_RF_DISABLED); } else{ ESP.deepSleep(50 * 1000 * 1000 , WAKE_RF_DEFAULT); } //deepsleepモード移行までのダミー命令 delay(1000); } Serial.println("idle"); pStringHHMM=StringHHMM; delay(950); } void Seven_seg(int d,int i){ boolean led[7]; switch(i){ case 0: led[0]=HIGH,led[1]=HIGH,led[2]=HIGH,led[3]=HIGH,led[4]=HIGH,led[5]=HIGH,led[6]=LOW; break; case 1: led[0]=LOW,led[1]=HIGH,led[2]=HIGH,led[3]=LOW,led[4]=LOW,led[5]=LOW,led[6]=LOW; break; case 2: led[0]=HIGH,led[1]=HIGH,led[2]=LOW,led[3]=HIGH,led[4]=HIGH,led[5]=LOW,led[6]=HIGH; break; case 3: led[0]=HIGH,led[1]=HIGH,led[2]=HIGH,led[3]=HIGH,led[4]=LOW,led[5]=LOW,led[6]=HIGH; break; case 4: led[0]=LOW,led[1]=HIGH,led[2]=HIGH,led[3]=LOW,led[4]=LOW,led[5]=HIGH,led[6]=HIGH; break; case 5: led[0]=HIGH,led[1]=LOW,led[2]=HIGH,led[3]=HIGH,led[4]=LOW,led[5]=HIGH,led[6]=HIGH; break; case 6: led[0]=HIGH,led[1]=LOW,led[2]=HIGH,led[3]=HIGH,led[4]=HIGH,led[5]=HIGH,led[6]=HIGH; break; case 7: led[0]=HIGH,led[1]=HIGH,led[2]=HIGH,led[3]=LOW,led[4]=LOW,led[5]=LOW,led[6]=LOW; break; case 8: led[0]=HIGH,led[1]=HIGH,led[2]=HIGH,led[3]=HIGH,led[4]=HIGH,led[5]=HIGH,led[6]=HIGH; break; case 9: led[0]=HIGH,led[1]=HIGH,led[2]=HIGH,led[3]=LOW,led[4]=LOW,led[5]=HIGH,led[6]=HIGH; break; } for(int j=0;j<7;j++){ if(led[j]){ pixels.setPixelColor(j+7*d, pixels.Color(r,g,b)); } else{ pixels.setPixelColor(j+7*d, pixels.Color(0,0,0)); } } } void ntpAdjust(){ WiFi.begin(ssid, password); int tries=100; while ( WiFi.status() != WL_CONNECTED && tries>0) { delay ( 500 ); Serial.print ( "." ); tries=tries-1; } if(tries>0){ timeClient.begin(); timeClient.update(); NTPstring=timeClient.getFormattedTime(); String Now = NTPstring; String sH=Now.substring(0,2); String sM=Now.substring(3,5); String sS=Now.substring(7,9); int hnow=sH.toInt(); int mnow=sM.toInt(); int snow=sS.toInt(); Serial.print(hnow),Serial.print(":"); Serial.print(mnow),Serial.print(":"); Serial.println(snow); rtc.setTime(hnow, mnow, snow); } } |
2017.1.21
こんにちは 電子工作に興味がありデジタル時計を作ってみたいと思い探したところ このホームページに辿り着きました。材料等は理解出来るのですが配線が判りません。すみませんが教えていただけないでしょうか?
haruichiさん こんにちは、
配線の説明が大雑把で申し訳ないです。
フルカラーLEDで大型の表示器を作るというのがこの記事の一つのポイントで、夜中に目が覚めて寝ぼけた目でも時刻がわかるのがセールスポイントです。フルカラーLEDは電源とグランドと1本の信号線で多数のLEDの制御ができるのがメリットです。2枚目の写真のように全てのLEDを数珠つなぎにハンダ付けをします。LEDにはDIとDOがありますので信号がDIから入ってDOから次のLEDのDIに接続しています。
Arduinoでリアルタイムクロック(RTC)を使うのはよく記事を目にしますのでその辺の配線は「arduino rtc ds1302」などで検索して試してみてください。ただし、この記事で使ったds1302は精度が悪くて一晩で2分ぐらいずれていました。夜中の2分ぐらいは全然問題ないのですが、現在はGPSで正確な表示になるように変更しています。
GPSは正確で良いのですが、電力消費が大きいのが難点です。精度の良いRTCを注文しているところですので届いたらまたRTCで試してみようと思います。
haruichiさんも自作の時計の制作楽しんでください。
kojiさん お返事ありがとうございます。Arduinoを使って制作したいと思います。
もう一つ質問なのですが LED28個となっていますが 間のコロン?(:)は このコードには無いのでしょうか?
haruichiさん、
HHとMMの間に:を入れてHH:MMにしようと思って、板にはコロンの穴を開けたのですが、コロンがなくても分かるのでやめました。コードはforループでHHMMの4桁を一気に処理していますが、HH部分とMM部分を分けて間にコロンの処理を挟むのがオーソドックスなやり方でしょうね。このコードを残すなら、配線でコロンを頭に持ってくるとか、お尻に持ってくるとかもありかもしれません。コロンを単色の普通のLEDにして別のDigital OUTで点滅するのもありかもしれませんが、色を変えたくなるかもしれないし、、、。
コロンを1秒間隔で点滅すると本物っぽくって良いですよね。数字の下にLEDを5個つけて10秒ごとに点灯させるとバーグラフのようになって面白いかもしれませんね。
何れにしても配線はいつ終わるんだろうと思いながら地道に続けるしかないので頑張ってください。プリント基板があれば楽だろうなと思うと、思います。