Freesteel Blog » Machining
Wednesday, July 1st, 2015 at 5:17 pm - Machining
Over the last few months, well, since December, I’ve been producing an awful lot of plastic scrap from the UP! 3d printer we have here.
We had better find a way of recycling this soon. I’ve got my eye on the plastic injection moulding machine as a potential consumer.
Here’s the work bench of chaotic iterations of circuitry and boxes to contain the circuits.
To be clear, none of it does anything, except get data and log data to an SD card.
Occasionally it gets a short-circuit which crashes the microcontroller.
I now have two data logging devices. I am busy printing off further legs and hooks to glue onto the second black one on the right so it can be strapped onto another hang-glider, or to my hang-glider beside the primary device, which will mean that I have two sensor boxes measuring the same factors and coming up with wildly different results, thus proving that this kit isn’t as great as it appears.
Building stuff is a great way of putting off actually doing anything with the data. But once I am in Austria in a campsitte and away from DoESLiverpool and its tempting 3D printers, I won’t have the option to put it off anymore.
Friday, June 5th, 2015 at 3:39 pm - Machining
This BNO055 absolute orientation sensor is just the thing I’ve been after for logging the hang-glider direction and heading. It combines the compass and accelerometer sensors into a single package with its own co-processor running proprietary sensor fusion software, so I don’t need to get into the business of decoding making sense of this sensor data.
The theory for calculating absolute orientation is as follows.
Absolute orientation is represented by three degrees of freedom: horizontal heading, roll and pitch. At rest (held within a particular orientation), there are two absolute vectors which can be sensed: the gravitational force (downwards) and the earth’s magnetic flux (about 23degrees off the down vector towards the north, if you are in the UK).
Knowing an absolute unit vector relative to your oriented frame constrains two degrees of freedom. Think of this as a fixed pin passing through your object like it’s a beetle on a specimen tray: the bug can only spin its body around the pin. Two such pins could nail down four degrees of freedom, but there’s only three, so the extra information is redundant and can be used to estimate the accuracy of the measurement.
Each of the sensors on the BNO055 device requires calibration, according to the datasheet:
3.10 Though the sensor fusion software runs the calibration algorithm of all the three sensors (accelerometer, gyroscope and magnetometer) in the background to remove the offsets, some preliminary steps had to be ensured for this automatic calibration to take place. The accelerometer and the gyroscope are relatively less susceptible to external disturbances, as a result of which the offset is negligible. Whereas the magnetometer is susceptible to external magnetic field and therefore to ensure proper heading accuracy, the calibration steps described below have to be taken.
I’ve been logging the quaternion heading from this sensor and then trying to relate it to the motions I was making. Unfortunately, sometimes there was a complete sudden reversal of the orientation mid-flow, even though I wasn’t making any sudden motions:
Here’s the log from this moment that occurred at the timestamp=61350
tstamp qw qx qy qz mag calibration status 61050 15158 336 41 6208 1 61150 15419 431 103 5522 1 61250 15664 510 164 4774 1 61350 722 234 -654 -16353 2 61450 244 -530 777 16355 2 61550 1460 -929 852 16270 2 61650 2277 -1019 921 16167 2 61750 3023 -1249 1137 16014 2 61850 3509 -1358 1335 15890 2 61950 4023 -1386 1477 15753 2
Funnily enough, for such a complicated packaged system, there are absolutely no configuration settings at all — except for one option known as NDOF_FMC_OFF, which is “the same as NDOF mode, but with the Fast Magnetometer Calibration turned OFF”. (NDOF stands for “9 Degrees of Freedom”, which I guess refers to the fusion of 3 magnetic flux axes, 3 accelerometer axes, 3 gyro axes into a single measurement.)
The fact that you can turn off the so-called “Fast Magnetometer Calibration” mode suggests there is something special about it: ie it might be buggy.
Anyway, I don’t have time to check out what this does otherwise. I’ve wasted enough on this already. I should go look at something else.
Which of course means I’m just putting this off till I have some logged flight data. Which might be complete junk.
Wednesday, June 3rd, 2015 at 12:33 pm - Machining
Origin at O with y-axis along Y being the side of the table, because we want to solve this by fixing the job to be machined in the fixed coordinate frame and pretend that the machine and tool are swinging all around it.
The blue lines represent the triangular main frame (with three approximately known lengths of about 745mm), the green lines the arm (with two lengths and an angle). This carries the cutter at point P and its triangle pivots at the movable point A1 due to changes in the length of J1 representing the linear position of the ballscrew.
The entire blue triangular frame pivots around the fixed point A0 due to changes in the length of J0. The absolute offsets on J0 and J1 from their connection to the common vertex are also unknown, which means we have a total of 2+3+3+1=9 dimensions which we can vary in our calculation to calibrate. (That last dimension is the length of the fixed edge between O and A0.)
def abanglefromtriangleabc(a, b, c): return acos((a*a + b*b - c*c)/(2*a*b)) a = 743.5035783400 # sides of mainframe triangle b = 754.8024952389 c = 745.4991150306 d = 697.7062405262 # length of O->A0 e = 695.5193939239 # length A0->"arm" f = 583.6487506837 # length A0->P ah = 0.0764480526 # angle in arm tblx = 525.4558306022 # offset in j0 armx = 396.1544040232 # offset in j1 ab = abanglefromtriangleabc(a, b, c) ac = abanglefromtriangleabc(a, c, b) def convertJ0J1toXY(j0, j1): tbl = j0 + tblx arm = j1 + armx aTBL = abanglefromtriangleabc(b, d, tbl) aARM = abanglefromtriangleabc(c, e, arm) avec = ab - aTBL; pvec = avec + ac - aARM + ah return (0 - a*sin(avec) + f*sin(pvec), d - a*cos(avec) + f*cos(pvec))
The game we’ve been playing for the last few weeks is to probe a perfectly circular disk mounted on the table with a known diameter, read out a series of joint values J0 and J1 from about 60 different positions, write a function that uses the 9 unknowns to project these measurements into cartesian space relative to O and the axis Y and provide a value of how close we are to having the right circle, and then use scipy.optimize.minimize to pick the values which minimizes this geometric constraint.
Unfortunately, this doesn’t seem to constrain it well enough, for we are getting good fitting solutions where the lengths of the main frame triangle are far from 745mm.
So that’s where we are at this week. I think we’re going to sod the calibration for a little while and just machine some stuff anyway, even if it isn’t perfectly right.
Tuesday, February 17th, 2015 at 11:15 am - Machining
The green is the raw plot of the accelerometer vector which was aligned with the crossbar of my bike on the ride. The red is the altitude, the yellow is my speed — clearly slower going up hill than going down as time advances from left to right. We stopped for a bit at the top of the hill.
This is smoothed with an exponential decay factor of 50/51 on a time sample rate of 0.1seconds, so a sort of 5 second time window.
This is applying the exponential smoothing filter backwards as well, which is a trick I heard about a few days ago. I haven’t worked out of the maths of it yet, but it looks good.
Here are some vertical lines showing periods of ascent and descent with the second white horizontal line denoting the overall average accelerometer reading that you can think of is approximating how much the bike cross bar is pointing up or pointing down from the horizontal. I can convince myself that it is negative on the uphills and positive on the downhills where it is tending to point more in the direction of gravity.
Here’s a zoomed-in section of where we peddled down the hill and then heaved our way back up the other side. Because the rates of descent and ascent are about the same it means the slope down must have been shallower as I don’t peddle up hills very fast.
Unfortunately I’m not competent enough to overlay this on a map to see these places on the contour lines, and I don’t have a bike wheel trip magnet to measure distance travelled properly.
Anyway, it’s not really for my bike; it’s for putting on my hang-glider. The bike is just a good way to test things till I can get out flying again.
Monday, February 16th, 2015 at 8:49 pm - Machining
Quick report on the misery of trying to get any good data out of these fancy good-for-nothing data sensors.
I did a bike ride on Sunday around Yorkshire, from Barbon to Dent, up the valley, down to the very fine Cafe Nova in Sedburg and then back to Kirby Lonsdale via a bridge over the river Lune where Becka and I went kayaking in January and got scared (it looked a bit tame in these water levels). This was the day after the day before where I broke my caving famine and did a nine hour Easegill traverse from Pippikin to Top Sink while the hard people (incl Becka) did the reverse route and went out Bye George to celebrate Tom’s birthday. (This was the same Tom who drove out to Austria with me last May so I could go hang-gliding when Becka stood me up to go on a caving holiday.) Hint: for my birthday I will not be going caving.
So, anyway, you’d think something as simple as the GPS-altitude and barometric readings would be somewhat related.
This is what the plot looks like of barometric pressure along the X-axis (zeroed at 990Mb) vs altitude, which ranges from 102m to 305m. Yellow is the first hour, where we went over the hill, and blue is the second hour peddling up the valley from Dent.
Not a great correlation. Here’s the same picture zoomed in. The squiggles are predominantly left and right accounting for the noise of the barometer readings.
Suppose I take a rolling average of sequences of 7m and plot the same here without all the noise, getting the yellow line.
Still pretty wobbly. The cyan is the plot of the barometric forumla which is:
101325*(1 – 2.25577e-5 * altitude)5.25588
This is near as damnit a straight line of slope -0.08488715682448557. Applying simple linear regression to the slope gives -0.08992119168062143, which is not a great match.
Maybe I ought to work out a way to do this calculation in run-time on the device itself to give a measure of how rubbish the altitude-barometer agreement is during operation so I don’t have to bring it back here and run these complicated python programs on the data.
Then I could see if it’s responsive to the mode of travel, eg bike vs walking up and down the hill.
The next correlation to look at from this data is tilt of the bike frame registered from the accelerometer vs the slope climb according to the GPS. I’ve got very little hope this will work, so have put it off. I’m already sure that the temperature vs altitude signal is completely lost in the noise, probably due to the proximity to the ground on which the sun was shining.
I hope to see something better if I ever get this thing in the air. Right now I’m 3D printing enclosures to grip on to the base bar and am gathering a desk full of lots of bits of useless bits of plastic. Got to push on and not be distracted.
Wednesday, February 4th, 2015 at 11:14 pm - Machining
So I had to bodge the wind sensor interrupt readings and filter out the glitches. Beyond that, there’s a heck of a lot of variation in the readings when in front of the fan (getting 12mph wind, according to the proper device), and even at the nozzle of the vacuum cleaner (where the wind speed was 42mph). Either there’s still turbulance or the sensor is wobbly. Not impressed.
Next up, there’s the sudden-air-temperature-from-flying-into-a-thermal detector based on the analog TMP36 connected to a large capacitor to bring the voltage changes down to zero, and so they can be put through two op-amps (one for positive and one for negative changes).
I turned on and off the hair drier behind the fan that points at the dangling circuitry and got this trace.
Wednesday, January 28th, 2015 at 11:52 am - Machining
After spending a few days with all my bits and break-out boards in a bowl and stirring them around aimlessly, I got all the major SPI components lined up on a breadboard, like so:
That’s an SD card writer, an OLED screen display, a bluetooth low energy and a GPS module.
The additional devices are on short 4-wire phone leads in plastic printed boxes of dubious design.
After a great deal of unplanned soldering and the use of header sockets so that none of the bits are permanently stuck in the wrong place, I’ve got a thing that looks like this:
There are issues. The barometer has a separate power supply and now doesn’t communicate, the wind-meter has a degree of noise in its signal, the I2C accelerometer is too complicated, the dallas temperature sensors can only be read one at a time, and all three SPI devices are incompatible with one another.
It’s been a lot of work, and I need a break. This has now outperformed my target over New Year period moping around Bull Pot Farm while everyone else goes caving.
I am now able to make numerous slices on this impellor model made of 38474 triangles with an angle change tolerance between contour sample points of 18degrees in about 5 to 10 seconds per slice using Pypy (or 80 seconds in Python3). The code is at bitbucket.org/goatchurch/barmesh. Use it at your peril. It’s just beginning to work, and the next thing I will do is break it.
Here are some pictures of the results of slicing an impellor shape that’s 20mm in diameter with a sphere of radius 0.2 using the command:
pypy -O main.py –stl=stlsamples/impellor1.stl -v -tswapyz -r0.2 -n52
Slices with ball radius 0.2 with the STL model shown
Offset slices without the STL model so you can see all the internal contours from the ball rolling along the inside surfaces of the model. These internal contours will need to be detected by connectivity and deleted.
View down the top so you can see the inner and outer offset slices of the central cylindrical through-hole.
From my initial profiling, 99% of the time is spent in the two functions MakePointZoneRF() and CutbarRF(). This is fantastic news as this is where all the point-line-triangle distance/offset-intersection calculations are done. And it’s intended to be very GPU-friendly. (I don’t actually have any experience with GPUs yet, but it could happen now I’ve got a real world use case.)
Tuesday, December 23rd, 2014 at 7:39 pm - Machining