ACS580 Adaptive programming

Pashok

Member
Join Date
Feb 2024
Location
Poland
Posts
3
Hi, all.
Have a problem with adaptive programming, I'm a beginner in this, usually do not use such type of solution.
Normally, I'm connecting 1 motor to 1 frequency converter and everything is ok. This time, the task was complicated by the presence of 2 motors with identical parameters that were connected to the inverter using contactors.
The conditions are as follows: in one cycle (engine stop - end of the cycle) only one engine should run, with each subsequent cycle the next engine should start, that is, they should start in turn. There is also a blockade of each engine (in case of breakdown or repair), then the logic should not switch the engine, but work with the available one.
As I see it, DI 1 - start command, DI 2 - blockade of the first, DI 3 - blockade of the second, RO1 - 1 contactor (select 1 engine), RO2 - 2 contactor (select 2 engine)
How to write logic using logic blocks in "Drive composer entry" app
Can anyone help me with this? Thank you.
 
I apologize that I cannot speak the Polish language, but it seems your English is pretty good, so hopefully you can understand well enough.

The key here is a software principle called "separation of concerns." There are two concerns here:
  • When any one engine should be running
  • Which engine to run when any one engine is running.
Applying "separation of concerns" means that we treat these issues separately.

When one motor should be running

This can be implemented on one rung with a simple Start/Stop Circuit pattern (see here, or almost any beginning tutorial of Ladder logic). The output ("RUN") bit of this "circuit" will be a bit that has either has a value of 0 when no engine should be running, or has a value of 1 when one engine should be running. The "separation of concerns" means that this bit does not "know" which of the two engines should be running, only that one of the engines should be running.

In prose, the logic for the Start/Stop Circuit can be stated like this:

IF ((value of start_command is 1) OR (value of run was 1 on the last scan cycle)) AND (stop_command is 0) THEN [assign value of run to 1] ELSE [assign value of run to 0]​

In the Start/Stop Circuit pattern, the OR is implemented by the parallel branches; the AND is implemented by the parallel branches in series with a contact on the stop command input; the assignments of either value to run is implemented with a coil.

Which motor should be running when one motor is running (i.e. when run bit value is 1)

Fortunately, there are only two motors, so the logic for this is straightforward. We can model (represent) which engine is to run with a single bit; we will call the bit which; the value of which is 0 when engine 1 is to run, and the value of which is 1 when engine 2 is to run. Let us ignore, for the moment, the problem of how to assign and/or change the value of which, and also the problem of how to handle a lockout (blockade) of either engine, and look instead how to command the motors to run using this which data model:

(A) IF (value of run is 1) AND (value of which is 0) THEN (assign value of engine1 to 1) ELSE (assign value of engine1 to 0)​
(B) IF (value of run is 1) AND (value of which is 1) THEN (assign value of engine2 to 1) ELSE (assign value of engine2 to 0)​
Note that this uses a another separation of concerns: engine1 is dependent only on the values of run and of which, but does not care about the value of engine2, and vice versa. I mention this because it is also possible to leave the engine1 logic alone, and make engine2 be dependent on the result of engine1, like this:

(B.alternate) IF (value of run is 1) AND (value of engine1 is 0) THEN (assign value of engine 2 to 1) ELSE (assign value of engine2 to 0).​
In other words, if any one motor should be running, but engine1 is not running, then engine2 must run. I mention this because, while both of these ways to control engine2 are simple, when we add in the logic for lockouts (blockades), it will be simpler to only apply that lockout logic to engine1, and let the result of that logic, e.g. when which value is 0 (i.e. engine1 should be active if neither engine is locked out) AND lockout1 is 1 (engine1 is locked out), propagate to the engine2 logic via the simpler (B.alternate) option above.

Lockout logic

Using (B.alternate) above, we only need to apply any lockout (blockade) logic to engine1.
  • If engine1 is locked out, then engine1 must be prevented from running, independent of the state of which
    • This can be implemented via an AND (value of lockout1 is 0) expression to (A) above.
    • So even if run value is 1 and which value is 0, if lockout1 value is 1, then (A) says "Nie mój cyrk, nie moje małpy"
  • If engine2 is locked out, then engine1 must run when run value is 1, independent of the state of which
    • This can be implement via an OR (value of lockout2 is 0) expression to the (value of which is 0) clause of (A) above
So (A) becomes:

(A.lockout) IF (value of run is 0) AND ((value of which is 0) OR (value of lockout2 is 1)) AND (value of lockout1 is 0) THEN (assign value of engine1 to 1) ELSE (assign value of engine1 to 0)​

It might also be wise to add an AND (value of lockout1 is 0) expression to (B.alternate) above, to ensure that, in case both engines' are locked out at the same time, that neither engine will be commanded to run.

Assigning a value to which

I left this bit for last, because it is my favorite. The specification is that which the engines 1 and 2 alternate which runs each time any one engine is commanded to run. To do this, we need a simple bit of logic to execute:

Code:
  which    which
