Andreschrosa Posted October 17, 2008 Share Posted October 17, 2008 I'm writing a sequence to scan my network switching between IPs and sending modbus function 17 (Report Slave ID) to discover where the equipments are located. To run modbus function 17 I took some code from the forum, but there you used modbus function 07, it should be diferent to get the parameters I need from 17, like equipment ID. global string ip ip = '10.50.8.79' device.Mod.Address = ip private string listequip[] = 0 for (private.j = 1, j<=255, j++) private string datain // lock port so regular driver doesn't interfere if (device.Mod.lockport()) try // clear buffer device.Mod.purge() // write output string device.Mod.write(chra({i,0x11,0xC0,0x2C})) // read 5 char response datain = device.Mod.read(15) // confirm valid response if (mid(datain,1,1) == chr(7)) // put result into channel MyChan.AddValue(asc(mid(datain,2,1))) i++ endif catch() endcatch // release port device.Mod.unlockport() endif endfor Link to comment Share on other sites More sharing options...
Andreschrosa Posted October 17, 2008 Author Share Posted October 17, 2008 global string ip ip = '10.50.8.79' device.Mod.Address = ip private string listequip[] = 0 private i = 0 for (private.j = 1, j<255, j++) private string datain // lock port so regular driver doesn't interfere if (device.Mod.lockport()) try // clear buffer device.Mod.purge() // write output string device.Mod.write(chra({j,0x11,0xC0,0x2C})) // read 5 char response datain = device.Mod.read(15) // confirm valid response if (mid(datain,1,1) == chr(15)) // put result into channel listequip[j] = mid(datain,11,1)+mid(datain,12,1) //MyChan.AddValue(asc(mid(datain,2,1))) endif catch() endcatch // release port device.Mod.unlockport() endif endfor However, this seens to not be writing anything to listequip... Link to comment Share on other sites More sharing options...
AzeoTech Posted October 17, 2008 Share Posted October 17, 2008 I can't tell you. You'd have to look at the comm monitor to see what the device is returning. My guess is that the second character is not chr(15) as you expect. I would also consider putting a breakpoint in so you can actually see what datain is, or just put a ? statement using the showhidden function: ? showhidden(datain) Put this right after the device.mod.read(15) Link to comment Share on other sites More sharing options...
Andreschrosa Posted October 17, 2008 Author Share Posted October 17, 2008 somehow when I enter the j variable in the watch window, I see it starts out at some random number (like 62,30,90) then it begins incrementing correctly and goes up to 255 in the 'for'. datain is not returning anything. any thoughts? global string ip ip = '10.50.8.79' device.Mod.Address = ip private string listequip[] = 0 global int j = 0 for (j=1, j<255, j++) global datain // lock port so regular driver doesn't interfere if (device.Mod.lockport()) try // clear buffer device.Mod.purge() // write output string device.Mod.write(chra({j,0x11,0xC2,0xEC})) // read 15 char response datain = device.Mod.read(asc(15)) ? showhidden(datain) // confirm valid response if (mid(datain,1,1) == chr(11)) // put result into channel listequip[j] = concat(mid(datain,11,1),mid(datain,12,1)) endif catch() endcatch // release port device.Mod.unlockport() endif endfor Link to comment Share on other sites More sharing options...
AzeoTech Posted October 17, 2008 Share Posted October 17, 2008 Sorry, I didn't look at your code close enough the first time. You can't put a variable inside of {} notation. Only constants. So, you have device.mod.write(chra({j,0x11...}) which is not allowed. You should do: device.mod.write(chr(j) + chra({0x11,0xc2,0xec})) Link to comment Share on other sites More sharing options...
Andreschrosa Posted October 20, 2008 Author Share Posted October 20, 2008 Thanks for your replys, they are helping me get the hang of DAQFactory fast I changed some code and now I see some response for function 17, but there is still something wrong. I'm using mobdubs RTU, by the way. The response I get from the command/alert window: 051710?\142v\2000018\214\13500H\241\245 the response I get from comm monitor window: Rx: \x05\x11\x0A?\x8Ev\xC8\x00\x12\xD6\x87\x00H\xF1\xF5 the expected response from the device: 05 11 0A 3F 8E 76 C8 00 12 D6 87 00 48 F1 F5 it's right on almost every bit, except 5 (wich disappears), 11 and 12 (the ones I need). Any thoughts on how to fix this will be appreciated. Code: j =5 global string datain // lock port so regular driver doesn't interfere if (device.Mod.lockport()) try // clear buffer device.Mod.purge() // write output string device.Mod.write(chr(j) + chra({0x11,0xC2,0xEC})) // read 15 char response datain = device.Mod.Read(chr(15)) ? showhidden(datain) // confirm valid response if (mid(datain,1,1) == chr(11)) // put result into channel listequip[j] = mid(datain,11,2) ? showhidden(listequip[5]) endif catch() endcatch // release port device.Mod.unlockport() endif Link to comment Share on other sites More sharing options...
AzeoTech Posted October 20, 2008 Share Posted October 20, 2008 When working with binary protocols you should select "Display all chars as ASCII Codes" in the monitor window, otherwise, DAQFactory will display chars that are displayable characters (i.e. ascii codes 32 to 127) as the character instead of in \xxx notation. It gets pretty confusing otherwise. Sorry, I know I said use ShowHidden(), but I wasn't really thinking and instead you should either use the monitor or use the asca() function, so: ? asca(datain) Asca() takes a string and returns an array of ascii codes. Link to comment Share on other sites More sharing options...
Andreschrosa Posted November 10, 2008 Author Share Posted November 10, 2008 That worked but now I come back to read slave ID to finish implementing it to actualy get the serial number, that would be [7][8][9][10] from the response frame, stored in the long format. The function like wrote bellow worked cause I previously used it to get [11][12] from the response, which is equipment type. This only returned a number on [12]. Now I must get then all [7]-[12]; and [7]-[10] must be concatenated like 0012D687 in hexa so that in they represent 1234567 in decimal (for exemple). However, the way the code is now, I only get the array {0,18,214,135} those are in ASCII of course, but I didnt figure out yet how to do this. function function17(end) global string input private string output // clear buffer device.Mod.purge() output = chr(end) + chr(0x11) output = output + calcCRC(output) ?AscA(output) // write output string device.Mod.write(output) // read 15 char response input = device.Mod.Read(15) ?AscA(input) // confirm valid response if (mid(input,1,1) == chra(17)) private string serial = mid(input,7,4) // + AscA(mid(input,11,1) + mid(input,12,1)) return (AscA(serial)) endif Link to comment Share on other sites More sharing options...
AzeoTech Posted November 10, 2008 Share Posted November 10, 2008 I think you want To.ULong() which will take an array of 4 values like {0,18,214,135} and make them into a single unsigned long. There are several other versions that affect byte ordering like To.urwLong() and To.urbLong() Link to comment Share on other sites More sharing options...
Andreschrosa Posted November 10, 2008 Author Share Posted November 10, 2008 In trying to thinker with the to.ulong function, I'm running into a few problems: if I enter the numbers manually, it works fine, ie. to.ulong({{135,214,18,0}}) it returns 1234567. However if I set it directly from the function, it dosent, ie. to.ulong({{fun[3,2,1,0]}}) it returns 66051. function function17(end) global string input private string output // clear buffer device.Mod.purge() output = chr(end) + chr(0x11) output = output + calcCRC(output) ?AscA(output) // write output string device.Mod.write(output) // read 15 char response input = device.Mod.Read(15) // confirm valid response if (mid(input,1,1) == chra(17)) private string serial = mid(input,7,4) return (asca(serial)) endif device.Mod.LockPort() global string fun = function17(5) device.Mod.UnlockPort() Link to comment Share on other sites More sharing options...
AzeoTech Posted November 10, 2008 Share Posted November 10, 2008 Hmm, I'm not sure why this always gets people. You can't put non-scalar values inside {}. No functions, no variables. If a function returns an array as yours does, there is no reason to use {} at all. You just do: to.ulong(function17(5)). Link to comment Share on other sites More sharing options...
Andreschrosa Posted November 10, 2008 Author Share Posted November 10, 2008 I cant use it like that, I must get from function17 response array and put bytes [7][8][9][10] to long, and then put bytes [11][12] into other variable. That's why I'm trying to do it like that. Link to comment Share on other sites More sharing options...
AzeoTech Posted November 10, 2008 Share Posted November 10, 2008 But function17 returns an array of 4 bytes. So you have two issues. One, you aren't getting 11 and 12, and two, you are then putting that in a string, "fun", not a numeric variable. I think you want to change function17 to return asca(mid(input,7,6)) which will return an array of 6 values. Then take the first 4 and use to.ulong. So: global fun = function17(5) global var1 = to.ulong(fun[0,3]) global var2 = fun[4,5] Link to comment Share on other sites More sharing options...
Andreschrosa Posted November 11, 2008 Author Share Posted November 11, 2008 Thanks! I had tried to change input to double inside the function and it didnt work cause the return was not double, now it works fine Link to comment Share on other sites More sharing options...
JohnyQuick Posted November 18, 2011 Share Posted November 18, 2011 I have not been successful trying to communicate with my device. So, I have been trying to use function 17 to find the device address. Then I read this from the manual: "The DX100 (M) inherits its Modbus address from the gas detector that it is connected to. Until the gas detector has its digital address configured, it defaults to an address of 00 which gives the DX100 (M) a Modbus address of 99. With this default address of 99 the Termination Unit ignores all attempts to communicate with it. Thus when initially installed and powered-up the DX100 (M) assumes this default Modbus address of 99 and ignores all attempts at communication. The gas detectors digital address must be changed from the default to enable Modbus communications via the DX100 (M). The address is configured using the SHC1 Handheld Interrogator. To set the address....." I thought I could just use the default address of 00, or 99 to talk to my device, but like I said, I haven't been successfull. Is there a way to "assign", FORCE, an address to my device using the modbus rtu protocol? Apparently, untill the default address of 00, for my device is changed, it does not allow communication. This appears to be a manufacturer's security thing, I assume. Thanks for all your help. Link to comment Share on other sites More sharing options...
AzeoTech Posted November 22, 2011 Share Posted November 22, 2011 Yeah, it sounds like you'll need to adjust the address of the gas detector. Until that is done you are going to get no where. You cannot use address 0 because that is a broadcast address for Modbus. There is nothing in the Modbus spec that allows you to change the ID. Some devices map the ID to a holding register, but you'd still have to be able to communicate with it using the existing ID first. With no valid ID, you can't use Modbus. Link to comment Share on other sites More sharing options...
JohnyQuick Posted November 22, 2011 Share Posted November 22, 2011 That explains the address of 0. My Device uses HART PROTOCOL, which alas, DF doesn't provide for. I have polled using HART OPC, from the HART people, but it still can't find the device. It's looking like I need an ,um expensive, "communicator" to talk to a "smart" HART Device. Or else, recalibrations from the factory.(also expensive).. HART is super-imposed on top of RS-485. Can you provide any help with talking, using the HART PROTOCOL?? Thanks Link to comment Share on other sites More sharing options...
AzeoTech Posted November 23, 2011 Share Posted November 23, 2011 No, I can't help much other than to say: start simple. Or, consider hardware that is Modbus instead of Hart Link to comment Share on other sites More sharing options...
JohnyQuick Posted November 24, 2011 Share Posted November 24, 2011 Yes , and it turns out Hart Protocol requires, nothing new I suppose, yet its own special Modem to talk to the device. One is on order for me. An RS232 to RS485, converter, wouldn't/won't work, with Hart Protocol. Hart Protocol appears to be anything but an DOT ORG organization. They are after your wallet , if ever an Hierarchy ever was. Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.