I haven't had as much time to work on this as I'd like. My daughter had a hip surgery a couple days ago, and she's and my other kids have been my focus lately. Anyway, the last time I was looking at this, I had some weird intermittent glitches that I was having a hard time tracking down. Given that the old code was basically taking the logic for a single sensor and running it six times (once for each sensor in the current setup), it wasn't really optimized and needed a major overhaul anyway. I spent a couple hours tonight to do that redesign and rewrite.
The first major change is that instead of having a separate ring buffer for each sensor, I now have a single ring buffer for all sensor data. This means that it's now obvious what order the sensors have been read. Previously, if processing lagged too much (usually because I was printing too much debug info to the serial port), it became impossible to keep the incoming sensor data in sync.
Since we now can easily tell what order the sensors have been read, I changed how the OOTC pulse is being read. Instead of each sensor separately detecting the OOTC pulse, it is now detected via cooperation of all sensors. This will be especially important in getting high precision angle measurements. While all sensors receive the signal at basically the same time and assert their lines together, the microcontroller has to service the interrupts serially, and hence they get timstamped separately. Now, when an OOTC pulse is detected, we look at all sensors to find which sensor's interrupt was processed first, as well as which sensor was processed first for deasserting the OOTC signal.
I also got rid of a little floating point math, which might speed things up a bit. I've also been able to verify that the ring buffer is being serviced frequently enough that there's no current risk of overflow.
I'm very happy to say that I'm now comfortable enough with the incoming data that I'm ready to start trying to triangulate position given the angles. But, this is my weakest area in this project, so it may take me a while to figure it out. If anybody has any pointers or references, I'd really like to hear them.
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.
I hope your daughter recovers quickly.
I've a couple of quick suggestions too. On the interrupt controller, use a ring buffer which has a 2^n number of entries, that way you can replace the modulo (which I would expect to be quite long) with an AND mask. Also, try removing the volatile from the ring buffer declaration, as this is likely to force a lot more RAM accesses and inhibit the compiler from doing register based optimisations.
Finally, and this may not be a real issue, have you considered feeding a few of the envelope signals in to an external AND gate (like the 74HC21) to detect the sync pulses on its own interrupt? This may let you do some other optimsations.
Are you sure? yes | no
Lee, I really appreciate the excellent feedback. I bet you've cut the instruction count in the ISR by at least half! Instead of removing the volatile entirely, I moved it to only the data buffer. I figure that the penalty for a stale read or write location is only a slight delay in processing of a value (no big deal, it's a race anyway), but a stale buffer value could introduce corruption. In practice, the compiler generates the code, it's probably safe anyway, but since there's only one buffer access per ISR, I'm not sure the volatile will have any impact there. It may be worthwhile to look at the assembly once everything is more polished.
Interesting thought, too, on the AND gate. It definitely would simplify the software side. It may also increase the number of sensors supported, since right now I'm using two inputs for each (so I can get separate interrupts for rising and falling edges) but with that change, you wouldn't need to know when a given sensor deasserts, just when it gets asserted. It's a good idea to chew on.
Thank You!
Are you sure? yes | no