---]/[------( )--

The prose equivalent would be

IF which THEN (assign value of which to 0) ELSE (assign value of which to 1)​

However, that code must execute as a one-shot e.g. on the single scan cycle when an engine stops running i.e. transitions from running to not running. On all other scan cycles, e.g. when an engine is running, or when an engine is not running but it was also not running on the previous scan cycle, the value of which must not change. I don't know what instructions are available to "Drive composer," but if there is an edge detector, the something like this might work:

Code:
      run    off_edge
------]N[------( )-----

where the off_edge bit will be 1 on the scan cycle when run transitions from 1 to 0. Then that off_edge bit can control the which bit like this (my favorite circuit):

Code:
    off_edge   which        which
--+---] [-------]/[-----+----( )----
  |                     |
  | off_edge   which    |
  +---]/[-------] [-----+

There are many other ways to toggle a bit; look at the [Downloads] link above, under the [Allen-Bradly] link, for the word "Alternator" on this web site.

One thing to mention is that, while this will work, it may not do exactly what is desired. For example, if engine 2 is locked out, the which bit will continue to flip back and forth between 0 and 1, and when the engine 2 lockout is removed, if that happens while no engine is running, engine 1 could still be the next engine to start. Or, if engine 1 is running while the value of lockout2 is 1, but the value of which is 1, then ending the lockout could immediately stop engine 1 and start engine 2, and that may not be a desirable behavior. There are ways to modify this approach so that does not happen; specifically, adding the lockout logic to the coil that writes the value of which, instead of having lockout logic before the coil that writes the value of engine1.

Finally, the ideas provided here are meant as an example only; there are many ways to "skin this cat" (English/American idiom). There will be many threads on this website that you can find using the search terms "lead lag" that solve a similar problem. I strongly suggest you read some of those threads and think about this problem and come up with a solution that makes the most sense to you.
 
I apologize that I cannot speak the Polish language, but it seems your English is pretty good, so hopefully you can understand well enough.

The key here is a software principle called "separation of concerns." There are two concerns here:
  • When any one engine should be running
  • Which engine to run when any one engine is running.
Applying "separation of concerns" means that we treat these issues separately.

When one motor should be running

This can be implemented on one rung with a simple Start/Stop Circuit pattern (see here, or almost any beginning tutorial of Ladder logic). The output ("RUN") bit of this "circuit" will be a bit that has either has a value of 0 when no engine should be running, or has a value of 1 when one engine should be running. The "separation of concerns" means that this bit does not "know" which of the two engines should be running, only that one of the engines should be running.

In prose, the logic for the Start/Stop Circuit can be stated like this:

IF ((value of start_command is 1) OR (value of run was 1 on the last scan cycle)) AND (stop_command is 0) THEN [assign value of run to 1] ELSE [assign value of run to 0]​

In the Start/Stop Circuit pattern, the OR is implemented by the parallel branches; the AND is implemented by the parallel branches in series with a contact on the stop command input; the assignments of either value to run is implemented with a coil.

Which motor should be running when one motor is running (i.e. when run bit value is 1)

Fortunately, there are only two motors, so the logic for this is straightforward. We can model (represent) which engine is to run with a single bit; we will call the bit which; the value of which is 0 when engine 1 is to run, and the value of which is 1 when engine 2 is to run. Let us ignore, for the moment, the problem of how to assign and/or change the value of which, and also the problem of how to handle a lockout (blockade) of either engine, and look instead how to command the motors to run using this which data model:

(A) IF (value of run is 1) AND (value of which is 0) THEN (assign value of engine1 to 1) ELSE (assign value of engine1 to 0)​
(B) IF (value of run is 1) AND (value of which is 1) THEN (assign value of engine2 to 1) ELSE (assign value of engine2 to 0)​
Note that this uses a another separation of concerns: engine1 is dependent only on the values of run and of which, but does not care about the value of engine2, and vice versa. I mention this because it is also possible to leave the engine1 logic alone, and make engine2 be dependent on the result of engine1, like this:

(B.alternate) IF (value of run is 1) AND (value of engine1 is 0) THEN (assign value of engine 2 to 1) ELSE (assign value of engine2 to 0).​
In other words, if any one motor should be running, but engine1 is not running, then engine2 must run. I mention this because, while both of these ways to control engine2 are simple, when we add in the logic for lockouts (blockades), it will be simpler to only apply that lockout logic to engine1, and let the result of that logic, e.g. when which value is 0 (i.e. engine1 should be active if neither engine is locked out) AND lockout1 is 1 (engine1 is locked out), propagate to the engine2 logic via the simpler (B.alternate) option above.

Lockout logic

Using (B.alternate) above, we only need to apply any lockout (blockade) logic to engine1.
  • If engine1 is locked out, then engine1 must be prevented from running, independent of the state of which
    • This can be implemented via an AND (value of lockout1 is 0) expression to (A) above.
    • So even if run value is 1 and which value is 0, if lockout1 value is 1, then (A) says "Nie mój cyrk, nie moje małpy"
  • If engine2 is locked out, then engine1 must run when run value is 1, independent of the state of which
    • This can be implement via an OR (value of lockout2 is 0) expression to the (value of which is 0) clause of (A) above
So (A) becomes:

(A.lockout) IF (value of run is 0) AND ((value of which is 0) OR (value of lockout2 is 1)) AND (value of lockout1 is 0) THEN (assign value of engine1 to 1) ELSE (assign value of engine1 to 0)​

It might also be wise to add an AND (value of lockout1 is 0) expression to (B.alternate) above, to ensure that, in case both engines' are locked out at the same time, that neither engine will be commanded to run.

Assigning a value to which

I left this bit for last, because it is my favorite. The specification is that which the engines 1 and 2 alternate which runs each time any one engine is commanded to run. To do this, we need a simple bit of logic to execute:

Code:
  which    which
---]/[------( )--

The prose equivalent would be

IF which THEN (assign value of which to 0) ELSE (assign value of which to 1)​

However, that code must execute as a one-shot e.g. on the single scan cycle when an engine stops running i.e. transitions from running to not running. On all other scan cycles, e.g. when an engine is running, or when an engine is not running but it was also not running on the previous scan cycle, the value of which must not change. I don't know what instructions are available to "Drive composer," but if there is an edge detector, the something like this might work:

Code:
      run    off_edge
------]N[------( )-----

where the off_edge bit will be 1 on the scan cycle when run transitions from 1 to 0. Then that off_edge bit can control the which bit like this (my favorite circuit):

Code:
    off_edge   which        which
--+---] [-------]/[-----+----( )----
  |                     |
  | off_edge   which    |
  +---]/[-------] [-----+

There are many other ways to toggle a bit; look at the [Downloads] link above, under the [Allen-Bradly] link, for the word "Alternator" on this web site.

One thing to mention is that, while this will work, it may not do exactly what is desired. For example, if engine 2 is locked out, the which bit will continue to flip back and forth between 0 and 1, and when the engine 2 lockout is removed, if that happens while no engine is running, engine 1 could still be the next engine to start. Or, if engine 1 is running while the value of lockout2 is 1, but the value of which is 1, then ending the lockout could immediately stop engine 1 and start engine 2, and that may not be a desirable behavior. There are ways to modify this approach so that does not happen; specifically, adding the lockout logic to the coil that writes the value of which, instead of having lockout logic before the coil that writes the value of engine1.

Finally, the ideas provided here are meant as an example only; there are many ways to "skin this cat" (English/American idiom). There will be many threads on this website that you can find using the search terms "lead lag" that solve a similar problem. I strongly suggest you read some of those threads and think about this problem and come up with a solution that makes the most sense to you.
Wow! This is like a university lecture, a lot of useful information!
My apologies for long time answer. Originally I'm from Ukraine but few years living and work in Poland.
Was too funny to see polish expression about circus and monkeys :) but thanks anyway.
If I had used a separate PLC I would have solved this problem using ST
But unfortunately, Drive Composer only allows you to work with a language similar to FBD (never use it), Logic blocks (Not/Or/Xor/AND, Ton, Tof) You have some inputs values DI o some float values. And you have outputs DO, AO or three included relays.

