W5500-EVB-PICOで動作するModbusTCPSlave

最終更新日:2023/6/12

※デモソースでの実行時電流使用量は0.17A程度でした。

※事前にNeoPixelの調査を行いました。

※W5500-EVB-PICO+GroveShieldForPiPicoの仕様を検討しました。

RP2040版ModbusTCPSlaveは出来ていたのですが、W5500-EVB-PICOに置き換えたいと思いました。
ベースのシールドボードをCytronMakerPiPicoとして検討し直しました。このシールドはI/OがLED対応しておりデバッグには便利です。一方、いろいろなI/Oが接続され一部PINが融通が効かなくなり、思案が必要です。
IOが占有されていることもあり、IOExpanderは利用したいと考え、I2Cポートは確保します。
NeoPixelが装備されているので是非使い道を検討しておきたいです。

W5500-EVB-PICOを使う場合SPI接続のW5500に割り当てているPinアサインを考慮して使えないピンが発生します。

このためタクトスイッチGP20/GP21を操作すると誤動作してしまいます。

実際の実行挙動ですが、


/*
 * 2023/3/23 T.Wanibe
 * 1.1.2
 *      4-7SEGLEDのドット対策
 *      Pin割り当て再考
 * 1.1
 *      W5500-EVB-PICOを入手したのでPINアサインを見直してビルド
 * 1.03
 *      1.02のHTML未修正部分の手直し
 *      メモリもフラッシュも可成り余裕があるのでこちらも見直す
 * 1.02
 *      1.01がすんなり動いたので更に以下の機能を追加する
 *      EEPROMによるパラメータ登録
 *      WebServer機能の追加
 * 1.01
 *      1.0 で とりあえずModbusMasterとの通信が出来るSlaveが作成出来ました。
 *      これまでにArduino-Picoに実装してきたコードを移植してもう少し肉付けしたいと思う
 *      Timer割込を追加してCP25のLEDを500msec毎の点滅にしたい。
 *      NTPクライアントによる時刻同期 及びTM1637に時刻表示
 * 最大1044480バイトのフラッシュメモリのうち、スケッチが91744バイト(8%)を使っています。
 * 最大262144バイトのRAMのうち、グローバル変数が10256バイト(3%)を使っていて、ローカル変数で251888バイト使うことができます。
  */
#define          TIMER_INTERRUPT_DEBUG          1
#define         _TIMERINTERRUPT_LOGLEVEL_       4
#include        <TimeLib.h>
#include        "TM1637.h"
#include        "RPi_Pico_TimerInterrupt.h"
#include        <SPI.h>
#include        "MgsModbus.h"                                           //このSketchと同じ階層に置く
#include        <EEPROM.h>
#include        <Adafruit_NeoPixel.h>
extern "C" {
#include        <hardware/watchdog.h>
};
#define         MbCoilDataLen           4                               // length of the MbCoilDataLen array (Equivalent16bit*2)
#define         MbDiscreteDataLen       4                               // length of the MbDiscreteDataLen array(Equivalent16bit*2)
#define         MbHoldDataLen           48                              // length of the MbHoldDataLen array
#define         MbInputDataLen          96                              // length of the MbInputDataLen array
#define         OK                      0
#define         NG                      1
#define         BAUDRATE                115200
#define         CLK                     7
#define         DIO                     6
#define         NICReset                20
#define         NICInit                 21
#define         SPI_SCK                 18
#define         SPI_RX                  16
#define         SPI_TX                  19
#define         SPI_CS                  17
#define         LED_PIN                 28                                      //NeoPixelsが接続されているPINを指定します。
#define         LED_COUNT               1                                      //NeoPixelsが連結されている数を登録します。
#define         BRIGHTNESS              50                                      // NeoPixelの明るさ設定です 0 (min) to 255 (max)
#define         TIMER0_INTERVAL_MS      1000
#define         HttpPort                80                                      //WebServer
#define         SEG_DP                  0x80
#define         vers                    "RPiPicoModbusTCP_Slave_1.0"
#define         webTitle                "RP2040版 ModbusTCP_Slave メニュー"
#define         topMenu1                "設定メニュー"
#define         topMenu2                "Modbus表示"
#define         titleStr                "RPiPicoModbusTCP"
#define         VenderString            "ToolsBox"
char            outputSTR[9];
const char      FVirsion[]      = "1.1.2";                      //フォーマット厳守 x.x.x
const char      SVirsion[]      = "1.1.2";                      //フォーマット厳守 x.x.x ソースコードのバージョン
//
uint32_t        delay_ms        = 8000;                                         //8秒 最大8.3秒
const int       NTPport         = 123;
const int       NTP_PACKET_SIZE = 48;                                           // NTP time stamp is in the first 48 bytes of the message
byte            packetBuffer[NTP_PACKET_SIZE];                                  //buffer to hold incoming and outgoing packets
// Ethernet settings (depending on MAC and Local network)
byte            mac[]           = {0x00,0x08,0xDC,0x54,0x4D,0xE2};              //WIZNET
byte            ip[]            = {192, 168, 0, 212};
byte            dns_server[]    = {192, 168, 0, 1};
byte            gateway[]       = {192, 168, 0, 1};
byte            subnet[]        = {255, 255, 255, 0};
byte            NTPip[]         = {192,168,0,199};                              //char*timeServerへの変換が必要内部管理は配列にする。
bool            gMBusConnect    = false;                                        //Modbus接続中はWebServer接続を502で逃げる
byte            fTogle1         = LOW;
bool            gRTCOK;
//WebServer
String          HTTP_req;
char            MacAddressStr[20];
char            IPAddressStr[20];
char            SubnetMaskStr[20];
char            GatewayStr[20];
char            NTPserverStr[20];
char            DateTimeStr[20];
//内部カウンタ
unsigned long   gNTPqueryCount  = 0;
long            gLoopCount      = 3;                                    //1時間毎に更新予定 最初は1分後に更新したくて初期値を調整
long            gLoopTime       = 0;                                    //Loop()の実行時間を求める
long            gResetCount     = 0;
long            gPreTime,gNowTime; 
unsigned long   OperatingTime   = 0;                                    //稼働時間 Count2で1秒
int             LinkStatus;
int             gHardwareStatus;
float           unit            = 2.33E-7;
unsigned long   baseMilis       = millis();
unsigned long   miliTime;
struct          time_tm         *tm;                                    //STM32dinoとRP2040の構造体が異なる
time_t          currentTime,recieveTime;
unsigned long   currentHour,currentMin,currentSec;
int8_t          TimeDisp[]      = {0x00,0x00,0x00,0x00};
uint32_t        timestamp, tempval,microVal,fractions;
float           timezone        = 9.0;
time_t          TimeZoneSec     = long(timezone * 3600);
const unsigned long seventyYears = 2208988800UL;
char            buf80[80];
char            buf32[32];
// これは、HTMLコードを「流す」ためのバッファーです。
// ””を含む最長の文字チェーン+1と同じ大きさでなければなりません。
char            buffer[256];
static int8_t   tube_tab[] = {  0x3f, 0x06, 0x5b, 0x4f,
                                0x66, 0x6d, 0x7d, 0x07,
                                0x7f, 0x6f, 0x77, 0x7c,
                                0x39, 0x5e, 0x79, 0x71
                                }; //0~9,A,b,C,d,E,F
//物理接続要素
int             dOsPins[]       = {0,1};
int             dIsPins[]       = {22};
int             aIsPins[]       = {26, 27};
byte            preData         = 255;
byte            preR            = 255;
byte            preG            = 255;
byte            preB            = 255;
bool            preShow         = true;
//物理接続配列要素数を求めておく
int             DObits          = sizeof(dOsPins)/sizeof(int);
int             DIbits          = sizeof(dIsPins)/sizeof(int);
int             AIbits          = sizeof(aIsPins)/sizeof(int);
//
const byte      ID = 0xA0;
//オブジェクトコンストラクタ
MgsModbus       Mb;
TM1637          tm1637(CLK,DIO);
EthernetUDP     Udp;
RPI_PICO_Timer  ITimer0(0);
EthernetServer  webServer(HttpPort);
EthernetClient  client;
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRBW + NEO_KHZ800);
                                                                        // 引数 1 = NeoPixel ストリップのピクセル数
                                                                        // 引数 2 = Arduino のピン番号 (ほとんどが有効)
                                                                        // 引数 3 = ピクセル タイプ フラグ、必要に応じて追加:
                                                                        //   NEO_KHZ800  800 KHz ビットストリーム (ほとんどの NeoPixel 製品 w/WS2812 LED)
                                                                        //   NEO_KHZ400  400 KHz (従来の「v1」(v2 ではない) FLORA ピクセル、WS2811 ドライバー)
                                                                        //   NEO_GRB     ピクセルは GRB ビットストリーム用に配線されています (ほとんどの NeoPixel 製品)
                                                                        //   NEO_RGB     ピクセルは RGB ビットストリーム用に配線されています (v2 ではなく v1 FLORA ピクセル)
                                                                        //   NEO_RGBW    ピクセルは GRBW ビットストリーム用に配線されています (NeoPixel RGBW 製品)
