最終更新日:2022年2月22日
※ブラウザで温度履歴が得られるようにソースコードを書いてみました。
※2022/2/4 DS18B20を2本接続した動作確認をしました。
STM32miniShieldをベースにしています。
温度センサDS18B20は安価なWaterPloofセンサとして流通しています。
特徴はデジタルセンサと云う事です。電源供給するとデフォルト設定の温度データを取得出来ます。コマンド送信してデータ深度を変更したり出来ます。I2Cモジュールのセンサは使いやすい物がたくさんありますが、WaterPloofとして使うには難しいモノが多いのでいざという場合を考慮してExampleを調査動作確認をしておく必要があります。
STM32duinoソースコード(Sketch)は以下の通りです。
購入したDS18B20ですがステンレス管に入ったモノでセンサケーブル1mタイプです。信号線は赤(Vcc)黄色(信号)黒(GND)です。
STM32MINIshiledのPA9/PA10はPullUp抵抗を入れていないためコネクタ側に付けました。
Specシートには4.7KΩが推奨されているようですが、5.1KΩを使いました。このコードを実行するに当たり追加が必要なライブラリは、
- OneWire.h
STM32MINI_DS18x20_Temperature.ino
/* * 2022年1月7日 T.Wanibe * 温度センサの調査の一環でMaximのDS18B20を使える様にExampleを用意しておきたく検討した * OneWire DS18S20, DS18B20, DS1822 Temperature Example * http://www.pjrc.com/teensy/td_libs_OneWire.html * DallasTemperatureライブラリは、このすべての作業を実行できます。 * https://github.com/milesburton/Arduino-Temperature-Control-Library */ #include <OneWire.h> OneWire ds(PA10); // on pin 10 (a 4.7K resistor is necessary) //−−−−−−−−−−−−−−−−− void setup(void) { Serial.begin(115200); } //−−−−−−−−−−−−−−−−− void loop(void) { byte i; byte present = 0; byte type_s; byte data[12]; byte addr[8]; float celsius, fahrenheit; if ( !ds.search(addr)) { Serial.println(F("No more addresses.")); Serial.println(); ds.reset_search(); delay(250); return; } Serial.print(F("ROM =")); for( i = 0; i < 8; i++) { Serial.write(' '); Serial.print(addr[i], HEX); } if (OneWire::crc8(addr, 7) != addr[7]) { Serial.println(F("CRC is not valid!")); return; } Serial.println(); // 最初のROMバイトはチップ種を示します switch (addr[0]) { case 0x10: Serial.println(F(" Chip = DS18S20")); // or old DS1820 type_s = 1; break; case 0x28: Serial.println(F(" Chip = DS18B20")); type_s = 0; break; case 0x22: Serial.println(F(" Chip = DS1822")); type_s = 0; break; default: Serial.println(F("Device is not a DS18x20 family device.")); return; } ds.reset(); ds.select(addr); ds.write(0x44, 1); // 最後に寄生物の電源を入れて、変換を開始します delay(1000); // 多分750msで十分かもしれません12bit分解能の場合 // ここでds.depower()を実行する場合がありますが、リセットによって処理されます。 present = ds.reset(); ds.select(addr); ds.write(0xBE); // スクラッチパッドを読む Serial.print(F(" Data = ")); Serial.print(present, HEX); Serial.print(F(" ")); for ( i = 0; i < 9; i++) { // we need 9 bytes data[i] = ds.read(); Serial.print(data[i], HEX); Serial.print(F(" ")); } Serial.print(F(" CRC=")); Serial.print(OneWire::crc8(data, 8), HEX); Serial.println(); //結果は16ビットの符号付き整数であるため、データを実際の温度に変換します。 //データは「int16_t」タイプに格納する必要があります。 //これは、32ビットプロセッサでコンパイルした場合でも常に16ビットです。 int16_t raw = (data[1] << 8) | data[0]; if (type_s) { raw = raw << 3; // デフォルトの9ビット解像度 if (data[7] == 0x10) { // 「残り数」は完全な12ビットの解像度を提供します raw = (raw & 0xFFF0) + 12 - data[6]; } } else { byte cfg = (data[4] & 0x60); // 低解像度では、下位ビットは未定義なので、ゼロにしましょう if (cfg == 0x00) raw = raw & ~7; // 9ビットの解像度、93.75ミリ秒 else if (cfg == 0x20) raw = raw & ~3; // 10ビットの解像度、187.5ミリ秒 else if (cfg == 0x40) raw = raw & ~1; // 11ビットの解像度、375ミリ秒 // デフォルトは12ビットの解像度、750ミリ秒の変換時間です } celsius = (float)raw / 16.0; fahrenheit = celsius * 1.8 + 32.0; Serial.print(F(" Temperature = ")); Serial.print(celsius); Serial.print(F(" Celsius, ")); Serial.print(fahrenheit); Serial.println(F(" Fahrenheit")); }実行結果ですが、室温でBME280の温度値と比較しても遜色ない値が返ってきました。約1秒毎に結果が返ってきますが、効率が良いとはいえないですね。複数センサのバス接続も要確認です。
このセンサは屋外でも使いやすそうです。
![]()
PA10の入力ポートに2基のDS18B20を接続し、上記STM32MINI_DS18x20_Temperature.inoをそのまま実行して見ました。
すんなり動作しました。
実行結果
ROM = 28 92 27 96 F0 1 3C D4 Chip = DS18B20 Data = 1 40 1 55 5 7F A5 81 66 C1 CRC=C1 Temperature = 20.00 Celsius, 68.00 Fahrenheit ROM = 28 7 12 96 F0 1 3C D8 Chip = DS18B20 Data = 1 4C 1 55 5 7F A5 A5 66 4 CRC=4 Temperature = 20.75 Celsius, 69.35 Fahrenheit No more addresses. ROM = 28 92 27 96 F0 1 3C D4 Chip = DS18B20 Data = 1 41 1 55 5 7F A5 81 66 82 CRC=82 Temperature = 20.06 Celsius, 68.11 Fahrenheit ROM = 28 7 12 96 F0 1 3C D8 Chip = DS18B20 Data = 1 4E 1 55 5 7F A5 A5 66 82 CRC=82 Temperature = 20.87 Celsius, 69.57 Fahrenheit No more addresses.Chip毎にROMにシリアルコードが書かれており区別されていますが、特定させる方法はこのコードでは対応していないのでもう少し検討が必要です。
ブラウザで温度履歴が得られるようにソースコードを書いてみました。GPS_NTPのコードを元にレタッチしてみました。
※最初のデバイスのデータ読み取りミスが発生しました。そこで、ダミー読み取りを追加して回避しています。このコードを実行するに当たり追加が必要なライブラリは、
/* * 20220215 T.Wanibe * 1.4.2 修正点: * 計測前にdelayは効果無し 結果を見る限り定期的に三時間毎に0.0になっているので、ダミー計測を試すことにした。 * 1.4.1 修正点: * ch1のDS18B20のデータ取得に失敗するケースの対策が不十分 よく判らないが、計測前にdelayを入れてみる * 1.4.0 修正点: * 一時間毎のデータで0と云う値が出ている。これはおかしい。データ取得に失敗している。 * 2ch目では発生していないことから、データ取得時待ち時間を置いてからデータ取得するように修正 *コメント * DS18B20をブラウザ表示するソフトウエアコードを書いているのですが、03までのスケッチは期待通りに動作しません。 * 時刻同期がなぜか失敗することが問題です。 * そこでベースとなるコードを変更して、機能追加し実現してみることにしました。 * 以下はオリジナルコードのコメントです。 * このコードはEthernet3のExample“Udp NTP Client”をSTM32MINIShieldで動く様にレタッチしました。. * BluePillにはRTCが搭載されていますが、精度が悪くバックアップ電源もありません。※接続は可能です * そこで起動時にNTPで時刻所得して登録し、LED&KEYに時刻表示します。 * 以後毎秒時刻更新します。 * 1時間毎にNTPにアクセスして時刻調整します。 * Michael Margolis氏が2010年9月4日に作成したモノをレタッチしています。 * 最大131072バイトのフラッシュメモリのうち、スケッチが69304バイト(52%)を使っています。 * 最大20480バイトのRAMのうち、グローバル変数が5576バイト(27%)を使っていて、ローカル変数で14904バイト使うことができます。 */ #include <libmaple/iwdg.h> #include <SPI.h> #include <Ethernet3.h> #include <EthernetUdp3.h> #include <TM1638.h> #include <RTClock.h> #include <EEPROM.h> #include <avr/pgmspace.h> #include <TextFinder.h> //WebSetting #include <OneWire.h> //DS18B20通信用ライブラリ //PIN #define W550io_Rst PA8 //NIC_Reset #define SPI1_NSS_PIN PA4 //NIC_ChipSelec #define UpdateInterval 86400 //更新間隔 #define dataPin PB4 #define clockPin PB3 #define strobePin PA15 #define BUILTIN_LED PC13 #define DS18B20Port PA10 #define LED1 PB8 #define LED2 PB9 #define HttpPort 80 //HTTP #define debug 1 #define iwdg_init_ms(N) iwdg_init(IWDG_PRE_256,((N)/8)) //設定時間をmsecとするためにマクロを用意する。 #define vers "STM32miniShield DS18B20 1.4" #define NTP_PACKET_SIZE 48 #define SECS_PER_HOUR 3600 //コントローラのMACアドレスを以下に入力してください。 //新しいイーサネットシールドには、シールドのステッカーにMACアドレスが印刷されています const char FVirsion[] = "1.4.2"; byte mac[] = {0x00,0x08,0xDC,0x54,0x4D,0xD1}; //Wiznet byte ip[] = {192, 168, 0, 205}; byte dns_server[] = {192, 168, 0, 1}; byte gateway[] = {0, 0, 0, 0}; byte subnet[] = {255, 255, 255, 0}; byte timeServer[] = {192,168,0,199}; byte packetBuffer[ NTP_PACKET_SIZE]; //着信および発信パケットを保持するバッファ // unsigned int localPort = 8888; //UDPパケットをリッスンするローカルポート char STRBUF[32]; char buffer[128]; int timezone = 9; // change to your timezone //オブジェクトコンストラクタ EthernetServer webServer(HttpPort); EthernetClient client; RTClock rtclock (RTCSEL_LSE); //RTC初期化 EthernetUDP Udp; tm_t tmm,tmm1; //UDPを介してパケットを送受信できるようにするUDPインスタンス TM1638 LedAndKey(dataPin, clockPin, strobePin); //データピンPB4、クロックピンPB3、およびストローブピンPA15でモジュールを定義する const byte ID = 0x9B; char buf1[32]; char buf2[32]; char MacAddressStr[20]; char IPAddressStr[20]; char SubnetMaskStr[20]; char GatewayStr[20]; char NTPserverStr[20]; char DateTimeStr[20]; String DateStr; String TimeStr; float gDayBuf[24][4]; //24時間分4要素データ確保 unsigned long OperatingTime = 0; //稼働時間 Count2で1秒 OneWire ds(PA10); // on pin 10 (a 4.7K resistor is necessary) boolean fDoneTime = false; //---------------------------------- void LANSetup(){ int idcheck = EEPROM.read(0); if (idcheck != ID){ //idがIDの値ではない場合、 //このスケッチがシールドを設定する前に使用されていなかったことを意味します //スケッチの始めに書かれた値を使用するだけです } if (idcheck == ID){ //idがIDと同じ値の場合、 //これは、このスケッチがシールドを設定するために使用されたことを意味します。 //EERPOMの値を読み取ってシールドを設定します。 for (int i = 0; i < 6; i++){ mac[i] = EEPROM.read(i+1); } for (int i = 0; i < 4; i++){ ip[i] = EEPROM.read(i+7); } for (int i = 0; i < 4; i++){ subnet[i] = EEPROM.read(i+11); } for (int i = 0; i < 4; i++){ gateway[i] = EEPROM.read(i+15); } //アクセスNTPサーバー for (int i = 0; i < 4; i++){ timeServer[i] = EEPROM.read(i+19); } } sprintf(MacAddressStr,"%02x.%02x.%02x.%02x.%02x.%02x",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]); sprintf(IPAddressStr,"%d.%d.%d.%d",ip[0],ip[1],ip[2],ip[3]); sprintf(SubnetMaskStr,"%d.%d.%d.%d",subnet[0],subnet[1],subnet[2],subnet[3]); sprintf(GatewayStr,"%d.%d.%d.%d",gateway[0],gateway[1],gateway[2],gateway[3]); sprintf(NTPserverStr,"%d.%d.%d.%d",timeServer[0],timeServer[1],timeServer[2],timeServer[3]); Ethernet.begin(mac, ip); } //-------------------------- void SetWebPage( EthernetClient client){ client.println(F("HTTP/1.1 200 OK")); client.println(F("Content-Type: text/html")); client.println(); // client.print(F("<!DOCTYPE HTML PUBLIC \"\">\n<html>\n<HEAD>\n\t<META http-equiv=\"Content-Type\" charset=UTF-8\">\n")); client.print(F("\t<META http-equiv=\"Content-Style-Type\">\n\t<TITLE>")); client.print(vers); client.print(F(" Setup Page</TITLE>\n</HEAD>\n")); client.print(F("<BODY marginwidth=\"0\" marginheight=\"0\" leftmargin=\"0\" style=\"margin: 0; padding: 0;\">\n<BLOCKQUOTE><BLOCKQUOTE>\n")); client.print(F("<table bgcolor=\"#17A1A5\" border=\"0\" width=\"100%\" cellpadding=\"1\" style=\"font-family:Verdana;color:#ffffff;font-size:12px;\">\n")); client.print(F("<tr><td>")); client.print(vers); client.print(F(" Setup Page</td></tr></table><br>\n")); // client.print(F("<script>\n\tfunction hex2num (s_hex) {\n\t\teval(\"var n_num=0X\" + s_hex);\n\t\treturn n_num;\n\t}\n</script>\n")); client.print(F("<tbody>\n<FORM><input type=\"hidden\" name=\"SBM\" value=\"1\">\n<table>\n<tr><td>MAC:</td><td>")); client.print(F("<input id=\"T1\" type=\"text\" size=\"3\" maxlength=\"2\" name=\"DT1\" value=\"")); client.print(mac[0],HEX); client.print(F("\">.<input id=\"T3\" type=\"text\" size=\"3\" maxlength=\"2\" name=\"DT2\" value=\"")); client.print(mac[1],HEX); client.print(F("\">.<input id=\"T5\" type=\"text\" size=\"3\" maxlength=\"2\" name=\"DT3\" value=\"")); client.print(mac[2],HEX); client.print(F("\">.<input id=\"T7\" type=\"text\" size=\"3\" maxlength=\"2\" name=\"DT4\" value=\"")); client.print(mac[3],HEX); client.print(F("\">.<input id=\"T9\" type=\"text\" size=\"3\" maxlength=\"2\" name=\"DT5\" value=\"")); client.print(mac[4],HEX); client.print(F("\">.<input id=\"T11\" type=\"text\" size=\"3\" maxlength=\"2\" name=\"DT6\" value=\"")); client.print(mac[5],HEX); // client.print(F("\"><input id=\"T2\" type=\"hidden\" name=\"DT1\"><input id=\"T4\" type=\"hidden\" name=\"DT2")); client.print(F("\"><input id=\"T6\" type=\"hidden\" name=\"DT3\"><input id=\"T8\" type=\"hidden\" name=\"DT4")); client.print(F("\"><input id=\"T10\" type=\"hidden\" name=\"DT5\"><input id=\"T12\" type=\"hidden\" name=\"DT6")); client.print(F("\"></td></tr>\n<tr><td>IP:</td><td><input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT7\" value=\"")); client.print(ip[0],DEC); client.print(F("\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT8\" value=\"")); client.print(ip[1],DEC); client.print(F("\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT9\" value=\"")); client.print(ip[2],DEC); client.print(F("\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT10\" value=\"")); client.print(ip[3],DEC); // client.print(F("\"></td></tr>\n<tr><td>MASK: </td><td><input type= \"text\" size=\"3\" maxlength=\"3\" name=\"DT11\" value=\"")); client.print(subnet[0],DEC); client.print(F("\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT12\" value=\"")); client.print(subnet[1],DEC); client.print(F("\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT13\" value=\"")); client.print(subnet[2],DEC); client.print(F("\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT14\" value=\"")); client.print(subnet[3],DEC); // client.print(F("\"></td></tr>\n<tr><td>GW: </td><td><input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT15\" value=\"")); client.print(gateway[0],DEC); client.print(F("\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT16\" value=\"")); client.print(gateway[1],DEC); client.print(F("\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT17\" value=\"")); client.print(gateway[2],DEC); client.print(F("\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT18\" value=\"")); client.print(gateway[3],DEC); // //client.print(F("\"></td></tr>\n<tr><td><br></td COLSPAN='2'>\n<HR ALIGN=LEFT>")); client.print(F("\"></td></tr><tr><td COLSPAN='2'>\n<HR ALIGN=CENTER></td><td>")); //1行空けたい // client.print(F("</td></tr><tr><td>NTPd: </td><td><input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT19\" value=\"")); client.print(timeServer[0],DEC); client.print(F("\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT20\" value=\"")); client.print(timeServer[1],DEC); client.print(F("\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT21\" value=\"")); client.print(timeServer[2],DEC); client.print(F("\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT22\" value=\"")); client.print(timeServer[3],DEC); client.print(F("\"></td></tr>\n<tr><td><br></td></tr><tr><td COLSPAN='2'><P ALIGN=RIGHT><input id=\"button1\"type=\"submit\" value=\"SUBMIT\" ")); // client.print(F("Onclick=\"")); client.print(F("document.getElementById('T2').value = hex2num(document.getElementById('T1').value);\n")); client.print(F("\t\tdocument.getElementById('T4').value = hex2num(document.getElementById('T3').value);\n")); client.print(F("\t\tdocument.getElementById('T6').value = hex2num(document.getElementById('T5').value);\n")); client.print(F("\t\tdocument.getElementById('T8').value = hex2num(document.getElementById('T7').value);\n")); client.print(F("\t\tdocument.getElementById('T10').value = hex2num(document.getElementById('T9').value);\n")); client.print(F("\t\tdocument.getElementById('T12').value = hex2num(document.getElementById('T11').value);\"")); // client.print(F("></td></tr></tbody>\n</table>\n</BLOCKQUOTE></BLOCKQUOTE>\n</form>\n</BODY>\n</html>\n")); } //-------------------------- 2021/8/12 void SetUtilPage( EthernetClient client){ client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println(); // client.print(F("<!DOCTYPE HTML PUBLIC \"\">\n<html>\n<HEAD>\n\t<META http-equiv=\"Content-Type\" charset=\"UTF-8\">\n")); client.print(F("\t<META http-equiv=\"Content-Style-Type\">\n\t<TITLE>")); client.print(vers); client.print(F(" Utility Page</TITLE>\n")); client.print(F("\t<script type='application/javascript' SRC='http://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.bundle.js'></script>\n")); client.print(F("\t<script type='application/javascript' SRC='./setup3'></script>\n")); client.print(F("\t<style>\n\t\tcanvas{\n")); client.print(F("\t\t\t-moz-user-select: none;\n")); client.print(F("\t\t\t-webkit-user-select: none;\n")); client.print(F("\t\t\t-ms-user-select: none;\n\t\t}\n")); client.print(F("\t\thtml { font-family: Helvetica; display: inline-block; margin: 0px auto;}\n")); client.print(F("\t\tbody{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;}\n")); client.print(F("\t\tp {font-size: 24px;color: #444444;margin-bottom: 10px;}\n")); client.print(F("\t</style>\n</HEAD>\n")); client.print(F("<BODY marginwidth=\"0\" marginheight=\"0\" leftmargin=\"0\" style=\"margin: 0; padding: 0;\" BGCOLOR=\"#ffffff\">\n")); client.print(F("<FORM>\n<BLOCKQUOTE><BLOCKQUOTE>\n")); client.print(F("<P><table bgcolor=\"#17A1A5\" border=\"0\" width=\"100%\" cellpadding=\"1\" style=\"font-family:Verdana;color:#ffffff;font-size:12px;\" CELLSPACING=\"2\">\n")); client.print(F("<tr><td>")); client.print(vers); client.print(F(" Utility Page</td></tr></table><br>\n")); // client.print(F("<TABLE WIDTH=\"100%\" BORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"0\">")); client.print(F("<TR>\n\t<TD WIDTH=\"25%\">FirmwareVirsion:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">")); client.print(FVirsion); client.print(F("</TD>\n</TR>")); client.print(F("<TR>\n\t<TD WIDTH=\"25%\">MacAddress:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">")); client.print(MacAddressStr); client.print(F("</TD>\n</TR>")); client.print(F("<TR>\n\t<TD WIDTH=\"25%\">IPAddress:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">")); client.print(IPAddressStr); client.print(F("</TD>\n</TR>")); client.print(F("<TR>\n\t<TD WIDTH=\"25%\">SubnetMask:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">")); client.print(SubnetMaskStr); client.print(F("</TD>\n</TR>")); client.print(F("<TR>\n\t<TD WIDTH=\"25%\" NOWRAP>Data acquisition time(Local):</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">")); client.print(DateTimeStr); client.print(F("</TD>\n</TR>")); client.print(F("<TR>\n\t<TD WIDTH=\"25%\" NOWRAP>Operating Time:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">")); sprintf(buf2,"%d[sec]",OperatingTime); client.print(buf2); client.print(F("</TD>\n</TR></TABLE></P>\n")); client.print(F("\t<div style='width:75%;'><canvas id='canvas' width='750' height='400' style='display: block; width: 750px; height: 400px;'></canvas></div>\n")); client.print(F("</CENTER></BLOCKQUOTE></BLOCKQUOTE>\n</form>\n")); client.print(F("<script>\n")); client.print(F("\t\tvar randomScalingFactor = function() {\n\t\t\treturn 18 + Math.random() * 10;\n\t\t};\n")); client.print(F("\t\tvar data_00 = [")); for(int i = 0; i<24 ;i++){ client.print(isnan(gDayBuf[i][0]) ? String('\0') : String(gDayBuf[i][0],6)); client.print(F(",")); } client.print(F("];\n")); client.print(F("\t\tvar data_01 = [")); for(int i = 0; i<24 ;i++){ client.print(isnan(gDayBuf[i][1]) ? String('\0') : String(gDayBuf[i][1],6)); client.print(F(",")); } client.print(F("];\n")); client.print(F("\t\tvar data_02 = [")); for(int i = 0; i<24 ;i++){ client.print(isnan(gDayBuf[i][2]) ? String('\0') : String(gDayBuf[i][2],2)); client.print(F(",")); } client.print(F("];\n")); client.print(F("\t\tvar data_03 = [")); for(int i = 0; i<24 ;i++){ client.print(isnan(gDayBuf[i][3]) ? String('\0') : String(gDayBuf[i][3],2)); client.print(F(",")); } client.print(F("];\n")); client.print(F("\t\tvar config = {")); client.print(F("\t\t\ttype: 'line',\n\t\t\tdata: {\n")); client.print(F("\t\t\t\tlabels: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12' , '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23'],\n")); client.print(F("\t\t\t\tdatasets: [{\n")); client.print(F("\t\t\t\t\tlabel: '温度1[℃]',\n")); client.print(F("\t\t\t\t\tdata: data_00,\n")); client.print(F("\t\t\t\t\tborderColor: window.chartColors.red,\n")); client.print(F("\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0)',\n")); client.print(F("\t\t\t\t\tfill: false,\n")); client.print(F("\t\t\t\t\tcubicInterpolationMode: 'monotone',\n")); client.print(F("\t\t\t\t\tyAxisID: 'y1'\n")); client.print(F("\t\t\t\t}, {\n")); client.print(F("\t\t\t\t\tlabel: '温度2[℃]',\n")); client.print(F("\t\t\t\t\tdata: data_01,\n")); client.print(F("\t\t\t\t\tborderColor: window.chartColors.blue,\n")); client.print(F("\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0)',\n")); client.print(F("\t\t\t\t\tfill: false,\n")); client.print(F("\t\t\t\t\tyAxisID: 'y2'\n")); client.print(F("\t\t\t\t}, {\n")); client.print(F("\t\t\t\t\tlabel: '温度3[℃]',\n")); client.print(F("\t\t\t\t\tdata: data_02,\n")); client.print(F("\t\t\t\t\tborderColor: window.chartColors.orange,\n")); client.print(F("\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0)',\n")); client.print(F("\t\t\t\t\tfill: false,\n")); client.print(F("\t\t\t\t\tyAxisID: 'y3'\n")); client.print(F("\t\t\t\t}, {\n")); client.print(F("\t\t\t\t\tlabel: '温度4[℃]',\n")); client.print(F("\t\t\t\t\tdata: data_03,\n")); client.print(F("\t\t\t\t\tborderColor: window.chartColors.yellow,\n")); client.print(F("\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0)',\n")); client.print(F("\t\t\t\t\tfill: false,\n")); client.print(F("\t\t\t\t\tyAxisID: 'y4'\n")); client.print(F("\t\t\t\t}]\n\t\t\t},\n")); client.print(F("\t\t\toptions: {\n\t\t\t\tresponsive: true,\n")); client.print(F("\t\t\t\ttitle: {\n\t\t\t\t\tdisplay: true,\n\t\t\t\t\ttext: '温度取得履歴'\n\t\t\t\t},\n")); client.print(F("\t\t\t\tlegend: {\n\t\t\t\t\tdisplay: true\n\t\t\t\t},\n")); client.print(F("\t\t\t\ttooltips: {\n\t\t\t\t\tenabled: true,\n\t\t\t\t\tmode: 'index'\n\t\t\t\t},\n")); client.print(F("\t\t\t\tscales: {\n\t\t\t\t\txAxes: [{\n\t\t\t\t\t\tdisplay: true,\n")); client.print(F("\t\t\t\t\t\tscaleLabel: {\n\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\tlabelString: '時刻 [時]'\n\t\t\t\t\t\t}\n\t\t\t\t\t}],\n")); client.print(F("\t\t\t\t\tyAxes: [{\n\t\t\t\t\t\tid:'y1',\n\t\t\t\t\t\tdisplay: true,\n")); client.print(F("\t\t\t\t\t\tscaleLabel: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.red,\n")); client.print(F("\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\tlabelString: '温度1[℃]'\n\t\t\t\t\t\t},\n")); client.print(F("\t\t\t\t\t\tticks: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.red,\n")); client.print(F("\t\t\t\t\t\t\tsuggestedMin: -20,\n\t\t\t\t\t\t\tsuggestedMax: 80\n\t\t\t\t\t\t}\n")); client.print(F("\t\t\t\t\t},{\n\t\t\t\t\t\tid:'y2',\n\t\t\t\t\t\tdisplay: true,\n")); client.print(F("\t\t\t\t\t\tscaleLabel: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.blue,\n")); client.print(F("\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\tlabelString: '温度2[℃]'\n\t\t\t\t\t\t},\n")); client.print(F("\t\t\t\t\t\tticks: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.blue,\n")); client.print(F("\t\t\t\t\t\t\tsuggestedMin: -20,\n\t\t\t\t\t\t\tsuggestedMax: 80\n\t\t\t\t\t\t}\n")); client.print(F("\t\t\t\t\t},{\n\t\t\t\t\t\tid:'y3',\n\t\t\t\t\t\tposition: 'right',\n\t\t\t\t\t\tdisplay: true,\n")); client.print(F("\t\t\t\t\t\tscaleLabel: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.orange,\n")); client.print(F("\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\tlabelString: '温度3[℃]'\n\t\t\t\t\t\t},\n")); client.print(F("\t\t\t\t\t\tticks: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.orange,\n")); client.print(F("\t\t\t\t\t\t\tsuggestedMin: -20,\n\t\t\t\t\t\t\tsuggestedMax: 80\n\t\t\t\t\t\t\t}\n")); client.print(F("\t\t\t\t\t},{\n\t\t\t\t\t\tid:'y4',\n\t\t\t\t\t\tposition: 'right',\n\t\t\t\t\t\tdisplay: true,\n")); client.print(F("\t\t\t\t\t\tscaleLabel: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.yellow,\n")); client.print(F("\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\tlabelString: '温度4[℃]'\n\t\t\t\t\t\t},\n")); client.print(F("\t\t\t\t\t\tticks: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.yellow,\n")); client.print(F("\t\t\t\t\t\t\tsuggestedMin: -40,\n\t\t\t\t\t\t\tsuggestedMax: 160\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}],\n")); client.print(F("\t\t\t\t}\n\t\t\t}\n\t\t};\n")); client.print(F("\t\twindow.onload = function() {\n\t\t\tvar ctx = document.getElementById('canvas').getContext('2d');\n")); client.print(F("\t\t\twindow.myLine = new Chart(ctx, config);\n\t\t};\n")); client.print(F("</script>\n")); client.print(F("</BODY></html>")); } //-------------------------- void checkWebPage( EthernetClient client) { Serial.println(F("new webClient")); boolean restart = false; if (client) { TextFinder finder(client ); while (client.connected()) { //digitalWrite(LED, HIGH); if (client.available()) { //この部分はすべてのテキスト検索を行います。 if( finder.find("GET /") ) { // 「setup」とい語が見つかった場合は、さらに探してください。 // その単語が見つからない場合は、検索を停止して先に進みます。 // これにより、後でスケッチに独自のWebページを配置できます。 if (finder.findUntil("setup", "\n\r")){ long cord = finder.getValue(); sprintf(buf1,"setupIn=%d",cord); Serial.println(buf1); switch(cord){ case 1: // 「SBM」という単語が見つかった場合は、さらに探し続けます。 // その言葉が見つからない場合は、探して停止します。 // SUBMITボタンが押されていない、何も押されていないことを意味します // セットアップページが構築されている場所に移動し、クライアントのブラウザに表示します。 if (finder.findUntil("SBM", "\n\r")){ byte SET = finder.getValue(); // これで、「DT」という文字を探している間に、「DT」の後ろにあるすべての数字を覚えて、 // 値を一致させて、mac、ip、subnet、およびgatewayに入れる必要があります。 while(finder.findUntil("DT", "\n\r")){ int val = finder.getValue(); // 「DT」のvalが1?6の場合、対応する値はMAC値でなければなりません。 if(val >= 1 && val <= 6) { mac[val - 1] = finder.getValue(); } // 「DT」のvalが7?10の場合、対応する値はIP値でなければなりません。 if(val >= 7 && val <= 10) { ip[val - 7] = finder.getValue(); } // 「DT」のvalが11?14の場合、対応する値はMASK値でなければなりません。 if(val >= 11 && val <= 14) { subnet[val - 11] = finder.getValue(); } // 「DT」のvalが15?18の場合、対応する値はGW値でなければなりません。 if(val >= 15 && val <= 18) { gateway[val - 15] = finder.getValue(); } // 「DT」のvalが19?22の場合、対応する値はTimeServer値でなければなりません。 if(val >= 19 && val <= 22) { timeServer[val - 19] = finder.getValue(); } } // すべてのデータを取得したので、EEPROMに保存できます for (int i = 0 ; i < 6; i++){ EEPROM.write(i + 1,mac[i]); } for (int i = 0 ; i < 4; i++){ EEPROM.write(i + 7, ip[i]); } for (int i = 0 ; i < 4; i++){ EEPROM.write(i + 11, subnet[i]); } for (int i = 0 ; i < 4; i++){ EEPROM.write(i + 15, gateway[i]); } for (int i = 0 ; i < 4; i++){ EEPROM.write(i + 19, timeServer[i]); } // IDを既知のビットに設定します。したがって、Arduinoをリセットすると、EEPROM値が使用されます。 EEPROM.write(0, ID); sprintf(MacAddressStr,"%02x.%02x.%02x.%02x.%02x.%02x",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]); sprintf(IPAddressStr,"%d.%d.%d.%d",ip[0],ip[1],ip[2],ip[3]); sprintf(SubnetMaskStr,"%d.%d.%d.%d",subnet[0],subnet[1],subnet[2],subnet[3]); sprintf(GatewayStr,"%d.%d.%d.%d",gateway[0],gateway[1],gateway[2],gateway[3]); // すべてのデータがEEPROMに書き込まれている場合、arduinoをリセットする必要があります。 //ハードウェアリセットボタンを使用する必要があります。 restart = true; }else{ } // この時点から、セットアップページの構築を開始し、クライアントのブラウザーに表示できます。 SetWebPage(client); break; case 2: // 新規にユーティリティ頁を作りました。 Serial.println(F("utilIn")); rtclock.getTime(tmm); sprintf(DateTimeStr,"%04u/%02u/%02u %02u:%02u:%02u",tmm.year+1970, tmm.month, tmm.day,tmm.hour, tmm.minute, tmm.second); SetUtilPage(client); break; case 3: //utils.jsが要求された。 Serial.println(F("utils.js")); LoadUtilsJS(client); break; default: PrintResponse404(client ); break; } }else{ pageIntroduction(client); } } break; } PrintResponse404(client ); } delay(1); client.stop(); if(restart) nvic_sys_reset(); } } //---------------------------- void pageIntroduction( EthernetClient client){ client.println(F("HTTP/1.1 200 OK")); client.println(F("Content-Type: text/html")); client.println(); // put your own html from here on sprintf(buf1,"%d.%d.%d.%d",ip[0],ip[1],ip[2],ip[3]); client.println(F("<HTML>\n<HEAD>\n\t<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html;CHARSET=UTF-8\">\n</HEAD>\n")); client.println(F("<BODY BGCOLOR='#ffffff'>\n<H2><CENTER><FONT COLOR='#00ff00'>DS18B20 SetUp Menu</FONT></CENTER></H2>\n")); client.println(F("<P><CENTER><TABLE WIDTH='300' BORDER='0' CELLSPACING='0' CELLPADDING='0'>\n\t<TR>\n\t\t<TD WIDTH='100%'>\n\t\t<OL>\n")); sprintf(buffer,"\t\t\t<LI><FONT SIZE='+1'><A HREF=\"http://%s/setup1\">設定メニュー</A>\n",buf1); client.println(buffer); sprintf(buffer,"\t\t\t<LI><A HREF=\"http://%s/setup2\">温度履歴表示</A></FONT>\n",buf1); client.println(buffer); client.print(F("\t\t</OL>\n\t\t</TD>\n\t</TR>\n</TABLE></CENTER>\n</BODY>\n</HTML>\n")); client.stop(); } //-------------------------- void PrintResponse404( EthernetClient client ) { client.println(F("HTTP/1.1 404 Not Found")); client.println(F("Content-Type: text/html")); client.println(F("Connnection: close")); client.println(); client.stop(); } //-------------------------- void LoadUtilsJS( EthernetClient client ) { client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println(); // client.println("'use strict';\n"); // client.println("window.chartColors = {"); client.println("\tred: 'rgb(255, 99, 132)',"); client.println("\torange: 'rgb(255, 159, 64)',"); client.println("\tyellow: 'rgb(255, 205, 86)',"); client.println("\tgreen: 'rgb(75, 192, 192)',"); client.println("\tblue: 'rgb(54, 162, 235)',"); client.println("\tpurple: 'rgb(153, 102, 255)',"); client.println("\tgrey: 'rgb(201, 203, 207)'"); client.println("};\n"); // client.println("(function(global) {"); client.println("\tvar MONTHS = ["); client.println("\t\t'January',"); client.println("\t\t'February',"); client.println("\t\t'March',"); client.println("\t\t'April',"); client.println("\t\t'May',"); client.println("\t\t'June',"); client.println("\t\t'July',"); client.println("\t\t'August',"); client.println("\t\t'September',"); client.println("\t\t'October',"); client.println("\t\t'November',"); client.println("\t\t'December'"); client.println("\t];\n"); // client.println("\tvar COLORS = ["); client.println("\t\t'#4dc9f6',"); client.println("\t\t'#f67019',"); client.println("\t\t'#f53794',"); client.println("\t\t'#537bc4',"); client.println("\t\t'#acc236',"); client.println("\t\t'#166a8f',"); client.println("\t\t'#00a950',"); client.println("\t\t'#58595b',"); client.println("\t\t'#8549ba'"); client.println("\t];\n"); // client.println("\tvar Samples = global.Samples || (global.Samples = {});"); client.println("\tvar Color = Chart.helpers.color;\n"); // client.println("\tfunction applyDefaultNumbers(config) {"); client.println("\t\tvar cfg = config || {};"); client.println("\t\tcfg.min = cfg.min || 0;"); client.println("\t\tcfg.max = cfg.max || 1;"); client.println("\t\tcfg.from = cfg.from || [];"); client.println("\t\tcfg.count = cfg.count || 8;"); client.println("\t\tcfg.decimals = cfg.decimals || 8;"); client.println("\t\tcfg.continuity = cfg.continuity || 1;\n"); // client.println("\t\treturn cfg;"); client.println("\t}\n"); // client.println("\tSamples.utils = {"); client.println("\t\t// Adapted from http://indiegamr.com/generate-repeatable-random-numbers-in-js/"); client.println("\t\tsrand: function(seed) {"); client.println("\t\t\tthis._seed = seed;"); client.println("\t\t},\n"); // client.println("\t\trand: function(min, max) {"); client.println("\t\t\tvar seed = this._seed;"); client.println("\t\t\tmin = min === undefined ? 0 : min;"); client.println("\t\t\tmax = max === undefined ? 1 : max;"); client.println("\t\t\tthis._seed = (seed * 9301 + 49297) % 233280;"); client.println("\t\t\treturn min + (this._seed / 233280) * (max - min);"); client.println("\t\t},\n"); // client.println("\t\tnumbers: function(config) {"); client.println("\t\t\tvar cfg = applyDefaultNumbers(config);"); client.println("\t\t\tvar dfactor = Math.pow(10, cfg.decimals) || 0;"); client.println("\t\t\tvar data = [];"); client.println("\t\t\tvar i, value;\n"); // client.println("\t\t\tfor (i = 0; i < cfg.count; ++i) {"); client.println("\t\t\t\tvalue = (cfg.from[i] || 0) + this.rand(cfg.min, cfg.max);"); client.println("\t\t\t\tif (this.rand() <= cfg.continuity) {"); client.println("\t\t\t\t\tdata.push(Math.round(dfactor * value) / dfactor);"); client.println("\t\t\t\t} else {"); client.println("\t\t\t\t\tdata.push(null);"); client.println("\t\t\t\t}"); client.println("\t\t\t}\n"); // client.println("\t\t\treturn data;"); client.println("\t\t},\n"); // client.println("\t\tlabels: function(config) {"); client.println("\t\t\tvar cfg = config || {};"); client.println("\t\t\tvar min = cfg.min || 0;"); client.println("\t\t\tvar max = cfg.max || 100;"); client.println("\t\t\tvar count = cfg.count || 8;"); client.println("\t\t\tvar step = (max - min) / count;"); client.println("\t\t\tvar decimals = cfg.decimals || 8;"); client.println("\t\t\tvar dfactor = Math.pow(10, decimals) || 0;"); client.println("\t\t\tvar prefix = cfg.prefix || '';"); client.println("\t\t\tvar values = [];"); client.println("\t\t\tvar i;\n"); // client.println("\t\t\tfor (i = min; i < max; i += step) {"); client.println("\t\t\t\tvalues.push(prefix + Math.round(dfactor * i) / dfactor);"); client.println("\t\t\t}\n"); // client.println("\t\t\treturn values;"); client.println("\t\t},\n"); // client.println("\t\tmonths: function(config) {"); client.println("\t\t\tvar cfg = config || {};"); client.println("\t\t\tvar count = cfg.count || 12;"); client.println("\t\t\tvar section = cfg.section;"); client.println("\t\t\tvar values = [];"); client.println("\t\t\tvar i, value;\n"); // client.println("\t\t\tfor (i = 0; i < count; ++i) {"); client.println("\t\t\t\tvalue = MONTHS[Math.ceil(i) % 12];"); client.println("\t\t\t\tvalues.push(value.substring(0, section));"); client.println("\t\t\t}\n"); // client.println("\t\t\treturn values;"); client.println("\t\t},\n"); // client.println("\t\tcolor: function(index) {"); client.println("\t\t\treturn COLORS[index % COLORS.length];"); client.println("\t\t},\n"); // client.println("\t\ttransparentize: function(color, opacity) {"); client.println("\t\t\tvar alpha = opacity === undefined ? 0.5 : 1 - opacity;"); client.println("\t\t\treturn Color(color).alpha(alpha).rgbString();"); client.println("\t\t}"); client.println("\t};\n"); // client.println("\t// DEPRECATED"); client.println("\twindow.randomScalingFactor = function() {"); client.println("\t\treturn Math.round(Samples.utils.rand(-100, 100));"); client.println("\t};\n"); // client.println("\t// INITIALIZATION\n"); // client.println("\tSamples.utils.srand(Date.now());\n"); // client.println("\t// Google Analytics"); client.println("\t/* eslint-disable */"); client.println("\tif (document.location.hostname.match(/^(www\\.)?chartjs\\.org$/)) {"); client.println("\t\t(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){"); client.println("\t\t(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),"); client.println("\t\tm=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)"); client.println("\t\t})(window,document,'script','//www.google-analytics.com/analytics.js','ga');"); client.println("\t\tga('create', 'UA-28909194-3', 'auto');"); client.println("\t\tga('send', 'pageview');"); client.println("\t}"); client.println("\t/* eslint-enable */\n"); // client.println("}(this));"); } //-------指定されたアドレスのタイムサーバーにNTP要求を送信します void sendNTPpacket(byte address[]){ memset(packetBuffer, 0, NTP_PACKET_SIZE); //バッファ内のすべてのバイトを0に設定します //NTP要求を形成するために必要な値を初期化する packetBuffer[0] = 0b11100011; // LI, Version, Mode packetBuffer[1] = 0; //階層、またはクロックのタイプ packetBuffer[2] = 6; //ポーリング間隔 packetBuffer[3] = 0xEC; //ピアクロックの精度 //ルート遅延およびルート分散用のゼロの8バイト packetBuffer[12] = 49; packetBuffer[13] = 0x4E; packetBuffer[14] = 49; packetBuffer[15] = 52; //すべてのNTPフィールドに値が与えられました。 //タイムスタンプを要求するパケットを送信できます: Udp.beginPacket(address, 123); //NTPリクエストはポート123へ Udp.write(packetBuffer, NTP_PACKET_SIZE); Udp.endPacket(); } //----------------- 割込CallBack void TimeUpdate(void){ //1000msec毎に呼ばれる OperatingTime++; } //------------------ void GetTemp(float &celsius) { byte i; byte present = 0; byte type_s; byte data[12]; byte addr[8]; //float celsius; if ( !ds.search(addr)) { Serial.println(F("No more addresses.")); ds.reset_search(); delay(100); return; } Serial.print(F("ROM =")); for( i = 0; i < 8; i++) { Serial.write(' '); Serial.print(addr[i], HEX); } if (OneWire::crc8(addr, 7) != addr[7]) { Serial.println(F("CRC is not valid!")); return; } // 最初のROMバイトはチップ種を示します switch (addr[0]) { case 0x10: Serial.println(F(" Chip = DS18S20")); // or old DS1820 type_s = 1; break; case 0x28: Serial.println(F(" Chip = DS18B20")); type_s = 0; break; case 0x22: Serial.println(F(" Chip = DS1822")); type_s = 0; break; default: Serial.println(F("Device is not a DS18x20 family device.")); return; } ds.reset(); ds.select(addr); ds.write(0x44, 1); // 最後に寄生物の電源を入れて、変換を開始します delay(750); // 多分750msで十分かもしれません12bit分解能の場合 // ここでds.depower()を実行する場合がありますが、リセットによって処理されます。 present = ds.reset(); ds.select(addr); ds.write(0xBE); // スクラッチパッドを読む Serial.print(F(" Data = ")); Serial.print(present, HEX); Serial.print(F(" ")); for ( i = 0; i < 9; i++) { // we need 9 bytes data[i] = ds.read(); Serial.print(data[i], HEX); Serial.print(F(" ")); } Serial.print(F(" CRC=")); Serial.print(OneWire::crc8(data, 8), HEX); Serial.println(); //結果は16ビットの符号付き整数であるため、データを実際の温度に変換します。 //データは「int16_t」タイプに格納する必要があります。 //これは、32ビットプロセッサでコンパイルした場合でも常に16ビットです。 int16_t raw = (data[1] << 8) | data[0]; if (type_s) { raw = raw << 3; // デフォルトの9ビット解像度 if (data[7] == 0x10) { // 「残り数」は完全な12ビットの解像度を提供します raw = (raw & 0xFFF0) + 12 - data[6]; } } else { byte cfg = (data[4] & 0x60); // 低解像度では、下位ビットは未定義なので、ゼロにしましょう if (cfg == 0x00) raw = raw & ~7; // 9ビットの解像度、93.75ミリ秒 else if (cfg == 0x20) raw = raw & ~3; // 10ビットの解像度、187.5ミリ秒 else if (cfg == 0x40) raw = raw & ~1; // 11ビットの解像度、375ミリ秒 // デフォルトは12ビットの解像度、750ミリ秒の変換時間です } celsius = (float)raw / 16.0; //fahrenheit = celsius * 1.8 + 32.0; Serial.print(F(" Temperature = ")); Serial.println(celsius); return; } //----------------- int getHourTime(void){ rtclock.getTime(tmm1); return tmm1.hour; } //----------------- int getMinuteTime(void){ rtclock.getTime(tmm1); return tmm1.minute; } //---------------- bool checkNTP(){ sendNTPpacket(timeServer); //NTPパケットをタイムサーバーに送信する delay(2000); //返信が利用可能かどうかを確認するのを待ちます if ( Udp.parsePacket() ) { //パケットを受信し、そこからデータを読み取ります Udp.read(packetBuffer, NTP_PACKET_SIZE); //パケットをバッファに読み込みます //タイムスタンプは、受信したパケットのバイト40から始まり、4バイト、つまり2ワードの長さです。 まず、2つの単語を抽出します。 unsigned long highWord = word(packetBuffer[40], packetBuffer[41]); unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]); //4バイト(2ワード)を長整数に結合します //これはNTP時間(1900年1月1日からの秒数)です。 unsigned long secsSince1900 = highWord << 16 | lowWord; Serial.print(F("Seconds since Jan 1 1900 = " )); Serial.println(secsSince1900); //NTP時間をUTC時刻に変換します: Serial.print("Unix time = "); //Unix時間は1970年1月1日に始まります。数秒で、2208988800になります。 const unsigned long seventyYears = 2208988800UL; //引き算します。 unsigned long epoch = secsSince1900 - seventyYears; // print Unix time: Serial.println(epoch); //時、分、秒を印刷します。JST(+9) Serial.print(F("The JST time is ")); //UTCはグリニッジ子午線(GMT)の時刻です epoch = epoch + (9 * 3600); rtclock.setTime(time_t(epoch)); //JSTを内部時計にセット Serial.print((epoch % 86400L) / 3600); //時間を印刷します(86400は1日あたりの秒数に相当) Serial.print(':'); int min = (epoch % 3600) / 60; if ( min < 10 ) { Serial.print('0'); //各時間の最初の10分では、先頭に「0」が必要です。 } Serial.print(min); //分を印刷する(3600は1分あたりの秒数に等しい) Serial.print(':'); int sec = epoch % 60; if ( sec < 10 ) { Serial.print('0'); //各分の最初の10秒で、先頭に「0」が必要になります } Serial.println(sec); //秒を印刷 return true; }else{ return false; } } //---------------- void setup() { // Open serial communications and wait for port to open: Serial.begin(115200); //シリアル通信を開ます。 pinMode(BUILTIN_LED,OUTPUT); digitalWrite(BUILTIN_LED,LOW); pinMode(LED1,OUTPUT); digitalWrite(LED1, HIGH); pinMode(LED2,OUTPUT); digitalWrite(LED2, LOW); //Ethernet3API Ethernet.setCsPin(SPI1_NSS_PIN); Ethernet.setRstPin(W550io_Rst); pinMode(W550io_Rst, OUTPUT); digitalWrite(W550io_Rst, LOW); delay(10); digitalWrite(W550io_Rst, HIGH); Serial.print(F("NIC_Reset\n")); LANSetup(); //イーサネットとUDPを開始します Udp.begin(localPort); Serial.print(F("server is at "));Serial.println(Ethernet.localIP()); fDoneTime = checkNTP(); rtclock.getTime(tmm); sprintf(STRBUF,"%02u%02u%02u",tmm.hour,tmm.minute,tmm.second); LedAndKey.setDisplayToString("000000",0,2); Serial.print(F("server is at "));Serial.println(Ethernet.localIP()); webServer.begin(); //データバッファクリア for(int i = 0;i<24;i++){ for(int j = 0;j<4;j++){ gDayBuf[i][j] = NAN; } } //タイマ割込設定 Timer1.pause(); // Timer1.setPrescaleFactor(7200); // 72MHz100uSEC Timer1.setOverflow(10000); // 1000mSEC Timer1.attachInterrupt(TIMER_UPDATE_INTERRUPT,TimeUpdate); // 割り込みサーブルーチンの宣言:TimeUpdate Timer1.setCount(0); // 0 Timer1.refresh(); Timer1.resume(); // iwdg_init_ms(30000); //ウォッチドッグをオンにして、オーバーフロー時間を設定します。 Serial.println(F("EndSetUp")); } //---------------- int preSet = -1; int preMSet = -1; void loop() { //このLoopはscantime=1秒程度です。そのため5秒経っても戻らなかったらリセットすることにします。 iwdg_feed(); //ウォッチドッグタイマーをリセットするには、ドッグ操作をフィードします // if(!(OperatingTime % 3600)){ //1時間に一回 fDoneTime = checkNTP(); } rtclock.getTime(tmm); sprintf(STRBUF,"%02u%02u%02u",tmm.hour,tmm.minute,tmm.second); LedAndKey.setDisplayToString(STRBUF,0,2); if(!(OperatingTime % 60)) Serial.println(F(".")); else Serial.print(F(".")); //digitalWrite(BUILTIN_LED,OperatingTime % 2); client = webServer.available(); //HTTP要求確認 if(client) checkWebPage(client); client.stop(); // コネクションを閉じる。 //時刻チェック int h = getHourTime(); //返値0-23 int m = getMinuteTime(); //返値0-59 if(preSet != h){ //1時間おきに時刻を確認し、データをメモリに確保 preSet = h; float celsius; //最初にダミー計測 for (int i = 0;i<2;i++){ GetTemp(celsius); } //本計測 for (int i = 0;i<2;i++){ GetTemp(celsius); if(celsius != 0.0){ gDayBuf[h][i] = celsius; } } //次回分のデータをNULL化 h = (h+1) % 24; for (int i = 0;i<4;i++){ gDayBuf[h][i] = NAN; } }else if(preMSet != m){ //1分おきにデータ取込 preMSet = m; float celsius; for (int i = 0;i<2;i++){ delay(100); GetTemp(celsius); } if(!fDoneTime){ fDoneTime = checkNTP(); } }else{ //計測しない } if(OperatingTime % 2){ digitalWrite(LED1, LOW); digitalWrite(LED2, HIGH); }else{ digitalWrite(LED1, HIGH); digitalWrite(LED2, LOW); } delay(200); } |
2022/2/16 上記ソースには問題があります。複数デバイスを接続した場合、取り出したデータがどのデバイスのモノなのか判らないのです。
DS18B20には48bitのIDが付加されているため、区別するようなコードであれば問題は発生しません。IDを事前に調べて、IDを指定して温度取得すれば良いです。そのようなコードに修正する必要があります。ただ、ソースコード内に事前に調べたDS18B20のIDを書き込むのはどうでしょうか?
setup()で接続されているDS18B20をリストアップし、順次データをふるい分けるようにすればとりあえずは解決するかと考えます。基本うまくゆきました。そして温度値の確からしさが向上したと思います。
※ArduinoやESP32では以下のライブラリをインクルードすれば実現出来るのですが、STM32duinoではbuild出来ません。
#include <OneWire.h> #include <DallasTemperature.h>思ったのですがDallasTemperature.h内でOneWire.hをコールしていて辻褄が合わなくなるのかと思いました。STM32duinoではOneWire.hが読み替えられているようです。
2022/2/22 前回のソースには時刻合わせのコードにバグがありました。修正しました。※一時間ずれる事がありました。
Udp.read(packetBuffer, NTP_PACKET_SIZE); //パケットをバッファに読み込みます //タイムスタンプは、受信したパケットのバイト40から始まり、4バイト、つまり2ワードの長さです。 まず、2つの単語を抽出します。 unsigned long highWord = word(packetBuffer[40], packetBuffer[41]); unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]); //4バイト(2ワード)を長整数に結合します //これはNTP時間(1900年1月1日からの秒数)です。 unsigned long secsSince1900 = highWord << 16 | lowWord; //NTP時間をUTC時刻に変換します: //Unix時間は1970年1月1日に始まります。数秒で、2208988800になります。 const unsigned long seventyYears = 2208988800UL; //引き算します。 unsigned long epoch = secsSince1900 - seventyYears; // print Unix time: epoch = epoch + (9 * 3600); rtclock.setTime(time_t(epoch)); //JSTを内部時計にセット上記コードには桁あふれのバグが潜在化しています。そこで以下のように修正しています。
Udp.read(packetBuffer, NTP_PACKET_SIZE); // read packet into the buffer unsigned long secsSince1900,nowTime; // convert four bytes starting at location 40 to a long integer secsSince1900 = (unsigned long)packetBuffer[40] << 24; secsSince1900 |= (unsigned long)packetBuffer[41] << 16; secsSince1900 |= (unsigned long)packetBuffer[42] << 8; secsSince1900 |= (unsigned long)packetBuffer[43]; nowTime = secsSince1900 - 2208988800UL + timezone * SECS_PER_HOUR; rtclock.setTime(time_t(nowTime));また、STM32F1の演算スタック容量の問題か?
rtclock.setTime(time_t(secsSince1900 - 2208988800UL + timezone * SECS_PER_HOUR));としてしまうと実行時エラーとなります。そのためnowTimeと云う中間変数を設けています。
/* * 20220222 T.Wanibe * 1.6.1 修正点: * NTP取得後の時刻設定がうまくゆかない件の対策 * 1.6.0 修正点: * 毎分の温度変化をグラフ表示出来る様に修正したいと考えました。setup4 * 1.5.1 修正点: * コードに無駄があったので修正した。接続デバイス数はsetup()内で自動判別するのが良いと思い変更 * 1.5.0 修正点: * ダミー計測をすることで値が0.0になることはなくなったが、2つのDS18B20を取り違えて計測してしまう事があり、連続性に問題がある。 * コードを変更してsetup()時に接続されているDS18B20のindexListを取得し、計測時にIDが合致するデータ列を意識するように変更した * 1.4.2 修正点: * 計測前にdelayは効果無し 結果を見る限り定期的に三時間毎に0.0になっているので、ダミー計測を試すことにした。 * 1.4.1 修正点: * ch1のDS18B20のデータ取得に失敗するケースの対策が不十分 よく判らないが、計測前にdelayを入れてみる * 1.4.0 修正点: * 一時間毎のデータで0と云う値が出ている。これはおかしい。データ取得に失敗している。 * 2ch目では発生していないことから、データ取得時待ち時間を置いてからデータ取得するように修正 *コメント * DS18B20をブラウザ表示するソフトウエアコードを書いているのですが、03までのスケッチは期待通りに動作しません。 * 時刻同期がなぜか失敗することが問題です。 * そこでベースとなるコードを変更して、機能追加し実現してみることにしました。 * 以下はオリジナルコードのコメントです。 * このコードはEthernet3のExample“Udp NTP Client”をSTM32MINIShieldで動く様にレタッチしました。. * BluePillにはRTCが搭載されていますが、精度が悪くバックアップ電源もありません。※接続は可能です * そこで起動時にNTPで時刻所得して登録し、LED&KEYに時刻表示します。 * 以後毎秒時刻更新します。 * 1時間毎にNTPにアクセスして時刻調整します。 * Michael Margolis氏が2010年9月4日に作成したモノをレタッチしています。 * 最大131072バイトのフラッシュメモリのうち、スケッチが71504バイト(54%)を使っています。 * 最大20480バイトのRAMのうち、グローバル変数が6952バイト(33%)を使っていて、ローカル変数で13528バイト使うことができます。 */ #include <libmaple/iwdg.h> #include <SPI.h> #include <Ethernet3.h> #include <EthernetUdp3.h> #include <TM1638.h> #include <RTClock.h> #include <EEPROM.h> #include <avr/pgmspace.h> #include <TextFinder.h> //WebSetting #include <OneWire.h> //DS18B20通信用ライブラリ //#include <DallasTemperature.h> //PIN #define W550io_Rst PA8 //NIC_Reset #define SPI1_NSS_PIN PA4 //NIC_ChipSelec #define UpdateInterval 86400 //更新間隔 #define dataPin PB4 #define clockPin PB3 #define strobePin PA15 #define BUILTIN_LED PC13 #define DS18B20Port PA10 #define LED1 PB8 #define LED2 PB9 #define HttpPort 80 //HTTP #define debug 1 #define iwdg_init_ms(N) iwdg_init(IWDG_PRE_256,((N)/8)) //設定時間をmsecとするためにマクロを用意する。 #define vers "STM32miniShield DS18B20 1.6" #define NTP_PACKET_SIZE 48 #define SECS_PER_HOUR 3600 #define maxDevices 10 //コントローラのMACアドレスを以下に入力してください。 //新しいイーサネットシールドには、シールドのステッカーにMACアドレスが印刷されています const char FVirsion[] = "1.6.2"; byte mac[] = {0x00,0x08,0xDC,0x54,0x4D,0xD1}; //Wiznet byte ip[] = {192, 168, 0, 205}; byte dns_server[] = {192, 168, 0, 1}; byte gateway[] = {0, 0, 0, 0}; byte subnet[] = {255, 255, 255, 0}; byte timeServer[] = {192,168,0,199}; byte packetBuffer[ NTP_PACKET_SIZE]; //着信および発信パケットを保持するバッファ // unsigned int localPort = 8888; //UDPパケットをリッスンするローカルポート char STRBUF[32]; char buffer[128]; int timezone = 9; // change to your timezone //オブジェクトコンストラクタ EthernetServer webServer(HttpPort); EthernetClient client; RTClock rtclock (RTCSEL_LSE); //RTC初期化 EthernetUDP Udp; tm_t tmm,tmm1; //UDPを介してパケットを送受信できるようにするUDPインスタンス TM1638 LedAndKey(dataPin, clockPin, strobePin); //データピンPB4、クロックピンPB3、およびストローブピンPA15でモジュールを定義する const byte ID = 0x9B; char buf1[32]; char buf2[32]; char MacAddressStr[20]; char IPAddressStr[20]; char SubnetMaskStr[20]; char GatewayStr[20]; char NTPserverStr[20]; char DateTimeStr[20]; String DateStr; String TimeStr; float gDayBuf[24][4]; //24時間分4要素データ確保 float gHourBuf[60][4]; //24時間分4要素データ確保 unsigned long OperatingTime = 0; //稼働時間 Count2で1秒 OneWire ds(PA10); // on pin 10 (a 4.7K resistor is necessary) boolean fDoneTime = false; int wdgTime = 40000; int devNum = maxDevices; //DS18B20の接続数 初期値は2としておきます。 メモリ確保のため byte gDS[maxDevices][8]; //---------------------------------- void LANSetup(){ int idcheck = EEPROM.read(0); if (idcheck != ID){ //idがIDの値ではない場合、 //このスケッチがシールドを設定する前に使用されていなかったことを意味します //スケッチの始めに書かれた値を使用するだけです } if (idcheck == ID){ //idがIDと同じ値の場合、 //これは、このスケッチがシールドを設定するために使用されたことを意味します。 //EERPOMの値を読み取ってシールドを設定します。 for (int i = 0; i < 6; i++){ mac[i] = EEPROM.read(i+1); } for (int i = 0; i < 4; i++){ ip[i] = EEPROM.read(i+7); } for (int i = 0; i < 4; i++){ subnet[i] = EEPROM.read(i+11); } for (int i = 0; i < 4; i++){ gateway[i] = EEPROM.read(i+15); } //アクセスNTPサーバー for (int i = 0; i < 4; i++){ timeServer[i] = EEPROM.read(i+19); } } sprintf(MacAddressStr,"%02x.%02x.%02x.%02x.%02x.%02x",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]); sprintf(IPAddressStr,"%d.%d.%d.%d",ip[0],ip[1],ip[2],ip[3]); sprintf(SubnetMaskStr,"%d.%d.%d.%d",subnet[0],subnet[1],subnet[2],subnet[3]); sprintf(GatewayStr,"%d.%d.%d.%d",gateway[0],gateway[1],gateway[2],gateway[3]); sprintf(NTPserverStr,"%d.%d.%d.%d",timeServer[0],timeServer[1],timeServer[2],timeServer[3]); Ethernet.begin(mac, ip); } //-------------------------- void SetWebPage( EthernetClient client){ client.println(F("HTTP/1.1 200 OK")); client.println(F("Content-Type: text/html")); client.println(); // client.print(F("<!DOCTYPE HTML PUBLIC \"\">\n<html>\n<HEAD>\n\t<META http-equiv=\"Content-Type\" charset=UTF-8\">\n")); client.print(F("\t<META http-equiv=\"Content-Style-Type\">\n\t<TITLE>")); client.print(vers); client.print(F(" Setup Page</TITLE>\n</HEAD>\n")); client.print(F("<BODY marginwidth=\"0\" marginheight=\"0\" leftmargin=\"0\" style=\"margin: 0; padding: 0;\">\n<BLOCKQUOTE><BLOCKQUOTE>\n")); client.print(F("<table bgcolor=\"#17A1A5\" border=\"0\" width=\"100%\" cellpadding=\"1\" style=\"font-family:Verdana;color:#ffffff;font-size:12px;\">\n")); client.print(F("<tr><td>")); client.print(vers); client.print(F(" Setup Page</td></tr></table><br>\n")); // client.print(F("<script>\n\tfunction hex2num (s_hex) {\n\t\teval(\"var n_num=0X\" + s_hex);\n\t\treturn n_num;\n\t}\n</script>\n")); client.print(F("<tbody>\n<FORM><input type=\"hidden\" name=\"SBM\" value=\"1\">\n<table>\n<tr><td>MAC:</td><td>")); client.print(F("<input id=\"T1\" type=\"text\" size=\"3\" maxlength=\"2\" name=\"DT1\" value=\"")); client.print(mac[0],HEX); client.print(F("\">.<input id=\"T3\" type=\"text\" size=\"3\" maxlength=\"2\" name=\"DT2\" value=\"")); client.print(mac[1],HEX); client.print(F("\">.<input id=\"T5\" type=\"text\" size=\"3\" maxlength=\"2\" name=\"DT3\" value=\"")); client.print(mac[2],HEX); client.print(F("\">.<input id=\"T7\" type=\"text\" size=\"3\" maxlength=\"2\" name=\"DT4\" value=\"")); client.print(mac[3],HEX); client.print(F("\">.<input id=\"T9\" type=\"text\" size=\"3\" maxlength=\"2\" name=\"DT5\" value=\"")); client.print(mac[4],HEX); client.print(F("\">.<input id=\"T11\" type=\"text\" size=\"3\" maxlength=\"2\" name=\"DT6\" value=\"")); client.print(mac[5],HEX); // client.print(F("\"><input id=\"T2\" type=\"hidden\" name=\"DT1\"><input id=\"T4\" type=\"hidden\" name=\"DT2")); client.print(F("\"><input id=\"T6\" type=\"hidden\" name=\"DT3\"><input id=\"T8\" type=\"hidden\" name=\"DT4")); client.print(F("\"><input id=\"T10\" type=\"hidden\" name=\"DT5\"><input id=\"T12\" type=\"hidden\" name=\"DT6")); client.print(F("\"></td></tr>\n<tr><td>IP:</td><td><input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT7\" value=\"")); client.print(ip[0],DEC); client.print(F("\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT8\" value=\"")); client.print(ip[1],DEC); client.print(F("\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT9\" value=\"")); client.print(ip[2],DEC); client.print(F("\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT10\" value=\"")); client.print(ip[3],DEC); // client.print(F("\"></td></tr>\n<tr><td>MASK: </td><td><input type= \"text\" size=\"3\" maxlength=\"3\" name=\"DT11\" value=\"")); client.print(subnet[0],DEC); client.print(F("\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT12\" value=\"")); client.print(subnet[1],DEC); client.print(F("\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT13\" value=\"")); client.print(subnet[2],DEC); client.print(F("\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT14\" value=\"")); client.print(subnet[3],DEC); // client.print(F("\"></td></tr>\n<tr><td>GW: </td><td><input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT15\" value=\"")); client.print(gateway[0],DEC); client.print(F("\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT16\" value=\"")); client.print(gateway[1],DEC); client.print(F("\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT17\" value=\"")); client.print(gateway[2],DEC); client.print(F("\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT18\" value=\"")); client.print(gateway[3],DEC); // //client.print(F("\"></td></tr>\n<tr><td><br></td COLSPAN='2'>\n<HR ALIGN=LEFT>")); client.print(F("\"></td></tr><tr><td COLSPAN='2'>\n<HR ALIGN=CENTER></td><td>")); //1行空けたい // client.print(F("</td></tr><tr><td>NTPd: </td><td><input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT19\" value=\"")); client.print(timeServer[0],DEC); client.print(F("\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT20\" value=\"")); client.print(timeServer[1],DEC); client.print(F("\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT21\" value=\"")); client.print(timeServer[2],DEC); client.print(F("\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT22\" value=\"")); client.print(timeServer[3],DEC); client.print(F("\"></td></tr>\n<tr><td><br></td></tr><tr><td COLSPAN='2'><P ALIGN=RIGHT><input id=\"button1\"type=\"submit\" value=\"SUBMIT\" ")); // client.print(F("Onclick=\"")); client.print(F("document.getElementById('T2').value = hex2num(document.getElementById('T1').value);\n")); client.print(F("\t\tdocument.getElementById('T4').value = hex2num(document.getElementById('T3').value);\n")); client.print(F("\t\tdocument.getElementById('T6').value = hex2num(document.getElementById('T5').value);\n")); client.print(F("\t\tdocument.getElementById('T8').value = hex2num(document.getElementById('T7').value);\n")); client.print(F("\t\tdocument.getElementById('T10').value = hex2num(document.getElementById('T9').value);\n")); client.print(F("\t\tdocument.getElementById('T12').value = hex2num(document.getElementById('T11').value);\"")); // client.print(F("></td></tr></tbody>\n</table>\n</BLOCKQUOTE></BLOCKQUOTE>\n</form>\n</BODY>\n</html>\n")); } //-------------------------- 2021/8/12 void SetPage1Day( EthernetClient client){ client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println(); // client.print(F("<!DOCTYPE HTML PUBLIC \"\">\n<html>\n<HEAD>\n\t<META http-equiv=\"Content-Type\" charset=\"UTF-8\">\n")); client.print(F("\t<META http-equiv=\"Content-Style-Type\">\n\t<TITLE>")); client.print(vers); client.print(F(" Utility Page</TITLE>\n")); client.print(F("\t<script type='application/javascript' SRC='http://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.bundle.js'></script>\n")); client.print(F("\t<script type='application/javascript' SRC='./setup3'></script>\n")); client.print(F("\t<style>\n\t\tcanvas{\n")); client.print(F("\t\t\t-moz-user-select: none;\n")); client.print(F("\t\t\t-webkit-user-select: none;\n")); client.print(F("\t\t\t-ms-user-select: none;\n\t\t}\n")); client.print(F("\t\thtml { font-family: Helvetica; display: inline-block; margin: 0px auto;}\n")); client.print(F("\t\tbody{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;}\n")); client.print(F("\t\tp {font-size: 24px;color: #444444;margin-bottom: 10px;}\n")); client.print(F("\t</style>\n</HEAD>\n")); client.print(F("<BODY marginwidth=\"0\" marginheight=\"0\" leftmargin=\"0\" style=\"margin: 0; padding: 0;\" BGCOLOR=\"#ffffff\">\n")); client.print(F("<FORM>\n<BLOCKQUOTE><BLOCKQUOTE>\n")); client.print(F("<P><table bgcolor=\"#17A1A5\" border=\"0\" width=\"100%\" cellpadding=\"1\" style=\"font-family:Verdana;color:#ffffff;font-size:12px;\" CELLSPACING=\"2\">\n")); client.print(F("<tr><td>")); client.print(vers); client.print(F(" Utility Page</td></tr></table><br>\n")); // client.print(F("<TABLE WIDTH=\"100%\" BORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"0\">")); client.print(F("<TR>\n\t<TD WIDTH=\"25%\">FirmwareVirsion:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">")); client.print(FVirsion); client.print(F("</TD>\n</TR>")); client.print(F("<TR>\n\t<TD WIDTH=\"25%\">MacAddress:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">")); client.print(MacAddressStr); client.print(F("</TD>\n</TR>")); client.print(F("<TR>\n\t<TD WIDTH=\"25%\">IPAddress:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">")); client.print(IPAddressStr); client.print(F("</TD>\n</TR>")); client.print(F("<TR>\n\t<TD WIDTH=\"25%\">SubnetMask:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">")); client.print(SubnetMaskStr); client.print(F("</TD>\n</TR>")); client.print(F("<TR>\n\t<TD WIDTH=\"25%\" NOWRAP>Data acquisition time(Local):</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">")); client.print(DateTimeStr); client.print(F("</TD>\n</TR>")); client.print(F("<TR>\n\t<TD WIDTH=\"25%\" NOWRAP>Num of connected sensors:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">")); client.print(devNum); client.print(F("</TD>\n</TR>")); client.print(F("<TR>\n\t<TD WIDTH=\"25%\" NOWRAP>Operating Time:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">")); sprintf(buf2,"%d[sec]",OperatingTime); client.print(buf2); client.print(F("</TD>\n</TR></TABLE></P>\n")); client.print(F("\t<div style='width:75%;'><canvas id='canvas' width='750' height='400' style='display: block; width: 750px; height: 400px;'></canvas></div>\n")); client.print(F("</CENTER></BLOCKQUOTE></BLOCKQUOTE>\n</form>\n")); client.print(F("<script>\n")); client.print(F("\t\tvar randomScalingFactor = function() {\n\t\t\treturn 18 + Math.random() * 10;\n\t\t};\n")); client.print(F("\t\tvar data_00 = [")); for(int i = 0; i<24 ;i++){ client.print(isnan(gDayBuf[i][0]) ? String('\0') : String(gDayBuf[i][0],6)); client.print(F(",")); } client.print(F("];\n")); client.print(F("\t\tvar data_01 = [")); for(int i = 0; i<24 ;i++){ client.print(isnan(gDayBuf[i][1]) ? String('\0') : String(gDayBuf[i][1],6)); client.print(F(",")); } client.print(F("];\n")); client.print(F("\t\tvar data_02 = [")); for(int i = 0; i<24 ;i++){ client.print(isnan(gDayBuf[i][2]) ? String('\0') : String(gDayBuf[i][2],2)); client.print(F(",")); } client.print(F("];\n")); client.print(F("\t\tvar data_03 = [")); for(int i = 0; i<24 ;i++){ client.print(isnan(gDayBuf[i][3]) ? String('\0') : String(gDayBuf[i][3],2)); client.print(F(",")); } client.print(F("];\n")); client.print(F("\t\tvar config = {")); client.print(F("\t\t\ttype: 'line',\n\t\t\tdata: {\n")); client.print(F("\t\t\t\tlabels: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12' , '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23'],\n")); client.print(F("\t\t\t\tdatasets: [{\n")); client.print(F("\t\t\t\t\tlabel: '温度1[℃]',\n")); client.print(F("\t\t\t\t\tdata: data_00,\n")); client.print(F("\t\t\t\t\tborderColor: window.chartColors.red,\n")); client.print(F("\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0)',\n")); client.print(F("\t\t\t\t\tfill: false,\n")); client.print(F("\t\t\t\t\tcubicInterpolationMode: 'monotone',\n")); client.print(F("\t\t\t\t\tyAxisID: 'y1'\n")); client.print(F("\t\t\t\t}, {\n")); client.print(F("\t\t\t\t\tlabel: '温度2[℃]',\n")); client.print(F("\t\t\t\t\tdata: data_01,\n")); client.print(F("\t\t\t\t\tborderColor: window.chartColors.blue,\n")); client.print(F("\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0)',\n")); client.print(F("\t\t\t\t\tfill: false,\n")); client.print(F("\t\t\t\t\tyAxisID: 'y2'\n")); client.print(F("\t\t\t\t}, {\n")); client.print(F("\t\t\t\t\tlabel: '温度3[℃]',\n")); client.print(F("\t\t\t\t\tdata: data_02,\n")); client.print(F("\t\t\t\t\tborderColor: window.chartColors.orange,\n")); client.print(F("\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0)',\n")); client.print(F("\t\t\t\t\tfill: false,\n")); client.print(F("\t\t\t\t\tyAxisID: 'y3'\n")); client.print(F("\t\t\t\t}, {\n")); client.print(F("\t\t\t\t\tlabel: '温度4[℃]',\n")); client.print(F("\t\t\t\t\tdata: data_03,\n")); client.print(F("\t\t\t\t\tborderColor: window.chartColors.yellow,\n")); client.print(F("\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0)',\n")); client.print(F("\t\t\t\t\tfill: false,\n")); client.print(F("\t\t\t\t\tyAxisID: 'y4'\n")); client.print(F("\t\t\t\t}]\n\t\t\t},\n")); client.print(F("\t\t\toptions: {\n\t\t\t\tresponsive: true,\n")); client.print(F("\t\t\t\ttitle: {\n\t\t\t\t\tdisplay: true,\n\t\t\t\t\ttext: '温度取得履歴'\n\t\t\t\t},\n")); client.print(F("\t\t\t\tlegend: {\n\t\t\t\t\tdisplay: true\n\t\t\t\t},\n")); client.print(F("\t\t\t\ttooltips: {\n\t\t\t\t\tenabled: true,\n\t\t\t\t\tmode: 'index'\n\t\t\t\t},\n")); client.print(F("\t\t\t\tscales: {\n\t\t\t\t\txAxes: [{\n\t\t\t\t\t\tdisplay: true,\n")); client.print(F("\t\t\t\t\t\tscaleLabel: {\n\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\tlabelString: '時刻 [時]'\n\t\t\t\t\t\t}\n\t\t\t\t\t}],\n")); client.print(F("\t\t\t\t\tyAxes: [{\n\t\t\t\t\t\tid:'y1',\n\t\t\t\t\t\tdisplay: true,\n")); client.print(F("\t\t\t\t\t\tscaleLabel: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.red,\n")); client.print(F("\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\tlabelString: '温度1[℃]'\n\t\t\t\t\t\t},\n")); client.print(F("\t\t\t\t\t\tticks: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.red,\n")); client.print(F("\t\t\t\t\t\t\tsuggestedMin: -20,\n\t\t\t\t\t\t\tsuggestedMax: 80\n\t\t\t\t\t\t}\n")); client.print(F("\t\t\t\t\t},{\n\t\t\t\t\t\tid:'y2',\n\t\t\t\t\t\tdisplay: true,\n")); client.print(F("\t\t\t\t\t\tscaleLabel: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.blue,\n")); client.print(F("\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\tlabelString: '温度2[℃]'\n\t\t\t\t\t\t},\n")); client.print(F("\t\t\t\t\t\tticks: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.blue,\n")); client.print(F("\t\t\t\t\t\t\tsuggestedMin: -20,\n\t\t\t\t\t\t\tsuggestedMax: 80\n\t\t\t\t\t\t}\n")); client.print(F("\t\t\t\t\t},{\n\t\t\t\t\t\tid:'y3',\n\t\t\t\t\t\tposition: 'right',\n\t\t\t\t\t\tdisplay: true,\n")); client.print(F("\t\t\t\t\t\tscaleLabel: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.orange,\n")); client.print(F("\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\tlabelString: '温度3[℃]'\n\t\t\t\t\t\t},\n")); client.print(F("\t\t\t\t\t\tticks: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.orange,\n")); client.print(F("\t\t\t\t\t\t\tsuggestedMin: -20,\n\t\t\t\t\t\t\tsuggestedMax: 80\n\t\t\t\t\t\t\t}\n")); client.print(F("\t\t\t\t\t},{\n\t\t\t\t\t\tid:'y4',\n\t\t\t\t\t\tposition: 'right',\n\t\t\t\t\t\tdisplay: true,\n")); client.print(F("\t\t\t\t\t\tscaleLabel: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.yellow,\n")); client.print(F("\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\tlabelString: '温度4[℃]'\n\t\t\t\t\t\t},\n")); client.print(F("\t\t\t\t\t\tticks: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.yellow,\n")); client.print(F("\t\t\t\t\t\t\tsuggestedMin: -40,\n\t\t\t\t\t\t\tsuggestedMax: 160\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}],\n")); client.print(F("\t\t\t\t}\n\t\t\t}\n\t\t};\n")); client.print(F("\t\twindow.onload = function() {\n\t\t\tvar ctx = document.getElementById('canvas').getContext('2d');\n")); client.print(F("\t\t\twindow.myLine = new Chart(ctx, config);\n\t\t};\n")); client.print(F("</script>\n")); client.print(F("</BODY></html>")); } //-------------------------- 2022/2/18 void SetPage1Hour( EthernetClient client){ client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println(); // client.print(F("<!DOCTYPE HTML PUBLIC \"\">\n<html>\n<HEAD>\n\t<META http-equiv=\"Content-Type\" charset=\"UTF-8\">\n")); client.print(F("\t<META http-equiv=\"Content-Style-Type\">\n\t<TITLE>")); client.print(vers); client.print(F(" Utility Page</TITLE>\n")); client.print(F("\t<script type='application/javascript' SRC='http://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.bundle.js'></script>\n")); client.print(F("\t<script type='application/javascript' SRC='./setup3'></script>\n")); client.print(F("\t<style>\n\t\tcanvas{\n")); client.print(F("\t\t\t-moz-user-select: none;\n")); client.print(F("\t\t\t-webkit-user-select: none;\n")); client.print(F("\t\t\t-ms-user-select: none;\n\t\t}\n")); client.print(F("\t\thtml { font-family: Helvetica; display: inline-block; margin: 0px auto;}\n")); client.print(F("\t\tbody{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;}\n")); client.print(F("\t\tp {font-size: 24px;color: #444444;margin-bottom: 10px;}\n")); client.print(F("\t</style>\n</HEAD>\n")); client.print(F("<BODY marginwidth=\"0\" marginheight=\"0\" leftmargin=\"0\" style=\"margin: 0; padding: 0;\" BGCOLOR=\"#ffffff\">\n")); client.print(F("<FORM>\n<BLOCKQUOTE><BLOCKQUOTE>\n")); client.print(F("<P><table bgcolor=\"#17A1A5\" border=\"0\" width=\"100%\" cellpadding=\"1\" style=\"font-family:Verdana;color:#ffffff;font-size:12px;\" CELLSPACING=\"2\">\n")); client.print(F("<tr><td>")); client.print(vers); client.print(F(" Utility Page</td></tr></table><br>\n")); // client.print(F("<TABLE WIDTH=\"100%\" BORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"0\">")); client.print(F("<TR>\n\t<TD WIDTH=\"25%\">FirmwareVirsion:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">")); client.print(FVirsion); client.print(F("</TD>\n</TR>")); client.print(F("<TR>\n\t<TD WIDTH=\"25%\">MacAddress:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">")); client.print(MacAddressStr); client.print(F("</TD>\n</TR>")); client.print(F("<TR>\n\t<TD WIDTH=\"25%\">IPAddress:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">")); client.print(IPAddressStr); client.print(F("</TD>\n</TR>")); client.print(F("<TR>\n\t<TD WIDTH=\"25%\">SubnetMask:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">")); client.print(SubnetMaskStr); client.print(F("</TD>\n</TR>")); client.print(F("<TR>\n\t<TD WIDTH=\"25%\" NOWRAP>Data acquisition time(Local):</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">")); client.print(DateTimeStr); client.print(F("</TD>\n</TR>")); client.print(F("<TR>\n\t<TD WIDTH=\"25%\" NOWRAP>Num of connected sensors:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">")); client.print(devNum); client.print(F("</TD>\n</TR>")); client.print(F("<TR>\n\t<TD WIDTH=\"25%\" NOWRAP>Operating Time:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">")); sprintf(buf2,"%d[sec]",OperatingTime); client.print(buf2); client.print(F("</TD>\n</TR></TABLE></P>\n")); client.print(F("\t<div style='width:75%;'><canvas id='canvas' width='750' height='400' style='display: block; width: 750px; height: 400px;'></canvas></div>\n")); client.print(F("</CENTER></BLOCKQUOTE></BLOCKQUOTE>\n</form>\n")); client.print(F("<script>\n")); client.print(F("\t\tvar randomScalingFactor = function() {\n\t\t\treturn 18 + Math.random() * 10;\n\t\t};\n")); client.print(F("\t\tvar data_00 = [")); for(int i = 0; i<60 ;i++){ client.print(isnan(gHourBuf[i][0]) ? String('\0') : String(gHourBuf[i][0],6)); client.print(F(",")); } client.print(F("];\n")); client.print(F("\t\tvar data_01 = [")); for(int i = 0; i<60 ;i++){ client.print(isnan(gHourBuf[i][1]) ? String('\0') : String(gHourBuf[i][1],6)); client.print(F(",")); } client.print(F("];\n")); client.print(F("\t\tvar data_02 = [")); for(int i = 0; i<60 ;i++){ client.print(isnan(gHourBuf[i][2]) ? String('\0') : String(gHourBuf[i][2],2)); client.print(F(",")); } client.print(F("];\n")); client.print(F("\t\tvar data_03 = [")); for(int i = 0; i<60 ;i++){ client.print(isnan(gHourBuf[i][3]) ? String('\0') : String(gHourBuf[i][3],2)); client.print(F(",")); } client.print(F("];\n")); client.print(F("\t\tvar config = {")); client.print(F("\t\t\ttype: 'line',\n\t\t\tdata: {\n")); client.print(F("\t\t\t\tlabels: ['0', '', '2', '', '4', '', '6', '', '8', '', '10', '', '12' , '', '14', '', '16', '', '18', '', '20', '', '22', '', '24', '', '26', '', '28', '', '30', '', '32' , '', '34', '', '36', '', '38', '', '40', '', '42', '', '44', '', '46', '', '48', '', '50', '', '52' , '', '54', '', '56', '', '', '59'],\n")); client.print(F("\t\t\t\tdatasets: [{\n")); client.print(F("\t\t\t\t\tlabel: '温度1[℃]',\n")); client.print(F("\t\t\t\t\tdata: data_00,\n")); client.print(F("\t\t\t\t\tborderColor: window.chartColors.red,\n")); client.print(F("\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0)',\n")); client.print(F("\t\t\t\t\tfill: false,\n")); client.print(F("\t\t\t\t\tcubicInterpolationMode: 'monotone',\n")); client.print(F("\t\t\t\t\tyAxisID: 'y1'\n")); client.print(F("\t\t\t\t}, {\n")); client.print(F("\t\t\t\t\tlabel: '温度2[℃]',\n")); client.print(F("\t\t\t\t\tdata: data_01,\n")); client.print(F("\t\t\t\t\tborderColor: window.chartColors.blue,\n")); client.print(F("\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0)',\n")); client.print(F("\t\t\t\t\tfill: false,\n")); client.print(F("\t\t\t\t\tyAxisID: 'y2'\n")); client.print(F("\t\t\t\t}, {\n")); client.print(F("\t\t\t\t\tlabel: '温度3[℃]',\n")); client.print(F("\t\t\t\t\tdata: data_02,\n")); client.print(F("\t\t\t\t\tborderColor: window.chartColors.orange,\n")); client.print(F("\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0)',\n")); client.print(F("\t\t\t\t\tfill: false,\n")); client.print(F("\t\t\t\t\tyAxisID: 'y3'\n")); client.print(F("\t\t\t\t}, {\n")); client.print(F("\t\t\t\t\tlabel: '温度4[℃]',\n")); client.print(F("\t\t\t\t\tdata: data_03,\n")); client.print(F("\t\t\t\t\tborderColor: window.chartColors.yellow,\n")); client.print(F("\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0)',\n")); client.print(F("\t\t\t\t\tfill: false,\n")); client.print(F("\t\t\t\t\tyAxisID: 'y4'\n")); client.print(F("\t\t\t\t}]\n\t\t\t},\n")); client.print(F("\t\t\toptions: {\n\t\t\t\tresponsive: true,\n")); client.print(F("\t\t\t\ttitle: {\n\t\t\t\t\tdisplay: true,\n\t\t\t\t\ttext: '温度取得履歴'\n\t\t\t\t},\n")); client.print(F("\t\t\t\tlegend: {\n\t\t\t\t\tdisplay: true\n\t\t\t\t},\n")); client.print(F("\t\t\t\ttooltips: {\n\t\t\t\t\tenabled: true,\n\t\t\t\t\tmode: 'index'\n\t\t\t\t},\n")); client.print(F("\t\t\t\tscales: {\n\t\t\t\t\txAxes: [{\n\t\t\t\t\t\tdisplay: true,\n")); client.print(F("\t\t\t\t\t\tscaleLabel: {\n\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\tlabelString: '時刻 [分]'\n\t\t\t\t\t\t}\n\t\t\t\t\t}],\n")); client.print(F("\t\t\t\t\tyAxes: [{\n\t\t\t\t\t\tid:'y1',\n\t\t\t\t\t\tdisplay: true,\n")); client.print(F("\t\t\t\t\t\tscaleLabel: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.red,\n")); client.print(F("\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\tlabelString: '温度1[℃]'\n\t\t\t\t\t\t},\n")); client.print(F("\t\t\t\t\t\tticks: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.red,\n")); client.print(F("\t\t\t\t\t\t\tsuggestedMin: -20,\n\t\t\t\t\t\t\tsuggestedMax: 80\n\t\t\t\t\t\t}\n")); client.print(F("\t\t\t\t\t},{\n\t\t\t\t\t\tid:'y2',\n\t\t\t\t\t\tdisplay: true,\n")); client.print(F("\t\t\t\t\t\tscaleLabel: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.blue,\n")); client.print(F("\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\tlabelString: '温度2[℃]'\n\t\t\t\t\t\t},\n")); client.print(F("\t\t\t\t\t\tticks: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.blue,\n")); client.print(F("\t\t\t\t\t\t\tsuggestedMin: -20,\n\t\t\t\t\t\t\tsuggestedMax: 80\n\t\t\t\t\t\t}\n")); client.print(F("\t\t\t\t\t},{\n\t\t\t\t\t\tid:'y3',\n\t\t\t\t\t\tposition: 'right',\n\t\t\t\t\t\tdisplay: true,\n")); client.print(F("\t\t\t\t\t\tscaleLabel: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.orange,\n")); client.print(F("\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\tlabelString: '温度3[℃]'\n\t\t\t\t\t\t},\n")); client.print(F("\t\t\t\t\t\tticks: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.orange,\n")); client.print(F("\t\t\t\t\t\t\tsuggestedMin: -20,\n\t\t\t\t\t\t\tsuggestedMax: 80\n\t\t\t\t\t\t\t}\n")); client.print(F("\t\t\t\t\t},{\n\t\t\t\t\t\tid:'y4',\n\t\t\t\t\t\tposition: 'right',\n\t\t\t\t\t\tdisplay: true,\n")); client.print(F("\t\t\t\t\t\tscaleLabel: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.yellow,\n")); client.print(F("\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\tlabelString: '温度4[℃]'\n\t\t\t\t\t\t},\n")); client.print(F("\t\t\t\t\t\tticks: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.yellow,\n")); client.print(F("\t\t\t\t\t\t\tsuggestedMin: -40,\n\t\t\t\t\t\t\tsuggestedMax: 160\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}],\n")); client.print(F("\t\t\t\t}\n\t\t\t}\n\t\t};\n")); client.print(F("\t\twindow.onload = function() {\n\t\t\tvar ctx = document.getElementById('canvas').getContext('2d');\n")); client.print(F("\t\t\twindow.myLine = new Chart(ctx, config);\n\t\t};\n")); client.print(F("</script>\n")); client.print(F("</BODY></html>")); } //-------------------------- void checkWebPage( EthernetClient client) { Serial.println(F("new webClient")); boolean restart = false; if (client) { TextFinder finder(client ); while (client.connected()) { //digitalWrite(LED, HIGH); if (client.available()) { //この部分はすべてのテキスト検索を行います。 if( finder.find("GET /") ) { // 「setup」とい語が見つかった場合は、さらに探してください。 // その単語が見つからない場合は、検索を停止して先に進みます。 // これにより、後でスケッチに独自のWebページを配置できます。 if (finder.findUntil("setup", "\n\r")){ long cord = finder.getValue(); sprintf(buf1,"setupIn=%d",cord); Serial.println(buf1); switch(cord){ case 1: // 「SBM」という単語が見つかった場合は、さらに探し続けます。 // その言葉が見つからない場合は、探して停止します。 // SUBMITボタンが押されていない、何も押されていないことを意味します // セットアップページが構築されている場所に移動し、クライアントのブラウザに表示します。 if (finder.findUntil("SBM", "\n\r")){ byte SET = finder.getValue(); // これで、「DT」という文字を探している間に、「DT」の後ろにあるすべての数字を覚えて、 // 値を一致させて、mac、ip、subnet、およびgatewayに入れる必要があります。 while(finder.findUntil("DT", "\n\r")){ int val = finder.getValue(); // 「DT」のvalが1?6の場合、対応する値はMAC値でなければなりません。 if(val >= 1 && val <= 6) { mac[val - 1] = finder.getValue(); } // 「DT」のvalが7?10の場合、対応する値はIP値でなければなりません。 if(val >= 7 && val <= 10) { ip[val - 7] = finder.getValue(); } // 「DT」のvalが11?14の場合、対応する値はMASK値でなければなりません。 if(val >= 11 && val <= 14) { subnet[val - 11] = finder.getValue(); } // 「DT」のvalが15?18の場合、対応する値はGW値でなければなりません。 if(val >= 15 && val <= 18) { gateway[val - 15] = finder.getValue(); } // 「DT」のvalが19?22の場合、対応する値はTimeServer値でなければなりません。 if(val >= 19 && val <= 22) { timeServer[val - 19] = finder.getValue(); } } // すべてのデータを取得したので、EEPROMに保存できます for (int i = 0 ; i < 6; i++){ EEPROM.write(i + 1,mac[i]); } for (int i = 0 ; i < 4; i++){ EEPROM.write(i + 7, ip[i]); } for (int i = 0 ; i < 4; i++){ EEPROM.write(i + 11, subnet[i]); } for (int i = 0 ; i < 4; i++){ EEPROM.write(i + 15, gateway[i]); } for (int i = 0 ; i < 4; i++){ EEPROM.write(i + 19, timeServer[i]); } // IDを既知のビットに設定します。したがって、Arduinoをリセットすると、EEPROM値が使用されます。 EEPROM.write(0, ID); sprintf(MacAddressStr,"%02x.%02x.%02x.%02x.%02x.%02x",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]); sprintf(IPAddressStr,"%d.%d.%d.%d",ip[0],ip[1],ip[2],ip[3]); sprintf(SubnetMaskStr,"%d.%d.%d.%d",subnet[0],subnet[1],subnet[2],subnet[3]); sprintf(GatewayStr,"%d.%d.%d.%d",gateway[0],gateway[1],gateway[2],gateway[3]); // すべてのデータがEEPROMに書き込まれている場合、arduinoをリセットする必要があります。 //ハードウェアリセットボタンを使用する必要があります。 restart = true; }else{ } // この時点から、セットアップページの構築を開始し、クライアントのブラウザーに表示できます。 SetWebPage(client); break; case 2: // 新規にユーティリティ頁を作りました。 Serial.println(F("SetPage1Day")); rtclock.getTime(tmm); sprintf(DateTimeStr,"%04u/%02u/%02u %02u:%02u:%02u",tmm.year+1970, tmm.month, tmm.day,tmm.hour, tmm.minute, tmm.second); SetPage1Day(client); break; case 3: //utils.jsが要求された。 Serial.println(F("utils.js")); LoadUtilsJS(client); break; case 4: //新規に一時間分の分単位グラフ表示を作りました Serial.println(F("SetPage1Hour")); rtclock.getTime(tmm); sprintf(DateTimeStr,"%04u/%02u/%02u %02u:%02u:%02u",tmm.year+1970, tmm.month, tmm.day,tmm.hour, tmm.minute, tmm.second); SetPage1Hour(client); break; default: PrintResponse404(client ); break; } }else{ pageIntroduction(client); } } break; } PrintResponse404(client ); } delay(1); client.stop(); if(restart) nvic_sys_reset(); } } //----------------------------2022年2月18日メニュー追加 void pageIntroduction( EthernetClient client){ client.println(F("HTTP/1.1 200 OK")); client.println(F("Content-Type: text/html")); client.println(); // put your own html from here on sprintf(buf1,"%d.%d.%d.%d",ip[0],ip[1],ip[2],ip[3]); client.println(F("<HTML>\n<HEAD>\n\t<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html;CHARSET=UTF-8\">\n</HEAD>\n")); client.println(F("<BODY BGCOLOR='#ffffff'>\n<H2><CENTER><FONT COLOR='#00ff00'>DS18B20 SetUp Menu</FONT></CENTER></H2>\n")); client.println(F("<P><CENTER><TABLE WIDTH='500' BORDER='0' CELLSPACING='0' CELLPADDING='0'>\n\t<TR>\n\t\t<TD WIDTH='100%'>\n\t\t<OL>\n")); sprintf(buffer,"\t\t\t<LI><FONT SIZE='+1'><A HREF=\"http://%s/setup1\">設定メニュー</A>\n",buf1); client.println(buffer); sprintf(buffer,"\t\t\t<LI><A HREF=\"http://%s/setup2\">温度履歴表示 時単位(最近一日)</A>\n",buf1); client.println(buffer); sprintf(buffer,"\t\t\t<LI><A HREF=\"http://%s/setup4\">温度履歴表示 分単位(最近一時間)</A></FONT>\n",buf1); client.println(buffer); client.print(F("\t\t</OL>\n\t\t</TD>\n\t</TR>\n</TABLE></CENTER>\n</BODY>\n</HTML>\n")); client.stop(); } //-------------------------- void PrintResponse404( EthernetClient client ) { client.println(F("HTTP/1.1 404 Not Found")); client.println(F("Content-Type: text/html")); client.println(F("Connnection: close")); client.println(); client.stop(); } //-------------------------- void LoadUtilsJS( EthernetClient client ) { client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println(); // client.println("'use strict';\n"); // client.println("window.chartColors = {"); client.println("\tred: 'rgb(255, 99, 132)',"); client.println("\torange: 'rgb(255, 159, 64)',"); client.println("\tyellow: 'rgb(255, 205, 86)',"); client.println("\tgreen: 'rgb(75, 192, 192)',"); client.println("\tblue: 'rgb(54, 162, 235)',"); client.println("\tpurple: 'rgb(153, 102, 255)',"); client.println("\tgrey: 'rgb(201, 203, 207)'"); client.println("};\n"); // client.println("(function(global) {"); client.println("\tvar MONTHS = ["); client.println("\t\t'January',"); client.println("\t\t'February',"); client.println("\t\t'March',"); client.println("\t\t'April',"); client.println("\t\t'May',"); client.println("\t\t'June',"); client.println("\t\t'July',"); client.println("\t\t'August',"); client.println("\t\t'September',"); client.println("\t\t'October',"); client.println("\t\t'November',"); client.println("\t\t'December'"); client.println("\t];\n"); // client.println("\tvar COLORS = ["); client.println("\t\t'#4dc9f6',"); client.println("\t\t'#f67019',"); client.println("\t\t'#f53794',"); client.println("\t\t'#537bc4',"); client.println("\t\t'#acc236',"); client.println("\t\t'#166a8f',"); client.println("\t\t'#00a950',"); client.println("\t\t'#58595b',"); client.println("\t\t'#8549ba'"); client.println("\t];\n"); // client.println("\tvar Samples = global.Samples || (global.Samples = {});"); client.println("\tvar Color = Chart.helpers.color;\n"); // client.println("\tfunction applyDefaultNumbers(config) {"); client.println("\t\tvar cfg = config || {};"); client.println("\t\tcfg.min = cfg.min || 0;"); client.println("\t\tcfg.max = cfg.max || 1;"); client.println("\t\tcfg.from = cfg.from || [];"); client.println("\t\tcfg.count = cfg.count || 8;"); client.println("\t\tcfg.decimals = cfg.decimals || 8;"); client.println("\t\tcfg.continuity = cfg.continuity || 1;\n"); // client.println("\t\treturn cfg;"); client.println("\t}\n"); // client.println("\tSamples.utils = {"); client.println("\t\t// Adapted from http://indiegamr.com/generate-repeatable-random-numbers-in-js/"); client.println("\t\tsrand: function(seed) {"); client.println("\t\t\tthis._seed = seed;"); client.println("\t\t},\n"); // client.println("\t\trand: function(min, max) {"); client.println("\t\t\tvar seed = this._seed;"); client.println("\t\t\tmin = min === undefined ? 0 : min;"); client.println("\t\t\tmax = max === undefined ? 1 : max;"); client.println("\t\t\tthis._seed = (seed * 9301 + 49297) % 233280;"); client.println("\t\t\treturn min + (this._seed / 233280) * (max - min);"); client.println("\t\t},\n"); // client.println("\t\tnumbers: function(config) {"); client.println("\t\t\tvar cfg = applyDefaultNumbers(config);"); client.println("\t\t\tvar dfactor = Math.pow(10, cfg.decimals) || 0;"); client.println("\t\t\tvar data = [];"); client.println("\t\t\tvar i, value;\n"); // client.println("\t\t\tfor (i = 0; i < cfg.count; ++i) {"); client.println("\t\t\t\tvalue = (cfg.from[i] || 0) + this.rand(cfg.min, cfg.max);"); client.println("\t\t\t\tif (this.rand() <= cfg.continuity) {"); client.println("\t\t\t\t\tdata.push(Math.round(dfactor * value) / dfactor);"); client.println("\t\t\t\t} else {"); client.println("\t\t\t\t\tdata.push(null);"); client.println("\t\t\t\t}"); client.println("\t\t\t}\n"); // client.println("\t\t\treturn data;"); client.println("\t\t},\n"); // client.println("\t\tlabels: function(config) {"); client.println("\t\t\tvar cfg = config || {};"); client.println("\t\t\tvar min = cfg.min || 0;"); client.println("\t\t\tvar max = cfg.max || 100;"); client.println("\t\t\tvar count = cfg.count || 8;"); client.println("\t\t\tvar step = (max - min) / count;"); client.println("\t\t\tvar decimals = cfg.decimals || 8;"); client.println("\t\t\tvar dfactor = Math.pow(10, decimals) || 0;"); client.println("\t\t\tvar prefix = cfg.prefix || '';"); client.println("\t\t\tvar values = [];"); client.println("\t\t\tvar i;\n"); // client.println("\t\t\tfor (i = min; i < max; i += step) {"); client.println("\t\t\t\tvalues.push(prefix + Math.round(dfactor * i) / dfactor);"); client.println("\t\t\t}\n"); // client.println("\t\t\treturn values;"); client.println("\t\t},\n"); // client.println("\t\tmonths: function(config) {"); client.println("\t\t\tvar cfg = config || {};"); client.println("\t\t\tvar count = cfg.count || 12;"); client.println("\t\t\tvar section = cfg.section;"); client.println("\t\t\tvar values = [];"); client.println("\t\t\tvar i, value;\n"); // client.println("\t\t\tfor (i = 0; i < count; ++i) {"); client.println("\t\t\t\tvalue = MONTHS[Math.ceil(i) % 12];"); client.println("\t\t\t\tvalues.push(value.substring(0, section));"); client.println("\t\t\t}\n"); // client.println("\t\t\treturn values;"); client.println("\t\t},\n"); // client.println("\t\tcolor: function(index) {"); client.println("\t\t\treturn COLORS[index % COLORS.length];"); client.println("\t\t},\n"); // client.println("\t\ttransparentize: function(color, opacity) {"); client.println("\t\t\tvar alpha = opacity === undefined ? 0.5 : 1 - opacity;"); client.println("\t\t\treturn Color(color).alpha(alpha).rgbString();"); client.println("\t\t}"); client.println("\t};\n"); // client.println("\t// DEPRECATED"); client.println("\twindow.randomScalingFactor = function() {"); client.println("\t\treturn Math.round(Samples.utils.rand(-100, 100));"); client.println("\t};\n"); // client.println("\t// INITIALIZATION\n"); // client.println("\tSamples.utils.srand(Date.now());\n"); // client.println("\t// Google Analytics"); client.println("\t/* eslint-disable */"); client.println("\tif (document.location.hostname.match(/^(www\\.)?chartjs\\.org$/)) {"); client.println("\t\t(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){"); client.println("\t\t(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),"); client.println("\t\tm=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)"); client.println("\t\t})(window,document,'script','//www.google-analytics.com/analytics.js','ga');"); client.println("\t\tga('create', 'UA-28909194-3', 'auto');"); client.println("\t\tga('send', 'pageview');"); client.println("\t}"); client.println("\t/* eslint-enable */\n"); // client.println("}(this));"); } //-------指定されたアドレスのタイムサーバーにNTP要求を送信します void sendNTPpacket(byte address[]){ memset(packetBuffer, 0, NTP_PACKET_SIZE); //バッファ内のすべてのバイトを0に設定します //NTP要求を形成するために必要な値を初期化する packetBuffer[0] = 0b11100011; // LI, Version, Mode packetBuffer[1] = 0; //階層、またはクロックのタイプ packetBuffer[2] = 6; //ポーリング間隔 packetBuffer[3] = 0xEC; //ピアクロックの精度 //ルート遅延およびルート分散用のゼロの8バイト packetBuffer[12] = 49; packetBuffer[13] = 0x4E; packetBuffer[14] = 49; packetBuffer[15] = 52; //すべてのNTPフィールドに値が与えられました。 //タイムスタンプを要求するパケットを送信できます: Udp.beginPacket(address, 123); //NTPリクエストはポート123へ Udp.write(packetBuffer, NTP_PACKET_SIZE); Udp.endPacket(); } //----------------- 割込CallBack void TimeUpdate(void){ //1000msec毎に呼ばれる OperatingTime++; } //------------------ bool SetDSDevice(int index) { byte i; byte present = 0; byte type_s; byte data[12]; byte addr[8]; //float celsius; if ( !ds.search(addr)) { Serial.println(F("No more addresses.")); ds.reset_search(); delay(100); return false; }else{ memcpy(gDS[index], addr, sizeof(addr)); return true; } } //------------------ void GetDSTemp(float &celsius,int index) { byte i; byte present = 0; byte type_s; byte data[12]; byte addr[8]; //float celsius; /* 検索不要 for (int i;i<devNum;i++){ ds.search(addr); if(memcmp(addr, gDS[i], sizeof(addr)) == 0) break; } ds.reset_search(); */ if (OneWire::crc8(gDS[index], 7) != gDS[index][7]) { Serial.println(F("CRC is not valid!")); return; } // 最初のROMバイトはチップ種を示します switch (gDS[index][0]) { case 0x10: Serial.println(F(" Chip = DS18S20")); // or old DS1820 type_s = 1; break; case 0x28: Serial.println(F(" Chip = DS18B20")); type_s = 0; break; case 0x22: Serial.println(F(" Chip = DS1822")); type_s = 0; break; default: Serial.println(F("Device is not a DS18x20 family device.")); return; } ds.reset(); ds.select(gDS[index]); ds.write(0x44, 1); // 最後に寄生物の電源を入れて、変換を開始します delay(750); // 多分750msで十分かもしれません12bit分解能の場合 // ここでds.depower()を実行する場合がありますが、リセットによって処理されます。 present = ds.reset(); ds.select(gDS[index]); ds.write(0xBE); // スクラッチパッドを読む //Serial.print(F(" Data = ")); //Serial.print(present, HEX); //Serial.print(F(" ")); for ( i = 0; i < 9; i++) { // we need 9 bytes data[i] = ds.read(); //Serial.print(data[i], HEX); //Serial.print(F(" ")); } //Serial.print(F(" CRC=")); //Serial.print(OneWire::crc8(data, 8), HEX); //Serial.println(); //結果は16ビットの符号付き整数であるため、データを実際の温度に変換します。 //データは「int16_t」タイプに格納する必要があります。 //これは、32ビットプロセッサでコンパイルした場合でも常に16ビットです。 int16_t raw = (data[1] << 8) | data[0]; if (type_s) { raw = raw << 3; // デフォルトの9ビット解像度 if (data[7] == 0x10) { // 「残り数」は完全な12ビットの解像度を提供します raw = (raw & 0xFFF0) + 12 - data[6]; } } else { byte cfg = (data[4] & 0x60); // 低解像度では、下位ビットは未定義なので、ゼロにしましょう if (cfg == 0x00) raw = raw & ~7; // 9ビットの解像度、93.75ミリ秒 else if (cfg == 0x20) raw = raw & ~3; // 10ビットの解像度、187.5ミリ秒 else if (cfg == 0x40) raw = raw & ~1; // 11ビットの解像度、375ミリ秒 // デフォルトは12ビットの解像度、750ミリ秒の変換時間です } celsius = (float)raw / 16.0; //fahrenheit = celsius * 1.8 + 32.0; Serial.print(F(" Temperature = ")); Serial.println(celsius); return; } //----------------- int getHourTime(void){ rtclock.getTime(tmm1); return tmm1.hour; } //----------------- int getMinuteTime(void){ rtclock.getTime(tmm1); return tmm1.minute; } //---------------- bool checkNTP(){ while (Udp.parsePacket() > 0); // discard any previously received packets Serial.println(F("Transmit NTP Request")); sendNTPpacket(timeServer); uint32_t beginWait = millis(); while (millis() - beginWait < 1500) { int size = Udp.parsePacket(); if (size >= NTP_PACKET_SIZE) { Serial.println(F("Receive NTP Response")); Udp.read(packetBuffer, NTP_PACKET_SIZE); // read packet into the buffer unsigned long secsSince1900,nowTime; // convert four bytes starting at location 40 to a long integer secsSince1900 = (unsigned long)packetBuffer[40] << 24; secsSince1900 |= (unsigned long)packetBuffer[41] << 16; secsSince1900 |= (unsigned long)packetBuffer[42] << 8; secsSince1900 |= (unsigned long)packetBuffer[43]; nowTime = secsSince1900 - 2208988800UL + timezone * SECS_PER_HOUR; rtclock.setTime(time_t(nowTime)); //JSTを内部時計にセット return true; } } Serial.println(F("No NTP Response :-(")); return false; // return 0 if unable to get the time } //---------------- void setup() { // Open serial communications and wait for port to open: Serial.begin(115200); //シリアル通信を開ます。 pinMode(BUILTIN_LED,OUTPUT); digitalWrite(BUILTIN_LED,LOW); pinMode(LED1,OUTPUT); digitalWrite(LED1, HIGH); pinMode(LED2,OUTPUT); digitalWrite(LED2, LOW); //Ethernet3API Ethernet.setCsPin(SPI1_NSS_PIN); Ethernet.setRstPin(W550io_Rst); pinMode(W550io_Rst, OUTPUT); digitalWrite(W550io_Rst, LOW); delay(10); digitalWrite(W550io_Rst, HIGH); Serial.print(F("NIC_Reset\n")); LANSetup(); //イーサネットとUDPを開始します Udp.begin(localPort); Serial.print(F("server is at "));Serial.println(Ethernet.localIP()); fDoneTime = checkNTP(); rtclock.getTime(tmm); sprintf(STRBUF,"%02u%02u%02u",tmm.hour,tmm.minute,tmm.second); LedAndKey.setDisplayToString("000000",0,2); Serial.print(F("server is at "));Serial.println(Ethernet.localIP()); webServer.begin(); //データバッファクリア for(int i = 0;i<24;i++){ for(int j = 0;j<4;j++){ gDayBuf[i][j] = NAN; } } for(int i = 0;i<60;i++){ for(int j = 0;j<4;j++){ gHourBuf[i][j] = NAN; } } //DS18B20の初期化 for(int i = 0;i<10;i++){ if(!SetDSDevice(i)){ devNum = i; break; } } //タイマ割込設定 Timer1.pause(); // Timer1.setPrescaleFactor(7200); // 72MHz100uSEC Timer1.setOverflow(10000); // 1000mSEC Timer1.attachInterrupt(TIMER_UPDATE_INTERRUPT,TimeUpdate); // 割り込みサーブルーチンの宣言:TimeUpdate Timer1.setCount(0); // 0 Timer1.refresh(); Timer1.resume(); // iwdg_init_ms(wdgTime); //ウォッチドッグをオンにして、オーバーフロー時間を設定します。 Serial.println(F("EndSetUp")); } //---------------- int preSet = -1; int preMSet = -1; void loop() { //このLoopはscantime=1秒程度です。そのため5秒経っても戻らなかったらリセットすることにします。 iwdg_feed(); //ウォッチドッグタイマーをリセットするには、ドッグ操作をフィードします // if(!(OperatingTime % 3600)){ //1時間に一回 fDoneTime = checkNTP(); } rtclock.getTime(tmm); sprintf(STRBUF,"%02u%02u%02u",tmm.hour,tmm.minute,tmm.second); LedAndKey.setDisplayToString(STRBUF,0,2); if(!(OperatingTime % 60)) Serial.println(F(".")); else Serial.print(F(".")); //digitalWrite(BUILTIN_LED,OperatingTime % 2); client = webServer.available(); //HTTP要求確認 if(client) checkWebPage(client); client.stop(); // コネクションを閉じる。 //時刻チェック int h = getHourTime(); //返値0-23 int m = getMinuteTime(); //返値0-59 if(preSet != h){ //1時間おきに時刻を確認し、データをメモリに確保 preSet = h; float celsius; //本計測 for (int i = 0;i<devNum;i++){ GetDSTemp(celsius,i); if(celsius != 0.0){ gDayBuf[h][i] = celsius; } } //次回分のデータをNULL化 h = (h+1) % 24; for (int i = 0;i<devNum;i++){ gDayBuf[h][i] = NAN; } }else if(preMSet != m){ //1分おきにデータ取込 preMSet = m; float celsius; //本計測 for (int i = 0;i<devNum;i++){ GetDSTemp(celsius,i); if(celsius != 0.0){ gHourBuf[m][i] = celsius; } } //次回分のデータをNULL化 m = (m+1) % 60; for (int i = 0;i<devNum;i++){ gHourBuf[m][i] = NAN; } if(!fDoneTime){ fDoneTime = checkNTP(); } }else{ //計測しない } if(OperatingTime % 2){ digitalWrite(LED1, LOW); digitalWrite(LED2, HIGH); }else{ digitalWrite(LED1, HIGH); digitalWrite(LED2, LOW); } delay(200); } |
免責事項
本ソフトウエアは、あなたに対して何も保証しません。本ソフトウエアの関係者(他の利用者も含む)は、あなたに対して一切責任を負いません。
あなたが、本ソフトウエアを利用(コンパイル後の再利用など全てを含む)する場合は、自己責任で行う必要があります。本ソフトウエアの著作権はToolsBoxに帰属します。
本ソフトウエアをご利用の結果生じた損害について、ToolsBoxは一切責任を負いません。
ToolsBoxはコンテンツとして提供する全ての文章、画像等について、内容の合法性・正確性・安全性等、において最善の注意をし、作成していますが、保証するものではありません。
ToolsBoxはリンクをしている外部サイトについては、何ら保証しません。
ToolsBoxは事前の予告無く、本ソフトウエアの開発・提供を中止する可能性があります。
商標・登録商標
Microsoft、Windows、WindowsNTは米国Microsoft Corporationの米国およびその他の国における登録商標です。
Windows Vista、Windows XPは、米国Microsoft Corporation.の商品名称です。
LabVIEW、National Instruments、NI、ni.comはNational Instrumentsの登録商標です。
I2Cは、NXP Semiconductors社の登録商標です。
その他の企業名ならびに製品名は、それぞれの会社の商標もしくは登録商標です。
すべての商標および登録商標は、それぞれの所有者に帰属します。