This demonstrates the process of communicating through ethernet to a SEL-2431 Voltage Regulator Control Panel using SEL Fast Message. Basic device commands and data cna be requested and displayed over a connected serial port. This is a basic version and full testing and documentation has yet to be completed.

Dependencies:   BufferedSerial analogAverager voltageRegulator netStatReg analogMinMax CounterMinMax

Files at this revision

API Documentation at this revision

Comitter:
masterkookus
Date:
Wed Oct 02 12:12:30 2019 +0000
Parent:
9:d6e7981dfc89
Child:
11:d40adc7de05f
Commit message:
Demand Report added and poll times optimized

Changed in this revision

main.cpp Show annotated file Show diff for this revision Revisions of this file
mydevices.h Show annotated file Show diff for this revision Revisions of this file
netdevices.h Show annotated file Show diff for this revision Revisions of this file
selMsg.cpp Show annotated file Show diff for this revision Revisions of this file
selMsg.h Show annotated file Show diff for this revision Revisions of this file
--- a/main.cpp	Tue Oct 01 15:51:59 2019 +0000
+++ b/main.cpp	Wed Oct 02 12:12:30 2019 +0000
@@ -39,7 +39,6 @@
 //Provides the deivce poll timing
 void heartbeat()
 {
-    //polltick=true;
     setTick(true);
 }
 
@@ -52,7 +51,6 @@
     net1.cltCloseConnection=false;
     net1.pollTime=0;
     net1.pollTimeout=0;
-    net1.pollInterval=setpollinterval;
     net1.pollRequestSent=false;
     net1.pollResponseReceived=false;
     net1.srv_sock.set_blocking(true);
@@ -62,13 +60,14 @@
     net1.srv.set_timeout(100);
     net1.pollEnabled=setpollenabled;
     net1.pollTimeoutCount=0;
-    net1.pollState=0;
+    net1.configState=0;
     net1.pollTimeoutCount=0;
     net1.sendRetryCount=0;
     net1.messageFailCount=0;
     net1.txMessageCount=0;
     net1.rxMessageCount=0;
-    net1.connectCmd=false;
+    net1.fmEnabled=false;
+    net1.fmdEnabled=false;
     
     /* Open the server on ethernet stack */
     net1.srv.open(eth);
@@ -96,12 +95,14 @@
     
     while(1)
     {
+        //Check to see if the Receive Buffer has anything
         while (!receiveBuffer.empty())
         {
             receiveBuffer.pop(cchar);
             cbuf[clen]=cchar;
             clen++;
         }
+        //If a Poll Request has been made and data has been received set flag
         if (net2->pollRequestSent)
         {
             if (clen>0)
@@ -109,17 +110,22 @@
                 net2->pollResponseReceived=true;
             }
         }
+        //Check to see if bulk data and reports being sent from device due to serial command
         if (net2->devMsgOpenRx)
         {
             sport0.write(cbuf,clen);
             clen=0;
         }
