implementation of parts of the unilynx protocol, for communicating with danfos photovoltaic inverters. Still BETA ! needs byte stuff/unstuff fixed, and some CRC are left out for niw...
unilynx.cpp
00001 /** 00002 * <describing text> 00003 * 00004 * @file commlynx_protocol.c.c 00005 * @ingroup <> 00006 * 00007 * @author MortenOJ 00008 * @date Aug 24, 2012 00009 * 00010 */ 00011 #include "mbed.h" 00012 #include "unilynx.h" 00013 #include "crc.h" 00014 00015 00016 Serial rs485(p26, p25); 00017 //#define DEBUG 00018 #ifdef DEBUG 00019 Serial pc(USBTX, USBRX); 00020 #endif 00021 00022 // Telegram format 00023 //---------------------------------------------------------------------------------------------------- 00024 // Start of frame / Header / Data / End of frame 00025 // Start / Address / Control / Source / Destination / Size / Type / Data / FCS / Stop 00026 // 1byte / 1byte / 1byte / 2bytes / 2bytes / 1byte / 1byte / 0-255bytes / 2bytes / 1byte 00027 //---------------------------------------------------------------------------------------------------- 00028 //unsigned char txStr[255]; 00029 00030 #define MY_ADDR0 0x28 00031 #define MY_ADDR1 0xD7 00032 00033 #define FRAME_START 0x7E 00034 #define FRAME_STOP 0x7E 00035 #define FRAME_ADDRESS 0xFF 00036 #define FRAME_CONTROL 0x03 00037 00038 #define PPPINITFCS16 0xFFFF /* Initial FCS value */ 00039 #define PPPGOODFCS16 0xf0b8 /* Good final FCS value */ 00040 00041 const unsigned char pingAllStr[12] = 00042 { 0x7E, 0xFF, 0x03, 0x00, 0x02, 0xFF, 0xFF, 0x00, 0x15, 0xB1, 0x8B, 0x7E }; 00043 00044 00045 char pingAllStrWoCrc[12] = 00046 { 0x7E, 0xFF, 0x03, 0x00, 0x02, 0xFF, 0xFF, 0x00, 0x15, 0, 0, 0x7E }; 00047 //{ 0x7E, 0xFF, 0x03, 0x00, 0x02, 0x12, 0x03, 0x00, 0x15, 0, 0, 0x7E }; 00048 /* func code 0x13*/ 00049 00050 char getNodeReqStrWoCrc[41] = { 00051 0x7E, 0xFF, 0x03, 0x00, 0x02, 0x28, 0xD7, 0x1D, 0x13, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 00052 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 00053 0xFF, 0x00, 0x00, 0x7E 00054 }; 00055 00056 char getNodeParamStrWoCrc[41] = 00057 { 0x7E, 0xFF, 0x03, 0x00, 0x02, 0x28, 0xD7, 0x0A, 0x01, 0xC8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x7E }; 00058 00059 00060 char tx[40]; 00061 00062 /* 00063 Steup RS 485 ON UART1,using DTR for direction control on RS485 00064 */ 00065 void rs485init(void) 00066 { 00067 rs485.baud(19200); 00068 #ifdef DEBUG 00069 pc.baud(115200); 00070 #endif 00071 LPC_PINCON->PINSEL4 &= 0x0ffff; 00072 LPC_PINCON->PINSEL4 |= 0x0AAAA; 00073 00074 LPC_UART1->RS485DLY = 128; 00075 00076 LPC_UART1->RS485CTRL &=~(1<<1); //Receiver enabled 00077 LPC_UART1->RS485CTRL &=~(1<<2); //AAD disabled 00078 LPC_UART1->RS485CTRL |= (1<<3); //DTR used for direction control 00079 LPC_UART1->RS485CTRL |= (1<<4); //direction control enabled 00080 LPC_UART1->RS485CTRL |= (1<<5); //DTR=1 when transmitting 00081 } 00082 00083 static void rs485write(char* str, int len) 00084 { 00085 int i; 00086 i=0; 00087 while(i < len) 00088 { 00089 /* Byte stuff needed ? */ 00090 /* if((*(str +i)) == 0x7E) 00091 { 00092 rs485.putc(0x7D); 00093 rs485.putc(0x5E); 00094 } 00095 else if((*(str +i)) == 0x7D) 00096 { 00097 rs485.putc(0x7D); 00098 rs485.putc(0x5D); 00099 } 00100 /* 00101 /* nope, TX as usual */ 00102 //else 00103 rs485.putc(*(str +i)); 00104 /* incr. index */ 00105 i++; 00106 } 00107 } 00108 00109 static void rs485read(char* str, int len) 00110 { 00111 int i; 00112 i=0; 00113 while(i < len) { 00114 (*(str +i)) = rs485.getc(); 00115 00116 #if 0 00117 /* Byte unstuff needed ? */ 00118 if(((*(str +i-1)) == 0x7D) &&((*(str +i)) == 0x5E)) 00119 { 00120 /* subtract first bytestuff-byte w 0x7E*/ 00121 (*(str +i-1)) = 0x7E; 00122 /*decrement indenx, so next byte will contain next RX char, 00123 and not byte-stuff leftovers..*/ 00124 i--; 00125 /*and btw. we need read one more char, since byte stuff has added one...*/ 00126 len++; 00127 } 00128 else if(((*(str +i-1)) == 0x7D) &&((*(str +i)) == 0x5D)) 00129 00130 { 00131 (*(str +i-1)) = 0x7D; 00132 i--; 00133 len++; 00134 } 00135 #endif 00136 i++; 00137 //TODO add timeout 00138 } 00139 } 00140 00141 /* 00142 Get node info, serial no etc... 00143 currently kept in local variables insode function. 00144 */ 00145 void getNodeInfo(void) 00146 { 00147 /* data of interest TODO MAKE GLOBAL AVAILIBLE */ 00148 char network, subnet, address; 00149 00150 /*local variables*/ 00151 char rx[42]; 00152 short fcs; 00153 /* fill in address */ 00154 getNodeReqStrWoCrc[5] = MY_ADDR0; 00155 getNodeReqStrWoCrc[6] = MY_ADDR1; 00156 /* calculate CRC and fill in string */ 00157 fcs = pppfcs16( PPPINITFCS16, &getNodeReqStrWoCrc[1], 37 ); 00158 fcs ^= 0xFFFF; 00159 getNodeReqStrWoCrc[38] = (unsigned char)(fcs & 0xFF); 00160 getNodeReqStrWoCrc[39] = (unsigned char)((fcs>>8) & 0xFF); 00161 /* send request */ 00162 rs485write(getNodeReqStrWoCrc,41); 00163 /* retrieve response */ 00164 rs485read(rx,41); 00165 //TODO CRC 00166 /* extract data*/ 00167 network = rx[33]; 00168 subnet = rx[34]; 00169 address = rx[35]; 00170 00171 //pc.printf("Network: %X Subnet: %X Address: %X",network,subnet, address); 00172 } 00173 00174 /* 00175 read a parameter from the inverter 00176 @param param_idx "index" used to retrieve parameter values 00177 @param param_sub_idx "sub-index" used to retrieve parameter values 00178 */ 00179 int readParameter(int param_idx, int param_sub_idx, int dest) 00180 { 00181 short fcs; 00182 short u16val; 00183 int u32val; 00184 char rx[24]; 00185 char flags; 00186 00187 00188 /* fill in address */ 00189 getNodeParamStrWoCrc[5] = MY_ADDR0; 00190 getNodeParamStrWoCrc[6] = MY_ADDR1; 00191 00192 getNodeParamStrWoCrc[10] = dest;//0x04;//0D;// 00193 getNodeParamStrWoCrc[11] = 0xD0;//((source<<4) | page); 00194 getNodeParamStrWoCrc[12] = (param_idx); 00195 getNodeParamStrWoCrc[13] = (param_sub_idx); 00196 getNodeParamStrWoCrc[14] = 0x80;// we want reply (DO_REPLY | IM_REQUEST | TYPE_U16); 00197 getNodeParamStrWoCrc[15] = 0; 00198 getNodeParamStrWoCrc[16] = 0; 00199 getNodeParamStrWoCrc[17] = 0; 00200 getNodeParamStrWoCrc[18] = 0; 00201 00202 /* calculate VRC and fill in string */ 00203 fcs = pppfcs16( PPPINITFCS16, &getNodeParamStrWoCrc[1], 18 ); 00204 fcs ^= 0xFFFF; 00205 getNodeParamStrWoCrc[19] = (unsigned char)(fcs & 0xFF); 00206 getNodeParamStrWoCrc[20] = (unsigned char)((fcs>>8) & 0xFF); 00207 00208 /* send request */ 00209 rs485write(getNodeParamStrWoCrc,22); 00210 /* retrieve response */ 00211 rs485read(rx,22); 00212 //TODO CRC 00213 /* extract data*/ 00214 flags = rx[14]; 00215 00216 switch (flags & 0x0F) { 00217 case 0x06: //decode U16 00218 u16val = ((rx[16]<<8)+rx[15]); 00219 return (int)u16val; 00220 break; 00221 case 0x07: //decode U32 00222 u32val = ((rx[18]<<24)+(rx[17]<<16)+(rx[16]<<8)+rx[15]); 00223 return u32val; 00224 break; 00225 default: 00226 #ifdef DEBUG 00227 com.printf("You got work to do !! Flags are: %X" ,rx[14]); 00228 #endif 00229 break; 00230 } 00231 } 00232 00233 void ping(void) 00234 { 00235 int rxcnt = 0; 00236 char rx[14]; 00237 short fcs; 00238 00239 for(int i=0; i < 12; i++) { 00240 rs485.putc(pingAllStr[i]); 00241 } 00242 while(1) { 00243 if(rs485.readable()) { 00244 rx[rxcnt++] = rs485.getc(); 00245 } 00246 /* reached stop 0x7E ? todo, timeout & CRC*/ 00247 if( rxcnt > 10) 00248 if(rx[rxcnt] == 0x7E) 00249 break; 00250 if( rxcnt == 11) 00251 break; 00252 } 00253 }
Generated on Sat Jul 23 2022 00:24:37 by 1.7.2