Need help with RS485 Com. - Programmers Heaven

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories

Welcome to the new platform of Programmer's Heaven! We apologize for the inconvenience caused, if you visited us from a broken link of the previous version. The main reason to move to a new platform is to provide more effective and collaborative experience to you all. Please feel free to experience the new platform and use its exciting features. Contact us for any issue that you need to get clarified. We are more than happy to help you.

Need help with RS485 Com.

chuff1chuff1 Posts: 2Member
I have been trying to communicate with a device (NG360 Inclinometer) using VB without much luck. I think the problem is in sending a one byte HEX number thru the com port.

The Com Port Protocol is as follows:
Baud Rate: 9600
Data Bits: 8
Parity: NONE
Stop Bit: 1
Protocol: NONE

I have included the Com Port settings, Communication Protocols and C++ code that works.

The procedure for getting an angle from the NG360 inclinometer is as follows:

Switch from read to write mode (clear Data Terminal Ready and set Request To Send signal)
(1) Send the 1 byte address: >> Hex B2
(2) Send the 1 byte enquiry: >> Hex 05
(3) wait 15ms for the inclinometer to analyze the input

Switch from read to write mode (clear Request To Send and set Data Terminal Ready signal)

(4) Receive 11 bytes: << Hex 02 + 359,99 + Hex 17 + 06 + Hex 24
STX ANGLE ETB Checksum $

In the case of an error:

(5) wait 15ms for inclinometer to switch from write to read mode

Switch from read to write mode (clear Request To Send and set Data Terminal Ready signal)
(6) Send Not Acknowledge >> Hex 15
(7) Go to (3)


/////////////////////////////////////////////////////////////////////////////

// global functions for the NG360 measurement

//

// The NG_functions use CCom as interface to the serial port. NG_GetAngle

// contains all the information one needs to know about the NG360 protocol.

//

// The error codes given by g_Com functions are inverted by ShowError.

/////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"

#include "NGprotocol.h"

#include "Com.h"

CCom g_Com; // the class for the serial port

SCom g_ComValues; // initialization values for the serial port

char g_cNGMaxRepeat; // maximum number of times the NG_GetAngle function tries to read a valid input string

char g_cNGMessageOut; // 0: hide NG_function error messages 1: show them

char g_cSysMessageOut; // 0: hide CCom error code messages 1: show them

/////////////////////////////////////////////////////////////////////////////

// NG_OpenPort: Initialize port to NG360 inclinometer - error return: <0>

char NG_OpenPort(char port)

{

if(port<1) return 0; // one may like to exclude portnumbers above 4, too

g_Com.cDuplex=1; // the RS485 uses half-duplex transmission

g_Com.cMessageOut=g_cNGMessageOut; // messages in g_Com are shown when they are shown in NG_functions

// global variables

g_cNGMaxRepeat=3; // send a maximum of 2 NAKs

// In this example every error is shown through a message box.

// -> In a 'real' application error handling should be kept in the background. If an error occurs

// -> (as a result of the sensor not getting the correct data/the computerside port being disturbed

// -> by other Windows activities) a second call to NG_GetAngle (or equivalent) will generally

// -> retrieve a valid datastring from the sensor. If there is still no result after two/three calls

// -> (for g_cNGMaxRepeat=3 => 2 NAKs for each call) the connection may be broken.

g_cNGMessageOut=1; // show NG_function error messages

g_cSysMessageOut=1; // show CCom error messages retrieved from system error codes

// comport initialization values

g_ComValues.BaudRate =CBR_9600;

g_ComValues.ByteSize =8;

g_ComValues.Parity =NOPARITY;

g_ComValues.StopBits =ONESTOPBIT;

g_ComValues.ReadIntervalTimeout =200;

g_ComValues.ReadTotalTimeoutMultiplier =7;

g_ComValues.ReadTotalTimeoutConstant =124;

g_ComValues.WriteTotalTimeoutMultiplier=0;

g_ComValues.WriteTotalTimeoutConstant =0;

if(g_Com.IsOpen()==0) // if the port was not already opened...

{

if(!ShowError(g_Com.Open(port))) // ...'make it so'

{

if(g_cNGMessageOut)

MessageBox(NULL,"NG_OpenPort: serial port could not be opened.","Port Error",MB_OK | MB_ICONSTOP);

return 0;

}

}

if(!ShowError(g_Com.OverwriteState(&g_ComValues))) // initialize with the choosen values

{

if(g_cNGMessageOut)

MessageBox(NULL,"NG_OpenPort: serial port could not be initialized.","Port Error",MB_OK | MB_ICONSTOP);

return 0;

}


return 1;

}

