Sign in to follow this  
Followers 0
BIGEYE

Rotational counter help

39 posts in this topic

I am new to PLC's and request some help with some code I need to write. I have a rotating irrigation arm on a bridge with a proximity switch that detects a pulse each time an arm passes, the bridge has two arms, therefore sees two pulses per revolution. I need to monitor the revolutions per minute or hour, and displey the RPM or RPH on an HMI. The PLC ia an SB SLC5/04 and the HMI is a Red Lion Controls VX5000. My thoughts are to count the pulses over a minute or hour period, then divide this total by 2. The result is displayed on the HMI. The start the next count and then update the HMI with the result. Can anyone comment on my thoughts and advise if there is a better way to acheive this. Also advise how I should write this code. TIA

Share this post


Link to post
Share on other sites
First, how fast are the pulses, and how long are they on and what is the scan time of your PLC? High speed pulses of short duration require special I/O modules. I suspect this is kind of slow, and normal input cards will work, but it is something to look at.

Share this post


Link to post
Share on other sites
The pulses are slow, I get about 4 pulses per rev, with each pulse about 1 second. I am able to count the pulses over a time period, this total is then divided by 4 to give me revs per minute or hour depending on the time period i choose ( either minute or hour depending on what is most suitable. At the end of my time period, my counter is reset and the count darts again for the next time period. What I am struggling with is the total, I need this to be held somewhere and also displayed on the him. Unfortunately, the total resets to 0 when the counter resets. In reality, the displayed total should indicate rpm or rph and not change unless the revs actually change. So all I am looking for is a revs per minute or revs per hour display. Hope this makes sense, or am I doing things the hard way. Is there a better way?

Share this post


Link to post
Share on other sites
When you timer times out MOV the current encoder count to another register. perform your /4 on that number and display the result. Then reset the counter. The displayed number won't change until the next timeout.

Share this post


Link to post
Share on other sites
That doesn't work, what I have already is 4 rungs of code as follows: Rung 1 Digital input I:4.0/12 XIC to a count up counter C23:4 with a preset of 32000 Rung 2 MOV instruction to move C23:4.ACC to Dest N16:6 Rung 3 DIV Source A N16:6 by Source B which is 4, Dest is N16:7 Rung 4 Time pulse XIC pulses once every hour, which resets counter RES C23:4

Share this post


Link to post
Share on other sites
Create a rung before your rung 1 Move the timer (not the counter reset) from rung 4 to this rung Place the timer contact into rungs (current numbering) 2 and 3. They will only fire once for each timeout. (If you notice that the counter counts back up to 1 at reset then place an XIO of I4:0/12 in the RES rung. Remove the Not DN conditional - I presume - from your timer rung. When you reset the counter also do a reset of the timer.) Edited by b_carlton

Share this post


Link to post
Share on other sites
Got it working by adding the second timer contact, have left site for today and will be revisiting tomorrow so will see how it is working, and will report back. Thanks guys for the help.

Share this post


Link to post
Share on other sites
If you continue as you are, your accuracy will be +/- 0.25 rpm (or rph) with 4 pulses per revolution or +/- 0.5 rpm (or rph) with 2 pulses per revolution. If that level of accuracy is sufficient and you are satisfied waiting a whole minute (or hour) to update the value then your current method will work fine. Another option to consider would be to measure the time between each pulse. Assuming each pulse is equally spaced through the revolution you can time between the start of each pulse and calculate the rpm (or rph). Not including some error checking, this can be accomplished in three rungs: First rung - TON with no input conditions - let it run continuously. Set the preset to 32000. Use your best judgement to figure out which time base to use. It all depends on how quickly this thing spins and how accurate you'll need the final answer to be. Second rung - XIO of the prox input followed by an OSR instruction - MOV the timer.acc value to an Integer and RES the timer Third rung - make sure the Integer is NEQ to 0, then DIV 3000 by the Integer to get rpm (assuming you used 0.01 as time base and you have two pulses per rev) If you have 4 pulses per rev you'll have to change the 3000 to 1500. You can make it 30000 (15000) to get an implied decimal if you're looking for some better accuracy. This will update the speed readout every time a pulse is recorded and provide much better accuracy than the method you've described. Edited by cbuysse

Share this post


Link to post
Share on other sites
Excellent, working like a charm. Thanks for all the help.

Share this post


Link to post
Share on other sites
Our ops people are well pleased with the rev counter, and now want to go one step further. Ops now want a display of the number of revs over a 24hr period. So for example, the 24hr period starts at 08:00 hrs and pulses start to accumulate from then, at the end of the 24hr period, the total is dispalyed. Another 24hr count period is started, at the end of which, the new total overwrites the old total and a new count period starts. The process is then repeated. I have wrote some code which has errors, and it looks cumbersome. I will be going back to site on Monday to try and sort it out. What would be the best way to write the code to acheive the objective? THA

Share this post


Link to post
Share on other sites
SLC's have a status word that represents the hour of the day, I believe it's S:40. It's always a number between 0 and 23. You can use that to determine when to make your calculations. First rung - XIO of the prox input and then CTU counter1 - set counter1.PRE to the number pulses per rev (is it 2 or 4 - you've stated different numbers) Second rung - XIO counter1.dn then CTU counter2 and RES counter1 - set counter2.PRE to 32767 Third rung - when S:40 is EQU to 8 (or whatever hour you want to use) OSR then MOV counter2.acc to a separate integer and RES counter2 - you need the OSR here so it won't try to do this for an entire hour between 0800 and 0859. This only works if you expect to have less than 32767 revolutions per day. That corresponds to about 22.75 rpm if this thing runs 24 hours a day. Anything less than that and you're fine. I just had another thought which may change everything. Is your prox picking up a flag on the shaft of the actual rotating part you're concerned about, or on a separate drive shaft? What I'm getting at is whether or not there is actually a whole number of prox pulses in one revolution. If it's not exactly 2 or exactly 4 this method won't work at all and you'll have to change some numbers on the rpm calculations.