+        //Check to see if at least 4 characters have been received
         else if (clen>3)
         {
+            //Cycle through received data to search for a command
             for (cbc=0;cbc<clen-3;cbc++)
             {
+                //Check to see if serial commands are currently being received
                 if (net2->serIsActive==true)
                 {
+                    //If relay acknowledges max metering command set bulk receive flag
                     if ((cbuf[cbc]==0x4d) && (cbuf[cbc+1]==0x45) && (cbuf[cbc+2]==0x54))
                     {
                         sport0.write(cbuf,clen);
@@ -128,7 +134,7 @@
                         clen=0;
                         break;
                     }
-                    
+                    //If relay acknowledges tap report command set bulk receive flag
                     if ((cbuf[cbc]==0x54) && (cbuf[cbc+1]==0x41) && (cbuf[cbc+2]==0x50))
                     {
                         sport0.write(cbuf,clen);
@@ -137,6 +143,7 @@
                         clen=0;
                         break;
                     }
+                    //If relay acknowledges level 1 login attempt increment command pointer to password
                     if ((cbuf[cbc]==0x41) && (cbuf[cbc+1]==0x43) && (cbuf[cbc+2]==0x43))
                     {
                         sport0.write(cbuf,clen);
@@ -144,6 +151,7 @@
                         clen=0;
                         break;
                     }
+                    //If relay sends mask character increment command pointer to send \r\n
                     if (cbuf[cbc]==0x2a)
                     {
                         sport0.write(cbuf,clen);
@@ -151,6 +159,7 @@
                         clen=0;
                         break;
                     }
+                    //If relay is in access level 1 or higher increment command pointer to desired command
                     if ((cbuf[cbc]==0x3d) && (cbuf[cbc+1]==0x3e))
                     {
                         sport0.write(cbuf,clen);
@@ -158,6 +167,7 @@
                         clen=0;
                         break;
                     }
+                    //If relay in level 0 increment command pointer to access command
                     if ((cbuf[cbc]==0x3d))
                     {
                         sport0.write(cbuf,clen);
@@ -166,32 +176,35 @@
                         break;
                     }
                 }
+                //Check fast message conficuration
                 if ((cbuf[cbc]==0xA5) && (cbuf[cbc+1]==0xC0))
                 {
                     sport0.write(cbuf,clen);
-                    net2->pollState=1;
+                    net2->configState=1;
                     clen=0;
                     break;
                 }
+                //Check fast meter configuration
                 if ((cbuf[cbc]==0xA5) && (cbuf[cbc+1]==0xC1))
                 {
                     sport0.write(cbuf,clen);
+                    //Ensure Analog channl count is correct
                     if (vReg1.numAnalog!=cbuf[6])
                     {
-                        printf("\r\nAnalog Channel Count Off\r\n");
-                        net2->pollState=0;
+                        printf("\r\nFast Meter Analog Channel Count Off\r\n");
                         clen=0;
                         break;
                     }
+                    //Ensure Digital register count is correct
                     if (vReg1.numDigital!=cbuf[8])
                     {
-                        printf("\r\nDigital Channel Count Off\r\n");
-                        net2->pollState=0;
+                        printf("\r\nFast Meter Digital Channel Count Off\r\n");
                         clen=0;
                         break;
                     }
                     char anum=16;
                     char nxc;
+                    //Verify Analog names are correct
                     for (txc=0;txc<vReg1.numAnalog;txc++)
                     {
                         for (nxc=0;nxc<6;nxc++)
@@ -204,10 +217,12 @@
                         }
                         anum = anum + 11;
                     }
-                    net2->pollState=2;
+                    net2->configState=3;
+                    net2->fmEnabled=true;
                     clen=0;
                     break;
                 }
+                //Receive data
                 if ((cbuf[cbc]==0xA5) && (cbuf[cbc+1]==0xD1))
                 {
                     char anum=cbc+4;
@@ -239,6 +254,64 @@
                     clen=0;
                     break;
                 }
+                //Check fast demand meter configuration
+                if ((cbuf[cbc]==0xA5) && (cbuf[cbc+1]==0xC2))
+                {
+                    sport0.write(cbuf,clen);
+                    //Ensure Analog channl count is correct
+                    if (vReg1.numDemAnalog!=cbuf[6])
+                    {
+                        printf("\r\nDemand Analog Channel Count Off\r\n");
+                        clen=0;
+                        break;
+                    }
+                    char anum=18;
+                    char nxc;
+                    //Verify Analog names are correct
+                    for (txc=0;txc<vReg1.numDemAnalog;txc++)
+                    {
+                        for (nxc=0;nxc<6;nxc++)
+                        {
+                            if(vReg1.analogs[txc+vReg1.numAnalog].analogName[nxc]!=cbuf[anum+nxc])
+                            {
+                                printf("%c %c\r\n",vReg1.analogs[txc+vReg1.numAnalog].analogName[nxc],cbuf[anum+nxc]);
+                                printf("\r\nPoint %d Failed\r\n",txc);
+                                break;
+                            }
+                        }
+                        anum = anum + 11;
+                    }
+                    net2->configState=9;
+                    net2->fmdEnabled=true;
+                    clen=0;
+                    break;
+                }
+                //Receive demand data
+                if ((cbuf[cbc]==0xA5) && (cbuf[cbc+1]==0xD2))
+                {
+                    char anum=cbc+4;
+                    for (txc=0;txc<vReg1.numDemAnalog;txc++)
+                    {
+                        valpack.bytes[3]=cbuf[anum];
+                        valpack.bytes[2]=cbuf[anum+1];
+                        valpack.bytes[1]=cbuf[anum+2];
+                        valpack.bytes[0]=cbuf[anum+3];
+                        vReg1.analogs[txc].analog1Value = valpack.cmdflt;
+                        anum = anum + 4;
+                        printf("%.2f\r\n",vReg1.analogs[txc].analog1Value);
+                    }
+                    vReg1.demTimeStamp.month=cbuf[anum];
+                    vReg1.demTimeStamp.day=cbuf[anum+1];
+                    vReg1.demTimeStamp.year=cbuf[anum+2];
+                    vReg1.demTimeStamp.hour=cbuf[anum+3];
+                    vReg1.demTimeStamp.min=cbuf[anum+4];
+                    vReg1.demTimeStamp.sec=cbuf[anum+5];
+                    timepack.bytes[1]=cbuf[anum+6];
+                    timepack.bytes[0]=cbuf[anum+7];
+                    vReg1.demTimeStamp.msec=timepack.cmdshort;
+                    printf("%d/%d/%d %d:%d:%d.%d\r\n",vReg1.demTimeStamp.month,vReg1.demTimeStamp.day,vReg1.demTimeStamp.year,vReg1.demTimeStamp.hour,vReg1.demTimeStamp.min,vReg1.demTimeStamp.sec,vReg1.demTimeStamp.msec);
+                    break;
+                }
             }
             if (clen>0)
             {
@@ -256,35 +329,40 @@
     {
         if (net2->cltIsActive)
         {
+            //Attempt to connect to server
             while (net2->sendState==3)
             {
+                //delay connect attempt if previous attempt unsuccessful
                 if (net2->connectRetry == true)
                 {
                     wait_ms(100);
                 }
-                net2->connectCmd=true;
+                //Attempt to connectg
                 ret = net2->srv_sock.connect(net2->srv_addr,net2->cltPort);
+                //If connect successful proceed to send data
                 if (ret==0)
                 {
                     net2->connectRetry = false;
                     printf("Connected %d\r\n",ret);
                     net2->sendState=4;
                 }
+                //If connect attempt failed check to see if may already be connected
                 else if (ret==-3015)
                 {
                     printf("May already be connected, attempting send.\r\n");
                     net2->connectRetry = false;
                     net2->sendState=4;
                 }
+                //If connect attempt failed on other error attempt reconnect
                 else
                 {
                     net2->connectRetry = true;
                     net2->sendRetryCount++;
                     printf("Connect Attempt Failed, Code: %d\r\n",ret);
+                    //If connect attempt failed exceeds 3 then end attempt
                     if (net2->sendRetryCount>3)
                     {
                         printf("Communication Failed, Closing\r\n");
-                        net2->connectCmd=false;
                         net2->connectRetry = false;
                         net2->sendRetryCount = 0;
                         net2->messageFailCount++;
@@ -294,14 +372,17 @@
                     }
                 }
             }
+            //Attempt to send data
             while (net2->sendState==4)
             {
+                //Delay send data attempt if previous attempt failed
                 if (net2->sendRetry == true)
                 {
                     wait_ms(100);
                 }
-                net2->connectCmd=false;
+                //Attempt to send data
                 ret = net2->srv_sock.send(net2->sendString,net2->sendLen);
+                //If data send successful proceed to wait for response
                 if (ret>=0)
                 {
                     printf("Send Result %d\r\n",ret);
@@ -310,11 +391,13 @@
                     net2->sendState=5;
                     net2->sendTime=0;
                 }
+                //If send attempt failed attempt to re-send data
                 else
                 {
                     net2->sendRetry = true;
                     net2->sendRetryCount++;
                     printf("Send Attempt Failed, Code: %d\r\n",ret);
+                    //If send attempt failed exceeds 3 then end attempt
                     if (net2->sendRetryCount>3)
                     {
                         printf("Communication Failed, Closing\r\n");
@@ -339,9 +422,12 @@
     int rxc;
     while (1)
     {
+        //If the client is active check to see if data has been received
         while (net2->cltIsActive)
         {
+            //Store the length of the received data
             rxlen=net2->srv_sock.recv(rxbuf, sizeof(rxbuf));
+            //if there is data then push data into received buffer
             if (rxlen>0)
             {
                 net2->aliveTime=0;
@@ -350,6 +436,7 @@
                     receiveBuffer.push(rxbuf[rxc]);
                 }
                 printf("Client Received Data\r\n");
+                //Increment received message counter
                 net2->rxMessageCount++;
             }
         }
@@ -364,9 +451,12 @@
     int rxc;
     while (1)
     {
+        //If the server is active check to see if data has been received
         while (net2->srvIsActive)
         {
+            //Store the length of the received data
             rxlen=net2->clt_sock.recv(rxbuf, sizeof(rxbuf));
+            //if there is data then push data into received buffer
             if (rxlen>0)
             {
                 net2->aliveTime=0;
@@ -375,6 +465,7 @@
                     receiveBuffer.push(rxbuf[rxc]);
                 }
                 printf("Server Received Data\r\n");
+                //Increment received message counter
                 net2->rxMessageCount++;
             }
         }
@@ -393,23 +484,30 @@
     
     while (1)
     {
+        //Check to see if there is any data received by serial port and store length
         rxlen=sport0.readable();
+        //If data is ready push into receive buffer
         if (rxlen>0)
         {
             for (rxc=0;rxc<rxlen;rxc++)
             {
                 rxbuf[rxindex+rxc]=sport0.getc();
+                //Check to see if a carriage return has been detected
                 if (rxbuf[rxindex+rxc]=='\r')
                 {
                     crRx=true;
                 }
             }
+            //Store the current cursor location in the buffer
             rxindex=rxindex+rxlen;
-            printf("%d\r\n",rxlen);
-            printf("%d\r\n",rxindex);
+            //printf("%d\r\n",rxlen);
+            //printf("%d\r\n",rxindex);
+            //Set the received length to zero
             rxlen=0;
+            //If there is data in the buffer and a carriage return has been detected search for a command
             if ((rxindex>2) && (crRx==true))
             {
+                //Set the carriage return flag false
                 crRx=false;
                 for (rxc=0;rxc<=rxindex-3;rxc++)
                 {
@@ -417,7 +515,8 @@
                     cmdpack.bytes[2]=rxbuf[rxc+1];
                     cmdpack.bytes[1]=rxbuf[rxc+2];
                     cmdpack.bytes[0]=rxbuf[rxc+3];
-                    printf("%08x\r\n",cmdpack.cmdint);
+                    //printf("%08x\r\n",cmdpack.cmdint);
+                    //Search for the Min/Max command
                     if (cmdpack.cmdint==0x4d45544d)
                     {
                         printf("MIN MAX METERING\r\n");
@@ -425,6 +524,7 @@
                         net2->devMsgPos=2;
                         rxindex=0;
                     }
+                    //Search for the Tap Report Command
                     if (cmdpack.cmdint==0x54415052)
                     {
                         printf("TAP REPORT\r\n");
@@ -433,6 +533,7 @@
                         rxindex=0;
                     }
                 }
+                //If no command found set cursor location to zero
                 if (rxindex>0)
                 {
                     printf("Serial Command Not Found");
@@ -452,6 +553,7 @@
     
     while(1)
     {
+        //Wait for someone to connect
         while (server->accept(client_socket, client_address) < 0)
         {
             //printf("Connection Failed.\r\n");
@@ -463,6 +565,15 @@
     }
 }
 
+void sendCmd(char cmdNum)
+{
+    sendLength.push(2);
+    for (char txc=0;txc<2;txc++)
+    {
+        sendBuffer.push(fmCmd[cmdNum][txc]);
+    }
+}
+
 int main()
 {
     EthernetInterface eth;
@@ -499,6 +610,8 @@
             incTime();
             currenttime=getTime();
             net1.pollTime++;
+            net1.fmPollTime++;
+            net1.fmdPollTime++;
             net1.sendTime++;
             if (net1.srvIsActive)
             {
@@ -514,7 +627,7 @@
             }
             if (net1.pollEnabled)
             {
-                if (net1.pollTime >= net1.pollInterval)
+                if (net1.pollTime >= setpollinterval)
                 {
                     if ((net1.sendState==0)||(net1.sendState==5))
                     {
@@ -533,19 +646,75 @@
                         }
                         else
                         {
-                            sendLength.push(2);
-                            for (txc=0;txc<2;txc++)
+                            if (net1.configState<9)
                             {
-                                sendBuffer.push(fmCmd[net1.pollState][txc]);
+                                sendCmd(net1.configState);
+                                if (net1.sendState==0)
+                                {
+                                    net1.sendState=1;
+                                    net1.pollRequestSent=true;
+                                }
+                            }
+                        }
+                        
+                    }
+                    net1.pollTime=0;
+                }
+                if (net1.fmPollTime >= setfmpollinterval)
+                {
+                    if (net1.serIsActive==false)
+                    {
+                        if ((net1.sendState==0)||(net1.sendState==5))
+                        {
+                            {
+                                if (net1.fmEnabled)
+                                {
+                                    sendCmd(2);
+                                    if (net1.sendState==0)
+                                    {
+                                        net1.sendState=1;
+                                        net1.pollRequestSent=true;
+                                    }
+                                }
                             }
                         }
-                        if (net1.sendState==0)
+                        if (net1.fmPollTime>setfmpollinterval)
                         {
-                            net1.sendState=1;
-                            net1.pollRequestSent=true;
+                            net1.fmPollTime=net1.fmPollTime-setfmpollinterval;
+                        }
+                        else
+                        {
+                            net1.fmPollTime=0;
                         }
                     }
-                    net1.pollTime=0;
+                }
+                if (net1.fmdPollTime >= setfmdemandpollinterval)
+                {
+                    if (net1.serIsActive==false)
+                    {
+                        if ((net1.sendState==0)||(net1.sendState==5))
+                        {
+                            {
+                                if (net1.fmdEnabled)
+                                {
+                                    sendCmd(4);
+                                    if (net1.sendState==0)
+                                    {
+                                        net1.sendState=1;
+                                        net1.pollRequestSent=true;
+                                    }
+                                }
+                            }
+                        }
+                        if (net1.fmdPollTime>setfmdemandpollinterval)
+                        {
+                            net1.fmdPollTime=net1.fmdPollTime-setfmdemandpollinterval;
+                        }
+                        else
+                        {
+                            net1.fmdPollTime=0;
+                        }
+                    }
                 }
                 if ((net1.sendState==5) || (net1.serIsActive))
                 {
@@ -573,9 +742,9 @@
                         }
                         if (net1.serIsActive)
                         {
-                            net1.devMsgOpenRx=false;
                             if ((net1.serTimeoutCount==sertimeoutperiods) || (net1.devMsgReq==0))
                             {
+                                net1.devMsgOpenRx=false;
                                 net1.cltCloseConnection=true;
                                 net1.devMsgReq=0;
                                 net1.serIsActive=false;
--- a/mydevices.h	Tue Oct 01 15:51:59 2019 +0000
+++ b/mydevices.h	Wed Oct 02 12:12:30 2019 +0000
@@ -3,7 +3,9 @@
 #define setclientaddress "10.150.1.242"
 #define setpolltimeout 200
 #define sertimeoutperiods 5
-#define setpollinterval 500
+#define setpollinterval 15 //In 10ms intervals
+#define setfmpollinterval 500 
+#define setfmdemandpollinterval 3100
 #define setslowpollinterval 1500
 #define setfastpollcount 5
 #define setpollenabled true
--- a/netdevices.h	Tue Oct 01 15:51:59 2019 +0000
+++ b/netdevices.h	Wed Oct 02 12:12:30 2019 +0000
@@ -25,15 +25,17 @@
     bool pollEnabled;
     bool pollRequestSent;
     bool pollResponseReceived;
+    bool fmEnabled;
+    bool fmdEnabled;
     unsigned int pollTimeout;
     unsigned int pollTime;
-    unsigned int pollInterval;
+    unsigned int fmPollTime;
+    unsigned int fmdPollTime;
     unsigned int pollTimeoutCount;
     unsigned int sendTimeout;
     unsigned int sendTime;
-    unsigned int sendInterval;
     unsigned int sendState;
-    unsigned int pollState;
+    unsigned int configState;
     
     unsigned int deivceType;
     
@@ -43,8 +45,6 @@
     char devMsgPos;
     bool devMsgOpenRx;
     
-    bool connectCmd;
-    
     bool attachRetry;
     bool sendRetry;
     bool connectRetry;
--- a/selMsg.cpp	Tue Oct 01 15:51:59 2019 +0000
+++ b/selMsg.cpp	Wed Oct 02 12:12:30 2019 +0000
@@ -4,6 +4,7 @@
 {
     vReg->numAnalog=0x11;
     vReg->numDigital=0x34;
+    vReg->numDemAnalog=0x0A;
     strcpy(vReg->analogs[0].analogName,"IL\0\0\0\0");
     strcpy(vReg->analogs[1].analogName,"ILA\0\0\0");
     strcpy(vReg->analogs[2].analogName,"VS\0\0\0\0");
@@ -21,4 +22,14 @@
     strcpy(vReg->analogs[14].analogName,"PF\0\0\0\0");
     strcpy(vReg->analogs[15].analogName,"PFLD\0\0");
     strcpy(vReg->analogs[16].analogName,"FREQ\0\0");
+    strcpy(vReg->analogs[17].analogName,"ILFDEM");
+    strcpy(vReg->analogs[18].analogName,"ILRDEM");
+    strcpy(vReg->analogs[19].analogName,"PFDEM\0");
+    strcpy(vReg->analogs[20].analogName,"PRDEM\0");
+    strcpy(vReg->analogs[21].analogName,"QFODEM");
+    strcpy(vReg->analogs[22].analogName,"QFIDEM");
+    strcpy(vReg->analogs[23].analogName,"QRODEM");
+    strcpy(vReg->analogs[24].analogName,"QRIDEM");
+    strcpy(vReg->analogs[25].analogName,"SFDEM\0");
+    strcpy(vReg->analogs[26].analogName,"SRDEM\0");
 }
--- a/selMsg.h	Tue Oct 01 15:51:59 2019 +0000
+++ b/selMsg.h	Wed Oct 02 12:12:30 2019 +0000
@@ -1,10 +1,12 @@
 #ifndef SELMSG_H 
 #define SELMSG_H 
 
-const char fmCmd[3][2] = {
+const char fmCmd[5][2] = {
     {0xA5,0xC0},
     {0xA5,0xC1},
-    {0xA5,0xD1}
+    {0xA5,0xD1},
+    {0xA5,0xC2},
+    {0xA5,0xD2}
 };
 
 const char serCmd[5][7] =  {
@@ -25,20 +27,6 @@
     0xA5,0xC0,0x17,0x02,0x03,0x00,0xA5,0xC1,0xA5,0xD1,0xA5,0xC2,0xA5,0xD2,0xA5,0xC3,0xA5,0xD3,0x01,0x00,0x00,0x05,0x21
 };
 
-/*const char vRegMsgCfg204] = {
-    0xA5,0xC1,0xBB,0x01,0x00,0x00,0x11,0x01,0x34,0x00,0x00,0x04,0x00,0x48,0x00,0x50,0x49,0x4C,0x00,0x00,0x00,0x00,0x01,0xFF,
-    0xFF,0x00,0x00,0x49,0x4C,0x41,0x00,0x00,0x00,0x01,0xFF,0xFF,0x00,0x00,0x56,0x53,0x00,0x00,0x00,0x00,0x01,0xFF,0xFF,0x00,
-    0x00,0x56,0x53,0x41,0x00,0x00,0x00,0x01,0xFF,0xFF,0x00,0x00,0x56,0x4C,0x00,0x00,0x00,0x00,0x01,0xFF,0xFF,0x00,0x00,0x56,
-    0x4C,0x41,0x00,0x00,0x00,0x01,0xFF,0xFF,0x00,0x00,0x56,0x43,0x4D,0x50,0x00,0x00,0x01,0xFF,0xFF,0x00,0x00,0x54,0x41,0x50,
-    0x50,0x4F,0x53,0x01,0xFF,0xFF,0x00,0x00,0x56,0x53,0x53,0x45,0x43,0x00,0x01,0xFF,0xFF,0x00,0x00,0x56,0x4C,0x53,0x45,0x43,
-    0x00,0x01,0xFF,0xFF,0x00,0x00,0x56,0x43,0x4D,0x50,0x53,0x43,0x01,0xFF,0xFF,0x00,0x00,0x50,0x4C,0x00,0x00,0x00,0x00,0x01,
-    0xFF,0xFF,0x00,0x00,0x51,0x4C,0x00,0x00,0x00,0x00,0x01,0xFF,0xFF,0x00,0x00,0x53,0x4C,0x00,0x00,0x00,0x00,0x01,0xFF,0xFF,
-    0x00,0x00,0x50,0x46,0x00,0x00,0x00,0x00,0x01,0xFF,0xFF,0x00,0x00,0x50,0x46,0x4C,0x44,0x00,0x00,0x01,0xFF,0xFF,0x00,0x00,
-    0x46,0x52,0x45,0x51,0x00,0x00,0x01,0xFF,0xFF,0x00,0x00,0x23
-    };*/
-
-//short2byte analogScaleOffset;
-
 struct analog1Sample {
     char analogName[6];
     float analog1Value;
@@ -75,8 +63,10 @@
 struct vRegData {
     char numAnalog;
     char numDigital;
-    struct analog1Sample analogs[17];
+    char numDemAnalog;
+    struct analog1Sample analogs[27];
     struct fmTimeStamp timeStamp;
+    struct fmTimeStamp  demTimeStamp;
     char digitalTargets[52];
 };