Ok,I ignored the binary format for the moment and focused on the calculations using MULD and DIVD for double BCD
numbers. What I have works, though I'm sure it isn't foolproof, and definitely not elegant or efficient. However,
it does put the correct numbers in V2001 and V2002, so far so good.
|c0|------LDD V1203 (11942 encoder counts/inch)
MULD V1201 (length as entered on HMI, IE. 26.25)
OUTD V1205 (temp storage of calculated value)
LD K100 (Constant 100 used as divisor to shift decimal)
OUT V1207 (DIVD doesn't appear to be able to use a constant?)
LDD V1205 (calculated value IE. 11942 * 2625 = 31347750)
DIVD V1207 (divide by constant 100 yields 313477)
OUTD V2001 (outputs 3447 in V2001, and 31 in V2002)
The '31' in V2002 is the # of complete revs (10,000 encoder counts per rev) of the servo motor, the '3447' in V2001 is the # of pulses for the partial revolution. Both values will be converted to binary and loaded into respective parameters in the Sureservo drive.
I'm not exactly clear on how to deal with binary numbers when inputing data from the HMI, and how to carry out the same calculations with binary rather than BCD...? Thanks for any input.
A few thoughts...
First, there is nothing _wrong_ with using BCD math. You just have to observe the limitations of the numbering format.
Second, the code you have works for your current situation. Hopefully you realize that your getting the correct numbers in V2001 and V2002 is a fluke that depends on you having a 10,000 count per rev encoder. Your math is incomlete if you change to a different encoder. As I said, your code works for your current situation, and is even elegant in this regard (avoids another divide.)
Third, dealing with binary is not that all that different than what you are doing now.
You have two options for dealing with data that was input from the HMI. First, you can leave the HMI data type set to BCD, convert the BCD info for use in the calculations; or second, (route I would take) set the HMI data type to binary (2 decimal places). This way, the HMI will put data into a Vmem that is already properly formatted for binary calculations.
Next, keep in mind the larger size limits of a binary Vmem. What used to be a LDD to get the number 11942 into the accumulator can now be a LD (LDD will still work, but then you can't use the next Vmem for anything and it will always be 0 if your constant doesn't exceed 65535.) Next would be a MULB (B is for Binary). Note that this too is now a single word instruction instead of a MULDB (or MULBD, I can't remember the correct spelling.)
Now, the result of this calculation _will_ be larger than 65535 from the numbers you have mentioned; so we still need the OUTD to put the result in storage (more on improving elegance here later).
Next, you would load your constant to remove the implied decimal places. In BCD math, this number is 100 (this is that whole human-readable thing here); in binary (hex actually) that number is 64. Fire up windows calculator in scientific mode for a handy converter. Enter a number in Dec mode and then change the mode to Hex to see the equivalent value. So, a LD K64 and an OUT to a Vmem to hold the constant (next Vmem will have to be empty as the instruction this constant is being used with will look at it as a double word.)
Next will be the DIVBD. Now, here is a difference with binary math vs. BCD. In BCD, all you had to do was OUTD and you had your two values. Just like magic. This won't be the case with binary (unless you changed encoders to a 65536 pulse per rev model.) To separate the revs from the pulses you will need to do another divide. Another LD K2710 (10000 in hex) and OUT to a Vmem and then another DIVBD is needed.
Now you have the number of revs in the accumulator and the number of additional pulses in the accumulator stack. An OUT will put the number of revs into a Vmem. You then need a POP to move the number of additional pulses from the stack to the accumulator where another OUT can place them in another Vmem.
Whew...
On improving elegance...
I would LD and OUT your constants at the beginning of the program. First, they will only be setup once instead of every time you calculate a move (this will improve scan time.) Second, you will be able to move from one instruction to the next without temporarily storing a calculated value just to setup a constant. Your MUL would be followed immediatly with a DIVBD. This will improve readability.
On a separate note on elegance...
If you stay with BCD, you can eliminate your divide to get rid of the implied decimal places. You can do a SHFR K8. This would be a cleaner way to handle the math, it would cut down on scan time; plus, it makes you look like a programming wiz
If you do this, PLEASE document your code for the guy after you. Also, it wouldn't hurt for you to look up the instruction and figure out exactly how and why that works (and why the same trick won't work with binary data.)
Brian