Help writing plc code for a bag filling process

I've written down without a sequence. I wanted to do it but i dont know how to. If you guys help how to do it in Tia portal i can, its not the same in parky's light system :(

Well done! It needs some work, but I think you have the understanding to get it right. I especially like how you did the rungs with the timers for the alarms: it shows you understand what is going on pretty well, and can simplify and clarify the needed logic into its best form.

Here are a few comments:

  • In Network 1 on the last rung, we do not need the contacts to test bits P2E, M2E and M1e after the contact for bit S1-loop.
    • Here is why: after the previous rung, any time the S1-loop bit is 1, then the other three bits (P2E, M2E, M1e) will always all be 1, so there is no need to test them with contacts on that last rung.
  • The last rung of Network 1 and the first rung of Network 2 both write either a 0 or a 1 to S2AlarmBit.
    • Having multiple unconditional outputs to the same bit is a common beginner mistake
      • Do not be embarrassed because we have almost all done this,
      • But please remember that it is now your turn to tell the next newbie who does this ;)
    • You are also re-using the data block [%DB1 S2_DB_Timer], which I think is not normally a good idea.
    • You should be able to combine (OR) those rungs together, or just OR the two <Is S1-loop a 1?> and <Is S1 a 1?> contacts together, then AND that result with the <Is S2 a 0?> contact, feed that into a single timer, and connect that timer's .Q to S2AlarmBit, like this:
Code:
    S1-loop        S2       %DB1    S2AlarmBit