Share this post


Link to post
Share on other sites
Thanks for that, the proximity switch picks up the arms of a filter. If you thnk of the letter X revolving about a pivot in the centre, the proximity switch picks up each leg as it passes, hence 4 pulses per rev. It rotates at about 1.4 RPM on average, so would pick up about 8064 pulses over a 24hr period. Edited by BIGEYE

Share this post


Link to post
Share on other sites
Then you should be all set. The integer file will show the total number of revolutions from yesterday. If you want to display the running total of today's you can use the counter2.acc value. Good luck to you.

Share this post


Link to post
Share on other sites
Thanks, will let you know how I get on on Monday.

Share this post


Link to post
Share on other sites
To calculate rate, you can measure the time between rising edges of the sensors and scale that immediately. The first result after starting from rest may need to be thrown out, but after that, you get an update as soon as the proximity switch first turns on again. For this, I have a TON (or RTO) on an unconditional rung. I then XIC the sensor input (usually mapped) through an inline oneshot instruction to a bit commented "Oneshot PX number 7 pulse" or whatever". I then XIC that bit to: 1) Optional store the acc of the timer (highest practical resolution for hte appliaction) in a register. 2) GEQ this value with zero. (Make sure you don't fault) then Div 6000 (or whatever value equates to minutes) by that accumulated number to get "rate per minute" in a floating point register. 3) RES the timer 4) Scale the floating point RPM into whatever value represents the real RPM of the overall machine. This is where you apply gearing, mutiple pulses per final revolution, etc. No need to wait for a long time, just a couple of pulses, although you may get a wrong first reading if you don't also freeze/adjust the timer when the PLC knows the machine is idle, and/or throw out the first reading after starting or changing direction. You can also use this oneshot bit to trigger long term counters for pretty accurate positioning for such a slow moving device. I am gettin on this thread late and barely scanned the other posts, forgive me if I am being redundant. Edited by OkiePC

Share this post


Link to post
Share on other sites
I have done the code like this, but it seems to have a couple of errors. Counter1 was not counting as it was continually being reset by the XIO and RES counter 1 in rung 2. I changed the XIO in rung 2 to an XIC. Counter 1 is now counting. Also, when the total is being rest, the accumulated total in the counter starts at 1 instead of 0, therefore it only needs to see another 3 pulses before resetting again. As a workaround, I have made the preset of counter1 set to 5.

Share this post