//------------EEPROM.read
void ReadID(){
        for (int i = 0; i < 6; i++){
                //mac[i]        = EEPROM.read(i+1);
                mac[i]          = EEPROM[i+1];
                if(Serial)      Serial.print("R_mac=");Serial.println(mac[i]);
        }
        for (int i = 0; i < 4; i++){
                //ip[i]         = EEPROM.read(i+7);
                ip[i]           = EEPROM[i+7];
                if(Serial)      Serial.print("R_ip=");Serial.println(ip[i]);
        }
        for (int i = 0; i < 4; i++){
                //subnet[i]     = EEPROM.read(i+11);
                subnet[i]       = EEPROM[i+11];
                if(Serial)      Serial.print("R_subnet=");Serial.println(subnet[i]);
        }
        for (int i = 0; i < 4; i++){
                //gateway[i]    = EEPROM.read(i+15);
                gateway[i]      = EEPROM[i+15];
                if(Serial)      Serial.print("R_gateway=");Serial.println(gateway[i]);
        }
        for (int i = 0; i < 4; i++){
                //NTPip[i]      = EEPROM.read(i+19);
                NTPip[i]        = EEPROM[i+19];
                if(Serial)      Serial.print("R_NTPip=");Serial.println(NTPip[i]);
        }
        //timezone = float(EEPROM.read(23)) / 10.0;
        timezone = float(EEPROM[23]) / 10.0;
        if(Serial)      Serial.print("R_timezone=");Serial.println(timezone);
}
//------------EEPROM.write
void WriteID(){
        for (int i = 0 ; i < 6; i++){
                //EEPROM.write(i + 1,mac[i]);
                EEPROM[i + 1]   = mac[i];
                if(Serial)      Serial.print("W_mac=");Serial.println(mac[i]);
        }
        for (int i = 0 ; i < 4; i++){
                //EEPROM.write(i + 7, ip[i]);
                EEPROM[i + 7]   = ip[i];
                if(Serial)      Serial.print("W_ip=");Serial.println(ip[i]);
        }
        for (int i = 0 ; i < 4; i++){
                //EEPROM.write(i + 11, subnet[i]);
                EEPROM[i + 11]  = subnet[i];
                if(Serial)      Serial.print("W_subnet=");Serial.println(subnet[i]);
        }
        for (int i = 0 ; i < 4; i++){
                //EEPROM.write(i + 15, gateway[i]);
                EEPROM[i + 15]  = gateway[i];
                if(Serial)      Serial.print("W_gateway=");Serial.println(gateway[i]);
        }
        for (int i = 0; i < 4; i++){
                //EEPROM.write(i + 19, NTPip[i]);
                EEPROM[i + 19]  = NTPip[i];
                if(Serial)      Serial.print("W_NTPip=");Serial.println(NTPip[i]);
        }
        //EEPROM.write(23,char(timezone * 10));
        EEPROM[23]      = char(timezone * 10);
        if(Serial)      Serial.print("W_timezone=");Serial.println(timezone);
        // IDを既知のビットに設定します。したがって、Arduinoをリセットすると、EEPROM値が使用されます。
        //EEPROM.write(256, ID);
        EEPROM[256]     =       ID;
        EEPROM.commit();                        //2.5.5.2で追加
        
        if(Serial)      Serial.print("W_ID=");Serial.println(ID,HEX);
}
//----------------------------------
void LANSetup(){
        EEPROM.begin(512);
        //int idcheck   = EEPROM.read(256);
        int idcheck     =       EEPROM[256];
        if(Serial)      Serial.print("R_ID=");Serial.println(idcheck,HEX);
        Serial.print(F("LocalID = 0x"));Serial.println(idcheck,HEX);
        if (idcheck == ID){
                //idがIDと同じ値の場合、
                //これは、このスケッチがシールドを設定するために使用されたことを意味します。
                //EERPOMの値を読み取ってシールドを設定します。
                ReadID();
        }else{
                //idが一致しない場合、初期値を書き込む事にします。
                WriteID();
        }
        EEPROM.end();
        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]);
}
//----------------------------MODBUS
int     GetDeviceInfo(){
        for (int i=0;i<DIbits;i++){
                Mb.SetBit(MB_FC_READ_DISCRETE_INPUT,i,!digitalRead(dIsPins[i]));        //bit 論理反転
        }
        for (int i=0;i<AIbits;i++){
                Mb.MbInputData[i]=analogRead(aIsPins[i]);                               //U16
        }
        return OK;            
}
//----------------------------MODBUS
int     SetDeviceInfo(){
        for (int i=0;i<DObits;i++){          
                digitalWrite(dOsPins[i],!Mb.GetBit(MB_FC_READ_COILS,i));                 //LEDはLOWで点灯                            
        }
        for (int i=0;i<4;i++){ 
                //if(Serial)      Serial.println(Mb.MbHoldData[i]);
        }        
        if((preData == Mb.MbHoldData[3])&&(preR == Mb.MbHoldData[0])&&(preG == Mb.MbHoldData[1])&&(preB == Mb.MbHoldData[2])){
        }else{
                preR    = Mb.MbHoldData[0] % 256;
                preG    = Mb.MbHoldData[1] % 256;
                preB    = Mb.MbHoldData[2] % 256;
                preData = Mb.MbHoldData[3] % 256;
                if(Serial)      Serial.println(preR);
                if(Serial)      Serial.println(preG);
                if(Serial)      Serial.println(preB);
                if(Serial)      Serial.println(preData);
        }
        if(Mb.GetBit(MB_FC_READ_COILS,2)){
                if(Serial)      Serial.println("CoilBit=True");
                strip.setPixelColor(0, preR, preG, preB, preData); 
                strip.show();
                //delay(500);
        }else{
                if(Serial)      Serial.println("CoilBit=False");
                strip.setPixelColor(0, 0, 0, 0, 0);
                //strip.clear(); 
                strip.show();
                //delay(500);
        }
        return OK;
}
//--------------
void custom_display(uint8_t bit_addr, uint8_t seg_data) {
        tm1637.start();
        tm1637.writeByte( 0x44 );
        tm1637.stop();
        tm1637.start();
        tm1637.writeByte(bit_addr | 0xc0);
        tm1637.writeByte(seg_data);
        tm1637.stop();
        tm1637.start();
        tm1637.writeByte(tm1637.cmd_disp_ctrl);
        tm1637.stop();
}
//-------------タイマ割込で呼ばれるルーチン クロック表示 500msec毎
bool    TimerHandler0(struct repeating_timer *t){
        OperatingTime++;
        currentTime     =       now();
        if(Serial)      Serial.println(currentTime);
        currentTime     %=  86400;
        currentHour     = currentTime / 3600;
        currentMin      = (currentTime % 3600)/60;
        TimeDisp[0]     = currentHour/ 10;
        TimeDisp[1]     = currentHour % 10;
        TimeDisp[2]     = currentMin / 10;
        TimeDisp[3]     = currentMin % 10;
        //if(fTogle1)     tm1637.point(POINT_OFF);
        //else            tm1637.point(POINT_ON);
        //tm1637.display(TimeDisp);
        if(fTogle1){
                custom_display( 0, tube_tab[TimeDisp[0]]);
                custom_display( 1, tube_tab[TimeDisp[1]] | SEG_DP);
                custom_display( 2, tube_tab[TimeDisp[2]]);
                custom_display( 3, tube_tab[TimeDisp[3]]);               
        }else{
                custom_display( 0, tube_tab[TimeDisp[0]]);
                custom_display( 1, tube_tab[TimeDisp[1]]);
                custom_display( 2, tube_tab[TimeDisp[2]]);
                custom_display( 3, tube_tab[TimeDisp[3]]);           
        }
        digitalWrite(LED_BUILTIN, fTogle1);
        fTogle1         = !fTogle1;
        return  true;
}
//---------------------
bool processNTP() {
        //利用可能なデータがある場合は、パケットを読み取ります
        //https://blog.goo.ne.jp/hiro239415/e/c426a545863921a13a9d6a70b7ae4484
        //NTP_Packet (48Byte)
        bool    req             =       false;
        int     packetSize      =       Udp.parsePacket();
        if(packetSize){
                digitalWrite(LED_BUILTIN,HIGH);                         //要求があったときにBuiltInLEDを点灯
                miliTime                = millis() - baseMilis;
                fractions               = uint32_t(float(miliTime % 1000) / unit);
                sprintf(buf32,"■%d\t%d\n",packetSize,fractions);
                if(Serial)     Serial.print(buf32);
                Udp.read(packetBuffer,NTP_PACKET_SIZE);
                if(Serial){
                        for (int i =0;i<48;i++){
                                Serial.print(packetBuffer[i],HEX);
                        }
                        Serial.println();
                }
                IPAddress       Remote  = Udp.remoteIP();
                int             PortNum = Udp.remotePort();
                //受信タイムスタンプ = サーバが受け取った時刻を予めセットしておく JSTなのでGMTに変換
                timestamp               = now()         - TimeZoneSec;
                miliTime                = millis()      - baseMilis;
                fractions               = uint32_t(float(miliTime % 1000) / unit);
                tempval                 = timestamp;
                packetBuffer[32]        = (tempval >> 24) & 0XFF;
                tempval                 = timestamp;
                packetBuffer[33]        = (tempval >> 16) & 0xFF;
                tempval                 = timestamp;
                packetBuffer[34]        = (tempval >> 8) & 0xFF;
                tempval                 = timestamp;
                packetBuffer[35]        = (tempval) & 0xFF;
                //
                microVal                = fractions;
                packetBuffer[36]        = (microVal >> 24) & 0xFF;
                microVal                = fractions;
                packetBuffer[37]        = (microVal >> 16) & 0xFF;
                microVal                = fractions;
                packetBuffer[38]        = (microVal >> 8) & 0xFF;
                microVal                = fractions;
                packetBuffer[39]        = microVal & 0xFF;
                 //ヘッダーセット
                packetBuffer[0]         = 0b00100100;                           // 閏秒警告なしLI, 4:SNTPサーバ(Version), 4:サーバ(Mode)
                packetBuffer[1]         = 1 ;                                   // 1:一次基準源(GPS等)(stratum
                packetBuffer[2]         = 5 ;                                   // ポーリング64秒デフォルト値 6(64秒)->5(32秒)
                packetBuffer[3]         = 0xF6;                                 // 精度 -3(0xFD)->-10(0xF6)に変更 msec
                packetBuffer[4]         = 0;                                    // ルート遅延
                packetBuffer[5]         = 0;
                packetBuffer[6]         = 8;
                packetBuffer[7]         = 0;
                packetBuffer[8]         = 0;                                    // ルート分散
                packetBuffer[9]         = 0;
                packetBuffer[10]        = 0xC;
                packetBuffer[11]        = 0;
                //
                packetBuffer[12]        = 71;                                   //"G";   ReferenceID
                packetBuffer[13]        = 80;                                   //"P";   ReferenceID
                packetBuffer[14]        = 83;                                   //"S";   ReferenceID
                packetBuffer[15]        = 0;                                    //"0";   ReferenceID
                // リファレンス時刻をセット(現在時間)
                timestamp               = now()         - TimeZoneSec;          //UTC
                if(Serial){
                        Serial.print(timestamp);Serial.print(F(":Time synchronization Request received\n"));
                }
                tempval                 = timestamp;
                microVal                = fractions;
                packetBuffer[16]        = (tempval >> 24) & 0XFF;
                tempval                 = timestamp;
                packetBuffer[17]        = (tempval >> 16) & 0xFF;
                tempval                 = timestamp;
                packetBuffer[18]        = (tempval >> 8) & 0xFF;
                tempval                 = timestamp;
                packetBuffer[19]        = (tempval) & 0xFF;
                packetBuffer[20]        = (microVal >> 24) & 0xFF;
                microVal                = fractions;
                packetBuffer[21]        = (microVal >> 16) & 0xFF;
                microVal                = fractions;
                packetBuffer[22]        = (microVal >> 8) & 0xFF;
                microVal                = fractions;
                packetBuffer[23]        = microVal & 0xFF;
                //オリジナル時間をコピー(サーバに要求が届いた時間)
                packetBuffer[24]        = packetBuffer[40];
                packetBuffer[25]        = packetBuffer[41];
                packetBuffer[26]        = packetBuffer[42];
                packetBuffer[27]        = packetBuffer[43];
                packetBuffer[28]        = packetBuffer[44];
                packetBuffer[29]        = packetBuffer[45];
                packetBuffer[30]        = packetBuffer[46];
                packetBuffer[31]        = packetBuffer[47];
                //送信時刻をセット
                timestamp               = now()         - TimeZoneSec;                  //UTC
                miliTime                = millis()      - baseMilis;
                fractions               = uint32_t(float(miliTime % 1000) / unit);
                tempval                 = timestamp;
                packetBuffer[40]        = (tempval >> 24) & 0XFF;
                tempval                 = timestamp;
                packetBuffer[41]        = (tempval >> 16) & 0xFF;
                tempval                 = timestamp;
                packetBuffer[42]        = (tempval >> 8) & 0xFF;
                tempval                 = timestamp;
                packetBuffer[43]        = (tempval) & 0xFF;
                //transmit_timestamp_fractions
                microVal                = fractions; 
                packetBuffer[44]        = (microVal >> 24) & 0xFF;
                microVal                = fractions;
                packetBuffer[45]        = (microVal >> 16) & 0xFF;
                microVal                = fractions;
                packetBuffer[46]        = (microVal >> 8) & 0xFF;
                microVal                = fractions;
                packetBuffer[47]        = microVal & 0xFF;
                //NTP要求を送信したIPアドレスとポートに応答します
                Udp.beginPacket(Remote, PortNum);
                Udp.write(packetBuffer,NTP_PACKET_SIZE);
                Udp.endPacket();
                digitalWrite(LED_BUILTIN,LOW);                                  //処理完了で消灯
                sprintf(buf32,"●%d\t%d\t%d\t%d\n",packetBuffer[20],packetBuffer[21],packetBuffer[22],packetBuffer[23]);
                if(Serial)      Serial.print(buf32);
                req     = true;
                gNTPqueryCount++;
        }
        return req;
}
//-----------------指定されたアドレスのタイムサーバーにNTP要求を送信します
void sendNTPpacket(const char * address) {
        // バッファ内のすべてのバイトを0に設定します
        memset(packetBuffer, 0, NTP_PACKET_SIZE);
        // NTP要求を形成するために必要な値を初期化します(パケットの詳細については、上記のURLを参照してください)
        packetBuffer[0]         = 0b11100011;                                   // LI, Version, Mode
        packetBuffer[1]         = 0;                                            // Stratum, or type of clock
        packetBuffer[2]         = 6;                                            // ポーリング64秒デフォルト値
        packetBuffer[3]         = 0xEC;                                         // 精度
        // ルート遅延とルート分散の場合は8バイトのゼロ
        packetBuffer[12]        = 0x31;                                         // '1'
        packetBuffer[13]        = 0x4E;                                         // 'N'
        packetBuffer[14]        = 0x31;                                         // '1'
        packetBuffer[15]        = 0x34;                                         // '4'
        //すべてのNTPフィールドに値が指定されているため、タイムスタンプを要求するパケットを送信できます。
        Udp.beginPacket(address, NTPport);                                      // NTP要求はポート123に送信されます
        Udp.write(packetBuffer, NTP_PACKET_SIZE);
        Udp.endPacket();
}
//-----------------受信したNTPパケットを解析してRTCにセットします
bool parseNTPpacket(){
        // 返信が利用可能かどうかを確認するのを待ちます
        bool result = false;
        if (Udp.parsePacket()) {
                // パケットを受信しました。そこからデータを読み取ります
                Udp.read(packetBuffer, NTP_PACKET_SIZE);                        // パケットをバッファに読み込みます
                // タイムスタンプは、受信したパケットのバイト40から始まり、4バイトです。
                unsigned long secsSince1900;
                // 位置40から始まる4バイトを長整数に変換します
                secsSince1900 =  (unsigned long)packetBuffer[40] << 24;
                secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
                secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
                secsSince1900 |= (unsigned long)packetBuffer[43];
                Serial.print("Seconds since Jan 1 1900 = ");
                Serial.println(secsSince1900);
                // エピックタイムに変換します。(local)
                unsigned long epoch = secsSince1900 - seventyYears + TimeZoneSec;
                Serial.print("Unix time = ");
                Serial.println(epoch);
                setTime(epoch);                                                 //RTC登録(LocalTime)
                result =  true;
        }else{
                result =  false;
        }
        return result;
}
//--------------------------Webserver
//--------OK_200
String OK_200           =
        "HTTP/1.1 200 OK\n"
        "Content-Type: text/html\n";
//--------NG_404
String NG_404           =
        "HTTP/1.1 404 Not Found\n"
        "Content-Type: text/html\n"
        "Connnection: close\n";
//--------LoadUtilsJS
String LoadUtilsJS1     =
        "'use strict';\n"
"window.chartColors = {\n"
        "\tred: 'rgb(255, 99, 132)',\n"
        "\torange: 'rgb(255, 159, 64)',\n"
        "\tyellow: 'rgb(255, 205, 86)',\n"
        "\tgreen: 'rgb(75, 192, 192)',\n"
        "\tblue: 'rgb(54, 162, 235)',\n"
        "\tpurple: 'rgb(153, 102, 255)',\n"
        "\tgrey: 'rgb(201, 203, 207)'\n"
"};\n"
"(function(global) {\n"
        "\tvar MONTHS = [\n"
                "\t\t'January',\n"
                "\t\t'February',\n"
                "\t\t'March',\n"
                "\t\t'April',\n"
                "\t\t'May',\n"
                "\t\t'June',\n"
                "\t\t'July',\n"
                "\t\t'August',\n"
                "\t\t'September',\n"
                "\t\t'October',\n"
                "\t\t'November',\n"
                "\t\t'December'\n"
        "\t];\n"
        "\tvar COLORS = [\n"
                "\t\t'#4dc9f6',\n"
                "\t\t'#f67019',\n"
                "\t\t'#f53794',\n"
                "\t\t'#537bc4',\n"
                "\t\t'#acc236',\n"
                "\t\t'#166a8f',\n"
                "\t\t'#00a950',\n"
                "\t\t'#58595b',\n"
                "\t\t'#8549ba'\n"
        "\t];\n"
        "\tvar Samples = global.Samples || (global.Samples = {});\n"
        "\tvar Color = Chart.helpers.color;\n"
        "\tfunction applyDefaultNumbers(config) {\n"
                "\t\tvar cfg = config || {};\n"
                "\t\tcfg.min = cfg.min || 0;\n"
                "\t\tcfg.max = cfg.max || 1;\n"
                "\t\tcfg.from = cfg.from || [];\n"
                "\t\tcfg.count = cfg.count || 8;\n"
                "\t\tcfg.decimals = cfg.decimals || 8;\n"
                "\t\tcfg.continuity = cfg.continuity || 1;\n"
                "\t\treturn cfg;\n"
        "\t}\n";