--+---] [----+-----]/[------[TON]------( )------
  |          |              T#50s
  |   S1     |
  +---] [----+
  • I strongly suggest you switch to @parky's approach. The differences will be that,
    • Instead of <Is S1-loop a 1> contacts, you will use Equals instructions like this: <Is CurrentStep equal to 10>, and
    • Instead of <Assign 1 to S1-loop> output --( )-- assignments, you will use MOV instructions like this: <MOVe 10 to CurrentStep>
    • The biggest benefit will be that you can see the current step (state) of the process by looking at the value of one integer tag, instead of having to check several bit tags.
    • Also, another benefit will be that your current step can never be inconsistent i.e. with one bit for each state, it is possible to mistakenly set more than one of them true for any one scan.
      • The worst you can do with the integer CurrentStep is set it to a wrong value (e.g. skipping a step), which is easier to debug because the MOV of that value will occur in typically exactly one place,
 
TIA has scaling blocks so you just use them.
I will try to come up with my interpretation of what you posted, it will not be what you want but will give you some ideas about using a sequence to drive the system, I do suggest you keep away from CSF for now and do it in LAD/FBD, that way as you seem to be somewhat familiar with ladder you can use that it will give you good grounding, I personally do not like CSF, it takes some getting used to and most of my previous clients say their engineers find it difficult to understand. I have used it & got some rather cutting comments like he did it that way to confuse us.
Perhaps some suggestions as I have done similar systems.
First of all, you should not need pistons to push boxes, 3 conveyors are all you need.
Infeed to present the box
Weigh conveyor to centre the box & weigh the product in
Outfeed conveyor to feed the full box out.
Perhaps you could have a reject should it fill wrong weight, or just stop the system.
The way I would see it working is conveyor 1 (infeed) runs once process is started, when the photocell S1 (at the outfeed of conveyor 1) is covered, it starts the weigh conveyor, when the box is in the centre of the weigh conveyor (S2) it stops, tares the load cells, proceeds to add the product.
When it reaches within 10% of required weight, it slows the feed, when it reaches the weight, it stops the feed & starts the weigh conveyor & the outfeed conveyor the weigh conveyor stops on box leaving S2 sensor plus a delay to allow the box to exit the weigh conveyor,
So the operation is:
on start run conveyor 1, box at end of conveyor 1 run weigh conveyor, when the box is on the weigh conveyor S2 then the weigh conveyor stops & tares the gross weight (box weight), if another box arrives at S1 conveyor 1 stops (build back) the weight is added, checked, then weigher conveyor runs as well as the outfeed conveyor. when the weigh conveyor is clear you could gross (remove tare from loadcells) and re-start infeed conveyor ready for the next fill.
What you do to put the box on the infeed & take the box off the outfeed you have not stated but just get the logic for the system as is first, there is also something you may want to do is stop system if an alarm is generated i.e. a motor trips or over/under fill, S1 or S2 become blocked after a time (box stuck).
 
Scaling to decrease motor speed as package approaches full weight

The logic in the images below shows one of of many possible ways to do the scaling; given the limitations of the NORM_X and SCALE_X instructions*, it might be cleaner to hide this in a custom function that uses simple arithmetic instructions (ADD, SUB, MUL, DIV) and application-specific input parameters:

  • somewhat full, full, and overfull weight limits from the HMI;
  • min and max motor speeds;
  • tare weight
  • gross weight measurement
Anyway, this uses the .ET of a timer data block that runs from 0 to 10,000ms, converted to DInt tag ton0_et_ms as a proxy for a net weight of 0 to 10,000g.

In the three images below,

  • the NORM_X instruction on the first rung scales input tag ton0_et_ms values of 8,000g (80% of target) to 10,200g (100% of target) to an output value of 0.0 to 1.0.
  • the MIN and MAX instructions on the second rung clamp that [0.0:1.0] value to values 0.0 to 0.9 (if there is a single CLAMP instruction, I missed it)
  • The SUB instruction on the second rung subtracts that clamped [0.0:0.9] value from 1.0, so the final output is in the range 1.0 down to 0.1, representing 100% motor speed down to 10% motor speed.
  • The first image shows the case where the "net weight" is less than 8,000g (80% of target, somewhat full): the final output is 1.0, and can be used to run the motor at 100% of max speed.
  • The second image shows the case where the net weight is 9,733g, between somewhat full and 10,200g (102% of target, overfull): the final output is 0.22, and can be used to run the more at around 22% of max speed.
  • The third image shows the case where the net weight if 10,000g (full, 100% of target): the final output is 0.1, which is chosen as I assume some motors cannot be run down to near 0%; at this point the motor would have been turned off via discrete output, so the speed is irrelevant
* Limitations of SCALE_X and NORM_X: cannot handle negative slope (inverted MIN/MAX limits) correctly; cannot clamp output.

Low weight, full speed
xxx.png
Intermediate weight, partial speed
yyy.png
Full weight, minimum speed
zzz.png
 
Last edited:
I am sorry for making the programme in turkish ,i will start a New version with proper English this time. And this time i will be making it with the step logic thanks to you parky, love you friend.

@drbitboy i will be taking your awesome comments into consideration and try to crack the case. Btw thanks for sending the logic i understand it more clearly now. Thank you a lot you are great and amazing. But i still wanna do something like ai :D. Maybe in future we can do something about that together. But not right now .This system has a lot of holes in it rn and i didnt even start on the HMI stuff yet.:)

I will be going out of Town for a 2-3days but dont think i've given up on This. We will accomplish This together.

Again Thank you guys and see you all in 2-3 days
 