Link to post
Share on other sites
Yep - I screwed up. Each "XIO" I mentioned above should have been "XIC". My apologies. I also forgot to take care of the situation where the counter will automatically count up one when you reset it and the counter input is still on, so get rid of the RES instructions and instead MOV 0 to the .acc value. Here's a screen shot showing what I should have described. I just ran it on my emulator and it works fine. Sorry for the confusion - chalk it up to holiday stress. Edited by cbuysse

Share this post


Link to post
Share on other sites
The changes work just fine, thank you very much for that. Can I ask what you are using as an amulator?

Share this post


Link to post
Share on other sites
I'm using Rockwell's Logix 500 Emulator. I'm not sure of any other programs to Emulate an A-B PLC, though I would be interested to know if others exist.

Share this post


Link to post
Share on other sites
Since adding this code, the plc has failed twice. My colleague went to it last time and found the plc to have an S5 fault. He reset this fault ant it went straight back in to fault. He then removed the code and was able to rest the S5 fault. He then put the code back in and it has been working fine for a few days. It has failed again today, and I will attend later. I can only assume that the plc has failed on the same fault. Any ideas?

Share this post


Link to post
Share on other sites
OK, exactly what was the fault? You can read the reason before resetting. Many times a value in a register has overflowed. Look for a large value (I see a 32767 in a counter in a screenshot.) If this is the reason then fix the math. Don't just reset and hope for the best.

Share this post


Link to post
Share on other sites
Check the OSR instruction bit address. Make sure that the same address is not being used somewhere else in the program. The fault you are describing indicates that a register value became larger than it could store - in this case it's most likely the .acc value for counter2. The only way that could happen in your code is if the MOV command didn't function. My first thought is that the OSR instruction isn't functioning correctly because that address is being used elsewhere.

Share this post


Link to post
Share on other sites
The one shots are unique, not used elsewhere. I will upload a PDF of the code when I get home tonight. Thanks

Share this post


Link to post
Share on other sites
Well here goes with my code, I hope it makes sense. I have 3 tanks with a rotation monitor on each tank. Rungs 53 to 59 are for Tank 1. Rungs 60 to 66 are for Tank 2. Rungs 67 to 73 are for Tank 3. Input I:4/12 is the Pulse input from the proximity switch on Tank 1 Input I:5/9 is the Pulse input from the proximity switch on Tank 2 Input I:6/10 is the Pulse input from the proximity switch on Tank 3 So basically the code is identical code for each Tank, only different addresses. Description Rung 53 has Timer T4:16 which times up. Rung 54 has the proximity switch pulse input for Tank 1. The tank sees 1 pulse per Rev. When it sees the pulse, the OSR B3:0/6 is triggered. This in turn moves the accumulated time from T4:16 to N16:44. It also resets Timer T4:16 back to 0, which then starts timing again until the next pulse from the proximity switch. Rung 55 has the NEQ block, so that when N16:44 is not equal to 0, then the maths are performed. The DIV block divides 600 by the accumulated time that was moved in to N16:44. This effectively gives me RPM to 1 decimal place. For example, if I had an accumulated time of 50 secs, the maths would be 600/50 = 12, our HMI is set to 1 decimal place so this reads as 1.2 RPM. The result is put into N16:45. The MUL block multiples whatever is in N16:45 to give me revs per hour (RPH). The result is put into N16:7 Rung 56 Has CTU C23:4 which counts the pulse passing the Proximity switch. C23:4 has a Preset of 1, because we now only have 1 pulse per rev. When the proximity switch sends the pulse, it resets C23:4, which then sites at 0 until the next pulse. Rung 57 has C23:4/DN, when this triggers by what happens in Rung 56, it causes C23:5 to increment by 1. This also moves 0 back in to C23:4 to reset the accumulated total to 0. Rung 58 When the S40 clock equals 9 hrs, OSR B3:0/11 is triggered and moves C23:5.ACC into N16:61. This is my count of Revs over the last 24 hrs. This also moves 0 back into C23:5.ACC thereby resetting the accumulated total back to 0. Rung 59 moves C23:5.ACC total to N16:63. This gives me a running total of revs. The other rungs do exactly the same for the other tanks, only different addresses. EAST CALDER RTU2 31-12-12 REVIS.pdf

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0