3 Debugging tricks to get there faster, especially in a loop

By “debugging” I mean using PAC Control’s Debug mode to step through your logic and figure out why it’s not behaving as you expected. Usually in Config mode you’d have checked the menu option: Configure > Full Debug so that you can step into blocks and see what’s going on.

Here are a few techniques I use when stepping through, in this case, a big loop that takes a while to run:

1. F10 is your friend
2. Avoid looping if there’s a built-in command
3. Break up a loop

1. F10 is your friend

You may have used the mouse to step over and into blocks, but did you know you can also use the function keys? For example, here in my big loop that takes a while to run, I may want to step through or into something in this loop, but not until I get up to a particular index.


[click on image to see animation]

Rather than stepping through one line at a time as shown above (same applies when stepping over blocks of all kinds), I can watch that nIndex fly up without lifting a finger. I just park my finger on the F10 key and hold it down. When nIndex gets close, I can do one step at a time until the relevant nIndex. I can also use F11 for “step into.”

2. Avoid the Loop

This isn’t exactly a debugging tip, but it could save you some coding, which can lead to writing bugs. :slight_smile: If you’re just initializing a numeric or string table to a bunch of the same thing, check out the commands MoveToNumTableElements or MoveToStrTableElements to do it for you. No loop required!

The syntax is identical for both commands, and -1 for the “End Index” tells the command “fill the whole table” so you don’t have to do the extra step of using GetLengthOfTable first. They look like this:
[INDENT]MoveToStrTableElements(/From/, /Start Index/, /End Index/, /Of Table/);
[/INDENT]For example, to fill my nBigTable with my favorite number (22, of course), I’d just use:

[INDENT]MoveToNumTableElements(22, 0, -1, nBigTable);
[/INDENT]All done! No loop needed!

3. Break up a loop

Normally, I could do this same thing for a loop in regular blocks by just adding an increment on nIndex and checking to see when that reached nLengthOfTable, like this:


If, for debugging purposes, I want to set a breakpoint (not supported within a block, unfortunately) when I get to a particular index, I’d just add one more just-for-debug condition to check for that value. Like this:


Once I’ve set the breakpoint on the condition I want to examine, I can let her rip, then step individually through the logic I want to watch closely. Just a little bit of simple “instrumenting,” AKA debug code.

Hope that helps.
-OptoMary

p.s. Did anyone spot what was missing from my loop which I might want to include if it takes more than a few seconds to run? I’ll send an OptoPrize to the first person to reply with the correct answer (or a handy debugging tip of their own). Quick! Type fast!

Where is your delay/wait statement?

Yes! Well done, klibberton! I’ll email you about the OptoPrize. Thanks for playing.

Of course, a delay statement would be even more important in a chart that loops forever, but always good to consider for any loop so other charts/tasks/communications don’t get starved.

-OptoMary

Mary

Do you think we will ever support debug level breakpoints within code blocks? Its one of the most annoying things about debugging hunks of code written in OptoScript. I have never understood the technical arguments against supporting it, (apart from the fact that its work for the Opto22 programmers!)

amen, mitchell

Have to agree that it would be very useful.

If the concept is giving a big headache, here’s something that perhaps could be implemented before the predicted end of the world on the 21 December 2012. A “breakpoint” instruction, written into the OptoScript code before download and compiling. This then pauses the chart, which surely is traceable in debug mode. Good enough for development work.

The existence of such a “breakpoint” instruction of this style is probably also something to check and report and also make the engineer sign his acceptance in blood before downloading. We wouldn’t want the code running for 2 years in a plant before finally hitting the condition that causes the optoscript to pause, without anyone ever realizing it.

Ah! Excellent idea. In fact you could write your own “instruction” and set a breakpoint inside it, which you wouldn’t have to worry about checking later because it has not effect on your logic (just there to set a breakpoint in it).

I just created a very boring empty (except for Block 0) subroutine called Breakpoint, added it to my strategy, set a breakpoint in it, and (when I’m set for “Full Debug”) I can step out of in into the middle of some OptoScript or other block I called it from! Neat-o.

Unfortunately, we have something weird going on in modern versions of PAC Control (8.0 and maybe others work fine) w/stepping out of a subroutine like that. I had to click on the white part of my sub to ungray the “step out” button, then when I was back in my block that called it, clicking the white part didn’t cure the grayed-out buttons. I had to close that window (say “No” to both questions that are asked), then open that chart again and you’re where you want to be.

I’ve submitted a bug report for that stepping out weirdness, but I love your idea of putting a command in there! Wish I’d thought of that sooner…

Keep them good ideas comin’.

-OptoMary

Due to multiple requests for a way to set a breakpoint in OptoScript, I’ve demonstrated how it can be done w/current versions of PAC Control here:
http://www.opto22.com/community/showthread.php?t=448&p=1618&viewfull=1#post1618