String LoadUtilsJS2     =
        "\tSamples.utils = {\n"
                "\t\t// Adapted from http://indiegamr.com/generate-repeatable-random-numbers-in-js/\n"
                "\t\tsrand: function(seed) {\n"
                "\t\t\tthis._seed = seed;\n"
                "\t\t},\n"
                "\t\trand: function(min, max) {\n"
                "\t\t\tvar seed = this._seed;\n"
                "\t\t\tmin = min === undefined ? 0 : min;\n"
                "\t\t\tmax = max === undefined ? 1 : max;\n"
                "\t\t\tthis._seed = (seed * 9301 + 49297) % 233280;\n"
                "\t\t\treturn min + (this._seed / 233280) * (max - min);\n"
                "\t\t},\n"
                "\t\tnumbers: function(config) {\n"
                        "\t\t\tvar cfg = applyDefaultNumbers(config);\n"
                        "\t\t\tvar dfactor = Math.pow(10, cfg.decimals) || 0;\n"
                        "\t\t\tvar data = [];\n"
                        "\t\t\tvar i, value;\n"
                        "\t\t\tfor (i = 0; i < cfg.count; ++i) {\n"
                                "\t\t\t\tvalue = (cfg.from[i] || 0) + this.rand(cfg.min, cfg.max);\n"
                                "\t\t\t\tif (this.rand() <= cfg.continuity) {\n"
                                "\t\t\t\t\tdata.push(Math.round(dfactor * value) / dfactor);\n"
                                "\t\t\t\t} else {\n"
                                "\t\t\t\t\tdata.push(null);\n"
                                "\t\t\t\t}\n"
                        "\t\t\t}\n"
                        "\t\t\treturn data;\n"
                "\t\t},\n"
                "\t\tlabels: function(config) {\n"
                        "\t\t\tvar cfg = config || {};\n"
                        "\t\t\tvar min = cfg.min || 0;\n"
                        "\t\t\tvar max = cfg.max || 100;\n"
                        "\t\t\tvar count = cfg.count || 8;\n"
                        "\t\t\tvar step = (max - min) / count;\n"
                        "\t\t\tvar decimals = cfg.decimals || 8;\n"
                        "\t\t\tvar dfactor = Math.pow(10, decimals) || 0;\n"
                        "\t\t\tvar prefix = cfg.prefix || '';\n"
                        "\t\t\tvar values = [];\n"
                        "\t\t\tvar i;\n"
                        "\t\t\tfor (i = min; i < max; i += step) {\n"
                        "\t\t\t\tvalues.push(prefix + Math.round(dfactor * i) / dfactor);\n"
                        "\t\t\t}\n"
                        "\t\t\treturn values;\n"
                "\t\t},\n"
                "\t\tmonths: function(config) {\n"
                        "\t\t\tvar cfg = config || {};\n"
                        "\t\t\tvar count = cfg.count || 12;\n"
                        "\t\t\tvar section = cfg.section;\n"
                        "\t\t\tvar values = [];\n"
                        "\t\t\tvar i, value;\n"
                        "\t\t\tfor (i = 0; i < count; ++i) {\n"
                                "\t\t\t\tvalue = MONTHS[Math.ceil(i) % 12];\n"
                                "\t\t\t\tvalues.push(value.substring(0, section));\n"
                        "\t\t\t}\n"
                        "\t\t\treturn values;\n"
                "\t\t},\n"
                "\t\tcolor: function(index) {\n"
                        "\t\t\treturn COLORS[index % COLORS.length];\n"
                "\t\t},\n"
                "\t\ttransparentize: function(color, opacity) {\n"
                        "\t\t\tvar alpha = opacity === undefined ? 0.5 : 1 - opacity;\n"
                        "\t\t\treturn Color(color).alpha(alpha).rgbString();\n"
                "\t\t}\n"
        "\t};\n";
String LoadUtilsJS3     =
        "\t// DEPRECATED\n"
        "\twindow.randomScalingFactor = function() {\n"
                "\t\treturn Math.round(Samples.utils.rand(-100, 100));\n"
        "\t};\n"
        "\t// INITIALIZATION\n"
        "\tSamples.utils.srand(Date.now());\n"
        "\t// Google Analytics\n"
        "\t/* eslint-disable */\n"
        "\tif (document.location.hostname.match(/^(www\\.)?chartjs\\.org$/)) {\n"
                "\t\t(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){\n"
                "\t\t(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),\n"
                "\t\tm=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)\n"
                "\t\t})(window,document,'script','//www.google-analytics.com/analytics.js','ga');\n"
                "\t\tga('create', 'UA-28909194-3', 'auto');\n"
                "\t\tga('send', 'pageview');\n"
        "\t}\n"
        "\t/* eslint-enable */\n"
"}(this));\n";
//--------WebTopPage
String WebTopPage1      =
"<HTML>\n"
"<HEAD>\n"
        "\t<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html;CHARSET=UTF-8\">\n"
        "\t<TITLE>";
String WebTopPage11      =
        "</TITLE>\n"
"</HEAD>\n"
"<BODY BGCOLOR='#ffffff'>\n"
"<H2><CENTER><FONT COLOR='#00ff00'>";
String WebTopPage12      =
"</FONT></CENTER></H2>\n"
"<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"
                "\t\t\t<LI><FONT SIZE='+1'><A HREF=\"http://";
String WebTopPage2       =
                "/setup1\">";
String WebTopPage21       =
                "</A>\n"
                "\t\t\t<LI><A HREF=\"http://";
String WebTopPage3       =
                "/setup2\">";
String WebTopPage31       =
                "</A></FONT>\n"
                "\t\t</OL>\n"
                "\t\t</TD>\n"
        "\t</TR>\n"
"</TABLE></CENTER>\n"
"</BODY>\n"
"</HTML>\n";
//-------------SetPage
String SetPage1         =
        "<!DOCTYPE HTML PUBLIC \"\">\n<html>\n<HEAD>\n\t<META http-equiv=\"Content-Type\" charset=Shift_JIS\">\n"
        "\t<META http-equiv=\"Content-Style-Type\">\n\t<TITLE>";
String SetPage2         =
        " Setup Page</TITLE>\n"
        "\t<SCRIPT>\n\t\tfunction HP(w1){parent.window.open(w1,'_top')}\n\t</SCRIPT>\n</HEAD>\n"
        "<BODY marginwidth=\"0\" marginheight=\"0\" leftmargin=\"0\" style=\"margin: 0; padding: 0;\">\n<BLOCKQUOTE><BLOCKQUOTE>\n"
        "<table bgcolor=\"#17A1A5\" border=\"0\" width=\"100%\" cellpadding=\"1\" style=\"font-family:Verdana;color:#ffffff;font-size:12px;\">\n"
        "<tr><td>";
String SetPage3         =
        " Setup Page</td></tr></table><br>\n"
        "<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"
        "<tbody>\n<FORM><input type=\"hidden\" name=\"SBM\" value=\"1\">\n<table>\n<tr><td>MAC:</td><td>"
        "<input id=\"T1\" type=\"text\" size=\"3\" maxlength=\"2\" name=\"DT1\" value=\"";
String SetPage4         =
        "\">.<input id=\"T3\" type=\"text\" size=\"3\" maxlength=\"2\" name=\"DT2\" value=\"";
String SetPage5         =
        "\">.<input id=\"T5\" type=\"text\" size=\"3\" maxlength=\"2\" name=\"DT3\" value=\"";
String SetPage6         =
        "\">.<input id=\"T7\" type=\"text\" size=\"3\" maxlength=\"2\" name=\"DT4\" value=\"";
String SetPage7         =
        "\">.<input id=\"T9\" type=\"text\" size=\"3\" maxlength=\"2\" name=\"DT5\" value=\"";
String SetPage8         =
        "\">.<input id=\"T11\" type=\"text\" size=\"3\" maxlength=\"2\" name=\"DT6\" value=\"";
String SetPage9         =
        "\"><input id=\"T2\" type=\"hidden\" name=\"DT1\"><input id=\"T4\" type=\"hidden\" name=\"DT2\n"
        "\"><input id=\"T6\" type=\"hidden\" name=\"DT3\"><input id=\"T8\" type=\"hidden\" name=\"DT4\n"
        "\"><input id=\"T10\" type=\"hidden\" name=\"DT5\"><input id=\"T12\" type=\"hidden\" name=\"DT6\n"
        "\"></td></tr>\n<tr><td>IP:</td><td><input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT7\" value=\"";
String SetPage10        =
       "\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT8\" value=\"";
String SetPage11        =
        "\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT9\" value=\"";
String SetPage12        =
        "\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT10\" value=\"";
String SetPage13        =
        "\"></td></tr>\n<tr><td>MASK: </td><td><input type= \"text\" size=\"3\" maxlength=\"3\" name=\"DT11\" value=\"";
String SetPage14        =
        "\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT12\" value=\"";
String SetPage15        =
        "\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT13\" value=\"";
String SetPage16        =
        "\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT14\" value=\"";
String SetPage17        =
        "\"></td></tr>\n<tr><td>GW: </td><td><input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT15\" value=\"";
String SetPage18        =
        "\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT16\" value=\"";
String SetPage19        =
        "\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT17\" value=\"";
String SetPage20        =
        "\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT18\" value=\"";
String SetPage21        =
        "\"></td></tr><tr><td COLSPAN='2'>\n<HR ALIGN=CENTER></td></tr>\n"
        "<tr><td>NTPip: </td><td><input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT19\" value=\"";
String SetPage22        =
        "\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT20\" value=\"";
String SetPage23        =
        "\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT21\" value=\"";
String SetPage24        =
        "\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT22\" value=\"";
String SetPage25        =
        "\"></td></tr>\n"
        "<tr><td>TimeZone:</td><td><input type=\"text\" size=\"3\" maxlength=\"5\" name=\"DT23\" value=\"";
String SetPage26        =
        "\"></td></tr>\n<tr><td><br></td></tr><tr><td COLSPAN='2'><P ALIGN=RIGHT>"
        "<INPUT TYPE=\"button\" VALUE=\"RETURN\" onClick=\"HP('http://";
String SetPage27        =      
        "/index')\"/><input id=\"button1\"type=\"submit\" value=\"SUBMIT\" "
        "Onclick=\""
        "document.getElementById('T2').value = hex2num(document.getElementById('T1').value);\n"
        "\t\tdocument.getElementById('T4').value = hex2num(document.getElementById('T3').value);\n"
        "\t\tdocument.getElementById('T6').value = hex2num(document.getElementById('T5').value);\n"
        "\t\tdocument.getElementById('T8').value = hex2num(document.getElementById('T7').value);\n"
        "\t\tdocument.getElementById('T10').value = hex2num(document.getElementById('T9').value);\n"
        "\t\tdocument.getElementById('T12').value = hex2num(document.getElementById('T11').value);\""
        "></td></tr></tbody>\n</table>\n</BLOCKQUOTE></BLOCKQUOTE>\n</form>\n</BODY>\n</html>\n";
//-------------UtilPage
String SetUtil1         =
        "<!DOCTYPE HTML PUBLIC \"\">\n<html>\n<HEAD>\n\t<META http-equiv=\"Content-Type\" charset=UTF-8\">\n"
        "\t<META http-equiv=\"Content-Style-Type\">\n\t<TITLE>Modbus ";
String SetUtil2         =
        " Utility Page</TITLE>\n"
        "\t<SCRIPT>\n\t\tfunction HP(w1){parent.window.open(w1,'_top')}\n\t</SCRIPT>\n</HEAD>\n"
        "<BODY marginwidth=\"0\" marginheight=\"0\" leftmargin=\"0\" style=\"margin: 0; padding: 0;\" BGCOLOR=\"#ffffff\">\n"
        "<FORM>\n<BLOCKQUOTE><BLOCKQUOTE>\n"
        "<P><table bgcolor=\"#17A1A5\" border=\"0\" width=\"100%\" cellpadding=\"1\" style=\"font-family:Verdana;color:#ffffff;font-size:12px;\" CELLSPACING=\"2\">\n"
        "<tr><td>Modbus ";
String SetUtil3         =
        " Utility Page</td></tr></table><br>\n"
         "<TABLE WIDTH=\"100%\" BORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"0\" style=\"table-layout: fixed\">"
        "<TR>\n\t<TD WIDTH=\"25%\">&nbsp;</TD><TD WIDTH=\"20%\">&nbsp;</TD><TD WIDTH=\"55%\"><P ALIGN=CENTER><INPUT TYPE=\"button\" VALUE=\"RETURN\" onClick=\"HP('http://";
String SetUtil4         =       
        "/setup9')\"/></TD>\n" 
        "<TR>\n\t<TD WIDTH=\"25%\">FirmwareVirsion:</TD>\n\t<TD WIDTH=\"11%\"></TD>\n\t<TD WIDTH=\"64%\">";
String SetUtil5         = 
        "</TD>\n</TR>"
        "<TR>\n\t<TD WIDTH=\"25%\">SourceVirsion:</TD>\n\t<TD WIDTH=\"11%\"></TD>\n\t<TD WIDTH=\"64%\">";
String SetUtil6         = 
        "</TD>\n</TR>"        
        "<TR>\n\t<TD WIDTH=\"25%\">MacAddress:</TD>\n\t<TD WIDTH=\"11%\"></TD>\n\t<TD WIDTH=\"64%\">";
String SetUtil7         =
        "</TD>\n</TR>"
        "<TR>\n\t<TD WIDTH=\"25%\">IPAddress:</TD>\n\t<TD WIDTH=\"11%\"></TD>\n\t<TD WIDTH=\"64%\">";
String SetUtil8         =
        "</TD>\n</TR>"
        "<TR>\n\t<TD WIDTH=\"25%\">SubnetMask:</TD>\n\t<TD WIDTH=\"11%\"></TD>\n\t<TD WIDTH=\"64%\">";
String SetUtil9         =
        "</TD>\n</TR>"
        "<TR>\n\t<TD WIDTH=\"25%\">Data acquisition time:</TD>\n\t<TD WIDTH=\"11%\"></TD>\n\t<TD WIDTH=\"64%\">";
