ASCII Commands Over RS485
-
@jan-reitinger Hi Jan, here is the code of the entire block:
#define COM_BAUDRATE 9600 //baudrate, e.g. 9600, 19200, 57600, 115200 #define COM_PARITY_NONE 0 //no parity #define COM_PARITY_ODD 1 //odd parity #define COM_PARITY_EVEN 2 //even parity #define BUFFER_SIZE 20 // MAXIMUM NUMBER OF BYTES TO SEND #define COMMAND_LENGTH_MAX 20 //maximum length of command //Assigning parameters to variables, these variables are read-only; string parameter(0) serialdevice;//serial device is defined by parameter p0 of the REXLANG Block (e.g. /dev/ttyS0 in Linux or COM1 in Windows) //Assigning inputs to variables bool input(0) IsGreenButtonSignalOn; bool input(1) IsRedButtonSignalOn; bool input(2) IsYellowButtonSignalOn; bool input(3) IsProcedureStandardSignal; //Assigning Variables to Outputs, these variables are WRITE-Only bool output(0) IsDeviceReady; bool output(1) IsDeviceInError; bool output(2) IsDeviceRunning; string output(3) ResponseFromDMX; long output(14) DebugMessage; long output(15) ConnectionStatus; //Variables Declaration const long cr = 13; // (cr) is the termination character, carrige return (0Dh); long hCom, s, receive; // Communication Handle long buffer[BUFFER_SIZE]; // buffer for incoming data long dataCount; // Number of bytes sent bool read = true; string data[BUFFER_SIZE+1]; int status=0; long a; void HomeMotor(void){ long readData[6]; readData[0]='L'; readData[1]='H'; readData[2]='O'; readData[3]='M'; readData[4]='E'; readData[5]='-'; s=Send(hCom,readData,6); return; } void ClearError(void){ a=Write(hCom,"@DMK01EO=1[CR]"); if(a>0){ DebugMessage=a; } else{ DebugMessage=-1; } } void MoveTo1000(void){ a=Write(hCom,"@01J+"); if(a>0){ DebugMessage=a; status=0; } else{ DebugMessage=-1; } } //the init procedure is executed once when the REXLANG function block initializes long init(void) { /* PUT YOUR CODE HERE */ hCom=-1; return 0; } //the main procedure is executed repeatedly (once in each sampling period) long main(void) { /* PUT YOUR CODE HERE */ if(hCom<0) { hCom = OpenCom(serialdevice,COM_BAUDRATE,COM_PARITY_NONE); //Opening Serial Device ConnectionStatus=hCom; } switch(status) { case 0: a=Write(hCom,"@00EO[CR]"); if(a>0){ status=1; } break; case 1: dataCount = Read(hCom, data,BUFFER_SIZE); if(dataCount>0){ if(data=="1"){ ResponseFromDMX="ON"; } else{ ResponseFromDMX="OFF"; } status = 0; } default: break; } return 0; } //the exit procedure is executed once when the task is correctly terminated // (system shutdown, downloading new control algorithm, etc.) long exit(void) { /* PUT YOUR CODE HERE */ if(hCom>=0){ Close(hCom); } return 0; }
-
@georgedumitru, I believe there's a mistake in the Write command. Instead of using the [CR], it should be the ASCII symbol "\r". My apologies for not thoroughly reading the controller manual. Furthermore, I'm considering putting the switch into an else statement:
long main(void) { /* PUT YOUR CODE HERE */ if(hCom<0) { hCom = OpenCom(serialdevice,COM_BAUDRATE,COM_PARITY_NONE); //Opening Serial Device ConnectionStatus=hCom; } else { switch(status) { case 0: a=Write(hCom,"@00EO\r"); if(a>0){ status=1; } break; case 1: dataCount = Read(hCom, data,BUFFER_SIZE); if(dataCount>0){ if(data=="1"){ ResponseFromDMX="ON"; } else{ ResponseFromDMX="OFF"; } status = 0; } default: break; } } return 0; }
-
@jan-reitinger Hi Jan, sorry if I'm being difficult here, but I am just curious, I am receiving a string in the return message. How can i process that to have the string in the output of the block? I managed to get a response from the device, and as long as the response is a single byte, that works just fine, but I am struggling to get a string out of the buffer. Do you have any suggestions?
-
@georgedumitru Hi George,
if you only need a control statement in the log, useTrace(1,data)
. If you want the string to output directly, this should work:... string output(3) outputstring; ... outputstring = data;
Cheers,
Jan -
@jan-reitinger said in ASCII Commands Over RS485:
trol statement in the log, use Trace(1,data). If you want the string to output directly, this should work:
That's what I thought, but every time I try to do that I get this as an error:
-
@georgedumitru Could you post line 111 here or ideally the whole code again?
This minimal example works for me:
#define BUFFER_SIZE 20 string output(1) outputstring; string data[BUFFER_SIZE+1]; long init(void) { data = "hello there"; return 0; } long main(void) { Trace(1,data); outputstring = data; return 0; } long exit(void) { return 0; }
-
Can you please help me with a conversion? I need to interrogate the position of the stepper motor, they have an ascii command I can send to do that, but the response is a 28-bit number. Can you tell me what I can use to get that number from the buffer?
-
@georgedumitru Hi,
When we refer to a 28-bit number, does this imply that the number is transmitted within 4 bytes? If that's the case, and the number is in floating-point format, you should usedouble buf2double(buf[,endian])
REXLANG function. -
@jan-reitinger said in ASCII Commands Over RS485:
buf2double
Hi, the number is not in floating-point format, is actually an int. But what I don't understand is how to use your function What exactly does it take in the argument. I never seen a function taking anything like yours and if I call just double myDouble = buf2double(myBuffer) I expect 100.000 and I get -7.403 669 410 330E-171 . So, how exacttly do i solve this?
-
@georgedumitru
Hello George,It's challenging to give advice remotely when I can't see what's happening. The data might be in a different format than expected. Could you use Trace() to print the contents of the buffer and share it here?
-
@jan-reitinger can you direct me to some documentation that shows how to actually use Trace() as I could definitely use that for myself too.
-
@georgedumitru I think the best documentation is this thread here on the forum. Byte array reading from communication is also discussed there.
Another helpful tool is definitely the example located at C:\Program Files\REX Controls\REXYGEN 2.50.12.14711\Examples\0203_Function_Blocks_REXLANG.