Prop controlled via serial, floating point and variable scaling [solved]
xanadu
Posts: 3,347
I'm working on part of a project. The entire thing goes like this:
1. API reads two coords (x,y) from some Windows program and writes them to a text file.
2. My Java app reads the text file every second and sends the values to the Propeller via serial.
3. Propeller read values, moves servos, sends confirmation it's done and waits for more.
Here is a video of everything working. I also demonstrate it not going to bad values that could physically damage it.
I have two issues.
Issue #1: The values in the text file need to be floating point.
Is that possible using SPIN/Serial?
Issue #2: The values in the text file need to be 1-180 for pan and 1-360 for tilt.
The API is going to write values that the Dynamixels can't use. I need to scale these values accordingly.
Pan servo = 1 to 360 degrees in text file, converted to 0 to 4095 by Propeller
Tilt servo = 1 to 180 degrees in text file, converted to 200 to 550 by Propeller
I could take it apart and make it so the bottom of the tilt is 0 and not 200, I feel like that would make it a lot easier.
For pan I just need to move 11.3 encoder ticks per degree, which seems easy enough. But before I get into that I really need to make sure I can pass the floating point numbers to the Propeller.
This doesn't need to be extremely accurate. I attached the SPIN code. Thank you.
EDIT: Added "serial math.zip" this is a broken down version of the problem, requiring only Propeller to run.
1. API reads two coords (x,y) from some Windows program and writes them to a text file.
2. My Java app reads the text file every second and sends the values to the Propeller via serial.
3. Propeller read values, moves servos, sends confirmation it's done and waits for more.
Here is a video of everything working. I also demonstrate it not going to bad values that could physically damage it.
I have two issues.
Issue #1: The values in the text file need to be floating point.
Is that possible using SPIN/Serial?
Issue #2: The values in the text file need to be 1-180 for pan and 1-360 for tilt.
The API is going to write values that the Dynamixels can't use. I need to scale these values accordingly.
Pan servo = 1 to 360 degrees in text file, converted to 0 to 4095 by Propeller
Tilt servo = 1 to 180 degrees in text file, converted to 200 to 550 by Propeller
I could take it apart and make it so the bottom of the tilt is 0 and not 200, I feel like that would make it a lot easier.
For pan I just need to move 11.3 encoder ticks per degree, which seems easy enough. But before I get into that I really need to make sure I can pass the floating point numbers to the Propeller.
This doesn't need to be extremely accurate. I attached the SPIN code. Thank you.
EDIT: Added "serial math.zip" this is a broken down version of the problem, requiring only Propeller to run.
Comments
Just use fixed point integer, say 0-360.00 and 0 to 180.00 and convert this in java on the PC.
Write it as 36000 (or18000) in your text file and divide on the prop while scaling to 4095.
value0to4095:= (degree0to36000 * 100) / 879
value200to550:=((degree0to18000 * 100) / 5142) + 200
should do this quite good
The bottom tilt is also just a addition of 200.00 to your calculated value out of the degrees.
Enjoy!
Mike
The app needs to have floating point because the API will only output degrees in 0.5 degree increments to the text file.
I will read the number in Java and do the math there to get the Dynamixel friendly value. Thanks for the example of the variable scaling.
If you do need to do floating point on the prop, there are some libraries like F32 that work, with trig function, conversions, log, etc. F32 is limited to single precision (32 bits per float), and the code becomes less transparent to read (everything is a function call).
I am using Tachyon Forth, and represent all angle in tenths of a degree. Pretty simple and fast.
I put the project aside and started playing with serial objects. I'm able to echo a floating point number via serial using this object.
That is great. Now I have to find a floating point Object and see if I can get the echo to include math.
Can anyone tell me why this doesn't work? All you need is PST, no servos, etc.
It is supposed to -
1. rx serial string with decimal (works)
2. float serial data string (no go)
3. float multiply by 11.37 (no go)
4. decimal to integer so rest of the code can use it (works)
Just need to figure out #2 and #3...
I wish Spin had a way to check calling parameter types. That would probably solve over half the problems that people encounter.
I'm glad there was Dynamixel code in SPIN, even if this part takes me a few days I'm still ahead
I think you are confused by the meaning of "decimal". Just saying "decimal" by itself is a bit ambiguous. You should use the term "decimal string" instead. decimalToInteger converts a decimal string to a 32-bit integer. FRound rounds a 32-bit floating point value and converts it to a 32-bit integer. The dec method prints a 32-bit integer as a decimal number.
I'm not familiar with Dynamixel, but from what I can tell it's a line of servos. I assume the driver code requires a fixed-point value to control it, so the result from FRound should work as long as it's scaled properly.
Thanks I will check it out. I'm using an AX and MX. There are only a couple of differences, the limit address and the increased goal positions. I like the Dynamixels a lot, I'm happy that there is more Propeller support for them, especially in SPIN.
I attached the file where stre.decimalToInteger will echo an integer if you give it a decimal string via pst. I'm not really sure why it works, but I would rather it round anyway.
It has to take a number, say 135.5 * 11.37 = 1540.63 then convert to int. 1540 = Dynamixel happy. The only part that doesn't work is * 11.37.
FTR, I use a FET (BSN20) level shifter between the Propeller and the Dynamixels. The Propeller serial pin is pulled up to 3.3v with a 3.3K resistor; this connects to the Source pin. The Drain pin connects to the Dynamixel buss and is pulled up to 5V with a 4.7K resistor. The Gate is connected to 3.3V. It's a standard circuit that gets used in I2C apps -- works well for half-duplex serial as well. Luckily, EFX-TEK products include this circuit so I had a ready test platform when I wanted to experiment with Dynamixels.
So the only thing left is how to multiply @mystr by 11.37 before doing the decimal to int.
You multiply by 11.37 and then round.
why not multiply by 1137 and then divide by 100?
No need for decimal point in your serial data, make 36000 out of 360 degrees and you have 2 fixed decimal places and are able to use integers for serial and for the calculation.
Way faster as any float object.
Stupid question - did you start the float Object? It needs a own COG.
And FRound is just rounding a float number, but it is still a Float, not a integer.
So your example
135.5 * 11.37 = 1540.63 then convert to int. 1540
is the same as
(1355 * 1137 ) / 1000 = 1540
confused,
Mike
I did start the float object, and I did try floating the rounding variable.
John Abshier
Josh, good call. That might be why Dave is getting different results. I uploaded the archive, there are additional objects I've been using in there as well. The notes at the top of the code explain the workflow. Thanks!
EDIT: Another solution would be to just copy the StringToFloat method to your top object. Then you would only have one reference to Float32Full.
Thanks!!
1=11
1.5=17
1.9=22
2=23
The Dynamixels are going to love this!
As it turns out the Dynamixel turns CCW as the absolute encoder values increase. That's no good so I had to add another operation to reverse it.
This doesn't work:
This does:
While it may be obvious to some, the Float32 Object should mention the decimal is required.
I ran an accuracy test using a pretty cheesy method but things are looking really good at this point.