Search This Blog

Saturday, July 28, 2018

Project Swiftlet - Progress Report - Semi-final

Projects / Project Swiftlet  Original post date: 09/20/2015

I don't quite get the point for insisting on making a video presentation. It is very ironic having to make one for something that is designed for visually impaired person. May be I am just not in the video generation or that Hackaday isn't for me.

Here is the non-video version of a progress report summary. Current phrase: progress as of Sept 21


Most of the hardware are implemented. I don’t foresee any big show stopper level surprises for the few hardware that are not tested as they are pretty basic.

Current issues:

  • There are a few minor hardware bugs that can be patched with barnacles until a new rev. of PCB is made. There are also some component values changes. Both of these have no impact on getting the rest of the project done.
  • Acoustic/mechanical issue with the ultrasonic. I have done all I can as there are no case for better mechanical support/damping of the sensor PCB for the left side. I have to increase the dead zone for close object out to 1ms (~ 17cm/6.7") for now to get range finder to work. I don't think that is a real life problem as the person already have limps making contact at that range.
  • Boost mode power supply introduces sub-harmonic noise for Ultrasonic sampling.
  • Not a big issue as the tiny speakers aren't good at reproducing audio below 800Hz anyway.
  • On the other hand this does raise the noise floor a bit for range finder.
  • Also not an issue when using Li-ion battery as it runs off a different power supply.
  • Analog comparator in the microcontroller doesn't work reliably for this application.
  1. Too "analog" for this application as I have to dynamically change the threshold. It overshoots causing glitches and has long settling time just like an analog comparator would.
  2. I switched over to the ADC and its digital comparator and that solved the issue for me.
  • I2S & audio play back: Mainly it is a time schedule issue as I only been working on this for a few days.
  1. I am on my own.. I have checked Teensy LC I2S not support at the moment in Paul's audio library. No ChibiOS activities for their Kinetis port. There are currently no open source implementation of this.
  2. Freescale documentation is very lacking on explanation on their terms which are different than their own app notes for other families.
  3. Deciphering the Processor Expert generated code isn't easy and the GUI doesn't have the exact setting that I want.
  4. Right now have to do a lot of trial and error with SWD debugger, scope just to get the various clock frequencies divider setting to work.

Work for the next phrase for enhancing capabilities:

Hardware implemented, but no custom driver and libraries implemented yet. Additional capabilities such as voice status/menu hinges on the 6DF sensor and for voice samples storage on the SPI FLASH. Then there is the issue of finding/getting a voice sample for distribution that is license free.

Wishlist:

  • Evaluate alternate battery holder (integrated into case???)
  • Case design, mechanical mounting
  • Improved Ultrasonic sensor board mechanical and mounting to eliminate acoustic issues.
  • Evaluate MEMS microphone to replace ultrasonic receiver, speakers to replace ultrasonic transmitter
  • Speaker enclosure to enhance performance

Project Swiftlet - Audio playback

Projects / Project Swiftlet  Original post date: 09/20/2015

AK4386 DAC requires a MCLK for its internal clock that is a multiple of the sampling frequency fs. It is an inexpensive simple DAC that requires no I2C programming. There are no internal fancy resampling PLL, so all its clock signals have to come from the I2S master.


One possible setting is MCLK is 8192 x 512 = 4.194304MHz Now that sounds innocent enough until you read the buried fine prints aka the "Chip Configuration" chapter in the KL16 reference manual. That chapter is Freescale's lazy way of telling you how they wired the individual peripheral blocks together instead of them maintaining the information in the actual chapters.

"That's right Al -- you lost. And let me tell what you didn't win" - Weird Al, "I Lost On Jeopardy"

Have you ever wonder why they show features that are not available in the peripherals chapter?

Lesson of the day: Read that chapter and errata when you are designing your hardware.

Not sure what they are thinking as not having a programmable MCLK. Sometimes, you cut too much corners to make a cheap part only to makes the feature not usable. ¯\_(ツ)_/¯

Note: Even though you can set the values of the MDR in the debugger, scope probing test shows MDR has no effects on the output frequency IRL.

Clock dividers are cheap and Freescale even use the more fancy fractional dividers for other on-chip peripherals except here for MCLK generation. Normally if you use a high frequency crystal, you can just pick one that matches the MCLK and hope you ever need to deal with fixed I2S speed. In the case of using the 32kHz clock and FLL, you are SOL as there are very limited fixed multiplier ratios available nor the crystal frequency is fast enough for MCLK. Or you can use a more expensive DAC that can source MCL, but Freescale isn't the one making money on the DAC.

I was reading this just before I went to bed. I couldn't sleep as I was trying to find a way around it. I then realized that the "System Clock" has a programmable divider, so as long as I am willing to live with the consequences of changing it on the fly.


FLL frequency = 32768Hz x 640 = 20.97152MHz. Divide it by 5 yields 4.194304MHz so setting DIV1 to div by 5 would do the trick. Scope probing shows that Freescale didn't cut corners on the divider as it shows 50% duty cycle for even a odd number divider.

The BICK is set to either x32 or >= x48, so I pick 8192Hz x 32 = 262.144kHz. The higher numbers are for higher than 16-bit resolution.


Telling the ARM that "Sync Width = 0x0f ", "Word 0 Width = 0x0f " and "Word N Width = 0x0f " seems to set the right frequency for Frame Sync signal fs = 8192Hz.

The digital waveforms like excellent - perfect square waves even for the MCLK that is on the opposite side of the chip. Very short traces, good ground returns helps.

FYI: Currently there are no known open source working code for the audio playback as of the original posting of this. There are no I2S support for Teensy LC nor ChibiOS.

Got much closer last night. DMA is now working and the playing back take about the right amount of time. No idea where the data is going as there is no audio. Probably something very simple that I overlooked. Got to get the dreaded video done today to meet the contest requirement. Going to be a boring video.

Seen AN4486 "MPC5604E Serial Audio Interface" a few times, but I wasn't really reading it. Interesting tidbits concerning the register settings for I2S setting in Chapter 5.2. The register bits are named differently, but the important parts are in the comment field.

While I more or less had most of these set correctly, it is still worth while to know what I don't need to change.

• The maximum supported frame size depends on SAI implementation. I2S requires two words per frame. Frame sync width – configures the length of the frame sync in number of bitclocks. The sync width cannot be longer than the first word of the frame. I2S requires frame sync asserted for first word.
SAI0.STCR4.B.FRSZ = 1; /* Configures number of words in each frame. The value written should be one less than the number of words in the frame. */
SAI0.STCR4.B.SYWD =31; /* Configures length of the frame sync. Example for I2S and 32-bit words are transmitted. The value written should be one less than the number of bitclocks. */
SAI0.STCR4.B.MF = 1; /* MSB is transmitted first */
SAI0.STCR4.B.FSE=1; /* Frame sync asserted one bit before the first bit of the frame */
SAI0.STCR4.B.FSP=1; /* Frame sync is active low */
SAI0.STCR4.B.FSD = 1; /* Frame sync is generated internally (Master mode) */
• Configure the Word 0 and next word sizes and first bit shifted. W0W – defines number of bits in the first word in each frame. The maximum supported bits in the first word in each frame are 32 bits. Words of fewer than 8 bits wide are not supported if there is only one word per frame. WNW – defines number of bits in each word for each word except the first in the frame. The maximum supported bits in the first word in each frame are 32 bits. Words of fewer than 8 bits wide are not supported.
SAI0.STCR5.B.WNW = 31; /* Number of bits in each word in each frame except the first word. Example for I2S and 32-bit words are transmitted. */
SAI0.STCR5.B.W0W =31; /* Number of bits in first word in each frame. Example for I2S and 32-bit words are transmitted. */
SAI0.STCR5.B.FBT = 0; /* Configures the bit index for the first bit transmitted for each word in the frame. */
• Clear the Transmit and Receive Mask registers.

SAI0.STMR0.R=0; /* Enable or mask word N in the frame. */
I have been playing with Processor Expert (PE) and it insists on not letting me select 8-bit data as the MSB for I2S playback. The reference manual leads me to believe that's possible. May be PE is right.

Anyway, I came up with the idea of first copying a 8-bit value to the MSB of a 16-bit variable by DMA and then link a 2nd DMA to copy the 16-bit word to the I2S peripheral thus doing a cheap conversion on the fly.

I also found out that I swapped the LRCLK and the BICK signal at the DAC. I fixed that by cutting traces and connecting the right signals together with fine magnetic wires. Now both the converted 16-bit sample and my old 8-bit code from yesterday sort of works.

I managed to get some noise from the speaker. It is a bit distorted. I think it is a matter of getting the right bits set and scaling the signal level down. At least now the bits seems to be going in the right place on the chips. The 1.5V boost converter is too noisy, so just have to use Li-ion battery until that's fixed.


Project Swiftlet - Noisy Cricket!?

Projects / Project Swiftlet  Original post date: 09/18/2015

I played around with changing the value of C19 to 220pF. This has the same effect of a high pass filter and it attenuate frequency below 1kHz by another 20dB, still the hums remains. This tells me that the noise didn't come from the transducer.

Spectrum plot of slowed down audio when running off AA NiMH (boost converter)


Spectrum plot of slowed down audio running off Li-ion battery (buck converter)


The differences tells me that it is power supply related noise. Since the frequency is sub-harmonics, I would assume that the boost converter is running in PFM mode for high efficiency under low load. There is a 3V LDO for the ARM microcontroller, so that means that the noise is coming from the ultrasonic receiver. I guess the low pass filter filter for the power supply rail isn't low enough.

I'll need to look at alternate PWM based boost converter or at least one with pin selectable PWM. The other alternative is to feed the analog circuit with its own LDO.

Silly me didn't check that first. One quick fix is to use MCP1640B or MCP1640D parts which are variants to the one I am using, but has the PFM mode disabled.




Project Swiftlet - Digital Rangefinder

Projects / Project Swiftlet  Original post date: 09/08/2015


I implement the sonar (analog) routine first to get a feel on the raw data.
  • Objects that have planar surface tends to return a reflection that have a quick rise time and exponential fall time in the envelope.
  • smaller objects/irregular objects have a more elliptical envelope.
  • Larger objects returns higher amplitudes
Do I simply return the first echo? Here is what I think:


I can use the analog comparator peripheral in the ARM. Initially, the threshold is set at around -0.75, then it is slowly increase to the steady state value. The variable comparator threshold is to ignore the ringing at the transmitter while trying to accommodate close range detection.

This is what the received signal looks like when there are no immediate obstacles. It picks up the ping from the transmitter right next to it and I am using that and the subsequent echo from my target to calculate the distance. This zeros out the time delay for the transmitter to build up its amplitude and the propagation delay of the analog circuits.

Top trace: Output of the analog comparator. In order to measure very close distances, I have to change the threshold of the comparator on the fly to be just outside of the envelope. If there is an object within that close range, the resulting echo will be strong enough to trigger the comparator. (see 2nd scope picture below)

My next step is to implement that variable threshold and if my code works, the comparator output would be clear after the first 500us or so, but still be able to detect a small object further out..


Note to self: This is around time when my regular scope blew up due to the hot summer temperature.  This is my old scope.

I can program in the analog threshold via the 6-bit DAC feeding the comparator. I am looking at he bottom half of the waveform. If the input analog voltage is below my voltage threshold, the comparator output goes high. There is an optional programmable glitch filter that can use to remove glitches.

The top trace of the scope picture shows the comparator output. The comparator output then trigger an interrupt and that very first pulse can trigger TPM input capture.


My quick and dirty measurement of what seems to be a minimum distance that I can measure. 4" or 10cm. That distance is where I can distinctly see a reflection coming back.



I tired a lot of things to get the analog comparator to work, but in the end it wasn't reliable enough.
I have inconsistent triggering of the voltage levels.
I have mis-triggering when I am changing the threshold with the 6-bit DAC. If I program the filter to eliminate the glitch, I start having problem not seeing triggers.


This is where the fine prints part that kills it for me: "Analog comparator initialization delay" means it would take up to 40us to settle down if I change the DAC! i.e. the DAC settling time plus worse case propagation delay etc This 40us window makes changing the threshold on the fly not reliable enough for my application. The 12-bit DAC is slightly faster on high power mode 15us (typ), but I had enough fooling around with analog comparators.

Fortunately, this is not the end of the story. There is a digital comparator inside the ADC block. It can be enabled to compare the ADC results with the threshold set in a register and cause an interrupt. This completely gets around the issues with analog comparator. The fastest 8-bit continuous conversion rate at ~11MHz Bus Clock takes 1.621 us. That's a tiny faction of a wavelength of the 40kHz signal and is below what can be resolved. I can live with the results - see the scope pictures below.


I toggle the GPIO line (top trace) where I start/stop the timer for debugging.


This shows the sensitivity of the trigger. That small echo is cause by the surface of the scope.


This is the table that I used to change the threshold on the fly. The units are in mV and seconds. It is a staircase threshold set outside the ringing of the transmit pulse. The values can be change to make the range finder more or less sensitive to echoes.


const uint8_t ADC0_Threshold[]=
{
 SONAR_ADC8_THRESHOLD(500UL),
 SONAR_ADC8_THRESHOLD(1200UL),
 SONAR_ADC8_THRESHOLD(1400UL)
};

const uint16_t Threshold_SetTime[] = 
{
 SONAR_TPM1_COUNT(600e-6),
 SONAR_TPM1_COUNT(1000e-6),
 SONAR_TPM1_COUNT(2000e-6)
};

This is the back of the chair at 10cm (4"). That's the point where the interrupt is re-enable. I might tweak back another 30us where that happens, but the number is close. 600us/2 x 340m/s = 10.2cm

Firmware progress 2 - Acoustics & Mechanical original post date: 09/16/2015

This is the break out board for the left hand side connected to the main PCB via a long ribbon cable.

This is the captured waveform. The receive waveform is quite a bit different due to the mechanical difference as the sensor PCb is only hanging on one edge, so there is little mechanical damping of the PCB.


So I mount the Sensor PCB in the Stickvise:

Mounting left side PCB in stick vise
This is what I got:

This little experiment tells me that those are cause by the vibration of the PCB!

I tried to isolate the transducer from the pcb by not mounting them flush. Here is what the waveform now looks like (without the stickvise). So while those extra vibrations are eliminated, the transducer takes longer to stop ringing.


So I went back to flush mounting the transducers. Replace the header connecting the boards while under the clamp so that the sensor PCB is mounted flush to the breakout PCB. I then glued the two PCB together with superglue.


Now added a 4.7K resistor across the receiver at the two solder jumper point. The resistor electrically damps out the receiver, so it helps quite a bit at the expense of losing a bit of sensitivity.


It is not perfect, but with a bit of tweak in that table values, I can make this work.

I changed the resistor to 22K as the sensitivity with the 4.7K as poor. The blind spot is increased to 1ms which is about 17cm (6.7"). The maximum range is at 5m and the signal was getting very weak. I have consistent result that agrees with the scope for both channels.

Project Swiftlet - Sonar

Projects / Project Swiftlet

Summary:

☑ Sonar generation working
☑ Sonar transmitter working
☑ Sonar receiver working
☑ Sonar Analog sampling working

Here is what the Sonar Tx signals looks from the ARM chip's TPM (Timer / PWM Module) before it get fed into the full bridge driver.

There is an app note AN5121 "Generating a Fixed Number of PWM Pulses Using TPM and DMA" , but the code is complicated and ties up a DMA channel.

I used a timer overflow interrupt to count the clock cycles and stop the PWM. I have decided to use 'Fast Interrupts" (i.e. bypasses the RTOS) as the overhead is a bit too much at 40,000 interrupts/sec.


The sonar transmitter driver circuit run on a different power rail. Now that power management circuit works, the driver also works.


Notice the amount of ringing from the transducer persists even though the 74LVC08 drivers pins are driven low. With the sonar receiver circuit barnacles done on the PCB, here is what a ping and its return echo looks like.

The waveform is now symmetrical as the LMV324 opamp I used is rail to rail output. (Old project log that shows module hacking here )Here is the current consumption profile during the ping. Each of the spikes on the right plateau is a ping.

Current consumption profile captured by Mooshimeter
Some back of the envelope calculations:

Speed of sound: 343.2m/s
Range of ultrasonic module: 5m
Playback speed: 32768/4 = 8192 samples/s
Sampling rate: 8192 x 20 = 163840 samples/s

Sample size = 163840 s/s x 2 bytes/sample x 5m x 2 / 343.2 m/s = 9576 bytes per channel, so ~ 18.7kB which would fit inside 32kB of RAM inside the ARM for now. By reducing the ADC resolution to 8-bit, the amount of samples stored in memory can be doubled so the sampling rate can be doubled.

There is an external 64kB SPI SRAM should a higher sample rate at 12-bit or higher is required in the future.

Made some progress with analog sampling of the echo waveform. Here is the current consumption profile. (The first plateau was from the previous session.) The spike is about 20mA and that's the ping + ADC + DMA. The peak value is probably higher, but is beyond what the sampling rate/bandwidth of the data logger.

Right now this is done on a debug shell, so the individual steps are farther apart and easier to see.


I saw some numbers filled up the ADC buffer in the debugger. I have to visualize the collected raw data somehow. I print the content as ASC text and import it into Excel, this is what I have. That looks like the familiar sonar echo waveform.


This is what it looks like in detail looks like when I plot the first 2 blips. Pretty sweet, eh?


Looks like I used the FLL frequency instead of the Peripheral bus clock for calculating the sampling rate and off by a factor of 2. The following shows the correct sampling frequency.


The following shows the data points on the waveform: This is sampled at 16380 samples/sec, giving roughly 4 data points per cycle for the 40kHz signal.


The sampling rate can easily double (or quadruple up to the 800+ksps spec if I crank up the FLL from 21MHz to 48MHz ), but I won't be able to fit the left and right side into ARM's internal memory. I can either drop the resolution down to 8-bit or reduce the range or have to do some fancy DMA streaming the data into the external SPI SRAM.

For now, I think I'll leave it as is.

I have written the raw data into a binary file and imported into Audacity. Here is what the spectrum plot looks like by playing back at 1/20th the speed.


There is a bit of low frequency humming. Since we are dealing with a slowed down 40kHz signal with very narrow bandwidth (limited by the transducers), we can pretty ignore most of it outside of 2kHz +/- 500Hz. Now this might not even be a issue for those tiny speakers already work like a high pass filter attenuating frequency below 800Hz.


"Firmware progress 3 - More sonar work" Original post date: 09/17/2015

I have modified the code so that samples are taken from the left and right side are collected in separate passes and interleaved to form "stereo" samples. It is done separately as the echoes might interfere with each other. There is also big savings on the hardware as both sides are MUX together shares the same amplifier and ADC.

This is my ultra low tech setup. The separation is about the width of the Dollar Store safety glasses. I'll probably going to be using this for most of the test


The left side hits the edge of the grey wall and the left side of the door frame while the right side hit the right side of the door frame.


This is the "stereo" waveforms collected, exported to Audacity, normalized and high pass filtered. To be quite honest, my brains can't quite processing that. I don't know how long it would take for me to do it.


Looks like the 22K resistor on the left side is a cleaner waveform. I solder in a 22K to the right side as well. (note the lack of ripples in the after picture) So yeah, I definitely want them.


Right now I use a buffer for sampling a mono audio and another one twice as big to hold the interleave "stereo" sample. 
There is an interesting algorithm to merge mono audio samples in place. which can lower the storage requirement allowing for either a lower memory model microcontroller to be used. http://num3ric.calepin.co/interleave-an-array-in-place.html

Next step: Writing code to play back to the stereo DAC on I2S. Lot of reference manual pages to read. :(

Sonar samples captured for the HaD Semifinal video, so might as well put the uncompressed .wav files on the GitHub for everyone. Actual samples are 8-bit, 8192 samples/s captured using Li-ion battery with no post-processing except normalized it.

My low tech setup for the test.


"DMA tricks for Kinetis KL" Original post date: 09/28/2015 

Normally this stuff is easy with the MK series eDMA, but the KL series has a very limited DMA that doesn't have a minor/major transfer loops. It can only transfer 8/16/32 bit of data into consecutive locations. i.e. we can't tell the DMA to skip every other byte in the transfer.

The DMA controller does offer linking which let you trigger a new DMA transfer from a DMA event. We are going to take advantage of it to break the operation into painfully smaller steps using multiple DMA channels.

Interleave 2 separate ADC samples into stereo sample using DMA transfer:

1. DMA1: ADC 8-bit samples (left samples) into buffer using 16-bit word transfer.

The MSB is filled with zeros which we'll over-written with the right samples later.


2. Now the fun part for the right side audio samples

  1. DMA1: Transfer from previous sample into a 16-bit variable. Source: 16-bit, increment; Destination: 16-bit; link to DMA2.
  2. DMA2: transfer new ADC sample into the MSB of a 16-bit variable. Source: 8-bit fixed address; Destination: 8-bit fixed address; link to DMA3.
  3. DMA3: transfer 16-bit word back to sample. Source: 16-bit fixed address; Destination: 16-bit increment.

Code name "Swiftlet" - PCB populating and bringup

Projects / Project Swiftlet  Original post date: 08/28/2015

Quick executive summary:

☑ ChibiOS compiles and runs.
☑ 3.0V/1.5V buck converter works.
☑ 3.0V LDO works.
☑ 3.3V boost converter works.
☑ Li-ion charger works.
☑ Debug cable - SWD connection
☑ MCG working with 32.768kHz crystal and FLL.
☑ My replacement for _pal_lld_init() (for configurating/initializing GPIO) works.
☑ Serial port setting and my debug shell works.
☑ Input battery voltage sensing and power selection works.
☑ Sonar receiver works with the barnacles that fixes the two following issues.

X U12A, mU12B, U12D: All of the inverting and non-inverting inputs are reversed!
X Receiver virtual ground impedance is too high causing oscillation.

☑ Haptic motor driver works
☑ Class D amplifier works
☑ DAC works after the barnacles

X DAC BICK & LRCK connection swapped.

After the long wait, the PCB finally arrived. Like my other PCB, the back silkscreen is missing. :( The silkscreen on this PCB is back to normal. As seen from below, the silkscreen is a bit offset. Thankfully I remove the silkscreen from most of the footprints.

Score PCB with a box cutter on both sides.


Snap the PCB

Repeat

Testing the Li-ion charger
☑ Li-ion charger working.

Trace between R1 & R2 not routed. R2 = 10K needs to be installed.
Had a bit of trouble of not having enough solder during reflow, but once I tin the chip side, then it is okay.
This was a much finer pitched QFN than I had soldered at this point.

Populating and testing power supplies for Li-ion and AA
☑ 3.0V/1.5V buck converter working.
☑ 3.0V LDO working.
☑ 3.3V boost converter working.

Solder the rest of the SMT parts. I leave out the through holes parts as I have no idea if they would survive a reflow in the toaster oven. The battery holders do not handle heat too well.


Pop it in the toaster oven just to make sure that the surface tension get to line up the parts.


Assemble the Sensor PCB and solder the two boards together.

The holes for transducer footprints are a bit tight as these are parts I pulled from pre-made modules, so there is a layer of solder on the pins that I didn't account for. The battery holders could still use a bit of space. I think the holes in the plastic posts are intended for self tapping screws.


The two 8-pins connector (Debug and expansion I/O) are a bit too close together. The IDC version exits at 90 degrees. So looks like I'll either have to kludge together something. Not a big deal as they are only for debugging and for me to get at the spare I/O pins.

The DF11 IDC connectors is a double decker - the bottom row is connected to the left column of the connector while the upper row is to the right. There is a plastic partition on the bottom layer to stop your wires getting to the right column. The connector takes 26AWG and it works for either loose wires or ribbon cables.

I used the back side of the box cutter blade to press down the wire until the insulation is pieced by the V shaped contacts. It makes an airtight connection and does not require any fancy crimping tools. This is the first time that I use this so I check all the connections with the continuity test on my multimeter and they are good. I would say this is a good system. The other end of that cable is split into to TTL serial adaptor and a SWD debugger.

SWD debugger detects something. It's ALIVE!

☑ Debug cable - SWD connection
☑ Microcontroller (not running any code at the moment)


I have added the headers for MDK's Configuration Wizard for some of ChibiOS options in hal_lld.h It is a lot easier than trying to figure out the hex values and a wrong one will permanently lock the device.

I got stuck on the NMI pin as it was enabled by default in ChibiOS and of course You would think that NMI_DIS = '1' would disable the NMI, but actually '0' does that! So having a GUI that spells things out will make life easier for the next person.


☑ Clock oscillator, MCG working. Wasted a bit of my time trying to change the clock setting when the code isn't called.
☑ My replacement for _pal_lld_init() is working better than the one that comes with ChibiOS.

You'll need access to the Reset pin as a way to access SWD if you run into trouble setting up the port pins, clock generator or stop/sleep mode. I made a small test pad for that. BTW, you can't even begin to do serial port debugging until you got the clock tree, I/O port, interrupts all configured correctly which can be tricky on the ARM, so using SWD is pretty much essential.

Found some hard coded constants inside serial_lld.c. No wonder why I couldn't change the baud rates and the oversampling rate. Got that fixed up with #define and now I see my familiar shell program. My shell program will make life a whole lot easier to try out small bits of code.


Seems like the power consumption at this point is around 13mA when powering the microcontroller from LDO. The current changes very little even when I am playing with different clock speed setting. Right now I am running the FLL at 20.971520MHz with the Core at 4.1943MHz (/5) and the bus/FLASH at 2.09715MHz (/2) as I am trying to converse power. At some point when I am playing with MEMS sensors that need some math, I might have to briefly increase the clock speed. Even with that type of clock speed, this will still have an advantage over a 8-bit trying to do math.

☑ Serial port setting and debug shell are now working.

I found the source for that extra 10mA of power drain. It turns out to be the power rail for the MEMS. With that tuned off, the power has dropped down to 2.9mA with the ARM running. It seems to make very little difference to what clock divider rate the ARM is running as (so far).

That extra 10mA seems to be kind of high when the datasheet talks about max 3mA during boot and ~600uA typ for full sampling rate. On the other hand, the part has not been initiated, so it is hard to say.

The efficiency of the 1.5V boost supply seems to get a bit better now that I got some of the power management I/O initialized. It went down from 24mA to 16.8mA and that's with more peripherals on the ARM going too.

☑ Input voltage sensing.

Changing the ADC filters C12, C13 from 0.1uF to 1nF because the RC time constant is a bit large.
Changing R10 to 220K, R7 to 1M, R9 to 562K because there is quite a bit of leakage current to the ARM ADC pins. Now the values are close to what they should be.

☒ U12A, mU12B, U12D: I forgot to flip the symbol vertically. All of the inverting and non-inverting inputs are reversed! This requires some surgery with barnacles.

☒ Receiver virtual ground impedance is too high causing oscillation

I guess I should actually trust the oscillation in the simulation and my gut instinct instead of the waveform measurements of the modules!? The new opamp that I am using has stronger drive which in turns feeding back to the virtual ground. The virtual ground impedance formed by 10K voltage divider and decoupled by a 10nF isn't low enough. A part of that output signal is injected on the reference virtual ground and causes oscillation.


I could use the uncommitted opamp as a buffer and according to LTSpice would work. I have decided to move the 1K virtual ground connection to GND. The latter makes no difference AC performance-wise to the bandpass filter and is much easier to fix. After fixing the miswiring and the resistor, the sonar receiver is now working. See here.

☑ Haptic motor driver working

The motor is driven from PWM with period, duty cycle, number of pulses and side (left/right/both) programmable. The following scope picture shows the voltage across the motor. I use dynamic braking so that the motor start and stop abruptly instead of coasting producing tabs. The motor is kind of small and I am not sure if I can sense its movement more easily than its noise.


There are still a lots of work to do.