String SetUtil10         =
        "</TD>\n</TR>"
        "<TR>\n\t<TD WIDTH=\"25%\">Operating time:</TD>\n\t<TD WIDTH=\"11%\"></TD>\n\t<TD WIDTH=\"64%\">";
String SetUtil11         =
        "</TD>\n</TR></TABLE></P>\n"
        "<P><HR ALIGN=LEFT></P>\n<P><TABLE WIDTH=\"100%\" BORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"0\" HEIGHT=\"800\" style=\"table-layout: fixed\">"
        "\t<tbody>\n\t<TR>\n\t\t<TD ROWSPAN=\"2\"  WIDTH=\"25%\">DI(02)InputStatus</TD>\n"
        "\t\t<TD COLSPAN=\"2\" HEIGHT=\"23\"></TD>\n"
        "\t\t<TD WIDTH=\"4%\" HEIGHT=\"23\" NOWRAP ALIGN=\"CENTER\">";
String SetUtil12         =
        "\t<TR>\n\t\t<TD WIDTH=\"4%\" HEIGHT=\"23\"><P ALIGN=RIGHT>0</TD>\n\t\t<TD WIDTH=\"7%\" HEIGHT=\"23\"></TD>\n"
        "\t\t<TD WIDTH=\"4%\" HEIGHT=\"23\" NOWRAP ALIGN=\"CENTER\">\n";
String SetUtil13         =
        "\t\t<INPUT TYPE=\"checkbox\" NAME=\"DI_15\" disabled=\"disabled\" ";
String SetUtil14         =
        "></TD>\n\t</TR>\n\t<TR>\n\t\t<TD COLSPAN=\"19\" HEIGHT=\"5\"><HR ALIGN=LEFT></TD>\n\t</TR>\n"
        "\t<TR>\n\t\t<TD ROWSPAN=\"3\"  WIDTH=\"25%\">Coil(01)CoilStatus</TD>\n"
        "\t\t<TD COLSPAN=\"2\" HEIGHT=\"23\"></TD>\n\t\t<TD WIDTH=\"4%\" HEIGHT=\"23\" NOWRAP ALIGN=\"CENTER\">";
String SetUtil15         =
        "\t\t<TD ROWSPAN=\"2\"  WIDTH=\"4%\"><P ALIGN=RIGHT>0</TD>\n"
        "\t\t<TD WIDTH=\"7%\" HEIGHT=\"23\"><P ALIGN=RIGHT>T</TD>\n\t\t<TD WIDTH=\"4%\" HEIGHT=\"23\" NOWRAP ALIGN=\"CENTER\">\n";
String SetUtil16         =
        "\t</TR>\n\t<TR>\n\t\t<TD WIDTH=\"7%\" HEIGHT=\"23\" ALIGN=\"RIGHT\">F</TD>\n"
        "\t\t<TD WIDTH=\"4%\" HEIGHT=\"23\" NOWRAP ALIGN=\"CENTER\">\n";
String SetUtil17         =
        "\t</TR>\n\t<TR>\n\t\t<TD COLSPAN=\"2\" HEIGHT=\"23\"></TD><TD COLSPAN=\"16\" HEIGHT=\"23\"></TD>\n"
        "\t</TR>\n\t<TR>\n\t\t<TD COLSPAN=\"19\" HEIGHT=\"30\"><HR ALIGN=LEFT></TD>\n\t</TR>\n"
        "\t<TR>\n\t\t<TD ROWSPAN=\"12\"  WIDTH=\"25%\">IR(04)InputRegistor</TD>\n";
String SetUtil18         =
        "\t\t<TD COLSPAN=\"2\" ALIGN=\"CENTER\">\n\t\tVstr</TD><TD COLSPAN=\"16\">";
String SetUtil19         =
        "</TD>\n\t\t</TR>\n\t\t<TR>\n"
        "\t\t<TD COLSPAN=\"2\" ALIGN=\"CENTER\">\n\t\tPstr</TD><TD COLSPAN=\"16\">";
String SetUtil20        =
        "</TD>\n\t\t</TR>\n\t\t<TR>\n"
        "\t\t<TD COLSPAN=\"2\" ALIGN=\"CENTER\">\n\t\tSver</TD><TD WIDTH=\"4%\">";
String SetUtil21        =
        "</TD>\n\t</TR></tbody>\n</TABLE>\n"
        "</BLOCKQUOTE></BLOCKQUOTE>\n</form>\n</BODY></html>";
