Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: NTPClient W5500Interface Watchdog device_configuration eeprom_flash mbed-rpc-nucleo mbed-rtos mbed
Fork of F103-Serial-to-Ethernet by
Revision 9:d2534ecf88c6, committed 2014-09-26
- Comitter:
- olympux
- Date:
- Fri Sep 26 20:07:34 2014 +0000
- Parent:
- 8:64848959adb9
- Child:
- 10:4cd965d79de0
- Commit message:
- Added & tested NTP
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/NTPClient.lib Fri Sep 26 20:07:34 2014 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/ban4jp/code/NTPClient/#c70ed0bfab2e
--- a/eeprom.lib Sun Sep 21 20:25:35 2014 +0000 +++ b/eeprom.lib Fri Sep 26 20:07:34 2014 +0000 @@ -1,1 +1,1 @@ -http://mbed.org/users/olympux/code/eeprom/#5da14988d0e5 +http://mbed.org/users/olympux/code/eeprom/#4bf7c01c5a48
--- a/main.cpp Sun Sep 21 20:25:35 2014 +0000
+++ b/main.cpp Fri Sep 26 20:07:34 2014 +0000
@@ -6,6 +6,7 @@
#include "mbed.h"
//#include "eeprom.h"
#include "EthernetInterface.h"
+#include "NTPClient.h"
#include "rtos.h"
@@ -15,22 +16,38 @@
#define ST_NUCLEO // hardware pin mapping
#ifdef ST_NUCLEO
-// ST Nucleo
+// Ethernet
SPI spi(PA_7, PA_6, PA_5); // mosi, miso, sclk
EthernetInterface eth(&spi, PC_8, PC_9); // spi, cs, reset
#endif
+// Serial
Serial uart(USBTX,USBRX);
-// Variables' number
-#define NumbOfVar ((uint8_t)0x0F) // REMEMBER: update this variable in eeprom.h too
+// Digital inputs
+// Digital outputs
+// Analog inputs
+// Analog outputs
+//AnalogOut ano0(p18);
+
+
+// eeprom
+#define NumbOfVar ((uint8_t)0x80) // REMEMBER: update this variable in eeprom.h too
+#define IP_ADDRESS_POS 0
+#define IP_SUBNET_POS 4
+#define IP_GATEWAY_POS 8
+#define TCP_SERVER_PORT_POS 12
+#define UDP_SERVER_PORT_POS 13
+#define FIRST_RUN_FLAG_POS 14
+#define MAC_ADDRESS_POS 15
// Virtual address defined by the user: 0xFFFF value is prohibited
uint16_t VirtAddVarTab[NumbOfVar] = {0x1212, 0x1313, 0x1414, 0x1515, // IP_Addr
0x2212, 0x2313, 0x2414, 0x2515, // IP_Subnet
0x3212, 0x3313, 0x3414, 0x3515, // IP_Gateway
0x4212, // TCP server port, not used
0x5212, // UDP server port, not used
- 0x8888 // 1st run?
+ 0x8888, // 1st run?
+ 0x6212, 0x6313, 0x6414 // MAC
};
extern "C" uint16_t EE_Init(void);
extern "C" uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data);
@@ -49,22 +66,56 @@
#define DEFAULT_IP_ADDRESS "192.168.0.249"
#define DEFAULT_IP_SUBNET "255.255.255.0"
#define DEFAULT_IP_GATEWAY "192.168.0.1"
+#define DEFAULT_MAC3 0x00
+#define DEFAULT_MAC4 0x00
+#define DEFAULT_MAC5 0x01
#define TCP_SERVER_WAIT_CLIENT_TIMEOUT 200
#define TCP_SERVER_RECEIVE_TIMEOUT 3000
#define UDP_SERVER_RECEIVE_TIMEOUT 200
// for static IP setting
-char * IP_Addr;
+uint8_t mac[6];
+char * IP_Addr; // pointers to
char * IP_Subnet;
char * IP_Gateway;
-char ip_addr[16], ip_subnet[16], ip_gateway[16]; // loaded from eeprom
-uint16_t tcp_server_port = 10000; // fixed
-uint16_t udp_server_port = 11000; // fixed
+uint16_t u16ip_addr[4], u16ip_subnet[4], u16ip_gateway[4]; // directly loaded from eeprom
+uint16_t first_run = 0; // first run flag
+uint16_t u16mac_addr[3]; // loaded from eeprom
+char ip_addr[16], ip_subnet[16], ip_gateway[16]; // chars, converted from u16ip_xxx
+
+const uint16_t tcp_server_port = 10000; // fixed
+const uint16_t udp_server_port = 11000; // fixed
char buffer[256]; // socket buffer
+NTPClient ntp;
+
+// Commands
+#define DEVICE_ID "NNIO"
+#define DISCOVERY_COMMAND "NNIODS"
+#define TCP_SERVER_PORT_COMAMND "NNIOTP"
+#define UDP_SERVER_PORT_COMAMND "NNIOUP"
+#define QUERY_STATUS_COMMAND (uint8_t)'Q'
+
+
+// Positions
+#define RECEIVING_PROTOCOL_OP_POS 4
+#define RECEIVING_PROTOCOL_EN_DO_POS RECEIVING_PROTOCOL_OP_POS + 0
+#define RECEIVING_PROTOCOL_EN_A0O_POS RECEIVING_PROTOCOL_OP_POS + 1
+#define RECEIVING_PROTOCOL_EN_A1O_POS RECEIVING_PROTOCOL_OP_POS + 2
+#define RECEIVING_PROTOCOL_EN_UART_POS RECEIVING_PROTOCOL_OP_POS + 3
+#define RECEIVING_PROTOCOL_COMMAND_POS RECEIVING_PROTOCOL_OP_POS + 4
+#define RECEIVING_PROTOCOL_ENABLE_OUTPUT (uint8_t)'O'
+
+
+#define RECEIVING_PROTOCOL_POS_IP 9
+#define RECEIVING_PROTOCOL_POS_DO 13
+#define RECEIVING_PROTOCOL_POS_A0O 21
+#define RECEIVING_PROTOCOL_POS_A01 23
+#define RECEIVING_PROTOCOL_POS_UART 25
+
/*
@@ -102,17 +153,11 @@
* Ethernet init
*/
int ethernet_init(void) {
- uint8_t mac[6];
-
- mbed_mac_address((char *)mac); // using the MAC address in LPC11U24 or LPC1178
- mac[0] = 0x00; mac[1] = 0x08; mac[2] = 0xDC; mac[3] = 0x00; mac[4] = 0x00; mac[5] = 0x00;
-
-
//printf("Start\n");
int ret = eth.init(mac, IP_Addr, IP_Subnet, IP_Gateway); // static
if (!ret) {
- //uart.printf("Initialized, MAC: %s\n", eth.getMACAddress());
+ uart.printf("Initialized, MAC: %s\n", eth.getMACAddress());
} else {
uart.printf("Error eth.init() - ret = %d\n", ret);
return -1;
@@ -134,72 +179,98 @@
* EEPROM functions
*/
void write_eeprom(char *buffer) {
+ // Write network configuration
+ // 4-byte IP address + 4-byte subnet + 4-byte gateway + 3-byte MAC
+
// Unlock the Flash Program Erase controller */
FLASH_Unlock();
// EEPROM Init
EE_Init();
// IP address
- EE_WriteVariable(VirtAddVarTab[0], *buffer++);
- EE_WriteVariable(VirtAddVarTab[1], *buffer++);
- EE_WriteVariable(VirtAddVarTab[2], *buffer++);
- EE_WriteVariable(VirtAddVarTab[3], *buffer++);
+ EE_WriteVariable(VirtAddVarTab[IP_ADDRESS_POS+0], *buffer++);
+ EE_WriteVariable(VirtAddVarTab[IP_ADDRESS_POS+1], *buffer++);
+ EE_WriteVariable(VirtAddVarTab[IP_ADDRESS_POS+2], *buffer++);
+ EE_WriteVariable(VirtAddVarTab[IP_ADDRESS_POS+3], *buffer++);
+
// IP subnet
- EE_WriteVariable(VirtAddVarTab[4], *buffer++);
- EE_WriteVariable(VirtAddVarTab[5], *buffer++);
- EE_WriteVariable(VirtAddVarTab[6], *buffer++);
- EE_WriteVariable(VirtAddVarTab[7], *buffer++);
+ EE_WriteVariable(VirtAddVarTab[IP_SUBNET_POS+0], *buffer++);
+ EE_WriteVariable(VirtAddVarTab[IP_SUBNET_POS+1], *buffer++);
+ EE_WriteVariable(VirtAddVarTab[IP_SUBNET_POS+2], *buffer++);
+ EE_WriteVariable(VirtAddVarTab[IP_SUBNET_POS+3], *buffer++);
+
// IP gateway
- EE_WriteVariable(VirtAddVarTab[8], *buffer++);
- EE_WriteVariable(VirtAddVarTab[9], *buffer++);
- EE_WriteVariable(VirtAddVarTab[10], *buffer++);
- EE_WriteVariable(VirtAddVarTab[11], *buffer++);
- //// TCP server port
- //EE_WriteVariable(VirtAddVarTab[12], *buffer++);
- //// UDP server port
- //EE_WriteVariable(VirtAddVarTab[13], *buffer++);
+ EE_WriteVariable(VirtAddVarTab[IP_GATEWAY_POS+0], *buffer++);
+ EE_WriteVariable(VirtAddVarTab[IP_GATEWAY_POS+1], *buffer++);
+ EE_WriteVariable(VirtAddVarTab[IP_GATEWAY_POS+2], *buffer++);
+ EE_WriteVariable(VirtAddVarTab[IP_GATEWAY_POS+3], *buffer++);
+
+ //// TCP server port, not used
+ //EE_WriteVariable(VirtAddVarTab[TCP_SERVER_PORT_POS], *buffer++);
+ //// UDP server port, not used
+ //EE_WriteVariable(VirtAddVarTab[UDP_SERVER_PORT_POS], *buffer++);
// erase first_run flag
- EE_WriteVariable(VirtAddVarTab[14], 0xA5A5);
+ EE_WriteVariable(VirtAddVarTab[FIRST_RUN_FLAG_POS], 0xA5A5);
+
+ // MAC address
+ EE_WriteVariable(VirtAddVarTab[MAC_ADDRESS_POS+0], *buffer++);
+ EE_WriteVariable(VirtAddVarTab[MAC_ADDRESS_POS+1], *buffer++);
+ EE_WriteVariable(VirtAddVarTab[MAC_ADDRESS_POS+2], *buffer++);
FLASH_Lock();
}
void load_eeprom(void) {
- uint16_t u16ip_addr[4], u16ip_subnet[4], u16ip_gateway[4];
- uint16_t first_run = 0;
+ mbed_mac_address((char *)mac);
EE_Init();
// check if 1st run
- EE_ReadVariable(VirtAddVarTab[14], &first_run);
+ EE_ReadVariable(VirtAddVarTab[FIRST_RUN_FLAG_POS], &first_run);
// if not first run, load network config
if (first_run == 0xA5A5) {
// IP address
- EE_ReadVariable(VirtAddVarTab[0], &u16ip_addr[0]);
- EE_ReadVariable(VirtAddVarTab[1], &u16ip_addr[1]);
- EE_ReadVariable(VirtAddVarTab[2], &u16ip_addr[2]);
- EE_ReadVariable(VirtAddVarTab[3], &u16ip_addr[3]);
+ EE_ReadVariable(VirtAddVarTab[IP_ADDRESS_POS+0], &u16ip_addr[0]);
+ EE_ReadVariable(VirtAddVarTab[IP_ADDRESS_POS+1], &u16ip_addr[1]);
+ EE_ReadVariable(VirtAddVarTab[IP_ADDRESS_POS+2], &u16ip_addr[2]);
+ EE_ReadVariable(VirtAddVarTab[IP_ADDRESS_POS+3], &u16ip_addr[3]);
+
// IP subnet
- EE_ReadVariable(VirtAddVarTab[4], &u16ip_subnet[0]);
- EE_ReadVariable(VirtAddVarTab[5], &u16ip_subnet[1]);
- EE_ReadVariable(VirtAddVarTab[6], &u16ip_subnet[2]);
- EE_ReadVariable(VirtAddVarTab[7], &u16ip_subnet[3]);
+ EE_ReadVariable(VirtAddVarTab[IP_SUBNET_POS+0], &u16ip_subnet[0]);
+ EE_ReadVariable(VirtAddVarTab[IP_SUBNET_POS+1], &u16ip_subnet[1]);
+ EE_ReadVariable(VirtAddVarTab[IP_SUBNET_POS+2], &u16ip_subnet[2]);
+ EE_ReadVariable(VirtAddVarTab[IP_SUBNET_POS+3], &u16ip_subnet[3]);
+
// IP gateway
- EE_ReadVariable(VirtAddVarTab[8], &u16ip_gateway[0]);
- EE_ReadVariable(VirtAddVarTab[9], &u16ip_gateway[1]);
- EE_ReadVariable(VirtAddVarTab[10], &u16ip_gateway[2]);
- EE_ReadVariable(VirtAddVarTab[11], &u16ip_gateway[3]);
+ EE_ReadVariable(VirtAddVarTab[IP_GATEWAY_POS+0], &u16ip_gateway[0]);
+ EE_ReadVariable(VirtAddVarTab[IP_GATEWAY_POS+1], &u16ip_gateway[1]);
+ EE_ReadVariable(VirtAddVarTab[IP_GATEWAY_POS+2], &u16ip_gateway[2]);
+ EE_ReadVariable(VirtAddVarTab[IP_GATEWAY_POS+3], &u16ip_gateway[3]);
+
//// TCP server port
- //EE_ReadVariable(VirtAddVarTab[12], &tcp_server_port);
+ //EE_ReadVariable(VirtAddVarTab[TCP_SERVER_PORT_POS], &tcp_server_port);
//// UDP server port
- //EE_ReadVariable(VirtAddVarTab[13], &udp_server_port);
+ //EE_ReadVariable(VirtAddVarTab[UDP_SERVER_PORT_POS], &udp_server_port);
+
+ // First run flag, already read above
+
+ // MAC address
+ EE_ReadVariable(VirtAddVarTab[MAC_ADDRESS_POS+0], &u16mac_addr[0]);
+ EE_ReadVariable(VirtAddVarTab[MAC_ADDRESS_POS+1], &u16mac_addr[1]);
+ EE_ReadVariable(VirtAddVarTab[MAC_ADDRESS_POS+2], &u16mac_addr[2]);
+ mac[3] = (uint8_t)(u16mac_addr[0] & 0x00FF);
+ mac[4] = (uint8_t)(u16mac_addr[1] & 0x00FF);
+ mac[5] = (uint8_t)(u16mac_addr[2] & 0x00FF);
//FLASH_Lock();
+
sprintf(ip_addr, "%d.%d.%d.%d", (uint8_t)u16ip_addr[0], (uint8_t)u16ip_addr[1], (uint8_t)u16ip_addr[2], (uint8_t)u16ip_addr[3]);
sprintf(ip_subnet, "%d.%d.%d.%d", (uint8_t)u16ip_subnet[0], (uint8_t)u16ip_subnet[1], (uint8_t)u16ip_subnet[2], (uint8_t)u16ip_subnet[3]);
sprintf(ip_gateway, "%d.%d.%d.%d", (uint8_t)u16ip_gateway[0], (uint8_t)u16ip_gateway[1], (uint8_t)u16ip_gateway[2], (uint8_t)u16ip_gateway[3]);
}
// if 1st run, use default addresses
else {
+ mac[0] = 0x00; mac[1] = 0x08; mac[2] = 0xDC;
+ mac[3] = DEFAULT_MAC3; mac[4] = DEFAULT_MAC4; mac[5] = DEFAULT_MAC5;
sprintf(ip_addr, DEFAULT_IP_ADDRESS);
sprintf(ip_subnet, DEFAULT_IP_SUBNET);
sprintf(ip_gateway, DEFAULT_IP_GATEWAY);
@@ -216,12 +287,12 @@
int main()
{
message_t message;
- int ret;
+ int n, ret;
/*
- * configure
+ * Configure
*/
- uart.baud(115200);
+ //uart.baud(115200);
/*
@@ -271,6 +342,23 @@
// Network processor
while (true) {
+#ifdef NTP
+ printf("Trying to update time...\r\n");
+ if (ntp.setTime("0.pool.ntp.org") == 0)
+ {
+ printf("Set time successfully\r\n");
+ time_t ctTime;
+ ctTime = time(NULL);
+ printf("Time is set to (UTC): %s\r\n", ctime(&ctTime));
+ }
+ else
+ {
+ printf("Error\r\n");
+ }
+#endif
+
+
+// FOR INTERFACING
#ifdef TCP_SERVER
// no tcp client connected
if (!tcp_client.is_connected())
@@ -285,73 +373,117 @@
// loop waiting and receiving data within timeout
tcp_client.set_blocking(false, TCP_SERVER_RECEIVE_TIMEOUT); // Timeout after x seconds
while (true) {
- int n = tcp_client.receive(buffer, sizeof(buffer));
+ n = tcp_client.receive(buffer, sizeof(buffer));
if (n <= 0) break;
- // got data, process it
- // send to uart
- buffer[n] = '\0';
- message.len = n;
- message.msg = buffer;
- uart_queue.put(&message);
+ // got some data, test it
+ //// send to uart
+ //buffer[n] = '\0';
+ //message.len = n;
+ //message.msg = buffer;
+ //uart_queue.put(&message);
+ //// echo to tcp client
+ //tcp_client.send_all(buffer, n);
+ //if (n <= 0) break;
- // echo to tcp client
- tcp_client.send_all(buffer, n);
- if (n <= 0) break;
+ // process received data
+ switch (n) {
+ // length 58-bytes, Receiving protocol
+ case 58: {
+ // check device id
+ char* id = strstr(buffer, DEVICE_ID);
+ if (id == NULL)
+ break;
+ else if ((id - buffer) > 0)
+ break;
+
+
+ // firstly, update outputs if required
+ // digital outputs
+ if (((uint8_t)buffer[RECEIVING_PROTOCOL_EN_DO_POS] - RECEIVING_PROTOCOL_ENABLE_OUTPUT) == 0) {
+ }
+ // analog output 0
+ if (((uint8_t)buffer[RECEIVING_PROTOCOL_EN_A0O_POS] - RECEIVING_PROTOCOL_ENABLE_OUTPUT) == 0) {
+ }
+ // analog output 0
+ if (((uint8_t)buffer[RECEIVING_PROTOCOL_EN_A1O_POS] - RECEIVING_PROTOCOL_ENABLE_OUTPUT) == 0) {
+ }
+ // UART
+ if (((uint8_t)buffer[RECEIVING_PROTOCOL_EN_UART_POS] - RECEIVING_PROTOCOL_ENABLE_OUTPUT) == 0) {
+ }
+
+ // then, check query status command and sending protocol if required
+ if (((uint8_t)buffer[RECEIVING_PROTOCOL_COMMAND_POS] - QUERY_STATUS_COMMAND) == 0) {
+ // sending protocol
+ }
+
+ break;
+ }
+ default:
+ break;
+ }
+
} // end loop if no data received within timeout
tcp_client.close();
} // if client connected
} // if no client connected
#endif
-
-#ifdef UDP_SERVER // used for setting configuration
+
+
+// ONLY FOR CONFIGRATION
+#ifdef UDP_SERVER
// wait for udp packet within timeout
- int n = udp_server.receiveFrom(ep_udp_client, buffer, sizeof(buffer));
- if (n < 0) continue;
+ n = udp_server.receiveFrom(ep_udp_client, buffer, sizeof(buffer));
+ if (n <= 0) continue;
- // got some data, process it
- // send to uart
+ // got some data, test it
+ //// send to uart
//buffer[n] = '\0';
//message.len = n;
//message.msg = buffer;
//uart_queue.put(&message);
-
- // echo
+ //// echo
//printf("Received packet from: %s\n", client.get_address());
//udp_server.sendTo(ep_udp_client, buffer, n);
// process received data
switch (n) {
- // length = 4, may be this is a discovery command, TCP port, or UDP port
- // Format: NNDS, NNTP or NNUP
- case 4:
+ // length = 6, a CONFIGURATION command (discovery command, TCP port, or UDP port)
+ // Format: NNIODS, NNIOTP or NNIOUP
+ case 6:
// discovery command
- if (strstr(buffer, "NNDS") != NULL) {
+ if (strstr(buffer, "NNIODS") != NULL) {
udp_server.sendTo(ep_udp_client, ip_addr, strlen(ip_addr));
}
// ask for TCP server port
- else if (strstr(buffer, "NNTP") != NULL) {
+ else if (strstr(buffer, "NNIOTP") != NULL) {
char port[5];
sprintf(port, "%5d", tcp_server_port);
udp_server.sendTo(ep_udp_client, port, strlen(port));
}
// ask for UDP server port
- else if (strstr(buffer, "NNUP") != NULL) {
+ else if (strstr(buffer, "NNIOUP") != NULL) {
char port[5];
sprintf(port, "%5d", udp_server_port);
udp_server.sendTo(ep_udp_client, port, strlen(port));
}
break;
- // length = 14, maybe this is a command to set network configuration
- // Format: 4E 4E C0 A8 00 78 FF FF FF 00 C0 A8 0 1 (NN 192.168.0.120; 255.255.255.0; 192.168.0.1)
- case 14:
- // check if two first chars = NN
- if (strstr(buffer, "NN") != NULL) {
- //printf("Received new network configuration\n");
- write_eeprom(&buffer[2]); // parameters from 3rd char
- }
+ // length = 19, SET NETWORK CONFIGURATION
+ // Format: 4E 4E 49 4F C0 A8 00 78 FF FF FF 00 C0 A8 00 01 00 00 01
+ // (NNIO; IP: 192.168.0.120; Subnet: 255.255.255.0; GW: 192.168.0.1; MAC: 0 0 1)
+ case 19:{
+ // check device id
+ char* id = strstr(buffer, DEVICE_ID);
+ if (id == NULL)
+ break;
+ else if ((id - buffer) > 0)
+ break;
+
+ //printf("Received new network configuration\n");
+ write_eeprom(&buffer[4]); // parameters from 3rd char, 15-bytes
break;
+ }
default:
break;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/readme.txt Fri Sep 26 20:07:34 2014 +0000
@@ -0,0 +1,63 @@
+CONFIGURATION SECTION (UDP)
+1. DISCOVERY Command
+ + UDP broadcast: 192.168.0.255 to port 11000
+ + Send: NNIODS
+ + Receive: IP address
+
+2. TCP SERVER PORT Command
+ + Send: NNIOTP
+ + Receive: 10000
+
+3. UDP SERVER PORT Command
+ + Send: NNIOUP
+ + Receive: 11000
+
+3. Set new network configuration
+ + Send: 19 bytes in total, NNIO + 15-byte
+ 15-byte = 4-byte IP address + 4-byte subnet + 4-byte gateway + 3-byte MAC
+
+INTERFACING SECTION (TCP)
+4. Receiving Protocol: 58-bytes in total
+ + Field ID (4-bytes) = NNIO
+ + Field OP (5-bytes): output control enable flag
+ Byte 1: Digital output
+ Byte 2: Analog output 0
+ Byte 3: Analog output 1
+ Byte 4: UART output
+ Byte 5: Command (Q: query status)
+ 'O': enable controlling output
+ Others: disable controlling output
+ If Command is 'Q', device will update its outputs if needed and send its status including new outputs
+ + Field IP (4-bytes): device IP address
+ + Field DO[n] (8-bytes): digital output values
+ 'H': output set to high
+ 'L': output set to low
+ + Field AO_0 (2-bytes): 16-bit analog output value, channel 0
+ Range is from 0x0000 to 0x0FFF
+ + Field AO_1 (2-bytes): 16-bit analog output value, channel 1
+ Range is from 0x0000 to 0x0FFF
+ + UART output (32-bytes): max 32 bytes, stop string by NULL
+ + End char: CR
+
+5. Sending Protocol: 39-bytes in total
+ + Field ID (4-bytes) = NNIO
+ + Field MAC (6-bytes)
+ + Field IP (4-bytes)
+ + Field DI[n]: 8-bit digital input values
+ 'H' if input is HIGH
+ 'L' if input is LOW
+ + Field DO[n]: 8-bit digital output values
+ 'H' if output is HIGH
+ 'L' if output is LOW
+ + Field AI_0 (2-bytes): analog 16-bit input value, channel 0
+ Range is from 0x0000 to 0x0FFF
+ + Field AI_1 (2-bytes): analog 16-bit input value, channel 1
+ Range is from 0x0000 to 0x0FFF
+ + Field AO_0 (2-bytes): 16-bit analog output value, channel 0
+ Range is from 0x0000 to 0x0FFF
+ + Field AO_1 (2-bytes): 16-bit analog output value, channel 1
+ Range is from 0x0000 to 0x0FFF
+ + End char: CR
+
+6 Commands:
+ + QUERY STATUS ('Q')
\ No newline at end of file
