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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers unilynx.cpp Source File

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 }