Fairford Posted September 23, 2015 Share Posted September 23, 2015 HiI am a DaqFactory novice so please excuse my ignorance if the following is trivial I’m connected with a Sprint DC Variable Speed Drive through the RS232 port. Communication is established and I can perform basic parameter functions. Using the line below, I can set the speed to 100%device.Sprint.Write(chra({0x04,0x30,0x30,0x30,0x30,0x02,0x41,0x61,0x31,0x30,0x30,0x03,0x12})) (EOX) (GroupID)( Unit ID )(STX)( Mnemon)( Value )(ETX)(BCC)Where:EOX = End of transmission. Clears the line at start of new messageSTX = Start of TextETX = End of textBCC = Block Check Character – verification check digit which is exclusive OR of Mnemon to ETXMnemon = Two hex character ASCII mnemonic for parameter. Aa in this case = SpeedValue = ASCII hex representation of parameter value. In this case 100 Whilst EOX, GroupID, Unit ID, STX and mnemonic can remain fixed in each transmission, I’d like to be able to dynamically change the value and check block (BCC) so that I can change the speed of the drive by reading a slider value (or similar). I’ve tried for many hours to place variables into the chra array to dynamically change the values and BCC, but I’ve failed miserably! Please can anyone help. With thanks Quote Link to comment Share on other sites More sharing options...
AzeoTech Posted September 23, 2015 Share Posted September 23, 2015 You can't put variables in static array notation (i.e. {1,2,3} is fine, but {1, myVariable, 3} is not). But write() just takes a string, and asca() generates a string, so you can just concatenate them: device.Sprint.Write(chra({0x04, 0x30, 0x30, 0x30, 0x30, 0x02, 0x41, 0x61}) + format("%03d", val) + chr(0x03) + bcc) where val is some number. Format() with %03d will prefix val to 3 digits with 0's, so 5 becomes 005 and 32 becomes 032. I'm not sure how you are calculating BCC, but lets say its just a sum of all the other characters rolled at 256. Then I'd do: private string out = chra({0x04, 0x30, 0x30, 0x30, 0x30, 0x02, 0x41, 0x61}) + format("%03d", val) + chr(0x03) private bcc = sum(asca(out)) & 0xff device.sprint.write(out + chr(bcc) Quote Link to comment Share on other sites More sharing options...
SteveMyres Posted September 24, 2015 Share Posted September 24, 2015 I thought as of about 5.90 or so you could put variables directly into an explicitly defined array. Am I mistaken about that? If so, please consider it a feature request. Quote Link to comment Share on other sites More sharing options...
AzeoTech Posted September 24, 2015 Share Posted September 24, 2015 No you can't. But its a request we are planning for as it trips a lot of people up. Quote Link to comment Share on other sites More sharing options...
OliS Posted April 20, 2020 Share Posted April 20, 2020 Hi, I'm trying to make a sequence function to formulate commands to be sent to a TMC stepper motor driver. Each command is in binary in 9 bytes, with some info about addresses, motors etc in each of first 4 bytes, then the value in the next 4 bytes (MSB), then the last being a checksum of the first 8 bytes. A typical command which works is this: device.TMC.Poll(ChrA({1, 2, 0, 0, 0, 0, 0, 100, 103})) My function based on the topic above is this: function Cmd(address, instruction, type, motor, valuein) private string out = format("%03d", address) + format("%03d", instruction) + format("%03d", type) + format("%03d", motor) + from.urbLong(to.uLong(from.urwLong(valuein))) private cks = sum(asca(out)) & 0xff return(out + cks) But isnt quite working - the Long conversion isnt concatenating with the rest of the string properly - could you tell me what I'm doing wrong please? Many thanks! Quote Link to comment Share on other sites More sharing options...
AzeoTech Posted April 21, 2020 Share Posted April 21, 2020 There is a common misunderstanding concerning the difference between binary bytes, and ASCII values. A serial stream is made up of bytes. A byte is a number from 0 to 255. A string is a bunch of bytes linked together one after another. A string is typically represented by the ASCII coded representation of each byte. ASCII is basically a coding scheme, where a byte value, say, 65, corresponds to a character used in the English language, in the case of 65, the upper case A. I say English because ASCII is largely limited to A-Z and doesn't include characters with accents, or any non-english characters. For that there are other mappings, the most common being UTF. But let's stick to ASCII since that is what DAQFactory uses. As I said, a serial stream is just bytes. Because the bytes are sent one after another (serially), it is convenient to use a string to store what bytes you are sending or receiving because a string is the same thing, a bunch of bytes one after another. So, when you do chra({1,2,0,0,0,0,0,100,103}) you are taking an array of numbers, {1,2,0,0,0,...} and using the chra() function to convert it into a string where each character in the string corresponds to one of those numbers, in order. In your case, that is it. Everything is in binary. In many serial streams, the device expects the ASCII representation of those numbers, not the numbers themselves. So while 100 binary is just 100, "100" ascii is actually 49, 48 and 48, where 49 corresponds to 1, and 48 corresponds to 0. The asca() function in DAQFactory takes a string and converts it into an array of bytes, so ? asca("100") returns {49,48,48}. Doing ? chra({1,2,0,0,0,0,0,100,103}) is going to print next to nothing because the string starts with numbers below 32, and any number below 32 is, in ASCII, called a control character and is not printable. Now, on to your code: when you do format("%03d", address) you are actually taking the number stored in address and converting it to the ASCII representation of that number. So, if address was 100, the format command would return the string "100", which is actually the three bytes 49,48,48 which is definitely NOT what you are after. You really just want the numbers going direct to the serial port. So, you want something like this: private out out[0] = address out[1] = instruction out[2] = type out[3] = motor out[4] = from.urbLong(to.uLong(from.urwLong(valuein))) private cks = sum(out) & 0xff return(chra(concat(out, cks))) Quote Link to comment Share on other sites More sharing options...
OliS Posted April 21, 2020 Share Posted April 21, 2020 Wow thanks so much! I love your program by the way, and the support you give is amazing too - if theres any way to support you then let me know, thanks Quote Link to comment Share on other sites More sharing options...
AzeoTech Posted April 21, 2020 Share Posted April 21, 2020 Tell your friends! Quote Link to comment Share on other sites More sharing options...
OliS Posted April 21, 2020 Share Posted April 21, 2020 Hi again, the following line works perfectly: device.QBCrig.Poll(ChrA({1, 1, 0, 0, 0, 0, 0, 100, 102})) Even though the output, as you said, is just control characters: ? ChrA({1, 1, 0, 0, 0, 0, 0, 100, 102}) But using the function as you suggested (I changed 'out' to 'tosend' as I thought that might be conflicting somehow with the 'out' in the poll function but it isnt...): function Cmdcopy(address, instruction, type, motor, valuein) private tosend tosend[0] = address tosend[1] = instruction tosend[2] = type tosend[3] = motor tosend[4] = from.urbLong(to.uLong(from.urwLong(valuein))) private cks = sum(tosend) & 0xff return(chra(concat(tosend, cks))) I get this: device.QBCrig.Poll(Cmdcopy(1, 1, 0, 0, 100)) C1136 Timeout: Cmdcopy Line 20: Cmdcopy Line 28: Line 1 and the actual output its trying to send is this: ? concat(tosend, cks) {{1, 0, 0, 0}, {1, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 100}, {2, 0, 0, 100}} ...which isnt correct, as there should always be 9 bytes sent and received. I'm confused as C1136 isnt in the user guide, and there are only 9 lines in the function above, so I assume lines 20 (Write(out)) and 28 (throw())refer to the poll function (basically the same as the given one), and there's a problem with the format from the function above. A little more help please? Quote Link to comment Share on other sites More sharing options...
AzeoTech Posted April 21, 2020 Share Posted April 21, 2020 The problem is the tosend[4]. from.urbLong() returns an array in the columns direction. You'll need to transpose that into the rows dimension: tosend[4] = transpose(from.urbLong(to.uLong(from.urwLong(valuein))),0) Quote Link to comment Share on other sites More sharing options...
OliS Posted April 21, 2020 Share Posted April 21, 2020 Brilliant, thanks, works great making control so much better than the trinamic IDE that came with the driver. The final code below for others if helpful: function Cmd(address, instruction, type, motor, valuein) private tosend tosend[0] = address tosend[1] = instruction tosend[2] = type tosend[3] = motor tosend[4] = transpose(from.urbLong(to.uLong(from.urwLong(valuein))),0) private cks = sum(tosend) & 0xff return(chra(concat(tosend, cks))) Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.