I decided to do this a little differently, I decided to add a pulse relay that will switch the contactors at each next start. At the same time, I made a small program with this "Drive composer" app, that will use the built-in relay in the frequency converter to send a short pulse of 1 seconds to control the pulse relay, and 2 second delay for starting frequency converter in work. Tomorrow i will try to cheek it, will build test stand in the workshop.
 
I decided to do this a little differently, I decided to add a pulse relay that will switch the contactors at each next start. At the same time, I made a small program with this "Drive composer" app, that will use the built-in relay in the frequency converter to send a short pulse of 1 seconds to control the pulse relay, and 2 second delay for starting frequency converter in work. Tomorrow i will try to cheek it, will build test stand in the workshop.

That sounds great, especially the part about the test stand. There is no better way to understand PLCs than to tell them to do something, and then see if they do what you expect, or if they do something else. The best lessons are when they do something else!!!!
 
The issue was resolved and tested. Everything works as intended. I'm adding it as an attachment, maybe it will be useful to someone.
 

Attachments

  • ABB-logic_switcher.pdf
    243.4 KB · Views: 4

Similar Topics

Hi all! I am hoping to find some help understanding the ABB VFD Connection to my Rockwell PLC. I have set up the VFD parameters based on...
Replies
4
Views
685
I'm in the midst of commissioning a number of these units and I'm having a trouble with a flying (re)start. The short background is that my PLC is...
Replies
3
Views
1,765
I am using a Red Lion DA30D Gateway to control 12 ABB drives via RS485 from a M580 PLC. I send -20000 to 20000 as the speed Setpoint to each...
Replies
2
Views
2,350
Ok, here is a question for our AD gurus... I am replacing the float switches in my lift tank with level control sensors feeding into a AD DO6 ...
Replies
1
Views
1,808
I am thinking about trying to connect a Controllogix version 19 to a Adaptive BigDot sign. It looks like this can be done from the serial port on...
Replies
13
Views
3,722
Back
Top Bottom