//-----------------------
void paramParse(String reqStr){
        int Code;
        int len         = reqStr.length();
        char* HTTP_c    = (char*)malloc(len+1);
        reqStr.toCharArray(HTTP_c, len);
        char bufff[10];
        //DT1 mac[0]            HEX
        int indexS      = reqStr.indexOf("DT1=");
        int indexE      = reqStr.indexOf("&",indexS);
        int k = 0;
        char c;
        for(int j = indexS;j<=indexE;j++){
                c = reqStr.charAt(j);
                if (c == '='){
                        int m = indexE - indexS;
                        for (int l = 1; l < m;l++){
                                c = reqStr.charAt(j+l);
                                if(c == '&'){
                                        bufff[k]='\0';                          //Serial.println(bufff);
                                        mac[0]=int(strtol(bufff, NULL, 16));    //Serial.print(bufff);Serial.println(mac[0]);
                                        break; 
                                }else{
                                        bufff[k++] = c;
                                }
                        }
                        break;
                }
        }
        //DT2 mac[1]            HEX
        indexS = reqStr.indexOf("DT2=");
        indexE = reqStr.indexOf("&",indexS);
        k = 0;
        for(int j = indexS;j<=indexE;j++){
                c = reqStr.charAt(j);
                 if (c == '='){
                        int m = indexE - indexS;
                        for (int l = 1; l < m;l++){
                                c = reqStr.charAt(j+l);
                                if(c == '&'){
                                        bufff[k]='\0';                          //Serial.println(bufff);
                                        mac[1]=int(strtol(bufff, NULL, 16));    //Serial.print(bufff);Serial.println(mac[1]);
                                        break; 
                                }else{
                                        bufff[k++] = c;
                                }
                        }
                        break;
                }        
        }
        //DT3 mac[2]            HEX
        indexS = reqStr.indexOf("DT3=");                                        //Serial.print("Pos=");Serial.println(indexS);
        indexE = reqStr.indexOf("&",indexS);                                    //Serial.print("Pos=");Serial.println(indexE);
        k = 0;
        for(int j = indexS;j<=indexE;j++){
                c = reqStr.charAt(j);                                           //Serial.println(c);
                if (c == '='){
                        int m = indexE - indexS;                                //Serial.print("m=");Serial.println(m);
                        for (int l = 1; l < m;l++){
                                c = reqStr.charAt(j+l);
                                if(c == '&'){
                                        bufff[k]='\0';                          //Serial.println(bufff);
                                        mac[2]=int(strtol(bufff, NULL, 16));    //Serial.print(bufff);Serial.println(mac[2]);
                                        break; 
                                }else{
                                        bufff[k++] = c;
                                }
                        }
                        break;
                 }
        }
        //DT4 mac[3]            HEX
        indexS = reqStr.indexOf("DT4=");
        indexE = reqStr.indexOf("&",indexS);
        k = 0;
        for(int j = indexS;j<=indexE;j++){
                c = reqStr.charAt(j);
                 if (c == '='){
                        int m = indexE - indexS;
                        for (int l = 1; l < m;l++){
                                c = reqStr.charAt(j+l);
                                if(c == '&'){
                                        bufff[k]='\0';                          //Serial.println(bufff);
                                        mac[3]=int(strtol(bufff, NULL, 16));    //Serial.print(bufff);Serial.println(mac[3]);
                                        break; 
                                }else{
                                        bufff[k++] = c;
                                }
                        }
                        break;
                }
        }
        //DT5 mac[4]            HEX
        indexS = reqStr.indexOf("DT5=");
        indexE = reqStr.indexOf("&",indexS);
        k = 0;
        for(int j = indexS;j<=indexE;j++){
                c = reqStr.charAt(j);
                if (c == '='){
                        int m = indexE - indexS;
                        for (int l = 1; l < m;l++){
                                c = reqStr.charAt(j+l);
                                if(c == '&'){
                                        bufff[k]='\0';                          //Serial.println(bufff);
                                        mac[4]=int(strtol(bufff, NULL, 16));    //Serial.print(bufff);Serial.println(mac[4]);
                                        break; 
                                }else{
                                        bufff[k++] = c;
                                }
                        }
                        break;
                }        
        }
        //DT6 mac[5]            HEX
        indexS = reqStr.indexOf("DT6=");
        indexE = reqStr.indexOf("&",indexS);
        k = 0;
        for(int j = indexS;j<=indexE;j++){
                c = reqStr.charAt(j);
                if (c == '='){
                        int m = indexE - indexS;
                        for (int l = 1; l < m;l++){
                                c = reqStr.charAt(j+l);
                                if(c == '&'){
                                        bufff[k]='\0';                          //Serial.println(bufff);
                                        mac[5]=int(strtol(bufff, NULL, 16));    //Serial.print(bufff);Serial.println(mac[5]);
                                        break; 
                                }else{
                                        bufff[k++] = c;
                                }
                        }
                        break;
                }        
        }
        //DT7 ip[0]             DEC
        indexS = reqStr.indexOf("DT7=");
        indexE = reqStr.indexOf("&",indexS);
        k = 0;
        for(int j = indexS;j<=indexE;j++){
                c = reqStr.charAt(j);
                if (c == '='){
                        int m = indexE - indexS;
                        for (int l = 1; l < m;l++){
                                c = reqStr.charAt(j+l);
                                if(c == '&'){
                                        bufff[k]='\0';                          //Serial.println(bufff);
                                        ip[0]=int(strtol(bufff, NULL, 10));     //Serial.print(bufff);Serial.println(ip[0]);
                                        break; 
                                }else{
                                        bufff[k++] = c;
                                }
                        }
                        break;
                }
        }
        //DT8 ip[1]             DEC
        indexS = reqStr.indexOf("DT8=");
        indexE = reqStr.indexOf("&",indexS);
        k = 0;
        for(int j = indexS;j<=indexE;j++){
                c = reqStr.charAt(j);
                if (c == '='){
                        int m = indexE - indexS;
                        for (int l = 1; l < m;l++){
                                c = reqStr.charAt(j+l);
                                if(c == '&'){
                                        bufff[k]='\0';                          //Serial.println(bufff);
                                        ip[1]=int(strtol(bufff, NULL, 10));     //Serial.print(bufff);Serial.println(ip[1]);
                                        break; 
                                }else{
                                        bufff[k++] = c;
                                }
                        }
                        break;
                }
        }
        //DT9 ip[2]             DEC
        indexS = reqStr.indexOf("DT9=");
        indexE = reqStr.indexOf("&",indexS);
        k = 0;
        for(int j = indexS;j<=indexE;j++){
                c = reqStr.charAt(j);
                if (c == '='){
                        int m = indexE - indexS;
                        for (int l = 1; l < m;l++){
                                c = reqStr.charAt(j+l);
                                if(c == '&'){
                                        bufff[k]='\0';                          //Serial.println(bufff);
                                        ip[2]=int(strtol(bufff, NULL, 10));     //Serial.print(bufff);Serial.println(ip[2]);
                                        break; 
                                }else{
                                        bufff[k++] = c;
                                }
                        }
                        break;
                }        
        }
        //DT10 ip[3]            DEC
        indexS = reqStr.indexOf("DT10=");
        indexE = reqStr.indexOf("&",indexS);
        k = 0;
        for(int j = indexS;j<=indexE;j++){
                c = reqStr.charAt(j);
                if (c == '='){
                        int m = indexE - indexS;
                        for (int l = 1; l < m;l++){
                                c = reqStr.charAt(j+l);
                                if(c == '&'){
                                        bufff[k]='\0';                          //Serial.println(bufff);
                                        ip[3]=int(strtol(bufff, NULL, 10));     //Serial.print(bufff);Serial.println(ip[3]);
                                        break; 
                                }else{
                                        bufff[k++] = c;
                                }
                        }
                        break;
                }
        }
        //DT11 subnet[0]        DEC
        indexS = reqStr.indexOf("DT11=");
        indexE = reqStr.indexOf("&",indexS);
        k = 0;
        for(int j = indexS;j<=indexE;j++){
                c = reqStr.charAt(j);
                 if (c == '='){
                        int m = indexE - indexS;
                        for (int l = 1; l < m;l++){
                                c = reqStr.charAt(j+l);
                                if(c == '&'){
                                        bufff[k]='\0';                          //Serial.println(bufff);
                                        subnet[0]=int(strtol(bufff, NULL, 10)); //Serial.print(bufff);Serial.println(subnet[0]);
                                        break; 
                                }else{
                                        bufff[k++] = c;
                                }
                        }
                        break;
                }        
        }
        //DT12 subnet[1]        DEC
        indexS = reqStr.indexOf("DT12=");
        indexE = reqStr.indexOf("&",indexS);
        k = 0;
        for(int j = indexS;j<=indexE;j++){
                c = reqStr.charAt(j);
                if (c == '='){
                        int m = indexE - indexS;
                        for (int l = 1; l < m;l++){
                                c = reqStr.charAt(j+l);
                                if(c == '&'){
                                        bufff[k]='\0';                          //Serial.println(bufff);
                                        subnet[1]=int(strtol(bufff, NULL, 10)); //Serial.print(bufff);Serial.println(subnet[1]);
                                        break; 
                                }else{
                                        bufff[k++] = c;
                                }
                        }
                        break;
                }        
        }
        //DT13 subnet[2]        DEC
        indexS = reqStr.indexOf("DT13=");
        indexE = reqStr.indexOf("&",indexS);
        k = 0;
        for(int j = indexS;j<=indexE;j++){
                c = reqStr.charAt(j); //Serial.println(bufff);
                if (c == '='){
                        int m = indexE - indexS;
                        for (int l = 1; l < m;l++){
                                c = reqStr.charAt(j+l);
                                if(c == '&'){
                                        bufff[k]='\0';                          //Serial.println(bufff);
                                        subnet[2]=int(strtol(bufff, NULL, 10)); //Serial.print(bufff);Serial.println(subnet[2]);
                                        break; 
                                }else{
                                        bufff[k++] = c;
                                }
                        }
                        break;
                }        
        }
        //DT14 subnet[3]        DEC
        indexS = reqStr.indexOf("DT14=");
        indexE = reqStr.indexOf("&",indexS);
        k = 0;
        for(int j = indexS;j<=indexE;j++){
                c = HTTP_req.charAt(j);
                 if (c == '='){
                        int m = indexE - indexS;
                        for (int l = 1; l < m;l++){
                                c = reqStr.charAt(j+l);
                                if(c == '&'){
                                        bufff[k]='\0';                          //Serial.println(bufff);
                                        subnet[3]=int(strtol(bufff, NULL, 10)); //Serial.print(bufff);Serial.println(subnet[3]);
                                        break; 
                                }else{
                                        bufff[k++] = c;
                                }
                        }
                        break;
                }        
        }
        //DT15 gateway[0]       DEC
        indexS = reqStr.indexOf("DT15=");
        indexE = reqStr.indexOf("&",indexS);
        k = 0;
        for(int j = indexS;j<=indexE;j++){
                c = reqStr.charAt(j);
                if (c == '='){
                        int m = indexE - indexS;
                        for (int l = 1; l < m;l++){
                                c = reqStr.charAt(j+l);
                                if(c == '&'){
                                        bufff[k]='\0';                          //Serial.println(bufff);
                                        gateway[0]=int(strtol(bufff, NULL, 10));//Serial.print(bufff);Serial.println(gateway[0]);
                                        break; 
                                }else{
                                        bufff[k++] = c;
                                }
                        }
                        break;
                }        
        }
        //DT16 gateway[1]       DEC
        indexS = reqStr.indexOf("DT16=");
        indexE = reqStr.indexOf("&",indexS);
        k = 0;
        for(int j = indexS;j<=indexE;j++){
                c = reqStr.charAt(j);
                if (c == '='){
                        int m = indexE - indexS;
                        for (int l = 1; l < m;l++){
                                c = reqStr.charAt(j+l);
                                if(c == '&'){
                                        bufff[k]='\0';                          //Serial.println(bufff);
                                        gateway[1]=int(strtol(bufff, NULL, 10));//Serial.print(bufff);Serial.println(gateway[1]);
                                        break; 
                                }else{
                                        bufff[k++] = c;
                                }
                        }
                        break;
                }        
        }
        //DT17 gateway[2]       DEC
        indexS = reqStr.indexOf("DT17=");
        indexE = reqStr.indexOf("&",indexS);
        k = 0;
        for(int j = indexS;j<=indexE;j++){
                c = reqStr.charAt(j);
                if (c == '='){
                        int m = indexE - indexS;
                        for (int l = 1; l < m;l++){
                                c = reqStr.charAt(j+l);
                                if(c == '&'){
                                        bufff[k]='\0';                          //Serial.println(bufff);
                                        gateway[2]=int(strtol(bufff, NULL, 10));//Serial.print(bufff);Serial.println(gateway[2]);
                                        break; 
                                }else{
                                        bufff[k++] = c;
                                }
                        }
                        break;
                }        
        }
        //DT18 gateway[3]       DEC
        indexS = reqStr.indexOf("DT18=");
        indexE = reqStr.indexOf("&",indexS);
        k = 0;
        for(int j = indexS;j<=indexE;j++){
                c = reqStr.charAt(j);
                if (c == '='){
                        int m = indexE - indexS;
                        for (int l = 1; l < m;l++){
                                c = reqStr.charAt(j+l);
                                if(c == '&'){
                                        bufff[k]='\0';                          //Serial.println(bufff);
                                        gateway[3]=int(strtol(bufff, NULL, 10));//Serial.print(bufff);Serial.println(gateway[3]);
                                        break; 
                                }else{
                                        bufff[k++] = c;
                                }
                        }
                        break;
                }
        }
        //DT19 NTPip[0]       DEC
        indexS = reqStr.indexOf("DT19=");
        indexE = reqStr.indexOf("&",indexS);
        k = 0;
        for(int j = indexS;j<=indexE;j++){
                c = reqStr.charAt(j);
                if (c == '='){
                        int m = indexE - indexS;
                        for (int l = 1; l < m;l++){
                                c = reqStr.charAt(j+l);
                                if(c == '&'){
                                        bufff[k]='\0';                          //Serial.println(bufff);
                                        NTPip[0]=int(strtol(bufff, NULL, 10));  //Serial.print(bufff);Serial.println(NTPip[0]);
                                        break; 
                                }else{
                                        bufff[k++] = c;
                                }
                        }
                        break;
                }        
        }
        //DT120 NTPip[1]       DEC
        indexS = reqStr.indexOf("DT20=");
        indexE = reqStr.indexOf("&",indexS);
        k = 0;
        for(int j = indexS;j<=indexE;j++){
                c = reqStr.charAt(j);
                if (c == '='){
                        int m = indexE - indexS;
                        for (int l = 1; l < m;l++){
                                c = reqStr.charAt(j+l);
                                if(c == '&'){
                                        bufff[k]='\0';                          //Serial.println(bufff);
                                        NTPip[1]=int(strtol(bufff, NULL, 10));  //Serial.print(bufff);Serial.println(NTPip[1]);
                                        break; 
                                }else{
                                        bufff[k++] = c;
                                }
                        }
                        break;
                }        
        }
        //DT21 NTPip[2]       DEC
        indexS = reqStr.indexOf("DT21=");
        indexE = reqStr.indexOf("&",indexS);
        k = 0;
        for(int j = indexS;j<=indexE;j++){
                c = reqStr.charAt(j);
                if (c == '='){
                        int m = indexE - indexS;
                        for (int l = 1; l < m;l++){
                                c = reqStr.charAt(j+l);
                                if(c == '&'){
                                        bufff[k]='\0';                          //Serial.println(bufff);
                                        NTPip[2]=int(strtol(bufff, NULL, 10));  //Serial.print(bufff);Serial.println(NTPip[2]);
                                        break; 
                                }else{
                                        bufff[k++] = c;
                                }
                        }
                        break;
                }        
        }
        //DT22 NTPip[3]       DEC
        indexS = reqStr.indexOf("DT22=");
        indexE = reqStr.indexOf("&",indexS);
        k = 0;
        for(int j = indexS;j<=indexE;j++){
                c = reqStr.charAt(j);
                if (c == '='){
                        int m = indexE - indexS;
                        for (int l = 1; l < m;l++){
                                c = reqStr.charAt(j+l);
                                if(c == '&'){
                                        bufff[k]='\0';                          //Serial.println(bufff);
                                        NTPip[3]=int(strtol(bufff, NULL, 10));  //Serial.print(bufff);Serial.println(NTPip[3]);
                                        break; 
                                }else{
                                        bufff[k++] = c;
                                }
                        }
                        break;
                }
        }
        //DT23 timezone       float
        indexS = reqStr.indexOf("DT23=");
        indexE = reqStr.indexOf("&",indexS);
        k = 0;
        for(int j = indexS;j<=indexE;j++){
                c = reqStr.charAt(j);
                if (c == '='){
                        int m = indexE - indexS;
                        for (int l = 1; l < m;l++){
                                c = reqStr.charAt(j+l);
                                if(c == '&'){
                                        bufff[k]='\0';                          //Serial.println(bufff);
                                        timezone =int((strtof(bufff, NULL)*10));
                                        break; 
                                }else{
                                        bufff[k++] = c;
                                }
                        }
                        break;
                }
        }
}
//------------------PrintSetUpPage
void PrintSetUpPage( EthernetClient client){
        client.println(OK_200);
        client.print(SetPage1);
        client.print(vers);
        client.print(SetPage2);
        client.print(vers);
        client.print(SetPage3);
        client.print(mac[0],HEX);
        client.print(SetPage4);
        client.print(mac[1],HEX);
        client.print(SetPage5);
        client.print(mac[2],HEX);
        client.print(SetPage6);
        client.print(mac[3],HEX);
        client.print(SetPage7);
        client.print(mac[4],HEX);
        client.print(SetPage8);
        client.print(mac[5],HEX);
        client.print(SetPage9);
        client.print(ip[0],DEC);
        client.print(SetPage10);
        client.print(ip[1],DEC);
        client.print(SetPage11);
        client.print(ip[2],DEC);
        client.print(SetPage12);
        client.print(ip[3],DEC);
        client.print(SetPage13);
        client.print(subnet[0],DEC);
        client.print(SetPage14);
        client.print(subnet[1],DEC);
        client.print(SetPage15);
        client.print(subnet[2],DEC);
        client.print(SetPage16);
        client.print(subnet[3],DEC);
        client.print(SetPage17);
        client.print(gateway[0],DEC);
        client.print(SetPage18);
        client.print(gateway[1],DEC);
        client.print(SetPage19);
        client.print(gateway[2],DEC);
        client.print(SetPage20);
        client.print(gateway[3],DEC);
        client.print(SetPage21);
        client.print(NTPip[0],DEC);
        client.print(SetPage22);
        client.print(NTPip[1],DEC);
        client.print(SetPage23);
        client.print(NTPip[2],DEC);
        client.print(SetPage24);
        client.print(NTPip[3],DEC);
        client.print(SetPage25);
        client.print(timezone,2);
        client.print(SetPage26);
        client.print(IPAddressStr);
        client.print(SetPage27);
}
//-------------PrintUtilPage
void PrintUtilPage( EthernetClient client){
        sprintf(DateTimeStr,"%04u/%02u/%02u %02u:%02u:%02u",year(), month(), day()-1,hour(), minute(), second()); 
        client.println(OK_200);
        client.print(SetUtil1);
        client.print(titleStr);
        client.print(SetUtil2);
        client.print(titleStr);
        client.print(SetUtil3);
        client.print(IPAddressStr);
        client.print(SetUtil4);
        client.print(FVirsion);
        client.print(SetUtil5);
        client.print(SVirsion);
        client.print(SetUtil6);
        client.print(MacAddressStr);
        client.print(SetUtil7);
        client.print(IPAddressStr);
        client.print(SetUtil8);
        client.print(SubnetMaskStr);
        client.print(SetUtil9);
        client.print(DateTimeStr);
        client.print(SetUtil10);
        sprintf(buffer,"%d[sec]",OperatingTime);
        client.print(buffer);
        client.print(SetUtil11);
        for (int i = 0;i<15;i++){
                sprintf(buffer,"%x</TD>\n\t\t<TD WIDTH=\"4%%\" HEIGHT=\"23\" ALIGN=\"CENTER\">",i);
                client.print(buffer);
        }
        sprintf(buffer,"%x</TD>\n\t</TR>\n",15);
        client.print(buffer);
        client.print(SetUtil12);
        for (int i = 0;i<15;i++){
                sprintf(buffer,"\t\t<INPUT TYPE=\"checkbox\" NAME=\"DI_%d\" disabled=\"disabled\" ",i);
                client.print(buffer);
                if(Mb.GetBit(MB_FC_READ_DISCRETE_INPUT,i) == true) client.print(F("CHECKED"));
                client.print(F("></TD>\n\t\t<TD WIDTH=\"4%\" HEIGHT=\"23\" ALIGN=\"CENTER\">\n"));
        }
        client.print(SetUtil13);
        if(Mb.GetBit(MB_FC_READ_DISCRETE_INPUT,15) == true) client.print(F("CHECKED"));
        client.print(SetUtil14);
        for (int i = 0;i<15;i++){
                sprintf(buffer,"%x</TD>\n\t\t<TD WIDTH=\"4%%\" HEIGHT=\"23\" ALIGN=\"CENTER\">",i);
                client.print(buffer);
        }
        sprintf(buffer,"%x</TD>\n\t</TR>\n",15);
        client.print(buffer);
        client.print(SetUtil15);
        for (int i = 0;i<16;i++){
                sprintf(buffer,"\t\t<INPUT TYPE=\"radio\"  NAME=\"CL_%02x\" disabled=\"disabled\" ",i);
                client.print(buffer);
                if(Mb.GetBit(MB_FC_READ_COILS,i) == true) client.print(F("CHECKED"));
                client.print(F("></TD>\n"));
                if(i<15) client.print(F("\t\t<TD WIDTH=\"4%\" HEIGHT=\"23\" ALIGN=\"CENTER\">\n"));
        }
        client.print(SetUtil16);
        for (int i = 0;i<16;i++){
                sprintf(buffer,"\t\t<INPUT TYPE=\"radio\"  NAME=\"CL_%02x\" disabled=\"disabled\" ",i);
                client.print(buffer);
                if(Mb.GetBit(MB_FC_READ_COILS,i) == false) client.print(F("CHECKED"));
                client.print(F("></TD>\n"));
                if(i<15) client.print(F("\t\t<TD WIDTH=\"4%\" HEIGHT=\"23\" ALIGN=\"CENTER\">\n"));
        }
        client.print(SetUtil17);
        for (int i = 0;i<8;i++){
                sprintf(buffer,"\t\t<TD WIDTH=\"4%%\" ALIGN=\"RIGHT\"  HEIGHT=\"23\">%d</TD>\n\t\t<TD WIDTH=\"4%%\" HEIGHT=\"23\"></TD><TD COLSPAN=\"16\" HEIGHT=\"23\">%d</TD>\n\t</TR>\n\t<TR>\n",i,Mb.MbInputData[i]);
                client.print(buffer);
        }
        client.print(SetUtil18);
        for (int i = 0;i<16;i++){
                word q  = Mb.MbInputData[i+8];
                client.print(char(q/256));
                client.print(char(q%256));
        }
        client.print(SetUtil19);
        for (int i = 0;i<16;i++){
                word q  = Mb.MbInputData[i+24];
                client.print(char(q/256));
                client.print(char(q%256));
        }
        client.print(SetUtil20);
        char    mainVer,minorVer,Rev;
        sscanf(SVirsion,"%1s.%1s.%1s",&mainVer,&minorVer,&Rev);
        client.print(mainVer);
        client.print(F("</TD><TD WIDTH=\"4%\">.</TD><TD WIDTH=\"4%\">"));
        client.print(minorVer);
        client.print(F("</TD><TD WIDTH=\"4%\">.</TD><TD WIDTH=\"4%\">"));
        client.print(Rev);
        client.print(F("</TD><TD COLSPAN=\"11\"></TD>\n\t\t</TR>\n\t\t<TR>\n"));
        client.print(F("\t\t<TD COLSPAN=\"2\" ALIGN=\"CENTER\">\n\t\tFver</TD><TD WIDTH=\"4%\">"));
        sscanf(FVirsion,"%1s.%1s.%1s",&mainVer,&minorVer,&Rev);
        client.print(mainVer);
        client.print(F("</TD><TD WIDTH=\"4%\">.</TD><TD WIDTH=\"4%\">"));
        client.print(minorVer);
        client.print(F("</TD><TD WIDTH=\"4%\">.</TD><TD WIDTH=\"4%\">"));
        client.print(Rev);
        client.print(F("</TD><TD COLSPAN=\"11\"></TD>\n\t\t</TR>\n\t\t<TR>\n"));
        client.print(F("\t\t<TD COLSPAN=\"19\" HEIGHT=\"23\"><HR ALIGN=LEFT></TD>\n\t</TR>\n"));
        //HR
        client.print(F("\t<TR>\n\t<TD ROWSPAN=\"16\"  WIDTH=\"25%\">HR(03)HolingRegistor</TD>\n"));
        for (int i = 0;i<16;i++){
                sprintf(buffer,"\t\t<TD WIDTH=\"4%%\" ALIGN=\"RIGHT\"  HEIGHT=\"23\">%d</TD>\n\t\t<TD WIDTH=\"4%%\" HEIGHT=\"23\"></TD>\n\t\t<TD COLSPAN=\"16\" HEIGHT=\"23\">%d",i,Mb.MbHoldData[i]);
                client.print(buffer);
                if(i<15) client.print(F("</TD>\n\t</TR>\n\t<TR>\n"));
        }
        client.print(SetUtil21);
}
//-------------WebPageTop
void pageIntroduction( EthernetClient client){
        client.println(OK_200);
        client.print(WebTopPage1);
        client.print(webTitle);
        client.print(WebTopPage11);
        client.print(webTitle);
        client.print(WebTopPage12);
        client.print(IPAddressStr);
        client.print(WebTopPage2);
        client.print(topMenu1);
        client.print(WebTopPage21);
        client.print(IPAddressStr);
        client.println(WebTopPage3);
        client.print(topMenu2);
        client.println(WebTopPage31);
        client.stop();
}
//-------------LoadUtilsJS
void pageLoadUtilsJS( EthernetClient client){
        client.println(OK_200);
        client.println(LoadUtilsJS1);                                     //バッファサイズを考慮して3分割しています。
        client.println(LoadUtilsJS2);
        client.println(LoadUtilsJS3);
        client.stop();
}
//------------PrintResponse404
void PrintResponse404( EthernetClient client ){
        client.println(NG_404);
        client.stop();
}
//--------------------------
void checkWebPage( EthernetClient client){
        if(Serial)      Serial.println(F("new webClient"));
        boolean restart = false;
        if (client) {
                // HTTPリクエスト空行(\r\n\r\n)で終わる。ので、空行を探す。
                boolean currentLineIsBlank = true;
                while (client.connected()) {
                        if( !client.available() ){
                                if(Serial)    Serial.print(F("."));
                                continue;
                        }
                        char c = client.read();
                        HTTP_req += c;
                        if(Serial)    Serial.print(c);
                        if( c == '\n'  && currentLineIsBlank ){                 // 空行発見。HTTPリクエスト終了。レスポンスを返す。
                                //Serial.print("RecieveLength=");Serial.println(HTTP_req.length());
                                if (HTTP_req.indexOf("/?")>0) {                 //setup?と/?を区別する必要がある
                                        if(Serial)    Serial.print(F("CASE1:"));Serial.print(gLoopCount);
                                        /*if(gLoopCount % 2){
                                                digitalWrite(LED_BUILTIN,HIGH); //Serial.println(F(" H"));
                                        }else{
                                                digitalWrite(LED_BUILTIN,LOW);  //Serial.println(F(" L"));
                                        }*/
                                        delay(100);
                                        HTTP_req = "";
                                        break;
                                }else if(HTTP_req.indexOf("setup")>0){
                                        //setup頁の場合 SBMが含まれていればEEPROMに書込、そうで無ければ表示のみ
                                        //setup?SBM=1&DT1=0&DT2=8&DT3=DC&DT4=54&DT5=4D&DT6=D0&DT1=0&DT2=8&DT3=220&DT4=84&DT5=77&DT6=208&DT7=192&DT8=168&DT9=0&DT10=200&DT11=255&DT12=255&DT13=255&DT14=0&DT15=192&DT16=168&DT17=0&DT18=1
                                        //TextFinderを使うとHTMLの切り出しは比較的容易これをSTRING型のままどう扱うか?
                                        if(Serial)    Serial.print(F("CASE2:"));Serial.println(gLoopCount);
                                        if (HTTP_req.indexOf("SBM")>0){
                                                //Serial.println(F("Found_SBM"));
                                                if(Serial)    Serial.print(F("CASE3:"));Serial.println(gLoopCount);
                                                paramParse(HTTP_req);
                                                // すべてのデータを取得したので、EEPROMに保存します。
                                                EEPROM.begin(512);
                                                WriteID();
                                                //データがEEPROMに書き込まれている場合は、arduinoをリセットする必要があります。
                                                //読込直す
                                                //int idcheck = EEPROM.read(256);
                                                int idcheck     =       EEPROM[256];
                                                if(Serial)    Serial.print(F("R_ID="));Serial.println(idcheck,HEX);
                                                if (idcheck == ID){
                                                        //idがIDと同じ値の場合、
                                                        //これは、このスケッチがシールドを設定するために使用されたことを意味します。
                                                        //EERPOMの値を読み取ってシールドを設定します。
                                                        ReadID();
                                                }
                                                EEPROM.end();
                                                //ハードウェアリセットボタンを使用する必要があります
                                                HTTP_req = "";
                                                client.stop();
                                                delay(1000);
                                                watchdog_reboot(0,0,1);
                                                break;
                                        }else if(HTTP_req.indexOf("setup1")>0){
                                                if(Serial)      Serial.println(F("setup1"));
                                                PrintSetUpPage(client);
                                                HTTP_req = "";
                                                break;
                                        }else if(HTTP_req.indexOf("setup2")>0){
                                                if(Serial)      Serial.println(F("setup2"));
                                                PrintUtilPage(client);
                                                HTTP_req = "";
                                                break;
                                        }else if(HTTP_req.indexOf("setup3")>0){
                                                if(Serial)      Serial.println(F("setup3"));
                                                //pageLoadUtilsJS(client);
                                                HTTP_req = "";
                                                break;
                                        }else if(HTTP_req.indexOf("setup9")>0){
                                                if(Serial)      Serial.println(F("setup9"));
                                                pageIntroduction(client);
                                                HTTP_req = "";
                                                break;
                                        }else{
                                                if(Serial)      Serial.print(F("CASE404-1"));
                                                pageIntroduction(client);
                                                HTTP_req = "";
                                                break;
                                        }
                                }else if(HTTP_req.indexOf("\n")>0) {
                                        if(Serial)      Serial.println(F("CASE4"));
                                        pageIntroduction(client);
                                        HTTP_req = "";
                                        break;
                                }else if(HTTP_req.indexOf("/index")>0) {
                                        if(Serial)      Serial.println(F("CASE5"));
                                        pageIntroduction(client);
                                        HTTP_req = "";
                                        break;
                                }else{
                                        if(Serial)      Serial.print(F("CASE404-2"));
                                        PrintResponse404(client);
                                        HTTP_req = "";
                                        break;
                                }
                                HTTP_req = "";
                                break;                          // ループを抜ける
                        }
                        if(c ==  '\n'){                         // 新しい行の始まり。
                                currentLineIsBlank = true;
                        } else if(c !=  '\r' ){                 // この行は空行ではなかった。
                                currentLineIsBlank = false;
                        }
                }
                delay(1);
                client.stop();
        }     
}
//--------------
void setup() {
        Serial.begin(BAUDRATE);
        /*
        while (!Serial) {
                ; // シリアルポートが接続されるのを待ちます。シリアルモニタを寄贈するまで待機します。
        }
        
        Serial.println("Start Ethernet Modbus TCP Example");
        */
        pinMode(LED_BUILTIN, OUTPUT);
        SPI.setSCK(SPI_SCK);
        SPI.setRX(SPI_RX);
        SPI.setTX(SPI_TX);
        SPI.setCS(SPI_CS);
        SPI.begin(); 
        //Ethernet3で使用可能なAPI
        pinMode(SPI_CS, OUTPUT);                                                //NIC_CS出力設定
        Ethernet.setCsPin(SPI_CS);                                              //NIC_CSアサイン
        Ethernet.setRstPin(NICReset);                                           //NIC_RSTアサイン
        //NICリセット処理
        pinMode(NICReset, OUTPUT);
        digitalWrite(NICReset, LOW);
        delay(10);                                                              //10msecパルス幅で初期化
        digitalWrite(NICReset, HIGH);
        // start Ethernet and UDP
        LANSetup();       
        Ethernet.begin(mac, ip);
        delay(100);
        Serial.print(F("My IP address: "));Serial.println(Ethernet.localIP());  // print your local IP address:
        Udp.begin(NTPport);
        webServer.begin();
        //最初にNTPサーバから時刻を取得する
        sprintf(buf32,"%d.%d.%d.%d",NTPip[0],NTPip[1],NTPip[2],NTPip[3]);
        sendNTPpacket(buf32);                                                   // NTPパケットをタイムサーバーに送信します
        delay(1000); 
        gRTCOK = parseNTPpacket();
        tm1637.init();
        tm1637.set(BRIGHT_TYPICAL);                                             //BRIGHT_TYPICAL = 2,BRIGHT_DARKEST = 0,BRIGHTEST = 7;
        //
        strip.begin();                                                          // INITIALIZE NeoPixel strip object (REQUIRED)
        strip.clear();                                                          // Turn OFF all pixels ASAP
        strip.setBrightness(BRIGHTNESS);
        // Fill along the length of the strip in various colors...
        strip.setPixelColor(0,255,0,0,0);                                      // Red
        strip.show();
        delay(1000);
        strip.setPixelColor(0,0,255,0,0);                                      // Green
        strip.show();
        delay(1000);
        strip.setPixelColor(0,0,0,255,0);                                      // Blue
        strip.show();
        delay(1000);
        strip.setPixelColor(0,0,0,0,255);                                      // True white (not RGB white)
        strip.show();
        delay(1000);
        //ModBusメモリ 初期化
        for(int i = 0;i<MbCoilDataLen;i++)      Mb.MbCoilData[i]=0x0000;        //メモリ初期化
        for(int i = 0;i<MbDiscreteDataLen;i++)  Mb.MbDiscreteData[i]=0;         //メモリ初期化
        for(int i = 0;i<MbHoldDataLen;i++)      Mb.MbHoldData[i]=0;             //メモリ初期化
        for(int i = 0;i<MbInputDataLen;i++)     Mb.MbInputData[i]=0;            //メモリ初期化
        //Serial.println(F("ModBusメモリ 初期化"));
        //出力LED初期化
        for (int i=0;i<DObits;i++){          
                Mb.SetBit(MB_FC_READ_COILS,i,false);                            //メモリマップはMb.MbData[0]
                pinMode(dOsPins[i],OUTPUT);
                digitalWrite(dOsPins[i], LOW);                                  //LEDはHIGHで点灯                            
        }
        //入力pin初期化
        for (int i=0;i<DIbits;i++){
                pinMode(dIsPins[i],INPUT);
                Mb.SetBit(MB_FC_READ_DISCRETE_INPUT,i,!digitalRead(dIsPins[i]));        //bit メモリマップはMb.MbData[1]
        }
        for (int i=0;i<AIbits;i++){
                Mb.MbInputData[i] = analogRead(aIsPins[i]);                     //U16
        }
        preShow = Mb.GetBit(MB_FC_READ_COILS,2);
        //マイクロ秒単位の間隔
        if (ITimer0.attachInterruptInterval(TIMER0_INTERVAL_MS * 500, TimerHandler0)){
                if(Serial){
                        Serial.print(F("Starting ITimer0 OK, millis() = ")); Serial.println(millis());
                }
        }else{
                if(Serial){
                        Serial.println(F("Can't set ITimer0. Select another freq. or timer"));
                }
        }
        watchdog_reboot(0,0,delay_ms);
        gPreTime        =       millis();
        if(Serial)      Serial.println(F("EndSetup"));
}
//-------------------
void loop() {
        //1秒のループ WDT8秒
        if (watchdog_caused_reboot()){
                if(Serial)    Serial.print("Rebooted by Watchdog!\n");
        }else{
                if(Serial)    Serial.print("Clean boot\n");
        }
        watchdog_update();
        // listen for incoming clients
        GetDeviceInfo();
        // start the Modbus TCP server
        gMBusConnect = Mb.MbsRun();                                             //SlaveServer
        Serial.print("gMBusConnect=");Serial.println(gMBusConnect);
        SetDeviceInfo();
        client          = webServer.available();                                //HTTP要求確認
        if(client)      checkWebPage(client);
        client.stop();
        gNowTime        = millis();
        gLoopTime       = gNowTime - gPreTime;
        gPreTime        = gNowTime;
}

