• Categories
  • Recent
  • Tags
  • Popular
  • Login
REXYGEN Community Forum
  • Categories
  • Recent
  • Tags
  • Popular
  • Login

ASCII Commands Over RS485

Communication (RS232, RS485, I2C, SPI, UDP, TCP, ...)
2
19
1.6k
Loading More Posts
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • G
    GeorgeDumitru
    last edited by 1 Aug 2023, 14:29

    Hi I am currently working on a project where I want to use a MonarcoHAT to control a DMX-K-SA-17 stepper motor controller. The two devices are communicating over RS-485 serial com (I Am using a USBtoRS485 connection). The DMX-K-SA-17 can be controlled using ASCII Commands. I have been struggling for a few weeks now to find a proper REXLANG Routine that will allow me to :
    a. Send commands in ascii format to the device
    b. Get the response of those commands once the command has been sent.

    Can anyone help me with this?

    J 1 Reply Last reply 2 Aug 2023, 07:31 Reply Quote 1
    • J
      Jan Reitinger @GeorgeDumitru
      last edited by Jan Reitinger 2 Aug 2023, 07:33 2 Aug 2023, 07:31

      @georgedumitru Hi George,
      a. To send commands in ASCII format to the device, you can use the Write() function. For example, the following code will send the command @00DI[CR] to the device:

      a = Write(socketHandle,"@00DI[CR]");
      

      if a>0, the write command was successful (see the error codes in the REXLANG doc for Write() function). The value of a will be the number of bytes that were written to the device.
      b. To receive the response from the motor controller, you can use the Read() function. For example, the following code will receive up to 10 bytes of data from the device:

      dataCnt = Read(socketHandle,data,DATA_SIZE); //receive data, max number of bytes = DATA_SIZE
      if (dataCnt > 0)	// data received
      {
        DO_SOMETHING
      }
      

      I've defined data as the string and DATA_SIZE as a constant in the code before:

      #define DATA_SIZE   10    //maximum number of bytes to receive
      string data[DATA_SIZE+1];  	//buffer for incoming data
      

      The main() procedure body can be a kind of state machine. I personally use a switch-case construction, but it can also be done externally using an ATMT block. For example, the following code will send a command in one tick and then wait to a response in the next ticks:

      switch(status)
        {
          case 0:
            a = Write(socketHandle,"@00DI[CR]");
            if(a == 6) {
      	status = 1;
            }
            break;
          case 1:
            dataCnt = Read(socketHandle,data,DATA_SIZE); //receive data, max number of bytes = BUFFER_SIZE
            if (dataCnt > 0)	// data received
            {
      	DO_SOMETHING
              status = 0;
            }
            break;
        default:
      

      Please note that this is just a simple example, and you will need to modify it to fit your specific needs. Try to go step by step. First get a simple response from the controller and then create complex code.

      Is there a reason why you are using the USB<->RS485 converter and not the RS485 directly on the Monarco HAT?

      Cheers,
      Jan

      G 2 Replies Last reply 2 Aug 2023, 07:41 Reply Quote 0
      • G
        GeorgeDumitru @Jan Reitinger
        last edited by 2 Aug 2023, 07:41

        @jan-reitinger said in ASCII Commands Over RS485:

        te command was successful (see the error codes in the REXLANG doc for Write() function). The value of a will be the number of bytes that were written to the device.

        Hi Jan, this is amazingly helpful. I just couldn't figure it out from the block documentation. This was exactly the pointer in the right direction I needed. Thank you very much!

        1 Reply Last reply Reply Quote 0
        • G
          GeorgeDumitru @Jan Reitinger
          last edited by 2 Aug 2023, 07:44

          @jan-reitinger As for why am I using a USB <-> RS-485, it was not my decision. If that is not going to meet my requirements in terms of speed, I will change it, but this is a project I jumped in kind of in the middle, after all the wiring and setup has been completed and I had nothing to say about it.

          J 1 Reply Last reply 2 Aug 2023, 09:50 Reply Quote 0
          • J
            Jan Reitinger @GeorgeDumitru
            last edited by 2 Aug 2023, 09:50

            @georgedumitru Let me know how you're doing. I've also found it helpful to set the status as an output of REXLANG block and to use tracking using the Trace() function. However, it is necessary to have the "Function block messages: Information" option checked in the System Log Configuration in REXYGEN.

            G 1 Reply Last reply 2 Aug 2023, 12:51 Reply Quote 0
            • G
              GeorgeDumitru @Jan Reitinger
              last edited by 2 Aug 2023, 12:51

              @jan-reitinger Hi Jan, the write is successful but the read doesn't return anything. This is where I always have issues. For some reason the read almost always misses the replay from the device.

              J 1 Reply Last reply 3 Aug 2023, 06:30 Reply Quote 0
              • J
                Jan Reitinger @GeorgeDumitru
                last edited by Jan Reitinger 3 Aug 2023, 06:36 3 Aug 2023, 06:30

                @georgedumitru Hello George,

                Would you mind sharing the part of the project related to communication with the controller? If you prefer to keep it private, please feel free to send it to support@rexcontrols.com.

                Thank you!

                G 1 Reply Last reply 3 Aug 2023, 08:19 Reply Quote 0
                • G
                  GeorgeDumitru @Jan Reitinger
                  last edited by 3 Aug 2023, 08:19

                  @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;
                  }
                  
                  
                  
                  
                  
                  
                  
                  
                  J 1 Reply Last reply 3 Aug 2023, 09:11 Reply Quote 0
                  • J
                    Jan Reitinger @GeorgeDumitru
                    last edited by Jan Reitinger 3 Aug 2023, 09:47 3 Aug 2023, 09:11

                    @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;
                    }
                    
                    G 1 Reply Last reply 4 Aug 2023, 09:41 Reply Quote 0
                    • G
                      GeorgeDumitru @Jan Reitinger
                      last edited by 4 Aug 2023, 09:41

                      @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?

                      J 1 Reply Last reply 7 Aug 2023, 06:22 Reply Quote 0
                      • J
                        Jan Reitinger @GeorgeDumitru
                        last edited by 7 Aug 2023, 06:22

                        @georgedumitru Hi George,
                        if you only need a control statement in the log, use Trace(1,data). If you want the string to output directly, this should work:

                        ...
                        string output(3) outputstring;
                        ...
                        outputstring = data;
                        

                        Cheers,
                        Jan

                        G 1 Reply Last reply 7 Aug 2023, 07:46 Reply Quote 0
                        • G
                          GeorgeDumitru @Jan Reitinger
                          last edited by 7 Aug 2023, 07:46

                          @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:

                          a3c625d1-eb27-44d0-bad6-45a86a04262f-image.png

                          J 1 Reply Last reply 7 Aug 2023, 17:36 Reply Quote 0
                          • J
                            Jan Reitinger @GeorgeDumitru
                            last edited by Jan Reitinger 7 Aug 2023, 19:05 7 Aug 2023, 17:36

                            @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;
                            }
                            
                            
                            1 Reply Last reply Reply Quote 0
                            • G
                              GeorgeDumitru
                              last edited by 14 Aug 2023, 12:09

                              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?

                              J 1 Reply Last reply 15 Aug 2023, 19:06 Reply Quote 0
                              • J
                                Jan Reitinger @GeorgeDumitru
                                last edited by 15 Aug 2023, 19:06

                                @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 use double buf2double(buf[,endian]) REXLANG function.

                                G 1 Reply Last reply 23 Aug 2023, 14:58 Reply Quote 0
                                • G
                                  GeorgeDumitru @Jan Reitinger
                                  last edited by 23 Aug 2023, 14:58

                                  @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?

                                  J 1 Reply Last reply 24 Aug 2023, 06:09 Reply Quote 0
                                  • J
                                    Jan Reitinger @GeorgeDumitru
                                    last edited by 24 Aug 2023, 06:09

                                    @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?

                                    G 1 Reply Last reply 24 Aug 2023, 06:51 Reply Quote 0
                                    • G
                                      GeorgeDumitru @Jan Reitinger
                                      last edited by 24 Aug 2023, 06:51

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

                                      J 1 Reply Last reply 24 Aug 2023, 17:53 Reply Quote 0
                                      • J
                                        Jan Reitinger @GeorgeDumitru
                                        last edited by Jan Reitinger 24 Aug 2023, 17:57 24 Aug 2023, 17:53

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

                                        1 Reply Last reply Reply Quote 0
                                        • First post
                                          Last post

                                        This is a community forum for REXYGEN users and fans. Detailed information can be found at REXYGEN homepage.

                                        There is also an outdated REXYGEN community forum.

                                        Powered by NodeBB.