/////////////////////////////////////////////////////////////////////////////

// NG_ClosePort: free port

void NG_ClosePort(void)

{

if(g_Com.IsOpen()==0)

return;

if(!ShowError(g_Com.Close()))

{

if(g_cNGMessageOut)

MessageBox(NULL,"NG_ClosePort: serial port could not be closed.","Port Error",MB_OK | MB_ICONSTOP);

}


}

/////////////////////////////////////////////////////////////////////////////

// NG_GetAngle: retrieve angle in degrees - return <-1> in case of error

// (an angle is always given in the interval [000.00,359.99])

//

// This is the only function here using the NG360 communication protocol!

/////////////////////////////////////////////////////////////////////////////

double NG_GetAngle(int address)

{

int i;

int repeat=0; // this many times NAK was send unsuccessfuly

int chk; // checksum - computed using XOR byte by byte for the first 8 bytes

char ctest=0; // test for success - 0: no valid data 1: success, c contains a valid data string

char c[32]; // the input/output string

char szAngle[32]; // the actual angle string, format <123,45> (german notation uses ',' instead of '.')

DWORD dwTime; // time in ms

double dAngle; // the return value

if(g_cNGMaxRepeat<1) return -1; // whoever gave this values

if(address<177 || address>255) return -1; // did not know how to do it

while(ctest==0 && repeat was already send

PurgeComm(g_Com.hCom,PURGE_RXCLEAR|PURGE_TXCLEAR);

sprintf(c,"%c",address);

if(!ShowError(g_Com.Write(c))) // write


return -1;

if(!ShowError(g_Com.Write("x05"))) // write

return -1;

FlushFileBuffers(g_Com.hCom);

}

dwTime=GetTickCount(); // time for the inclinometer to switch from

while(GetTickCount()-dwTime<15.); // read mode to write mode


// input length: 11 bytes

// format: 02h 1 2 3 , 4 5 17h 0 8 $

// <STX> < d >< d > <$>

// angle in degrees checksum

ShowError(g_Com.Read(c,11)); // read input string

ctest=1;

if(strlen(c)==11) // test the input length

{

chk=0;

for(i=0;i<8;i++) // compute the checksum using byte0 XOR byte1 XOR ... XOR byte7

chk^=c[i]; // and compare the resulting 8-bit value with the ASCII coded,

if(chk!=strtol(c+8,NULL,16)) // hexadecimal value in the input string

ctest=0; // - failure if they are not equal

strcpy(szAngle,c+1);szAngle[6]=0;szAngle[7]=0; // get the angle string

for(i=0;i<6;i++) // Don't believe everything! One may check the correct angle format, too.

{

if(szAngle[i]!='0' && (szAngle[i]<'1' || szAngle[i]>'9') && szAngle[i]!=',' && szAngle[i]!='.')

{

ctest=0;

i=6;

}

} // ...this, of course, was highly optional

} else {

ctest=0;

}

if(ctest==0)

{

repeat++;

dwTime=GetTickCount(); // wait for the sensor to switch from write

while(GetTickCount()-dwTime<15.); // to read mode

if(!ShowError(g_Com.Write("x15"))) // write <NAK> - the inclinometer should rewrite its data...

return -1;

FlushFileBuffers(g_Com.hCom); // ...and send it out immidiately

}

}

if(ctest==1)

{

dAngle=atof(szAngle); // this will only give whole degree values, as the atof

if(szAngle[3]==',') // does not understand the <,>

{

if(szAngle[4]>='0' && szAngle[4]<='9')

{

dAngle+=(double)(szAngle[4]-'0')/10.; // add the 1/10 and 1/100 parts of

if(szAngle[5]>='0' && szAngle[5]<='9') // a degree manually...

dAngle+=(double)(szAngle[5]-'0')/100.;

}

}

return dAngle;

}

if(g_cNGMessageOut) // if this point is reached, the reading failed g_cNGMaxRepeat times

MessageBox(NULL,"NG_GetAngle: no data received","Port Error",MB_OK | MB_ICONSTOP);

return -1;

}

/////////////////////////////////////////////////////////////////////////////

// ShowError: just in case one wants to know what the operation system

// thinks about the latest error

char ShowError(DWORD ErrorCode)

{

if(ErrorCode!=0)

{

if(g_cSysMessageOut==FALSE)

return 0;

char Msg[1024];


FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,NULL,ErrorCode,

MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),

Msg,1024,NULL);

MessageBox(NULL,Msg,"Error",MB_OK | MB_ICONSTOP);

return 0;

}

else

{

return 1;

}

}

Sign In or Register to comment.