MgsModbus.h

/*
 * 2021/04/23 T.Wanibe Retouch
 * 20191029 T.Wanibe 保持メモリを個別に持たないとうまくゆかない
 * 個別に4つのメモリを保持するように変更
 * 20191028 T.Wanibe 一般的なModbusデバイスとして構築出来るように
 * MgsModbusをレタッチすることにした。『ModbusPoll』とかLabVIEWの
 * Modbusライブラリを元に調査したところ、MgsModbusはスレーブサーバ
 * としてちゃんと機能するライブラリだと云う事が確認出来た。
 * STM32duinoとしてコンパイル出来ないライブラリが殆ど。ライブラリ側で
 * Arduinoしか意識していない為と思われる。
 * MgsModbusはシンプルであるが故にSTM32duinoでもコンパイルが通り実行
 * 可能となる。
 * が、アドレスマップがゼロベースであったり、4つのブロックの内Coilブロック
 * しかうまくアクセス出来ない点も確認出来た。
 * 一般的なModbusデバイスとして認識出来るように大胆なデバッグを実施する
 * ことにした。
 * まず、Localな扱いとした。inoと同じフォルダに配置すること。
 * Slave機能のコードのみ残して(Masterのコードは削除)
 * 
 * MgsModbus.h-Modbus TCPマスターおよびスレーブ用のArduinoライブラリ。
 * V-0.1.1著作権(C)2013 Marco Gerritse
 * Arduino 1.0で作成およびテスト済み
 * 
 * このライブラリは、
 *  MgsModbus.h-Modbus TCPマスターおよびスレーブ用のArduinoライブラリ。
 * を原点としています。
 * 
 * テストに使用される外部ソフトウェア:
 * ★Modbus Poll 
 *      Modbus Poll x64 version 9.1.0 Build 1286, self-installing
 * ★LabVIEW Modbusライブラリ     
 *      NI Modbus Library v1.1.5.39 by National Instruments
 * ??
 * このライブラリは、すべてのmodbusデータ(mbData []配列)に単一のメモリブロック
 * を使用します。
 * 16ビットアクセスまたはアクセスビットを介して、いくつかのmodbus機能を介して同じ
 * データに到達できます。 MbDataの長さは少なくとも1でなければなりません。
 * ●スレーブの場合、次のmodbus機能が実装されます:1、2、3、4、5、6、15、16
 * ●内部および外部アドレスは1ベースに修正しています。
 * ●EtherNetライブラリは『Ethernet3』を採用しています。W5500を安定して使用する為です。
 */

