/* アナレンマをAmbient http://ambidata.io/ に作図するテスト Ch:200にアナレンマを作図。Ch:202にパネル電圧を作図 2016/12/14 ラジオペンチ http://radiopench.blog96.fc2.com/ */ #include // ESP8266用ライブラリ #include // UDP通信を行うライブラリ #include "Ambient.h" // Ambient用のライブラリ #define PIN_LED 13 // IO 13(5番ピン)にLEDを接続する #define SSID "***************" // 無線LANアクセスポイントのSSID #define PASS "*****************" // パスワード #define AmbientChannelId_200 200 // チャネルID=200 #define AmbientWriteKey_200 "***********" // ライトキー(16桁の16進数) #define AmbientChannelId_202 202 // チャネルID=202 #define AmbientWriteKey_202 "***********" // ライトキー(16桁の16進数) char s[12]; float jaTime; unsigned int localPort = 2390; unsigned long unixTime; // unix時刻(1970年1月1日からの秒数) unsigned long jstTime; // JST時刻 unix +9Hr unsigned long xd; unsigned int daySince2016; // 2016年1月1日からの日数 IPAddress timeServerIP; // time.nist.gov NTP server address const char* ntpServerName = "ntp.nict.jp"; // NICTのNTPを使用 const int NTP_PACKET_SIZE = 48; // NTPパケット用バッファサイズ = 48 bytes byte packetBuffer[NTP_PACKET_SIZE]; // NTPパケットバッファ const float k1 = 0.024414; // 電圧変換係数 k1 * ADC = パネル電圧(V) const float k2 = 2.0; // 夜の開始判定電圧(これ以下なら夜の始まり) const float k3 = 6.0; // 昼の開始判定電圧(これ以上なら昼の始まり) const float t1Min = 0.15; // 夜明け時刻最小 const float t1Max = 0.3; // 夜明け時刻最大 const float t2Min = 0.64; // 日の入り時刻最小 const float t2Max = 0.84; // 最大 float panelVoltage; float t1 = 0.0; // 日の入り時刻 float t2 = 0.0; // 日没時刻 float tDayLong; // 昼間の時間 float tCulmination; // 南中時刻 boolean ItIsNoon = false; // 昼ならtrue WiFiUDP udp; // A UDP instance to let us send and receive packets over UDP Ambient ambient; WiFiClient client; extern "C" { // ESP8266でADCを使うためのおまじない #include "user_interface.h" } void setup() { pinMode(12, OUTPUT); // t1表示LED pinMode(14, OUTPUT); // t2表示LED pinMode(PIN_LED, OUTPUT); digitalWrite(PIN_LED, HIGH); // LED点灯 Serial.begin(115200); // 動作確認のためのシリアル出力開始 ItIsNoon = DayNightCheck(); // 開始時の昼夜判定 Serial.println(); Serial.print("Start DN="); Serial.println(ItIsNoon); digitalWrite(PIN_LED, LOW); } void loop() { // メインループ for (int i = 0; i < 6; i++) { digitalWrite(PIN_LED, HIGH); panelVoltage = k1 * system_adc_read(); // パネル電圧測定 Serial.print("Voltage = " ); Serial.println(panelVoltage); if ( ItIsNoon == true) { // これまでが昼で if (panelVoltage < k2) { // 測定結果が夜だったら、 ItIsNoon = false; D2N(); // 昼から夜へ変わった時の処理を実行 } } else { // これまでが夜で if (panelVoltage > k3) { // 測定結果が朝だったら、 ItIsNoon = true; N2D(); // 夜から昼に変わった時の処理 t2 = 0; // 昨夜の記録は消す digitalWrite(14, LOW); } } digitalWrite(PIN_LED, LOW); delay(10000); // 10秒周期で実行 } digitalWrite(PIN_LED, HIGH); // 動作中表示 if ((t1 != 0) && (t2 != 0)) { // t1とt2が両方0以外なら日没直後処理 Serial.println("Morning to Night data obtained !"); if (t1t2Check() == true) { // t1,t2が変な値になっていないかチェック ambient.begin(AmbientChannelId_200, AmbientWriteKey_200, &client); // ID:200のAmbient開始 SetAnalemmaInf(); // アナレンマ作図データーセット Serial.println("Analemma information send to Ambient ch200"); ambient.send(); // Ambientへ送信 } t1 = 0; digitalWrite(12, LOW); t2 = 0; digitalWrite(14, LOW); } else { // 通常の処理(電圧をID:202へ送信) ambient.begin(AmbientChannelId_202, AmbientWriteKey_202, &client); // ID:202のAmbient開始 dtostrf(panelVoltage, 5, 2, s); // 少数点以下2桁 ambient.set(1, s); // パネル電圧をセット Serial.print("Ambient ch202 send :" ); Serial.println(s); ambient.send(); // Ambientへ送信 } digitalWrite(PIN_LED, LOW); // 動作表示LED off } boolean DayNightCheck() { // 開始時の昼夜判定 boolean x; panelVoltage = k1 * system_adc_read(); if ( panelVoltage > (k2 + k3) / 2.0 ) { // 中央値で判定 x = true; // 昼なのでtrueを返す } else { x = false; // 夜なのでfalse } return x; } void D2N() { // 昼から夜へ変化した時の処理 (Day to Night) connectWiFi(); // WiFiに接続 xd = readNTP(); // NTPから時刻情報取得 t2 = jaTime; // 日本時間 digitalWrite(14, HIGH); // t2に値が入ったことを表示 Serial.print("Night Started. t2= "); Serial.println(t2, 6); } void N2D() { // 夜から昼へ変化した時の処理 (Night to Day) connectWiFi(); // WiFiに接続 xd = readNTP(); t1 = jaTime; // 日の出時刻を記録 digitalWrite(12, HIGH); Serial.print("Noon Started. t1= "); Serial.println(t1, 6); } boolean t1t2Check() { // t1,t2が正常範囲内かチェック boolean flag = false; if ((t1Min < t1) && (t1 < t1Max)) { if ((t2Min < t2) && (t2 < t2Max)) { flag = true; // OKならtrue } } return flag; } void SetAnalemmaInf() { // アナレンマの情報をバッファにセット dtostrf(t1, 7, 5, s); // t1 ambient.set(2, s); dtostrf(t2, 7, 5, s); // t2 ambient.set(3, s); tDayLong = t2 - t1; // 昼間の時間 (t2-t1) dtostrf(tDayLong, 7, 5, s); ambient.set(4, s); tCulmination = (t1 + t2) * 0.5; // 南中時刻 (t1+t2)/2 dtostrf(tCulmination, 7, 5, s); ambient.set(5, s); daySince2016 = ((xd + 32400UL - (24 * 3600 * 16801UL)) / (24 * 3600)) + 1; // 日付連番 dtostrf(daySince2016, 7, 0, s); // 2016/1/1=1の日付連番 ambient.set(6, s); } void connectWiFi() { // WiFi接続 // Serial.println(); Serial.print("Connecting to "); // WiFi接続中 // Serial.println(SSID); // 固定IPアドレスで接続 IP Address, Gate way, Subnet mask の順に指定 WiFi.config(IPAddress(192, 168, 0, 27), IPAddress(192, 168, 0, 1), IPAddress(255, 255, 255, 0)); WiFi.begin(SSID, PASS); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.print("WiFi connected. IP address: "); Serial.println(WiFi.localIP()); // Serial.print("Starting UDP "); udp.begin(localPort); // Serial.print("Local port: "); Serial.println(udp.localPort()); } unsigned long readNTP() { // NTPから時刻を取得 unsigned long epoch; unsigned long highWord; unsigned long lowWord; unsigned long secsSince1900; // Serial.println(); // 先頭で改行 WiFi.hostByName(ntpServerName, timeServerIP); // サーバー選択 // Serial.println(timeServerIP); // 時々ミスするので調査用にIPアドレス表示 sendNTPpacket(timeServerIP); // 時刻問い合わせパケット送信 delay(1000); // 返事が来るまでちょっと待つ int cb = udp.parsePacket(); // 受信文字数を取得 if (!cb) { // cbが空なら Serial.println("no packet yet"); } else { // Serial.print("packet received, length="); // Serial.println(cb); udp.read(packetBuffer, NTP_PACKET_SIZE); // データーをパケットバッファに読み取り highWord = word(packetBuffer[40], packetBuffer[41]); lowWord = word(packetBuffer[42], packetBuffer[43]); secsSince1900 = highWord << 16 | lowWord; // 32ビットに合成 // Serial.print("Seconds since Jan 1 1900 = " ); // Serial.println(secsSince1900); // now convert NTP time into everyday time: Serial.print("Unix time = "); // Unix time starts on Jan 1 1970. In seconds, that's 2208988800: const unsigned long seventyYears = 2208988800UL; // subtract seventy years: epoch = secsSince1900 - seventyYears; Serial.println(epoch); // print Unix time: jaTime = (float) ((epoch + (9 * 3600)) % (24 * 3600)) / (24 * 3600); // Serial.println(jaTime, 6); } return epoch; // UnixTimeを返す } unsigned long sendNTPpacket(IPAddress& address) { // NTPリクエストパケット送信 // Serial.println("sending NTP packet..."); memset(packetBuffer, 0, NTP_PACKET_SIZE); // set all bytes in the buffer to 0 // Initialize values needed to form NTP request packetBuffer[0] = 0b11100011; // LI, Version, Mode packetBuffer[1] = 0; // Stratum, or type of clock packetBuffer[2] = 6; // Polling Interval packetBuffer[3] = 0xEC; // Peer Clock Precision // 8 bytes of zero for Root Delay & Root Dispersion packetBuffer[12] = 49; packetBuffer[13] = 0x4E; packetBuffer[14] = 49; packetBuffer[15] = 52; udp.beginPacket(address, 123); //NTP requests are to port 123 udp.write(packetBuffer, NTP_PACKET_SIZE); udp.endPacket(); }