Automation Direct

Using the NetEdit3 I am communicating with the DL06.
I am having trouble addressing the memory of the DL06.
The Memory_StartAddress seems to be following the AB method of addressing.
How can I address V3000 in the DL06 ?

Hello,

You have to remember that the DL06 uses octal addressing.

There are two ways in which you can read/write address v3000 which is in the user memory address space of the DL06.

1.  Use absolute addressing:

   .Memory_Type = V_Registers_plcds  'absolute addressing of V memory
   .Memory_StartAddress = &O3000  'remember that addresses are octal
   .Memory_LengthInWords = 1  'read one word
   .Memory_Function = ReadMemory_plcds  'read memory
   .Control_Update

The above will read one word at address V3000.  When the Done events fires,

   .Memory_DataInt(0) will contain the value read from V3000.

This is the easiest and recommended method since you are dealing with octal addresses.

2.  Use User Memory addressing:

   .Memory_Type = User_DataWords_plcds  'user memory type
   .Memory_StartAddress = &O3000 - &O1400  'user memory is defined as V1400 to V7337
   .Memory_LengthInWords = 1
   .Memory_Function = ReadMemory_plcds
   .Control_Update

The above will read one word at address V3000.  When the Done events fires,

   .Memory_DataInt(0) will contain the value read from V3000.

Note that user memory starts at V1400 so you need to use V1400 as an offset for your V3000 read.   Subtracting V1400 from V3000 leaves octal 1400, so the above could be written: .Memory_StartAddress = &O1400 also.  It is easier for me to always do the subtraction explicitly when using anything other than absolute addressing since I always have to look up the V memory ranges (in Octal) that are represented by each memory type in the PLC.

Hope this helps.

Regards,
Phil Covington
vHMI

Hi... I recently purchased a copy of your DLL for interfacing with my PLC. I'm currently trying to get it working and I'm running into a problem. It seems that after I create the custom properties, the IP Address property is being flagged as read only. Here is the code I am trying to get working:

=======================================================================
Dim PLC As vHMIPLCDirectCommLib.CDevice
Dim WithEvents PLCStruct As vHMIPLCDirectCommLib.CPLCDEthernet

Private Sub Command1_Click()
Set PLCStruct = PLC.CreateDevice(PLCD_Ethernet)

With PLCStruct
  '.Communications_CommProtocol = IP_plcde
  .Communications_PLCIPAddress = "192.168.0.52" 'This is where it fails
  .Communications_DeviceID = 1
  .Memory_Function = Connect_eth
  .Control_Update
End With
End Sub

Public Sub Form_Load()
  Set PLC = New vHMIPLCDirectCommLib.CDevice
End Sub

Private Sub Command2_Click()
End
End Sub
=============================================================


Do you have any ideas where I'm going wrong? I'm following the example included with the driver by the letter and it just doesn't seem to work. Thanks in advance for any help you can give!


Hello,

The Automation Direct driver actually only connects to the PLC by device ID.  Either through the DirectSoft program communication setup or the program called NetEdit from http://www.hosteng.com you need to associate the PLC IP address with the PLC Device ID (or Module ID).  The PLCIPAddress will be a read only property in the driver since it really only connects by device ID.