#include "Arduino.h"
#include <SPI.h>
#include <Ethernet3.h>
#ifndef MgsModbus_h
#define MgsModbus_h
#define MbCoilDataLen           2       // length of the MbCoilDataLen array (Equivalent16bit*2)
#define MbDiscreteDataLen       2       // length of the MbDiscreteDataLen array(Equivalent16bit*2)
#define MbHoldDataLen           64      // length of the MbHoldDataLen array
#define MbInputDataLen          40      // length of the MbInputDataLen array
#define MB_PORT                 502
enum MB_FC {
        MB_FC_NONE                     = 0,
        MB_FC_READ_COILS               = 1,
        MB_FC_READ_DISCRETE_INPUT      = 2,
        MB_FC_READ_REGISTERS           = 3,
        MB_FC_READ_INPUT_REGISTER      = 4,
        MB_FC_WRITE_COIL               = 5,
        MB_FC_WRITE_REGISTER           = 6,
        MB_FC_WRITE_MULTIPLE_COILS     = 15,
        MB_FC_WRITE_MULTIPLE_REGISTERS = 16
};
enum MB_XC {
        MB_XC_NONE                      = 0,
        MB_XC_Illegal_Function          = 1,
        MB_XC_Illegal_Data_Address      = 2,
        MB_XC_Illegal_Data_Value        = 3,
        MB_XC_Slave_Device_Failure      = 4,
        MB_XC_Acknowledge               = 5,
        MB_XC_Slave_Device_Busy         = 6,
        MB_XC_Negative_Acknowledge      = 7,
        MB_XC_Memory_Parity_Error       = 8,
        MB_XC_Gateway_Path_Unavailable  = 10,
        MB_XC_Gateway_Target_Failed     = 11
};
class MgsModbus
{
        public:
                // general
                MgsModbus();
                word MbCoilData[MbCoilDataLen];                 // memory block that holds all the modbus user data
                word MbDiscreteData[MbDiscreteDataLen];         // memory block that holds all the modbus user data
                word MbHoldData[MbHoldDataLen];                 // memory block that holds all the modbus user data
                word MbInputData[MbInputDataLen];               // memory block that holds all the modbus user data                
                boolean GetBit(MB_FC fc,word Number);
                boolean SetBit(MB_FC fc,word Number,boolean Data);       // returns true when the number is in the MbData range
                // modbus master
                //void Req(MB_FC FC, word Ref, word Count, word Pos);
                //void MbmRun();
                //IPAddress remSlaveIP;
                // modbus slave
                bool MbsRun();  
                word GetDataLen();
        private: 
                // general
                MB_FC SetFC(int fc);
                // modbus master
                //uint8_t MbmByteArray[260];                    // send and recieve buffer
                //MB_FC MbmFC;
                //int MbmCounter;
                //void MbmProcess();
                //word MbmPos;
                //word MbmBitCount;
                //modbus slave
                uint8_t MbsByteArray[260];                      // send and recieve buffer
                MB_FC MbsFC;
                MB_XC MbsXC;
};
#endif

MgsModbus.cpp

/* 
 *  2021/04/23 T.Wanibe Retouch
 */
#include "MgsModbus.h"
//
EthernetServer MbServer(MB_PORT);
EthernetClient MbmClient;
#define DEBUG   1
MgsModbus::MgsModbus()
{
}
char buf[32];
//****************** Recieve data for ModBusSlave ****************
//      2021/3/5 接続が有った場合はtrueをない場合はfalseを返すように変更
bool MgsModbus::MbsRun()
{ 
        bool    flagConnected   = false;
        MbsXC                   = MB_XC_NONE;
        //****************** Read from socket ****************
        EthernetClient client   = MbServer.available();
        flagConnected           = client.available();
        if(flagConnected){
                digitalWrite(LED_BUILTIN, LOW);
                delay(1);
                int i = 0;
                while(client.available()){
                        MbsByteArray[i] = client.read();
                        i++;
                }
                MbsFC = SetFC(MbsByteArray[7]);  //Byte 7 of request is FC
#if DEBUG
                Serial.print(F("\nREQUEST:"));
                for(int j = 0;j<i;j++){
                        sprintf(buf,"%02x ",MbsByteArray[j]);
                        Serial.print(buf);
                }
                Serial.println(F(""));
                digitalWrite(LED_BUILTIN, HIGH);
#endif                
        }
        int Start, WordDataLength, ByteDataLength, CoilDataLength, MessageLength;
        //SwitchCaseに変更しようとしたがコンパイルエラーが発生するので諦めた
        if(MbsFC == MB_FC_READ_COILS) {                                                 //****************** Read Coils (1) **********************
                Start           = word(MbsByteArray[8],MbsByteArray[9]);                //StartAddress確認
                CoilDataLength  = word(MbsByteArray[10],MbsByteArray[11]);              //データ長の確認
#if DEBUG
                sprintf(buf,"01StartADRS=%d Length=%d",Start,CoilDataLength);
                Serial.println(buf);
#endif  
                if((Start<0) || ((CoilDataLength + Start) > (MbCoilDataLen * 16))){
                        //Exception MB_XC_Illegal_Data_Address
                        MbsXC           = MB_XC_Illegal_Data_Address;
                        MbsByteArray[7] = 0x10 + MbsByteArray[7];
                        MbsByteArray[8] = MbsXC;
                        MessageLength = 9;
                }else{
                        ByteDataLength  = CoilDataLength / 8;
                        if(ByteDataLength * 8 < CoilDataLength) ByteDataLength++;      
                        CoilDataLength  = ByteDataLength * 8;
                        MbsByteArray[5] = ByteDataLength + 3;                           //Number of bytes after this one.
                        MbsByteArray[8] = ByteDataLength;                               //Number of bytes after this one (or number of bytes of data).
                        for(int i = 0; i < ByteDataLength ; i++){
                                MbsByteArray[9 + i] = 0;                                // To get all remaining not written bits zero
                                for(int j = 0; j < 8; j++){
                                        bitWrite(MbsByteArray[9 + i], j, GetBit(MB_FC_READ_COILS,Start + i * 8 + j));
                                }
                        }
                        MessageLength = ByteDataLength + 9;
                }      
                //
        }else if(MbsFC == MB_FC_READ_DISCRETE_INPUT) {                                  //****************** Read Coils (2) **********************
                Start           = word(MbsByteArray[8],MbsByteArray[9]);                //StartAddress確認
                CoilDataLength  = word(MbsByteArray[10],MbsByteArray[11]);              //データ長の確認
#if DEBUG
                sprintf(buf,"02StartADRS=%d Length=%d",Start,CoilDataLength);
                Serial.println(buf);
#endif
                if((Start<0) || ((CoilDataLength + Start) > (MbDiscreteDataLen * 16))){
                        //Exception MB_XC_Illegal_Data_Address
                        MbsXC           = MB_XC_Illegal_Data_Address;
                        MbsByteArray[7] = 0x10 + MbsByteArray[7];
                        MbsByteArray[8] = MbsXC;
                        MessageLength = 9;
                }else{
                        ByteDataLength  = CoilDataLength / 8;
                        if(ByteDataLength * 8 < CoilDataLength) ByteDataLength++;      
                        CoilDataLength  = ByteDataLength * 8;
                        MbsByteArray[5] = ByteDataLength + 3;                           //Number of bytes after this one.
                        MbsByteArray[8] = ByteDataLength;                               //Number of bytes after this one (or number of bytes of data).
                        for(int i = 0; i < ByteDataLength ; i++){
                                MbsByteArray[9 + i] = 0;                                // To get all remaining not written bits zero
                                for(int j = 0; j < 8; j++){
                                        bitWrite(MbsByteArray[9 + i], j, GetBit(MB_FC_READ_DISCRETE_INPUT,Start + i * 8 + j));
                                }
                        }
                        MessageLength = ByteDataLength + 9;
                }
                //
        }else if(MbsFC == MB_FC_READ_REGISTERS) {                                       //****************** Read Registers (3) ******************
                Start           = word(MbsByteArray[8],MbsByteArray[9]);
                WordDataLength  = word(MbsByteArray[10],MbsByteArray[11]);
                if((Start<0) || ((WordDataLength + Start) > MbInputDataLen)){
                        //Exception MB_XC_Illegal_Data_Address
                        MbsXC           = MB_XC_Illegal_Data_Address;
                        MbsByteArray[7] = 0x10 + MbsByteArray[7];
                        MbsByteArray[8] = MbsXC;
                        MessageLength = 9;
                }else{
                        ByteDataLength  = WordDataLength * 2;
                        MbsByteArray[5] = ByteDataLength + 3;                           //Number of bytes after this one.
                        MbsByteArray[8] = ByteDataLength;                               //Number of bytes after this one (or number of bytes of data).
                        for(int i = 0; i < WordDataLength; i++){
                                MbsByteArray[ 9 + i * 2] =      highByte(MbHoldData[Start + i]);
                                MbsByteArray[10 + i * 2] =      lowByte(MbHoldData[Start + i]);
                        }
                        MessageLength = ByteDataLength + 9;
                }
                //
        }else if(MbsFC == MB_FC_READ_INPUT_REGISTER) {                                  //****************** Read Registers (4) ******************
                Start           = word(MbsByteArray[8],MbsByteArray[9]);
                WordDataLength  = word(MbsByteArray[10],MbsByteArray[11]);
                if((Start<0) || ((WordDataLength + Start) > MbHoldDataLen)){
                        //Exception MB_XC_Illegal_Data_Address
                        MbsXC           = MB_XC_Illegal_Data_Address;
                        MbsByteArray[7] = 0x10 + MbsByteArray[7];
                        MbsByteArray[8] = MbsXC;
                        MessageLength = 9;
                }else{
                        ByteDataLength  = WordDataLength * 2;
                        MbsByteArray[5] = ByteDataLength + 3;                           //Number of bytes after this one.
                        MbsByteArray[8] = ByteDataLength;                               //Number of bytes after this one (or number of bytes of data).
                        for(int i = 0; i < WordDataLength; i++){
                                MbsByteArray[ 9 + i * 2] =      highByte(MbInputData[Start + i]);
                                MbsByteArray[10 + i * 2] =      lowByte(MbInputData[Start + i]);
                        }
                        MessageLength = ByteDataLength + 9;
                }
                //
        }else if(MbsFC == MB_FC_WRITE_COIL) {                                           //****************** Write Coil (5) **********************
                Start           = word(MbsByteArray[8],MbsByteArray[9]);
#if DEBUG
                sprintf(buf,"05StartADRS=%d",Start);
                Serial.println(buf);
#endif  
                if((Start<0) || (Start > (MbCoilDataLen * 16))){
                        //Exception MB_XC_Illegal_Data_Address
                        MbsXC           = MB_XC_Illegal_Data_Address;
                        MbsByteArray[7] = 0x10 + MbsByteArray[7];
                        MbsByteArray[8] = MbsXC;
                        MessageLength   = 9;
                }else{
                        if (word(MbsByteArray[10],MbsByteArray[11]) == 0xFF00){SetBit(MB_FC_WRITE_COIL,Start,true);}
                        if (word(MbsByteArray[10],MbsByteArray[11]) == 0x0000){SetBit(MB_FC_WRITE_COIL,Start,false);}
                        MbsByteArray[5] = 2;                                            //Number of bytes after this one.
                        MessageLength   = 8;
                }
                //
        }else if(MbsFC == MB_FC_WRITE_REGISTER) {                                       //****************** Write Register (6) ******************
                Start                   = word(MbsByteArray[8],MbsByteArray[9]);
                if((Start<0) || (Start > MbHoldDataLen)){
                        //Exception MB_XC_Illegal_Data_Address
                        MbsXC           = MB_XC_Illegal_Data_Address;
                        MbsByteArray[7] = 0x10 + MbsByteArray[7];
                        MbsByteArray[8] = MbsXC;
                        MessageLength = 9;
                }else{
                        MbHoldData[Start]       = word(MbsByteArray[10],MbsByteArray[11]);
                        MbsByteArray[5]         = 6;                                    //Number of bytes after this one.
                        MessageLength           = 12;
                }
                //
        }else if(MbsFC == MB_FC_WRITE_MULTIPLE_COILS) {                                 //****************** Write Multiple Coils (15) **********************
                Start           = word(MbsByteArray[8],MbsByteArray[9]);
                CoilDataLength  = word(MbsByteArray[10],MbsByteArray[11]);              //データ長の確認
                if((Start<0) || ((CoilDataLength + Start) > (MbCoilDataLen * 16))){
                        //Exception MB_XC_Illegal_Data_Address
                        MbsXC           = MB_XC_Illegal_Data_Address;
                        MbsByteArray[7] = 0x10 + MbsByteArray[7];
                        MbsByteArray[8] = MbsXC;
                        MessageLength   = 9;
                }else{
                        MbsByteArray[5] = 6;
                        for(int i = 0; i < CoilDataLength; i++){
                                SetBit(MB_FC_WRITE_MULTIPLE_COILS,Start + i,bitRead(MbsByteArray[13 + (i/8)],i-((i/8)*8)));
                        }
                        MessageLength = 12;
                }
                //
        }else if(MbsFC == MB_FC_WRITE_MULTIPLE_REGISTERS) {                             //****************** Write Multiple Registers (16) ******************
                Start                   = word(MbsByteArray[8],MbsByteArray[9]);
                WordDataLength          = word(MbsByteArray[10],MbsByteArray[11]);
                if((Start<0) || ((WordDataLength + Start) > MbHoldDataLen)){
                        //Exception MB_XC_Illegal_Data_Address
                        MbsXC           = MB_XC_Illegal_Data_Address;
                        MbsByteArray[7] = 0x10 + MbsByteArray[7];
                        MbsByteArray[8] = MbsXC;
                        MessageLength = 9;
                }else{
                        ByteDataLength  = WordDataLength * 2;
                        MbsByteArray[5] = 6;
                        for(int i = 0; i < WordDataLength; i++){
                                MbHoldData[Start + i] =  word(MbsByteArray[ 13 + i * 2],MbsByteArray[14 + i * 2]);
                        }
                        MessageLength = 12;
                }
        }else{
                //Exception 01:IllegalFunction
                MbsXC           = MB_XC_Illegal_Function;
                ByteDataLength  = 0;
                MbsByteArray[7] = 0x10 + MbsByteArray[7];
                MbsByteArray[8] = MbsXC;
                MessageLength = 9 + ByteDataLength;
        }
        //
        MbsFC = MB_FC_NONE;
        client.write(MbsByteArray, MessageLength);
#if DEBUG
        Serial.print(F("\nRESPONS:"));
        for(int i = 0;i<MessageLength;i++){
                sprintf(buf,"%02x ",MbsByteArray[i]);
                Serial.print(buf);
        }
        Serial.println(F(""));
#endif 
        return flagConnected;
}
//****************** ?? ****************** 20210423 retouch
MB_FC MgsModbus::SetFC(int fc){
        MB_FC FC;
        switch(fc){
                case 1:
                        FC = MB_FC_READ_COILS;
                        break;
                case 2:
                        FC = MB_FC_READ_DISCRETE_INPUT;
                        break;
                case 3:
                        FC = MB_FC_READ_REGISTERS;
                        break;
                case 4:
                        FC = MB_FC_READ_INPUT_REGISTER;
                        break;
                case 5:
                        FC = MB_FC_WRITE_COIL;
                        break;
                case 6:
                        FC = MB_FC_WRITE_REGISTER;
                        break;
                case 15:
                        FC = MB_FC_WRITE_MULTIPLE_COILS;
                        break;
                case 16:
                        FC = MB_FC_WRITE_MULTIPLE_REGISTERS;
                        break;
                default:
                        FC = MB_FC_NONE;
        }
        return FC;
}
//---------------------
word MgsModbus::GetDataLen(){
        int MbDataLen;
        switch(MbsFC){
                case MB_FC_READ_COILS:
                case MB_FC_WRITE_COIL:
                case MB_FC_WRITE_MULTIPLE_COILS:
                        MbDataLen = MbCoilDataLen;
                        break;
                case MB_FC_READ_DISCRETE_INPUT:
                        MbDataLen = MbDiscreteDataLen;
                        break;
                case MB_FC_READ_REGISTERS:
                case MB_FC_WRITE_REGISTER:
                case MB_FC_WRITE_MULTIPLE_REGISTERS:
                        MbDataLen = MbHoldDataLen;
                        break;
                case MB_FC_READ_INPUT_REGISTER:
                        MbDataLen = MbInputDataLen;
                        break;
                default:
                        MbDataLen = 0;
        }
        return MbDataLen;
}
//---------------------
boolean MgsModbus::GetBit(MB_FC fc,word Number){
        boolean Tmp;
        int ArrayPos = Number / 16;
        int BitPos = Number - ArrayPos * 16;
        if(fc == MB_FC_READ_DISCRETE_INPUT){
                Tmp = bitRead(MbDiscreteData[ArrayPos],BitPos);
        }else{
                Tmp = bitRead(MbCoilData[ArrayPos],BitPos);
        }
        return Tmp;
}
//---------------------
boolean MgsModbus::SetBit(MB_FC fc,word Number,boolean Data){
        boolean Overrun;
        int ArrayPos = Number / 16;
        int BitPos = Number - ArrayPos * 16;
        if(fc == MB_FC_READ_DISCRETE_INPUT){
                Overrun = ArrayPos > MbDiscreteDataLen * 16;                            // check for data overrun
                if (!Overrun){                 
                        bitWrite(MbDiscreteData[ArrayPos],BitPos,Data);
                }
        }else{
                Overrun = ArrayPos > MbCoilDataLen * 16;                                // check for data overrun
                if (!Overrun){                 
                        bitWrite(MbCoilData[ArrayPos],BitPos,Data);
                }                        
        }
        return Overrun;
}