Last edited:
I think the seq one is ok for the weigher conveyor etc. the infeed conveyor would be simpler to do with one coil so no need to do a sequence, I suggest each section be individual so the infeed runs itself, as this will run a new box onto S1 if S1 is clear, here is a very quick & dirty program I threw together, there are a number of areas that could be tidied up (well a lot) but it does work, there is one step not required (Step 5) but i left it in as it does not affect anything, I have done the weigh bit as step flags instead of a seq. word, but easy to change just instead of a step flag move a value into the seq. word & and instead of the step flag contacts use compares. but have a go both ways it will help you learn. As I said before, a pusher is not what would be used in real life you just have a conveyor with loadcells on it so 3 conveyors & a feeder of some sort. But I have taken your pusher & made it two so when on the weigher section conveyor one pusher pushes the box onto the weigh pan & the other pushes it off. [Again your spec is very vague as far as to the equipment and assumed you would use just a loadcell amplifier or coms to get the weight, so have not configured a tare to send to the weigher but done it in the PLC by storing the current weight of the weigher plus the box weight, so in effect we have a tare i.e. 0.0 when empty box is in place, this is grossed again when the box is removed.
This is a simple example & although have a check for out of tolerance have not done a recovery. This is just some idea to show how it might work & give you ideas, I know I could simplify it (Drbitboy will no doubt comment) but the idea was to give you ideas rung by rung so split them into small chunks also I would not use ladder at all but FBD here I have tried to make it a little like TIA but you will have to use their functions as the symbols are probably different.
The logic posted has a very crude simulation just so I could test it & I used an HMI simulator for display purposes, not fancy just plopped on the fields so I could see what was happening, so don't get the idea I write my HMI's like this.

Weigher HMI.png
 

Attachments

  • Weigh.pdf
    124.8 KB · Views: 25

My only comment is that @parky's approach is great; bugs, if there are any any, which I doubt, can be left as an exercise for the student.

The OP would be well-served to notice a few things in particular:

Patterns and KISS


That simple, repeating pattern i.e.
Code:
                 Transition
      Weigher     Condition      Weigher   Weigher
     Step(N-1)   To Step(N)*    Step(N+1)  Step(N)
--+-----] [---------<...>----+-----]/[-------( )---
  |                          |
  |   Weigher                |
  |   Step(N)                |
  +-----] [------------------+

 * The [Transition Condition To Step(N)] could also be called [End Step(N-1)]
is the heart of of the step handling logic; it is a form of the Start/Stop Pattern cf. here, from here. It ensures that

  • each step's boolean can only transition from 0 to 1 when the previous step's boolean is 1 AND that previous step has come to an end
  • each step's boolean maintains (seals in) its own value when it is 1, so the transition condition into that step need be true for only one scan
  • each step's boolean transition back to 0 when the next step's boolean becomes 1
There is a reason the Start/Stop Pattern is almost always used early on in teaching logic: it keeps coming up again and again.

One aspect of using patterns is flexibility: they are easy to extend. For example, the OP mentioned monitoring for conditions that indicate an error has occurred. An --]/[-- test on an boolean, which boolean would have a value of 1 to indicate an error has occurred, could be added to the main branch of the pattern above to assign 0 to all [Weigher Step(N)] booleans. A similar approach could be used to have an HMI-driven transition from Auto to Manual cancel the current step.

Organization

@parky separated the output logic from the step handling logic; in fact, the output logic is in a separate POU(Mitsi)/Block(TIA).

This is a form of the generic programming concept called Separation of Concerns. In this case:

  • the inputs and the step number of the current scan determine the step for the rest of this scan and the next scan;
  • each step is concerned with as few things as possible, and doing just one thing is best;
  • the step only determines the output.
It may not be obvious, but this makes the code much easier to read, and, more importantly, to validate as correct.

Encapsulation

As noted above, each step does one thing. One result of this is that, it seems to me, there are more individual steps than were apparent in OP's original vision. But this is good, because if many things were happening in any one step, then the logic, both transitional and output, for that step would become more complex, more difficult to read, debug, and validate, more likely to have an unforeseen edge case that causes failure.

Another result is portability. For example, the existing step logic pattern rungs are ordered from the first step to the last step. This means that, at the end of scans where step transitions occur, the booleans for Step(N-1) and Step(N) will be 1. This is unlikely to cause a problem since scans are short (milliseconds). However, if for example it was important that two outputs could not be on at the same time even for so brief a time, then simply reordering the step logic pattern rungs from last to first would resolve the issue: on a scan when Step(N+1) would transition to 1, that would assign 0 to Step(N) on a later rung in the same scan.
 
Last edited:
Here's a step sequence using SET/RESET in omrons's CX Programmer. That's from a machine I was troubleshooting a few years ago.
I added annotation to clarify where the rungs start.
 
Both Step flags or seq. compares work equally well but seq. is better as if you call your flags step 1, step 2 etc. and you need to add in another step then it becomes a little messy, although in many applications each step will be a single operation it does not have to be so for example a step may consist of 2 or more operations like run two pumps.
Also take for example a pick & place machine the up/down pick unit will operate on two steps i.e. pick a parts station (down) & place at fit station (down) so this is a good reason for keeping your outputs in a separate block.
STEP 1 (pick)
------| |--------+-------( ) SOL DOWN
........................|
STEP 4 (Place). ..|
------| |--------+

Seq. words are especially good for batching processes driven from a recipe
for example: a batch process may have a number of operations

1. Add Water
2. Heat
3. Add ingredient 1
4. Mix & Heat
5. Add ingredient 2
6. Mix & Heat
7. Add ingredient 3
7. Mix & Heat
8. Take sample
8. Discharge
By using a sequence word you can split each type of operation into areas for example:
Initialisation 1-199
Add Water 200-299
Mix & Heat 300-399
Add Ingredient 1 400-499
Add Ingredient 2 500-599
Add Ingredient 3 600-699
Take sample 700-799
Discharge 800-899
Next Stage Check 1000 (jumped to after each of the above stages to load the recipe stage & check what operation is in the recipe)
So at the start of batching it runs through seq. 1-199 (checks)
At the end it forces the seq. to 1000 to load & check the recipe stage if for example the type is 1 then it forces the seq. word to Add water (100)
The first recipe stage is loaded (assume Water addition but could be any addition) It then runs through the seq. 100-199 then jumps to 1000 this then loads the next recipe stage, checks the type & forces the seq. word to that stage.
Each of the recipe operations could be in separate functions so these are called conditionally based on the seq. word limits for that stage i.e. if seq. is >= 100 AND <= 199 call water addition.
Most additions will not need 100 steps but by making the steps in 10 or more means if you need to add some operation within the stage it makes it simple.
Also a bonus is if you have an HMI or Scada system most have message fields that display messages based on a value in a variable, so the Seq. word also becomes a way of displaying the current operation on the screen.
 
Hello friends, im back.

After due consideration i will be moving my operation to a seqeuence. I will be sharing my seq-code as soon as possible to check with you guys. Your opinions matter a lot to me.

My biggest issue still stands though. I've considered using @drbitboy's full, overfull way for speed control. I've done some research and i think i can use PID for speed control. But if i dont know how. I dont know if i will need to scale the speed values to 0-100 or how can i use it to scale it according to the fullness of the box.

I am currently reading this

https://cache.industry.siemens.com/...00_pid_control_function_manual_enUS_en-US.pdf

But any help would be appreciated.

Maybe other than using PID i could be connecting my speed driver and loadcell transmitter and call a driver read block or something like that. And use them to control speed with the weigh value
 
Do not use PID for filling, the idea is as the weight gets closer to the target then it will slow down, however, this will cause the fill time to extend considerably do not see the need for PID unless you limit the low end i.e have a non zero bottom end,
 
PID uses feedback control i.e. it is a reactive model, and can handle some un-modeled system changes.

Reducing speed as the measured weight approaches the target weight is essentially a P-only* feedback model. However, it also has aspects of feedforward control i.e. it is a predictive model; un-modeled system changes will cause an error.

Feedforward is the better choice assuming the model is adequate.

* With most if not all Siemens PID instructions, it looks like the Integral and Derivative actions can be deactivated by assigning a value of 0.0 to both Ti and Td parameters.

In the OP's case, a P-only PID might work with

  • The measured weight as the PV
  • Setpoint at a bit over 100% of the target weight
    • E.g. 102%
    • The higher it is
      • the faster it will approach the target at the end of a fill
      • and the larger the possible overfill
  • The proportional gain set to generate an output of 100% at some value under 100% of the target weight
    • E.g. 80%, so a proportional band of 0.2 (20% = 100% - 80%), equivalent to the gain of 5 (100% / (100% - 20%))
    • This, with the setpoint above, would cause the motor speed to slow as the target weight approached.
The rest of the logic could handle the sequencing e.g. when to stop the filling process i.e. when the measured value is at or just below the target weight:

  • Disable the P-only PID, or put it into manual and set the output to 0.0
  • Remove the RUN signal to the motor/VFD
  • Close the valve by assigning 0 to P1
Using the PID in this fashion is using a sledgehammer to crack a nut, but it does encapsulate a portion of the required functionality into a single instruction.

Tuning the setpoint, gain, and stop-fill parameters would be another issue. Since the filling device (VFD, motor, material feeder, valve) behavior is more or less constant, it is likely that the best setpoint stop fill will be some fixed weights above and below, respectively, the actual target fill weight, and the proportional band will be a fixed weight below the the target fill weight.
 
Using the PID in this fashion is using a sledgehammer to crack a nut,

I am stomped rn :D . i cant find a way to do this

What are the exact issues with reducing the motor speed linearly as the weight increases? I don't see PID as a solution here either

Now that we have eliminated PID as an option I am stuck. I cant think of another way to do this. What would you guys suggest?

And btw i am almost done with the code. I've done it exactly like @parky's step design. I will start the alarms and notifications now. After that i will start to work on my HMI. But after im done with my alarms and notifications i will send pdf or screenshots of my code so you guys can see it.
 
Last edited:
What's wrong with this code? Looks like it would work in my opinion.

The logic in the images below shows one of of many possible ways to do the scaling; given the limitations of the NORM_X and SCALE_X instructions*, it might be cleaner to hide this in a custom function that uses simple arithmetic instructions (ADD, SUB, MUL, DIV) and application-specific input parameters:

  • somewhat full, full, and overfull weight limits from the HMI;
  • min and max motor speeds;
  • tare weight
  • gross weight measurement
Anyway, this uses the .ET of a timer data block that runs from 0 to 10,000ms, converted to DInt tag ton0_et_ms as a proxy for a net weight of 0 to 10,000g.

In the three images below,

  • the NORM_X instruction on the first rung scales input tag ton0_et_ms values of 8,000g (80% of target) to 10,200g (100% of target) to an output value of 0.0 to 1.0.
  • the MIN and MAX instructions on the second rung clamp that [0.0:1.0] value to values 0.0 to 0.9 (if there is a single CLAMP instruction, I missed it)
  • The SUB instruction on the second rung subtracts that clamped [0.0:0.9] value from 1.0, so the final output is in the range 1.0 down to 0.1, representing 100% motor speed down to 10% motor speed.
  • The first image shows the case where the "net weight" is less than 8,000g (80% of target, somewhat full): the final output is 1.0, and can be used to run the motor at 100% of max speed.
  • The second image shows the case where the net weight is 9,733g, between somewhat full and 10,200g (102% of target, overfull): the final output is 0.22, and can be used to run the more at around 22% of max speed.
  • The third image shows the case where the net weight if 10,000g (full, 100% of target): the final output is 0.1, which is chosen as I assume some motors cannot be run down to near 0%; at this point the motor would have been turned off via discrete output, so the speed is irrelevant
* Limitations of SCALE_X and NORM_X: cannot handle negative slope (inverted MIN/MAX limits) correctly; cannot clamp output.

Low weight, full speedIntermediate weight, partial speedFull weight, minimum speed
 

Similar Topics

i am new to these things. I have no intention of using this in a commercial way whatsoever. I wanted to write a small plc programme for myself. We...
Replies
18
Views
7,737
Hi, I have very limited knowledge in PLC. I uploaded the updated version of the software from our supplier on Omron PLC CP1H. It was also UM...
Replies
8
Views
13,797
Hi friends I am doing my major project and I need your help in writing a Ladder logic plc program. My project is to detect the edges of a block...
Replies
1
Views
4,801
Hi, every body! I have a small project. I wrote programmer control two pump motors by plc s7-300. Now I want to write programmer connect PLC to PC...
Replies
2
Views
4,572
Hello, First, let me start by letting you know that i am not a PLC programmer, nor am i a PLC user, in fact the first time i even heard of their...
Replies
18
Views
10,527
Back
Top Bottom