I designed a control algorithm in PAC Control Basic for the B3000 Ethernet I/O brain that would be responsible for controlling the motors to the marginators. In terms of basic functionality, everything is working perfectly:
However, when I run the chart and monitor the variables, I notice that the ‘Encoder Count #’ values are not being updated, especially when I move from the Quadrature Counter points to the Encoder Count variables. This is problematic since I am trying to calculate the percentage load on each marginator given the encoder counts.
In the watch window, I can see that the external values (XVAL) of the Quadrature Counter points are being updated, but the internal values (IVAL) are not being updated at all. Could this be the reason why my Encoder Count variables are not being updated, especially when I move the values from the Quadrature Counter points? Also, I notice that my Encoder Count values are stuck at 1 when I have initialized them both to 0, which doesn’t make any sense to me.
Here’s what my ‘Obtain Encoder Counts’ block contains:
So, my question is what do I need to fix to ensure that my Encoder Count variables are being updated?
I have never used the quadrature module, so I hung back answering this post, hoping that someone with first hand knowledge would jump in…
A quick look at doc 1701, the pac control command reference, page 145 shows that you should perhaps be using the command ‘Get Counter’ rather than ‘Move’ to get the counts and put them in your variable.
This will also explain why you are seeing the ‘1’ in your variable, its because its looking at the point, not the [I]point feature[/I] (which should be configured as a counter).
Take a look at page 277 of doc 1700, you can see the instructions for using quadrature counters there.
Pretty sure a tweak of this command will have you up and running.
Thanks Ben! That command you suggested works perfectly. But now, I’ve ran into another issue: my Marginator_Percentage values are not being calculated at all. Here’s what I have in my OptoScript block “Calculate Marginator Load Percentages”:
Is there something I’m missing in this block, or would it perhaps have something to do with how I am setting up my variables?
Excellent question! Let me guess, both those Percent values are always coming out as 5?
[B]SHORT ANSWER:[/B]
Change your fractions:
(75/60134) to (75[B].0[/B]/60134[B].0[/B])
and
(75/30092) to (75[B].0[/B]/30092[B].0[/B])
then you should be good to go.
[B]LONGER ANSWER:[/B]
You’re running into one of the more subtle OptoScript considerations: how types get converted. I’d be happy to go into way more detail than most people want if anyone’s interested.
Yes, my Percent values were always stuck at 5. Your solution fixed my problem!
Speaking of type conversions, just out of curiosity, would PAC Control Basic have a type-casting function, such as ToInteger(value) or ToDouble(value) where it would simply cast those values to a specific data type?
Anyways, thank you Ben and Mary! I can now finish up this project!
There are a few type-casting-like commands in PAC Control’s “Logical Commands.” I’ve had reason to use:
“Move 32 Bits” and the relatively new “Int32 to Float Bits” or “Float to Int32 Bits” commands. There’s also “Make Integer 64” and “Get High Bits of Integer 64” or “Get Low Bits of Integer 64” which are kind of in that category too.
Thanks Mary. Had I known those commands were responsible for type-casting, I would have used the “Int32 to Float Bits” command for each literal in my equation.
Funny thing was that I had my Encoder Count variables declared as an Integer 32 type before (which was the default assigned data type given the Quadrature Counter), but I changed it to Float type when I figured that I would need to calculate the load percentage (which would also have to be a Float type.) Keeping the variables’ data type consistent throughout the equation has always been a habit of mine, but I never suspected that my fractional constants would cause a data type conflict.
I’ve had calculations not come out as I expected in the past – happens more often that I’d like to admit. The trick I use to sort it out: break down the formula into smaller pieces for debugging. Since your literals didn’t originally include a decimal point, but you were dealing mostly with floats, I figured that might be the problem, so I confirmed that by putting just that part in both an Int32 and a Float 32. The OptoScript compiler’s methods for when/how to do conversions behind-the-scenes aren’t always as I’ve expected or assumed initially.
In general, it is a good habit to try to keep the data types consistent throughout, as you suggest.
Anyway, for literals just adding a .0 at the end is all you want to do for this situation. I hope I didn’t mislead you with that Int32ToFloatBits command (which, BTW, is new in 9.2 so you won’t see it in 9.1). It’s not exactly a type-casting command like those you might be used to in other programming languages.
For example (and I wasn’t going to get this detailed, but now I’m on a roll!) if you had the following OptoScript:
The first (1) would yield 0 (this is what you ran into), because the division happens on the 2 integers, and the 0 integer result gets converted to a float AFTER the division.
The second line (2) yields the 0.5 result like sought in your example.
And (3) will get you… (guesses, anyone?) a divide by zero error in your queue and a QNAN in your float. Not what you expected? I had to think about that a bit and use this IEEE float converter: IEEE-754 Floating Point Converter
to figure out that 0x00000002 / 0x00000001 as floats works out to be: 2.8E-45 / 1.4E-45. In other words, your denominator is a really small value, smaller than what’s supported by our 32-bit floats. (For more info, see this Using Float Tech note.)
Clear as mud? Anyone? Should we make a little animated video to show how these types all work?