AngryRobot

Storing multiple bits, indexing when a button is pressed.

22 posts in this topic

The title of this probably makes no sense, but I really wasn't sure what to call this thread.

I'm working on a program for a Q Series, using ladder with labels.  This machine is going to have several status messages for the operator displayed on the HMI at the same time.  If I can figure this out my plan is to have a string display in the footer of a Proface HMI, with a "view next message" button.  Then I will write strings to the display giving the operator the status information and they will be able to press the next button to view the message- alternatively I could have a timer also that will auto refresh the display to the next message.  

 

What I can't figure out, is how to queue the messages and have them wait for the button press or the timer to activate their MOV statement.  Essentially, I need to advance a register by one every time the "next" command is given- but if that status message is not active then I need to immediately skip to the next message.

 

I've thought about just incrementing a data register, but then how do I skip non-active messages? 

Share this post


Link to post
Share on other sites

I believe proface has an alarm table similar to the Mits GOT series displays. You could then create a table with all the messages you would like to display and call that screen via the button. 

Share this post


Link to post
Share on other sites

Well, that is the way I have always handled faults.  I place an alarm display object on a pop up window and call the pop up when the fault bit/tag in the PLC is active.

 

Using the Proface alarms table still wouldn't allow me to have a single line display that changed between messages.  Using a single line alarm display would only display the first active alarm.   

 

Share this post


Link to post
Share on other sites

I think I've figured out how to get it done.  I just needed to find the first in first out instructions.  I've used them with some Omron PLCs in the past but have never used them with Mitsubishi, so I didn't realize they were called FIFW/FIFR and not FIFO. 

Share this post


Link to post
Share on other sites

Well, using FIFW/R does accomplish what I was trying to do in a round about way... but its destructive when you read the list. 

 

Is there a way to simply index through an array?

 

I do this exact thing in a Logix5000 program.  I was able to use UDT's in that program to boil this down to one rung of logic.  I don't expect to be able to make it as sleek in GX Works 2, but I'm struggling to even figure out how to index the array.

Share this post


Link to post
Share on other sites

ArrayLabel[someIntegerVariable]

There you have indexing, just place brackets and any integer you have the index value in.

Share this post


Link to post
Share on other sites

I can't specify the element of an array based on the value of another data area can I?

 

IE:  I have a 5 element array TEST[0]-TEST[4]; I can't increment label POINTER and then call the array element like TEST[POINTER]?

 

EDIT:

Ok, figured that out.  I had to go back to just using an assigned data area IE D4000 instead of TEST and then used Z0 as my pointer.

Edited by AngryRobot

Share this post


Link to post
Share on other sites
14 minutes ago, AngryRobot said:

Ok, figured that out.  I had to go back to just using an assigned data area IE D4000 instead of TEST and then used Z0 as my pointer.

Yeah, "Simple Ladder" is not as good that way. You should move to "Structured Ladder" ;-)

Share this post


Link to post
Share on other sites

I'm willing to give it a try to create a function block to achieve a specific task... but no way in hades would I program an entire machine in FBD.

 

So, I actually got it working using the direct devices with just two rungs.  One increments my pointer and one looks at the array element and moves it to my output area if it is greater than zero, if equal to zero it increments the pointer to check the next element.  I then specify how many elements I have and reset the pointer back to 1 if I reach the end.

 

This works... but the delay as it increments the pointer, checks the element, and then increments again is a bit of a pain.  If I had 100 possible messages, and only the first two are active, then it takes over a second to get back to displaying message one when I hit the button from number two.

 

You have any suggestions on how to only jump to the elements that are greater than zero?  If it has to be done in structured ladder then so be it, I will create the function block in structured ladder.

Share this post


Link to post
Share on other sites

Have you looked into FOR-NEXT loops? Not sure if I understand you correctly, and you're not posting any code examples, but below you can find a trivial example of a FOR-NEXT loop with comments. You can make the FB in Structured Ladder, and then use it in Simple Ladder. That way you can avoid manual hardware addressing since the compiler finds addresses for you.

EDIT: Forgot to add a reset of the "activeValues" array, but you get the picture. Just reset the whole array before the loop runs...

for-next.png

Edited by kaare_t

Share this post


Link to post
Share on other sites

That looks pretty similar to what I am doing now, but with labels instead of the D area.  I believe it would have the same problem I am currently having with a long delay as it cycles through the entire array index.  

 

Here is a picture of the two rungs I have:

EDIT: POINT is an alias for Z0

 

array.png

Edited by AngryRobot

Share this post


Link to post
Share on other sites

I agree, but do you use FOR-NEXT? If not, every cycle depends on one CPU scan (which lets say is 10ms -> 100 scans = 1 second), while FOR-NEXT will loop inside the scan making it much faster (but of course slowing down the rest of the scan).