20230324 上記コードをビルドし実行中の電流使用量を調べました。

USB経由で電源供給し、そのUSB端子にUSBテスタを挿入して電流使用量を調査したところ、0.17A程度でした。
ModbusMasterを接続し、1000msecポーリング、7segLEDで時刻表示、CytronMakerPiPicoのLEDはほぼ全灯状態です。

また、上記コードの簡単な仕様を書いておきます。

(01)Coil接点 2点 GP0とGP1を index0/1に割り当てています index2をNeoPixelの点灯/消灯に割り当てています。
※内部では32点(2word)分確保していますが、外部端子として16点をExpanderを利用して拡張します。

(02)Read接点 1点 GP22を index0に割り当てています。
※内部では32点(2word)分確保していますが、外部端子として16点をExpanderを利用して拡張します。

(03)保持レジスタ 16ワード 入力レジスタ値に対するアラート設定値やDAC出力値、カウンタ設定値等を入力設定出来ます。
index0/1/2/3をNeoPixelの色情報R/G/B/※ に割り当てています。

(04)入力レジスタ 16ワード デバイスの情報や特定の入力値を表示します。
index0=AI0(GP26) index1=AI1(GP27) index2=ボード内温度 に割り当てています。

Coil(01)
アドレス 機能 備考
00 GP0  
01 GP1  
02 GP28  
03 予約  
04 予約  
05 予約  
06 予約  
07 予約  
08 予約  
09 予約  
10 予約  
11 予約  
12 予約  
13 予約  
14 予約  
15 予約  
16 外部出力OUTPUT_0  
17 外部出力OUTPUT_1  
18 外部出力OUTPUT_2  
19 外部出力OUTPUT_3  
20 外部出力OUTPUT_4  
21 外部出力OUTPUT_5  
22 外部出力OUTPUT_6  
23 外部出力OUTPUT_7  
24 外部出力OUTPUT_8  
25 外部出力OUTPUT_9  
26 外部出力OUTPUT_10  
27 外部出力OUTPUT_11  
28 外部出力OUTPUT_12  
29 外部出力OUTPUT_13  
30 外部出力OUTPUT_14  
31 外部出力OUTPUT_15  

Input(02)
アドレス 機能 備考
00 GP22  
01 予約  
02 予約  
03 予約  
04 予約  
05 予約  
06 予約  
07 予約  
08 予約  
09 予約  
10 予約  
11 予約  
12 予約  
13 予約  
14 予約  
15 予約  
16 外部入力INPUT_0  
17 外部入力INPUT_1  
18 外部入力INPUT_2  
19 外部入力INPUT_3  
20 外部入力INPUT_4  
21 外部入力INPUT_5  
22 外部入力INPUT_6  
23 外部入力INPUT_7  
24 外部入力INPUT_8  
25 外部入力INPUT_9  
26 外部入力INPUT_10  
27 外部入力INPUT_11  
28 外部入力INPUT_12  
29 外部入力INPUT_13  
30 外部入力INPUT_14  
31 外部入力INPUT_15  

Hold(03)
アドレス 機能 ByteH ByteL 備考
00 NeoPixel R値

uint
 
01 NeoPixel G値

uint
 
02 NeoPixel B値

uint
 
03 予備

uint
 
04 予備

uint
 
05 予備    
06 予備

int
 
07 予備

int
 
08 予備

uint
 
09 予備

uint
 
10 予備

uint
 
11 予備

uint
 
12 予備

uint
 
13 予備

uint
14 予備

U32
 
 
15 予備
16 予備

U32
 
 
17 予備
18 予備

uint
 
19 予備

uint
 
20 予備

uint
 
21 予備

uint
 
22 予備

uint
 
23 予備

uint
 
24 予備

I16
25 予備

I16
26 予備

I16
27 予備

I16
28 予備

I16
29 予備

I16
30 予備

I16
31 予備

I16
32 予備

I16
33 予備

I16
34 予備

I16
35 予備

I16
36 予備

I16
37 予備

I16
38 予備

I16
39 予備

I16

Input(04)
アドレス 機能 ByteH ByteL 備考
00 入力データ_0

ADC_0
GP26 +3.3V=1023 +0V=0
01 入力データ_1

ADC_1
GP27 +3.3V=1023 +0V=0
02 入力データ_2

ADC_BuiltIn
ボード温度
03 入力データ_3

予約
 
04 入力データ_4

 
 
05 入力データ_5

 
 
06 入力データ_6

 
 
07 入力データ_7

 
 
08 入力データ_8

 
 
09 入力データ_9

 
 
10 入力データ_10

 
 
11 入力データ_11

 
 
12 入力データ_12

西暦
現在時刻
TZ:タイムゾーン 日本の場合+9=90ハワイ-8=-80
59分01秒=59×256+01=15105(0x5901)
13 入力データ_13

14 入力データ_14

TZ

15 入力データ_15

16 VenderString_0_1 ‘\0’ ‘’ ベンタ名31max文字+\0
17 VenderString_2_3 ‘’ ‘’
18 VenderString_4_5 ‘’ ‘’
19 VenderString_6_7 ‘’ ‘’
20 VenderString_8_9 ‘’ ‘’
21 VenderString_10_11 ‘’ ‘’
22 VenderString_12_13 ‘’ ‘’
23 VenderString_14_15 ‘’ ‘’
24 VenderString_16_17 ‘’ ‘’
25 VenderString_18_19 ‘’ ‘’
26 VenderString_20_21 ‘’ ‘’
27 VenderString_22_23 ‘’ ‘’
28 VenderString_24_25 ‘’ ‘’
29 VenderString_26_27 ‘’ ‘’
30 VenderString_28_29 ‘’ ‘’
31 VenderString_30_31 ‘’ ‘’
32 ProductString_0_1 ‘\0’ ‘’ 製品名31max文字+\0
33 ProductString_2_3 ‘’ ‘’
34 ProductString_4_5 ‘’ ‘’
35 ProductString_6_7 ‘’ ‘’
36 ProductString_8_9 ‘’ ‘’
37 ProductString_10_11 ‘’ ‘’
38 ProductString_12_13 ‘’ ‘’
39 ProductString_14_15 ‘’ ‘’
40 ProductString_16_17 ‘’ ‘’
41 ProductString_18_19 ‘’ ‘’
42 ProductString_20_21 ‘’ ‘’
43 ProductString_22_23 ‘’ ‘’
44 ProductString_24_25 ‘’ ‘’
45 ProductString_26_27 ‘’ ‘’
46 ProductString_28_29 ‘’ ‘’
47 ProductString_30_31 ‘’ ‘’
48 SystemVerValue0_1 ‘\1’ ‘\0’ システムバージョン表記
バイト単位で0/1/2/3
49 SystemVerValue2_3 ‘\0’ ‘\0’
50 FirmwareVerVarlue0_1 ‘\1’ ‘\0’ ファームウエアバージョン表記
バイト単位で0/1/2/3
51 FirmwareVerVarlue2_3 ‘\0’ ‘\0’
52 予約 ‘’ ‘’  
53 予約 ‘’ ‘’  
54 予約 ‘’ ‘’  
55 予約 ‘’ ‘’  
56 予約 ‘’ ‘’  
57 予約 ‘’ ‘’  
58 予約 ‘’ ‘’  
59 予約 ‘’ ‘’  
60 予約 ‘’ ‘’  
61 予約 ‘’ ‘’  
62 予約 ‘’ ‘’  
63 予約 ‘’ ‘’  


戯言(nonsense)に戻る


問い合わせ頁の表示


免責事項

本ソフトウエアは、あなたに対して何も保証しません。本ソフトウエアの関係者(他の利用者も含む)は、あなたに対して一切責任を負いません。
あなたが、本ソフトウエアを利用(コンパイル後の再利用など全てを含む)する場合は、自己責任で行う必要があります。

本ソフトウエアの著作権は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社の登録商標です。
その他の企業名ならびに製品名は、それぞれの会社の商標もしくは登録商標です。
すべての商標および登録商標は、それぞれの所有者に帰属します。