Wow, long time no see, huh? To make a long story short, my life has been pretty hectic since the last log I posted, but lately I've finally gotten some time to work on this project.
Picking up where I left off, I had just received the PCBs and was getting ready to do some bringup - and bringup I did! The first board I populated was meant to be for dev test only. It lacked both a MCU (hadn't arrived yet) and a USB port (no point without the MCU). It did have all the other features though, like the LDC chips, voltage regulator, and a slightly melted reset button. Glamor shots:
I used this board in combination with an Arduino to do some checkouts on the LDCs.
In doing so, I found a couple mistakes I made with this board:
- The footprint for the current limiting resistor for the LED (R1) is 0603, while the actual part I ordered is 0402
- This was not a big issue as I was still able to verify the voltage regulator worked with a multimeter.
- The capacitor I chose for the coils was too big (2nf) and pushed the parallel resistance of the coil very low.
- This was a big issue, as the LDC chips have a minimum parallel resistance spec that needs to be met. I was able to compensate for this error on one coil by enabling the 'high current drive' feature on the LDC, but this unfortunately that feature is only available when you're driving 1 coil, not multiple.
All in all though, the dev board served its purpose quite well and enabled me to prove out a number of systems. By this point I had finally received the MCU I planned to use and it was time to tackle the real deal. I headed back to the soldering bench, populated another PCB, soldered it up, and was ready to get to programming.
Unfortunately, the universe had other plans... I noticed when I was spreading the solder paste that it was a bit thin. This actually led to several shorts on the board. The reset button would short power and ground, one LDC has a channel shorted, and the current limiting resistor had tombstoned. After fixing all of these issues, however, it did successfully power on. I plugged in the MCU to my computer and BAM, the bootloader for the STM32 popped right up, which meant the USB implementation was good. NICE! So naturally, I kept rolling and opened up STM32CubeIDE to get to programming. I setup my IOC file to enable all my peripherals that I needed, typed up a basic Hello World program and told it to build aaaaand
tools\arm-none-eabi\bin\ld.exe: os3m_dev.elf section `.text' will not fit in region `FLASH' tools\arm-none-eabi\bin\ld.exe: region `FLASH' overflowed by 22292 bytes
...oh no. That's not good.
Turns out, the MCU I bought did not have enough flash space to fit even my Hello World program. Like way not enough (16kb). Unsurprisingly, the HAL to operate the USB peripheral is quite large, but I didn't have a good feel for just how large it was before I decided on my specific MCU. (I could've done all this compiling ahead of time and saved myself some time, but alas, hindsight is 20/20). I tried changing the optimizer settings a bit to see if it could reduce the code size a bit, and it did, but ultimately was not enough to help what was a pretty hopeless situation.
At that point I decided to pivot to try to do as much as possible with the hardware I had. The HAL for UART and I2C comms was much smaller and did fit into the flash section so I focused on trying to get something working. I first started with Hello World but this time using serial. This fit no problem, and worked just fine. I then ported over the arduino library I had been using for the LDCs, stripped it way down to only the subset of functions I wanted, and tried to implement it. Now, you might remember what I said above about the parallel resistance of the coils being too low for the LDC to take multiple coil measurements. The way you decrease the parallel resistance is by reducing the capacitance of the parallel capacitor (for a fixed coil inductance, which in my case is determined by the PCB properties). Any reasonable person at this stage might have gone ahead and ordered some new capacitors with a smaller value. That's probably what I should have done, but instead I decided to call in my circuits 101 knowledge and try my luck placing 2 0402 capacitors in series to lower my 2nf caps down to 1nf. Believe it or not, I did actually manage to do it:
It doesn't look the greatest, but it does work. I would not recommend this to anyone, though. I validated the modified driver worked, sending the LDC's data over serial, and was ecstatic. Here I found another improvement I'd like to make for the future revision of this board - wiring the INTB pins for the LDCs back to the STM32 so the LDCs would be able to signal that they have new data ready (rather than having the STM32 poll them).
My original plan was to use steel washers mounted vertically as the sensing targets. I had designed in slots for small washers to be placed into the walls of the knob so they would be effectively hidden. See the hot glued slots here:
This did not work as well as expected, and resulted in almost negligible response from the LDCs. From there, I tried a variety of different targets. Everything from aluminum washers to PC case screws to copper BBs. Using TI's LDC target design app note, I determined that a far better target would be something placed face-to-face with the sensor and be made of either copper, aluminum, nickel, or silver. These metals have some of the highest conductivities which result in the largest induced eddy currents, and thus the greatest inductance shift when they're placed in proximity to a sensing coil. This led me to look into coins, specifically the dime and the penny, for use as sensing targets. After testing them out and seeing success with both, I decided to go with the dime for its lower size.
As a result of this design decision, I had to redesign the lower part of the knob to accommodate dimes being mounted in the proper places:
As an aside here, I also thought this would be a great test for PrusaSlicer's new organic support generation (available in the current alpha release), and I was right. Absolutely game changing stuff here:
They peeled off with no issues, leaving a very nice finish. And all there was left to do was to assemble it all together:
It's beautiful... and also highlights one of the things I love most about this mouse - how modular the design is. I only had to reprint the part I cared about, while leaving the flexure and base intact. I powered up the device again and saw all the serial data spilling out, showing reasonable values and good responsiveness to movements of the knob.
Now this is where things got a bit complicated and I got stuck... stay tuned for the next update to find out more