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...

Dependencies:   mbed

Committer:
morten_opprud
Date:
Mon Aug 27 18:30:37 2012 +0000
Revision:
0:66a099b01e08
Child:
1:df4e9da66448
alive, can ping, read info and query first values from ulx :-);

Who changed what in which revision?

UserRevisionLine numberNew contents of line
morten_opprud 0:66a099b01e08 1 /**
morten_opprud 0:66a099b01e08 2 * <describing text>
morten_opprud 0:66a099b01e08 3 *
morten_opprud 0:66a099b01e08 4 * @file commlynx_protocol.c.c
morten_opprud 0:66a099b01e08 5 * @ingroup <>
morten_opprud 0:66a099b01e08 6 *
morten_opprud 0:66a099b01e08 7 * @author MortenOJ
morten_opprud 0:66a099b01e08 8 * @date Aug 24, 2012
morten_opprud 0:66a099b01e08 9 *
morten_opprud 0:66a099b01e08 10 */
morten_opprud 0:66a099b01e08 11
morten_opprud 0:66a099b01e08 12 //#include <stdio.h>
morten_opprud 0:66a099b01e08 13 //#include <stdlib.h>
morten_opprud 0:66a099b01e08 14 #include "mbed.h"
morten_opprud 0:66a099b01e08 15 #include "unilynx.h"
morten_opprud 0:66a099b01e08 16 #include "crc.h"
morten_opprud 0:66a099b01e08 17
morten_opprud 0:66a099b01e08 18 #define DEBUG
morten_opprud 0:66a099b01e08 19
morten_opprud 0:66a099b01e08 20 Serial rs485(p26, p25);
morten_opprud 0:66a099b01e08 21 Serial pc(USBTX, USBRX);
morten_opprud 0:66a099b01e08 22
morten_opprud 0:66a099b01e08 23
morten_opprud 0:66a099b01e08 24 // Telegram format
morten_opprud 0:66a099b01e08 25 //----------------------------------------------------------------------------------------------------
morten_opprud 0:66a099b01e08 26 // Start of frame / Header / Data / End of frame
morten_opprud 0:66a099b01e08 27 // Start / Address / Control / Source / Destination / Size / Type / Data / FCS / Stop
morten_opprud 0:66a099b01e08 28 // 1byte / 1byte / 1byte / 2bytes / 2bytes / 1byte / 1byte / 0-255bytes / 2bytes / 1byte
morten_opprud 0:66a099b01e08 29 //----------------------------------------------------------------------------------------------------
morten_opprud 0:66a099b01e08 30 //unsigned char txStr[255];
morten_opprud 0:66a099b01e08 31
morten_opprud 0:66a099b01e08 32 #define MY_ADDR0 0x28
morten_opprud 0:66a099b01e08 33 #define MY_ADDR1 0xD7
morten_opprud 0:66a099b01e08 34
morten_opprud 0:66a099b01e08 35 #define FRAME_START 0x7E
morten_opprud 0:66a099b01e08 36 #define FRAME_STOP 0x7E
morten_opprud 0:66a099b01e08 37 #define FRAME_ADDRESS 0xFF
morten_opprud 0:66a099b01e08 38 #define FRAME_CONTROL 0x03
morten_opprud 0:66a099b01e08 39
morten_opprud 0:66a099b01e08 40 #define PPPINITFCS16 0xFFFF /* Initial FCS value */
morten_opprud 0:66a099b01e08 41 #define PPPGOODFCS16 0xf0b8 /* Good final FCS value */
morten_opprud 0:66a099b01e08 42
morten_opprud 0:66a099b01e08 43 const unsigned char pingAllStr[12] =
morten_opprud 0:66a099b01e08 44 { 0x7E, 0xFF, 0x03, 0x00, 0x02, 0xFF, 0xFF, 0x00, 0x15, 0xB1, 0x8B, 0x7E };
morten_opprud 0:66a099b01e08 45
morten_opprud 0:66a099b01e08 46
morten_opprud 0:66a099b01e08 47
morten_opprud 0:66a099b01e08 48 /*const char getNodeReqStr[41] =
morten_opprud 0:66a099b01e08 49 { 0x7E, 0xFF, 0x03, 0x00, 0x02, 0x12, 0x03, 0x1D, 0x13, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
morten_opprud 0:66a099b01e08 50 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
morten_opprud 0:66a099b01e08 51 0xFF, 0xC9, 0x35, 0x7E };
morten_opprud 0:66a099b01e08 52 */
morten_opprud 0:66a099b01e08 53 /*
morten_opprud 0:66a099b01e08 54 const char getNodeReqStr[41] =
morten_opprud 0:66a099b01e08 55 { 0x7E, 0xFF, 0x03, 0x00, 0x02, 0x12, 0x03, 0x1D, 0x13, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
morten_opprud 0:66a099b01e08 56 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
morten_opprud 0:66a099b01e08 57 0xFF, 0xC9, 0x35, 0x7E };
morten_opprud 0:66a099b01e08 58 */
morten_opprud 0:66a099b01e08 59
morten_opprud 0:66a099b01e08 60 char pingAllStrWoCrc[12] =
morten_opprud 0:66a099b01e08 61 { 0x7E, 0xFF, 0x03, 0x00, 0x02, 0xFF, 0xFF, 0x00, 0x15, 0, 0, 0x7E };
morten_opprud 0:66a099b01e08 62 //{ 0x7E, 0xFF, 0x03, 0x00, 0x02, 0x12, 0x03, 0x00, 0x15, 0, 0, 0x7E };
morten_opprud 0:66a099b01e08 63 /* func code 0x13*/
morten_opprud 0:66a099b01e08 64
morten_opprud 0:66a099b01e08 65 char getNodeReqStrWoCrc[41] = {
morten_opprud 0:66a099b01e08 66 0x7E, 0xFF, 0x03, 0x00, 0x02, 0x28, 0xD7, 0x1D, 0x13, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
morten_opprud 0:66a099b01e08 67 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
morten_opprud 0:66a099b01e08 68 0xFF, 0x00, 0x00, 0x7E
morten_opprud 0:66a099b01e08 69 };
morten_opprud 0:66a099b01e08 70
morten_opprud 0:66a099b01e08 71 char getNodeParamStrWoCrc[41] =
morten_opprud 0:66a099b01e08 72 { 0x7E, 0xFF, 0x03, 0x00, 0x02, 0x28, 0xD7, 0x0A, 0x01, 0xC8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x7E };
morten_opprud 0:66a099b01e08 73
morten_opprud 0:66a099b01e08 74
morten_opprud 0:66a099b01e08 75 char tx[40];
morten_opprud 0:66a099b01e08 76
morten_opprud 0:66a099b01e08 77 void rs485init(void)
morten_opprud 0:66a099b01e08 78 {
morten_opprud 0:66a099b01e08 79 rs485.baud(19200);
morten_opprud 0:66a099b01e08 80 pc.baud(115200);
morten_opprud 0:66a099b01e08 81
morten_opprud 0:66a099b01e08 82 LPC_PINCON->PINSEL4 &= 0x0ffff;
morten_opprud 0:66a099b01e08 83 LPC_PINCON->PINSEL4 |= 0x0AAAA;
morten_opprud 0:66a099b01e08 84
morten_opprud 0:66a099b01e08 85 LPC_UART1->RS485DLY = 128;
morten_opprud 0:66a099b01e08 86
morten_opprud 0:66a099b01e08 87 LPC_UART1->RS485CTRL &=~(1<<1); //Receiver enabled
morten_opprud 0:66a099b01e08 88 LPC_UART1->RS485CTRL &=~(1<<2); //AAD disabled
morten_opprud 0:66a099b01e08 89 LPC_UART1->RS485CTRL |= (1<<3); //DTR used for direction control
morten_opprud 0:66a099b01e08 90 LPC_UART1->RS485CTRL |= (1<<4); //direction control enabled
morten_opprud 0:66a099b01e08 91 LPC_UART1->RS485CTRL |= (1<<5); //DTR=1 when transmitting
morten_opprud 0:66a099b01e08 92 }
morten_opprud 0:66a099b01e08 93
morten_opprud 0:66a099b01e08 94 void rs485write(char* str, int len)
morten_opprud 0:66a099b01e08 95 {
morten_opprud 0:66a099b01e08 96 int i;
morten_opprud 0:66a099b01e08 97 i=0;
morten_opprud 0:66a099b01e08 98 while(i < len)
morten_opprud 0:66a099b01e08 99 {
morten_opprud 0:66a099b01e08 100 rs485.putc(*(str +i));
morten_opprud 0:66a099b01e08 101 i++;
morten_opprud 0:66a099b01e08 102 }
morten_opprud 0:66a099b01e08 103 #ifdef DEBUG2
morten_opprud 0:66a099b01e08 104 i=0;
morten_opprud 0:66a099b01e08 105 pc.printf("TX:");
morten_opprud 0:66a099b01e08 106 while(i < len)
morten_opprud 0:66a099b01e08 107 {
morten_opprud 0:66a099b01e08 108 pc.putc(*(str +i));
morten_opprud 0:66a099b01e08 109 i++;
morten_opprud 0:66a099b01e08 110 }
morten_opprud 0:66a099b01e08 111 #endif
morten_opprud 0:66a099b01e08 112 }
morten_opprud 0:66a099b01e08 113
morten_opprud 0:66a099b01e08 114 static void rs485read(char* str, int len)
morten_opprud 0:66a099b01e08 115 {
morten_opprud 0:66a099b01e08 116 int i;
morten_opprud 0:66a099b01e08 117 i=0;
morten_opprud 0:66a099b01e08 118 while(i < len) {
morten_opprud 0:66a099b01e08 119 (*(str +i)) = rs485.getc();
morten_opprud 0:66a099b01e08 120 i++;
morten_opprud 0:66a099b01e08 121 //TODO add timeout
morten_opprud 0:66a099b01e08 122 }
morten_opprud 0:66a099b01e08 123 #ifdef DEBUG
morten_opprud 0:66a099b01e08 124 i=0;
morten_opprud 0:66a099b01e08 125 pc.printf("RX:");
morten_opprud 0:66a099b01e08 126 while(i < len)
morten_opprud 0:66a099b01e08 127 {
morten_opprud 0:66a099b01e08 128 pc.putc(*(str +i));
morten_opprud 0:66a099b01e08 129 i++;
morten_opprud 0:66a099b01e08 130 }
morten_opprud 0:66a099b01e08 131 #endif
morten_opprud 0:66a099b01e08 132
morten_opprud 0:66a099b01e08 133 }
morten_opprud 0:66a099b01e08 134
morten_opprud 0:66a099b01e08 135 void getNodeInfo(void)
morten_opprud 0:66a099b01e08 136 {
morten_opprud 0:66a099b01e08 137 /* data of interest TODO MAKE GLOBAL AVAILIBLE */
morten_opprud 0:66a099b01e08 138 char network, subnet, address;
morten_opprud 0:66a099b01e08 139
morten_opprud 0:66a099b01e08 140 /*local variables*/
morten_opprud 0:66a099b01e08 141 char rx[42];
morten_opprud 0:66a099b01e08 142 short fcs;
morten_opprud 0:66a099b01e08 143 /* fill in address */
morten_opprud 0:66a099b01e08 144 getNodeReqStrWoCrc[5] = MY_ADDR0;
morten_opprud 0:66a099b01e08 145 getNodeReqStrWoCrc[6] = MY_ADDR1;
morten_opprud 0:66a099b01e08 146 /* calculate CRC and fill in string */
morten_opprud 0:66a099b01e08 147 fcs = pppfcs16( PPPINITFCS16, &getNodeReqStrWoCrc[1], 37 );
morten_opprud 0:66a099b01e08 148 fcs ^= 0xFFFF;
morten_opprud 0:66a099b01e08 149 getNodeReqStrWoCrc[38] = (unsigned char)(fcs & 0xFF);
morten_opprud 0:66a099b01e08 150 getNodeReqStrWoCrc[39] = (unsigned char)((fcs>>8) & 0xFF);
morten_opprud 0:66a099b01e08 151 /* send request */
morten_opprud 0:66a099b01e08 152 rs485write(getNodeReqStrWoCrc,41);
morten_opprud 0:66a099b01e08 153 /* retrieve response */
morten_opprud 0:66a099b01e08 154 rs485read(rx,41);
morten_opprud 0:66a099b01e08 155 /* extract data*/
morten_opprud 0:66a099b01e08 156 network = rx[33];
morten_opprud 0:66a099b01e08 157 subnet = rx[34];
morten_opprud 0:66a099b01e08 158 address = rx[35];
morten_opprud 0:66a099b01e08 159
morten_opprud 0:66a099b01e08 160 //pc.printf("Network: %X Subnet: %X Address: %X",network,subnet, address);
morten_opprud 0:66a099b01e08 161 }
morten_opprud 0:66a099b01e08 162
morten_opprud 0:66a099b01e08 163 void readParameter(int param_idx, int param_sub_idx)
morten_opprud 0:66a099b01e08 164 {
morten_opprud 0:66a099b01e08 165 short fcs;
morten_opprud 0:66a099b01e08 166 char rx[24];
morten_opprud 0:66a099b01e08 167 char flags;
morten_opprud 0:66a099b01e08 168
morten_opprud 0:66a099b01e08 169 /* fill in address */
morten_opprud 0:66a099b01e08 170 getNodeParamStrWoCrc[5] = MY_ADDR0;
morten_opprud 0:66a099b01e08 171 getNodeParamStrWoCrc[6] = MY_ADDR1;
morten_opprud 0:66a099b01e08 172
morten_opprud 0:66a099b01e08 173 getNodeParamStrWoCrc[10] = 0x04;//0D;//dest;
morten_opprud 0:66a099b01e08 174 getNodeParamStrWoCrc[11] = 0xD0;//((source<<4) | page);
morten_opprud 0:66a099b01e08 175 getNodeParamStrWoCrc[12] = (param_idx);
morten_opprud 0:66a099b01e08 176 getNodeParamStrWoCrc[13] = (param_sub_idx);
morten_opprud 0:66a099b01e08 177 getNodeParamStrWoCrc[14] = 0x80;// we want reply (DO_REPLY | IM_REQUEST | TYPE_U16);
morten_opprud 0:66a099b01e08 178 getNodeParamStrWoCrc[15] = 0;
morten_opprud 0:66a099b01e08 179 getNodeParamStrWoCrc[16] = 0;
morten_opprud 0:66a099b01e08 180 getNodeParamStrWoCrc[17] = 0;
morten_opprud 0:66a099b01e08 181 getNodeParamStrWoCrc[18] = 0;
morten_opprud 0:66a099b01e08 182
morten_opprud 0:66a099b01e08 183 /* calculate VRC and fill in string */
morten_opprud 0:66a099b01e08 184 fcs = pppfcs16( PPPINITFCS16, &getNodeParamStrWoCrc[1], 18 );
morten_opprud 0:66a099b01e08 185 fcs ^= 0xFFFF;
morten_opprud 0:66a099b01e08 186 getNodeParamStrWoCrc[19] = (unsigned char)(fcs & 0xFF);
morten_opprud 0:66a099b01e08 187 getNodeParamStrWoCrc[20] = (unsigned char)((fcs>>8) & 0xFF);
morten_opprud 0:66a099b01e08 188
morten_opprud 0:66a099b01e08 189 /* send request */
morten_opprud 0:66a099b01e08 190 rs485write(getNodeParamStrWoCrc,22);
morten_opprud 0:66a099b01e08 191 /* retrieve response */
morten_opprud 0:66a099b01e08 192 rs485read(rx,22);
morten_opprud 0:66a099b01e08 193 /* extract data*/
morten_opprud 0:66a099b01e08 194 flags = rx[14];
morten_opprud 0:66a099b01e08 195
morten_opprud 0:66a099b01e08 196 switch (flags & 0x0F)
morten_opprud 0:66a099b01e08 197 {
morten_opprud 0:66a099b01e08 198 case 0x07: //U32
morten_opprud 0:66a099b01e08 199 pc.printf("VAl: %d %d %d %d",rx[15],rx[16],rx[17],rx[18]);
morten_opprud 0:66a099b01e08 200 break;
morten_opprud 0:66a099b01e08 201 default:
morten_opprud 0:66a099b01e08 202 pc.printf("Flags: %X" ,rx[14]);
morten_opprud 0:66a099b01e08 203 break;
morten_opprud 0:66a099b01e08 204 }
morten_opprud 0:66a099b01e08 205 }
morten_opprud 0:66a099b01e08 206
morten_opprud 0:66a099b01e08 207
morten_opprud 0:66a099b01e08 208 void test(void)
morten_opprud 0:66a099b01e08 209 {
morten_opprud 0:66a099b01e08 210 //pc.baud(19200);
morten_opprud 0:66a099b01e08 211
morten_opprud 0:66a099b01e08 212 while(1) {
morten_opprud 0:66a099b01e08 213 if(pc.readable())
morten_opprud 0:66a099b01e08 214 rs485.putc(pc.getc());
morten_opprud 0:66a099b01e08 215
morten_opprud 0:66a099b01e08 216 if(rs485.readable())
morten_opprud 0:66a099b01e08 217 pc.putc(rs485.getc());
morten_opprud 0:66a099b01e08 218 }
morten_opprud 0:66a099b01e08 219 }
morten_opprud 0:66a099b01e08 220
morten_opprud 0:66a099b01e08 221 void ping(void)
morten_opprud 0:66a099b01e08 222 {
morten_opprud 0:66a099b01e08 223 int rxcnt = 0;
morten_opprud 0:66a099b01e08 224 char rx[14];
morten_opprud 0:66a099b01e08 225 short fcs;
morten_opprud 0:66a099b01e08 226
morten_opprud 0:66a099b01e08 227 for(int i=0; i < 12; i++) {
morten_opprud 0:66a099b01e08 228 rs485.putc(pingAllStr[i]);
morten_opprud 0:66a099b01e08 229 // pc.putc(pingAllStr[i]);
morten_opprud 0:66a099b01e08 230 }
morten_opprud 0:66a099b01e08 231 while(1) {
morten_opprud 0:66a099b01e08 232 if(rs485.readable()) {
morten_opprud 0:66a099b01e08 233 rx[rxcnt++] = rs485.getc();
morten_opprud 0:66a099b01e08 234 // pc.putc(rx[rxcnt]);
morten_opprud 0:66a099b01e08 235 }
morten_opprud 0:66a099b01e08 236 /* reached stop 0x7E ? todo, timeout & CRC*/
morten_opprud 0:66a099b01e08 237 if( rxcnt > 10)
morten_opprud 0:66a099b01e08 238 if(rx[rxcnt] == 0x7E)
morten_opprud 0:66a099b01e08 239 break;
morten_opprud 0:66a099b01e08 240
morten_opprud 0:66a099b01e08 241 if( rxcnt == 11)
morten_opprud 0:66a099b01e08 242 break;
morten_opprud 0:66a099b01e08 243 }
morten_opprud 0:66a099b01e08 244
morten_opprud 0:66a099b01e08 245 for(int i=0; i < 12; i++) {
morten_opprud 0:66a099b01e08 246 pc.putc(pingAllStr[i]);
morten_opprud 0:66a099b01e08 247 }
morten_opprud 0:66a099b01e08 248 for(int i=0; i < 12; i++) {
morten_opprud 0:66a099b01e08 249 pc.putc(rx[i]);
morten_opprud 0:66a099b01e08 250 }
morten_opprud 0:66a099b01e08 251
morten_opprud 0:66a099b01e08 252 pc.printf("Done");
morten_opprud 0:66a099b01e08 253 }