I have attached NetEdit from Host Engineering (who writes all of Automation Direct's programming software).

Regards,

Phil Covington
vHMI


I am just starting to use your AutomationDirect driver and it looks really good.  Could you give me a brief description of the Memory_ReadAsBits property?


Hello,

Setting  .Memory_ReadAsBits = True will cause a read of memory to be returned as an individual bit in the .Memory_DataInt() property.  Setting it to False (the default) will cause the memory to be returned as 8 bits packed into one .Memory_DataInt() element.

If set to True the property .Memory_LengthInWords will set the number of elements returned.  For example .Memory_LengthInWords = 16 will return 16 bits in .Memory_DataInt(0) through .Memory_DataInt(15).

If set to False the property .Memory_LengthInWords will set the number of words returned.  For example .Memory_LengthInWords = 16 will return 16 words in .Memory_DataInt(0) through .Memory_DataInt(15).

Hope this helps.

Regards,

Phil Covington
vHMI




another question (about the AutomationDirect Ethernet driver), if you don't mind.

can you tell me about the polling methods (Control_StartPolling and Control_StopPolling) and the Control_UpdateInterval property?

I am trying to do some rapid (~100 readings/second) data acquisition but cannot get more than 4 or 5 per second.


Hello,

The .Control_UpdateInterval property sets the polling rate in milliseconds.

Basically what the driver does in polling mode is repeatedly call the .Control_Update method when .Control_StartPolling is called.  To stop polling you just call the .Control_StopPolling method.  The Done event will be fired repeatedly with the results from the last polling cycle.  The results are returned in the .Memory_DataInt, .Memory_DataFloat, and Memory_DataLong properties as usual.  If you poll faster than the PLC can return data, the fastest polling rate will effectively be the rate at which the PLC returns the data.

How many words are you trying to read from the PLC at one time (what .Memory_LengthInWords value are you using)?
You can get an idea of how long it takes for the PLC to return data by calling the .Control_Update method after setting up the data points you want to read and then examining the value of the .Communications_ElaspedTimer property after the Done event has fired.  This property will give you the time it took to read the data in milliseconds.  That way you can see if you can realistically expect to read the amount of data you want in the amount of time you want.

Please also note that the protocol can return a maximum of 64 contiguous words (or 1024 bits) in any one transaction.

Hope this helps.

Regards,

Phil Covington
vHMI






Allen Bradley

I purchased the vHMI ActiveX probably about 2 years ago. I have only done AB ints, floats, and longs to date. I would like to use it to read counters, timers, etc. I think I should use "sub_element" addressing but I'm not sure how to use it. Could you provide an example of how to read accumulator of a counter (slc500 over Ethernet).

Hello,

It looks like you are using the old combined Serial/Ethernet driver.  The new versions are separated into a serial DF1 version (ABD) and Ethernet version (ABE) which supports all the *Logix types in addition to SLC500 and PLC5.  If you need to talk to the MicroLogix or ControlLogix (or want to talk to the ENI module) you might want to look at the new drivers at http://www.vhmiautomation.com

You will want to do something like this to read a counter:

   ab.Memory_Type = C_Counter_eth
   ab.Memory_FileAddress = 5  'file address for your counters
   ab.Memory_Function = ReadMemory_eth
   ab.Memory_StartAddress = 1 'start at counter 1
   ab.Control_UseSubElementAddressing = True
   ab.Memory_SubElement = 0  'Note for counter 0=Control, 1=preset, 2=accumulated
   ab.Memory_LengthInWords = 3 'each subelement is 1 word
   ab.Control_Update

So when the done event fires you will have:

ab.Memory_DataInt(0)  - subelement 0 which is the control word of counter 1
ab.Memory_DataInt(1)  - subelement 1 which is the preset of counter 1
ab.Memory_DataInt(2)  - subelement 2 which is the accumulated value of counter 1

If you set the ab.Memory_LengthInWords = 6 ( or 2 x 3 subelement words) you will get the next counter's subelements like this:

counter 1:
ab.Memory_DataInt(0)  - subelement 0 which is the control word
ab.Memory_DataInt(1)  - subelement 1 which is the preset
ab.Memory_DataInt(2)  - subelement 2 which is the accumulated value

counter 2:
ab.Memory_DataInt(3)  - subelement 0 which is the control word
ab.Memory_DataInt(4)  - subelement 1 which is the preset
ab.Memory_DataInt(5)  - subelement 2 which is the accumulated value

and so on...

Timers work exactly the same way.

Note that the ab.Memory_SubElement property sets which subelement you start reading at.  The valid values for counters and timers are 0 - 2.  If you start at ab.Memory_SubElement = 1 then ab.Memory_DataInt(0) will contain subelement 1 (preset) of counter 1.  The ab.Memory_SubElement works in conjunction with the ab.Memory_LengthInWords property to set the start subelement and the number of subelements respectively.  Each subelement consumes 1 word.
Hope this helps.

Regards,
Phil Covington
vHMI

Hi,

I had purchased your plc drivers and hmi package a few years back,
I had done an application with the AB Ethernet with no problems.
I am currently working on a Serial DF1 and am having problems with the Set_Bit and Clr_Bit using a SLC 500
Message that it is not supported?
Is this a problem? Is there a way to set and reset individual bits with this driver and the SLC500?
I have version 1.0.0.0 vHMIABCommLib.dll

Hello,

Set and Clear Bit are not supported in the AB protocol for DF1.  This is a shortcoming of AB's protocol and not the driver.  I am working on an update for the DF1 driver that does support these functions for all PLC types.  Basically what you have to do is first read the word whose bit your are interested in.  Then you set or clear the bit in that word and rewrite it to the PLC.  The driver should be ready in a few weeks.

Regards,

Phil Covington
vHMI


Is there an upgrade policy?

Hello,

The combined serial/ethernet version of the driver is the older version that only supports the SLC500 and PLC5.   The new versions of the drivers have been sperated into a serial DF1 version (ABD) and an ethernet version (ABE).  Both also support the *Logix processors in addition to the SLC500 and PLC5.

Unfortunately there is not upgrade path from the combined driver to the new ABD and ABE drivers.  Either driver is available from the website for 49.99 at http://www.vhmiautomation.com

The alternative to purchasing a new driver is to implement the Read Word -> Set/Reset Bit -> Write word functionality in your own programming.  You basically just need to set a flag so that when the Read Word part of the sequence fires the Done event you trigger the Set/Reset Bit -> Write Word part next in the sequence.  That is how it is implemented in the new ABE driver behind the scenes since the AB protocol does not support Bit Set/Reset for some CPU types in the protocol.

Regards,

Phil Covington
vHMI


Hi Phil...
 
Thanks for send me the ftp links and passwords.
 
I installed all .msi files and  I  started to work...
 
My hardware is a SLC500 5/03 ,  1761-NET-ENI interface and an ethernet switch.
I got communication with RSlinks gateway using fixed IP in my computer 192.168.0.61
and fixed IP in the 1761-NET-ENI interface.   I did a test with RSLogix500 to program and
read/write data in 5/03 processor.  Everything was running fine... I shut off all Rockwell softwares..
  
I run your ABEdemo ...just to check the communication...
I filled the IP address field with 1761-NET-ENI IP  interface and choose SCL processor.
But I got a socket error  at right side...
 
Do you know what could happend ???
 
Thanks

Hello,

A socket error indicates that you either do not have the correct port set in the PLC or in the ActiveX DLL.  Check which port number your ENI is configured for and set the Port number in the ActiveX DLL to the same.  Common port numbers are 2222 for SLC500 and 44818 for *Logix PLCs.   The ENI uses 44818.

Regards,
Phil Covington
vHMI



Modbus

I have a question concerning write a Register to my GE FANUC PLC. I create my modbus device in code and can write individual %M bits. But when trying to write to a register and using a double variable, I’m not sure how to implement (.memory_DataFloat) The Problem is that each (double) value takes up two Registers in the PLC. For example if I’m trying to put %R1 to equal 1.504 (A REAL NUMBER) it uses %R1 and %R2 for that value. So the next register I can use is %R3. Using the .Memory_DataInt will only all me to write a INT value. How does the .Memory_DataFloat work and how can I use it to write Double values.

Thanks for you help.

These are my declarations:

Dim dev1 As vHMIModbusMaster.CDevice
Public WithEvents GEmodbus1 As CModbusSerial
Public WithEvents GEmodbus2 As CModbusSerial
Public WithEvents GEmodbus3 As CModbusSerial
Public WithEvents GEmodbus4 As CModbusSerial
Public WithEvents GEmodbus5 As CModbusSerial

Set dev1 = New vHMIModbusMaster.CDevice
Set GEmodbus1 = dev1.CreateDevice(Modbus_Serial_Master)

With GEmodbus1

.Memory_Type = HoldingRegisters_ser
.Memory_StartAddress = 99
.Memory_LengthInWords = 17
.Memory_DataInt(0) = gintSetpoints(2)
.Memory_Function = WriteMemory_ser
.Control_Update

End With

EX:

With GEmodbus1

.memory_Type = HoldingRegisters_ser
.memory_StartAddress = 200
.Memory_LengthInWords = 17
.Memory_DataFloat(0) = gdblSetpoint(1)
.Memory_DataFloat(2) = gdblSetpoint(2)
.Memory_Function = writememory_ser
.Control_Update

End With


Hello,

.memory_DataFloat (0) is the same as .memory_DataInt(0) and .memory_DataInt(1) except the data in the two words are placed in floating point format.

So to write a floating point number starting at %R1 you need to specify a .memory_LengthInWords = 2 since you are actually taking up two words (%R1,%R2) in the PLC memory.

To write two consecutive floating point values you would specify .memory_LenghInWords = 4 since you are writing to %R1, %R2 for the first float and %R3,%R4 for the second float. You are using 4 words.

It is the same way with reading float values. You have to remember that each floating point (or Long) value takes up two words in the PLC memory and set the .memory_LengthInWords accordingly.

When you go from an index of 0 to 1 (.memory_DataFloat(0), memory_DataFloat(1)) you are advancing by two words (ie. .memory_DataInt(0), .memory_DataInt(1) to .memory_DataInt(2), .memory_DataInt(3)). The driver actually just sees words but the actual respresentation of those words is determined by whether you look at .memory_DataInt, .memory_DataFloat, or .memory_DataLong. .memory_DataFloat and .memory_DataLong each require 32 bits, or two words. The PLC actually only sees all numbers as 16 bit words.

Hope this helps.

Regards,

Phil Covington
vHMI


Another quick question hopefully.

If I need to start from two different Registers: I'm getting Registers
written over. Is this the right code?

The first part works great. But when I try to write to the PLC starting at
the R219 address it overwrites .Memory_DataFloat(0). I thought that the
data would already be written to the PLC. Hopefully you can help. Thanks

With GEmodbus1
.Memory_Type = HoldingRegisters_ser
.Memory_StartAddress = 170
.Memory_LengthInWords = 14
.Memory_DataFloat(0) = gdblPoints(0)
.Memory_DataFloat(1) = gdblPoints(1)
.Memory_DataFloat(2) = gdblPoints(2)
.Memory_DataFloat(3) = gdblPoints(3)
.Memory_DataFloat(4) = gdblPoints(4)
.Memory_DataFloat(5) = gdblPoints(5)
.Memory_DataFloat(6) = gdblPoints(6)
.Memory_DataFloat(7) = gdblPoints(7)
.Memory_Function = WriteMemory_ser

.Memory_StartAddress = 219
.Memory_LengthInWords = 32
.Memory_DataFloat(0) = gdblPoints(8)
.Memory_DataFloat(1) = gdblPoints(9)
.Memory_DataFloat(2) = gdblPoints(10)
.Memory_DataFloat(3) = gdblPoints(11)
.Memory_DataFloat(4) = gdblPoints(12)
.Memory_DataFloat(5) = gdblPoints(13)
.Memory_DataFloat(6) = gdblPoints(14)
.Memory_DataFloat(7) = gdblPoints(15)
.Memory_DataFloat(8) = gdblPoints(16)
.Memory_DataFloat(9) = gdblPoints(17)
.Memory_DataFloat(10) = gdblPoints(18)
.Memory_DataFloat(11) = gdblPoints(19)
.Memory_DataFloat(12) = gdblPoints(20)
.Memory_DataFloat(13) = gdblPoints(21)
.Memory_DataFloat(14) = gdblPoints(22)
.Memory_DataFloat(15) = gdblPoints(23)
.Memory_Function = WriteMemory_ser
.Control_Update
End With


Hello,

Data is not written or read from the PLC until you call the .Control_Update method.  In your code below you are not writing over the registers - you are changing the values in the .Memory_DataFloat()s before you even write the first set to the PLC because you have not called .Control_Update for the first group.

You need to do something like this:

    .Memory_Type = HoldingRegisters_ser
       .Memory_StartAddress = 170
       .Memory_LengthInWords = 14
       .Memory_DataFloat(0) = gdblPoints(0)
       .Memory_DataFloat(1) = gdblPoints(1)
       .Memory_DataFloat(2) = gdblPoints(2)
       .Memory_DataFloat(3) = gdblPoints(3)
       .Memory_DataFloat(4) = gdblPoints(4)
       .Memory_DataFloat(5) = gdblPoints(5)
       .Memory_DataFloat(6) = gdblPoints(6)
       .Memory_DataFloat(7) = gdblPoints(7)
       .Memory_Function = WriteMemory_ser
    .Control_Update

Then wait for the Done event to fire indicating that the data has been successfully written to the PLC and then do the next group:

    .Memory_StartAddress = 219
       .Memory_LengthInWords = 32
       .Memory_DataFloat(0) = gdblPoints(8)
       .Memory_DataFloat(1) = gdblPoints(9)
       .Memory_DataFloat(2) = gdblPoints(10)
       .Memory_DataFloat(3) = gdblPoints(11)
       .Memory_DataFloat(4) = gdblPoints(12)
       .Memory_DataFloat(5) = gdblPoints(13)
       .Memory_DataFloat(6) = gdblPoints(14)
       .Memory_DataFloat(7) = gdblPoints(15)
       .Memory_DataFloat(8) = gdblPoints(16)
       .Memory_DataFloat(9) = gdblPoints(17)
       .Memory_DataFloat(10) = gdblPoints(18)
       .Memory_DataFloat(11) = gdblPoints(19)
       .Memory_DataFloat(12) = gdblPoints(20)
       .Memory_DataFloat(13) = gdblPoints(21)
       .Memory_DataFloat(14) = gdblPoints(22)
       .Memory_DataFloat(15) = gdblPoints(23)
       .Memory_Function = WriteMemory_ser
       .Control_Update

YOU SHOULD NOT try to write both groups within the same sub or function.  You are not guaranteed that the data has been successfully written until the Done event is fired after calling .Control_Update for the first group.

Some people will poll the .Control_IsBusy property in a DoEvents loop to wait after the first .Control_Update.  I do not generally recommend this since it is a crappy procedural way of doing things and goes against the event driven model (that is what the Done event is for).  It is better to set a flag in the Done event and use a timer to periodically check the flag to know when to write the next group with .Control_Update. For more complex applications I recommend setting up a state machine to sequentially write groups of values to the PLC.

Regards,
Phil Covington
vHMI

BACK