I've got some questions:

  1. What CPU do you have (specific Q model)?
  2. Is the scan time critical in your application or can you handle some ms more delay each scan caused by the FOR-NEXT loop?

Share this post


Link to post
Share on other sites

I am using a Q03UD.  The cycle time is not super critical, but it would be noticeable if it changed by more than 2 or 3ms.

 

 

Share this post


Link to post
Share on other sites

Run a test. I think that the complete cycle time (scantime) will be less than 1ms by running just 100 loops in FOR-NEXT. But just do a test, I don't have one where I'm located now, but it's just a tiny piece of code inside the FOR-NEXT loop so my guess is that you won't see any difference in the cycle time (scantime). You can even try to run 1000 loops, or 10000 loops just to see the difference.

Share this post


Link to post
Share on other sites

I ended up doing away the button idea and just went with timers to auto scroll through the messages.  I also gave up on the idea of trying to use a loop or indexing array and just created a function block with a rung for each message using a step logic.  Each rung looks at a bit that is set elsewhere in the program to indicate if the message logic is true or not.  If it is true then it moves the message number to a data area and starts a timer.  Once the timer is done I increment my step and examine the next message bit.  If the message bit is not true then I instantly increment the step.  In the last step I move the first step number back into the step register and start over.

I'm at home now so I can't post screen shots, but it works exactly as I want, it is just a little crude.  I was hoping to make something slick, and I just ended up with a plain old self-repeating step logic routine. ;)

At least Works lets me specify the internal variables of a function block (ie: Message_FB.Status_1).  I was able to put all of the logic in a FB and use the internal variables for each of the status message bits.  So it is a reusable FB now... I guess I could use it for all sorts of things now.

Share this post


Link to post
Share on other sites

No, no, no! Always develop according to DRY ("Don't repeat yourself") as long as you have the possibility for it. If you have a good reason for it, feel free to share it since I'm basically lost right now. The loop would even work if you didn't use labels, you just switch the labels with addresses (and use a 'Z' for the indexing part inside the loop), so that cannot be the reason.

What happens if you for some reason need to change a compare statement, or something else (tiny or huge) in your sequence? One mistake when copying/modifying those 100 lines of code and your out. Also you have to redo all lines of code relevant (in your case 100 lines) which is very time-consuming and frustrating.

I made a small test, just to prove how little impact 100 loops have in your case (see attached screenshot). 100 loops increases scan-time by 0.2ms to a total of 0.6ms in my almost empty project. I must also emphasize that your repeating code takes just as much time as the looped code!

for-next.png

Share this post


Link to post
Share on other sites

Well, I went that way because it was the best way I could come up with to handle the messages that didn't need to be displayed.  I wrote a FOR loop, but I was using a timer to control the indexing and not the scan time.  When I tried just using the index increment every time the PLC scanned it caused everything to run out of control.  Because I need the message to display for a certain amount of time, but if the index increments every scan then the index gets way ahead of the actual message.  And when I used the timer it cause a long delay between the last active message and scrolling back around to the first one.

But now that I think about it...I could have just included some sort of mute bit before the increment command.  Something like:

 

MUTE INC
  [/]----------------------[INC Z0]
  
                        MUTE INC   
  [<> K0 D1000Z0]----------()
  
  

 

I can't believe I didn't think of that yesterday.  Sometimes I just need a day away from the computer I think.

Share this post


Link to post
Share on other sites

Wait... so you can't use a timer in a FBD function block?  What the hell Mitsubishi.

Share this post


Link to post
Share on other sites
5 hours ago, AngryRobot said:

I can't believe I didn't think of that yesterday.  Sometimes I just need a day away from the computer I think.

Hehe, that's just how it is sometimes :-)

4 hours ago, AngryRobot said:

Wait... so you can't use a timer in a FBD function block?  What the hell Mitsubishi.

Not sure what you mean here... Post a screenshot and we'll see, but of course timers (and everything else) is supported in FBD!

P.S. You know you can also write a function block in Simple Ladder right? Just select it instead of "Structured Ladder/FBD" when creating the FB... If you feel that bad about Structured Ladder/FBD then why not go the Simple Ladder route?

Share this post


Link to post
Share on other sites

Yeah I've created a lot of FBs in simple ladder.  But I didn't think I could index a label with another label in the simple ladder function block?  I thought I could only do that in the FBD environment?

Share this post


Link to post
Share on other sites

When I try to put a timer in the FBD function block, I get a compile error saying "The function block that is not use macrocode is used by function block of call destination.(Ladder Block No.4)    C5119"

 

How do I create a timer in a FBD function block?

Share this post


Link to post
Share on other sites

Not sure about that error, your FBD Function Block should have Macrocode enabled!

Use one of the built-in FB timers (10ms or 100ms) to ensure that you get automatically assigned timer variables inside the FB.

10msTimer.png

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