Sonar for the visually impaired

This is a low cost portable Ultrasonic range finder and sonar device to help a visually impaired person navigate indoors.

Similar projects worth following
The goal of this is to design an easy to use, low cost, light weight with long battery life device for the visually impaired person. I am going to optimize the design for manufacturing.

With the help of 2 ultrasonic range finders on each side of my head giving me audio/haptic feedback on the relative distances on both sensors, I should be able to orient myself towards the centre of an indoor passage. Stair detection is possible with the device. A proximity alert would warn me when I am about to run into a wall.

There is also an analog sonar mode that plays back the return ultrasonic echo at 1/20 speed. A similar research project and paper was published. With training, this allows more information of the surrounding than the range finder.

I believe that the goal is realistic, within reach and yet can change the life of others for the better. This is a new area for me to learn and explore, I'll try to document and share my thoughts and my notes in the project logs.

Motivation and what I am trying to do:

I got this idea when I was watching Daredevil on TV. Our hero is a blind person with a heightened senses. He even fights crimes in his spare time. But we live in reality and don't get superhuman senses from unknown chemicals.

On the other hand, a very crude form of echo location might be something within reach of a hacker. This is not meant to be a toy prop, but an experiment to see if I can design something low cost that would help a visually impaired person to navigate indoors.

It is a serious problem as there are 40 millions people world wide and 1.3 millions in the US that are legally blind. This is a personal project right now funded by myself. At some point when the project is ready for alpha release, I'll present this and work with the local groups in the area for a trial and hopefully production.

What this can do and how it is different than similar projects:

There are a few projects/design that I came across. My design has a different design philosophy. I want tighter integration for better battery life, size, weight reductions than is possible with using off the shelf modules. The design should also be intuitive and ergonomic for the end user.

Two range finders (one for each side) are located on a pair of glasses. As the head is turned, each of the range finders would try to map out the distances in front. With simple math, the device can figure the amount of correction to get the user to walk parallel to the hallway.

With simple geometry, the angle ϴ can be worked out. The device can then inform the user how much correction is needed to stay parallel to the wall.

tanϴ = w / (d1 - d2), so ϴ = arctan( w / (d1 - d2) )

The device can detect the distance and the amount of drop in front e.g. a staircase Since the head mounted sensors have a relative a fixed height (vs sensors on hand) makes it easier for the detection.

We can calculate the following from what we know or measure. Angle ϴ - measured by the Accelerometer; distance l return by the range finder while h is the height of the transducer from the floor.

depth of the stair from the sensor is h2 = l x cos ϴ so the relative depth of the stairs is h2 - h
distance from the step is d = l x sin ϴ

This type of information can be presented more easily by voice feedback.

One of the reason for a head mounted device is that voice feedback can be provided easily and discretely. Voice feedback allows for more complex information to be presented. e.g. the device should be able to tell the user the measured distance to a wall or the object.

The dual speakers or dual haptic feedback from the differences of the distances would help the person to align the heading towards the centre of a hallway. When walking, the body naturally follows the direction of one's head. The absolute distances from the sensor can be used to implement a proximity alarm that tells the me that he/she is about to run into a wall or a person approaches.

The sampling alternates between one of the two range finders. This reduces the interference otherwise would result. It also reduce peak power consumption and allows me to share the same receiver circuit. The update rate can be reduced if the person is moving slowly or that the reflection is far away.

The unit is powered by a rechargeable Li-ion battery with a target battery life of weeks. Readily available AA Alkaline/NiMH batteries can be used as emergency replacement. The circuit is designed to optimize power consumptions. Unused circuits are shut down to minimize power consumption. The unit can be placed in sleep mode if it remains stationary for a long time.


Unlike most of my projects, this is a new area for me. As such the project logs documents my learning process. I have compiled a TOC of the projects logs and organize them as below. At some further point, I might come back and document the implementation in a more conventional way like my other projects. Until then, hopefully they help the...

Read more »

  • 2 × TCT40-16T/R2 (Aliexpress or removed from HCSR04 module) 40kHz Ultrasonic Transducer Tx/Rx pair
  • 2 × Mobile phone Vibration Motors (China)
  • 1 × MKL16Z256VLH4 (Freescale ARM M0+) 256kB FLASH, 32kB RAM ARM Cortex M0+ / Microcontroller
  • 1 × FXOS8700 (Freescale Sensor) 6-Axis Sensor with Integrated Linear Accelerometer and Magnetometer
  • 1 × Protected 14500 Li-ion battery 3.7V (can use AA Alkaline/NiMH battery as emergency replacement) Battery

View all 14 components

  • DMA tricks for Kinetis KL

    K.C. Lee09/28/2015 at 16:17 0 comments

      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.

  • Progress Report - Semi-final

    K.C. Lee09/20/2015 at 03:55 0 comments

    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 impair person. May be I am just not in the video generation.

    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.
      • 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.
      • 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.
      • 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.
      • Freescale documentation is very lacking on explanation on their terms which are different than their own app notes for other families.
      • Deciphering the Processor Expert generated code isn't easy and the GUI doesn't have the exact setting that I want.
      • 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.


    • 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

  • Audio playback

    K.C. Lee09/20/2015 at 02:47 0 comments

    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 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. N
    o 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....

    Read more »

  • Noisy Cricket!?

    K.C. Lee09/18/2015 at 02:00 0 comments

    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.

  • Firmware progress 3 - More sonar work

    K.C. Lee09/17/2015 at 17:05 0 comments

    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.

    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 set up for the test.

  • Firmware progress 2 - Acoustics & Mechanical

    K.C. Lee09/16/2015 at 22:18 0 comments

    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:

    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.

  • Firmware progress 1 - Digital Range Finder

    K.C. Lee09/08/2015 at 16:22 0 comments

    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.

    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[]=
    Read more »

  • Firmware Progress - Power

    K.C. Lee09/03/2015 at 14:48 0 comments

    Power supply block diagram:

    Here is the dependency graph of the component blocks. I like to draw these things out before coding.

    I am going to try coding it in a table and an iterative loop inside a function to resolve the dependency, turn on/off the component etc. That layer of abstraction would be useful for porting/organizing my code.

    I think this is what I am going to do:
    • For each of the nodes in the graph, the following are stored
      • I/O port address, bit number and polarity
      • a bitmap of its dependants
      • a bitmap representing itself
      • a link to its parent
    • There is a global bitmap variable to holds the current device that are on.
    • Each time a node is enabled, it adds its bitmap to the global bitmap. It then iterates up the graph by following the parent link.
    • Each time a node is disabled, it looks at its dependants bitmap. If it is set (shouldn't happens), it ignores the request. If it is cleared, it removes itself from the global bitmap. It then iterates up the graph.

    Now the power management routes handles the power on/off and keep tracks of dependency. e.g. If I want to turn on Audio L, it know to also turn on Amplifier/DAC, Peripheral Supply and all the way up to 3.3V. If I turn on and off other devices using Peripheral Supply, it knows not to turn that off until all the devices on the rail are off. This simplifies the coding as the devices do not need to know the power dependency.

    The following is captured current consumption using Mooshimeter. This is for using NiMH battery at around 1.3V. This is without putting the ARM into sleep mode etc. Power profile plots like this is useful for debugging and optimizing the design. Energy consumption can be reduce by only powering the peripherals or branches of power rails when needed.

    The current consumption went up in discrete steps because at each stage ARM peripherals and power for external circuits are turned on. It managed to capture 2 of the 3 pings as spikes.

    The following shows the debug shell commands during this test.

    The decoupling caps on the power rail charges up as MOSFET turns on and this causes an inrush current that shows up as a bigh spike on the rising edge of the current step. I can try using the slew rate control and play around with the drive strength on the ARM I/O pin. There is also the pull down resistors that could be used instead of the output driver. This should slow down the rise time and reduces the inrush current.

  • Firmware progress 1 - Sonar

    K.C. Lee09/01/2015 at 14:22 0 comments


    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. By the way, this is

    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.

    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 some how.

    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.

  • PCB Bring up - basic sanity

    K.C. Lee08/28/2015 at 03:12 0 comments

    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


    ☑ 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.

    ☑ 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 desiable 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...

    Read more »

View all 33 project logs

  • 1
    Step 1

    This PCB assembly uses 0402 and 0.4mm QFN parts. This requires some experiences in SMT assembly.

    1. Use this as general PCB cutting and SMT assembly instruction for the cheapo home assembly. Alternatively make separate PCB and use a stencil.
    2. Reflow the SMT parts.
    3. Hand solder the through hole components
    4. Assemble the sensor boardsNote that left side and right side are mounted differently.
      Left side uses the bottom row of connection and requires shorting the two solder jumpers.
      Right side uses the top row and a different angle connector orientation.
    5. Assemble them to the main PCB for the right side and breakout PCB to the left side
    6. Prepare cable

    Sketchup 3D model on github: 0.0 Rel 0/Sketch3D

    Additional assembly pictures, bring up, bug list

View all instructions

Enjoy this project?



Frank Buss wrote 05/10/2018 at 04:37 point

Nice project. I like the idea of high level processing of the sensor data. But even just converting the distance to pitch could be useful. Maybe add a button to change modes?

Once I implemented a stereo version of the Arduino script for this project, and with logarithmic scaling:

  Are you sure? yes | no

oshpark wrote 05/09/2018 at 08:18 point

Thanks for the idea on battery holder!

  Are you sure? yes | no

Roman wrote 06/27/2016 at 18:55 point

Very cool project. this could become a product. Once in a while one could benefit from the "Third Eye" on the back.  

  Are you sure? yes | no

K.C. Lee wrote 06/27/2016 at 19:21 point

Thanks.  These projects are a bit too much for the HaD contest time frame.  Now I just need the time to finish it.

  Are you sure? yes | no

Alan Green wrote 11/29/2015 at 00:12 point

Thanks so much for posting all of this information.

  Are you sure? yes | no

Kyle wrote 05/22/2015 at 14:02 point

Awesome project. I actually thought about this exact project once. I got the idea from the TV show Superhumans, there was a kid that lost his sight and he navigated by clicking with his tongue and listening for the echo. It was actually pretty remarkable. He could ride a bicycle and even identify objects by standing near them.

  Are you sure? yes | no

K.C. Lee wrote 05/22/2015 at 16:18 point

Thanks.  I heard about that trick on the internet too, but it is probably not for everyone.

  Are you sure? yes | no

K.C. Lee wrote 05/20/2015 at 22:02 point

The idea can probably be done in analog with a bit of help with logic chips for sequencing the left/right range finders etc.  Instead of measuring the time with a digital counter, you can it to control a ramp (integrator).  You have 2 analog voltages from each sensors representing the distances that you can work with just like a line follower bot.

I am no stranger of working bare metal on a microcontroller or designing my own hardware from scratch.  I find it easier to read a 1000+ pages of reference manual than trying to understand someone else's poorly documented code.  

I might implement this on ARM or Silabs 8-bit microcontrollers.  They both have very decent development environments and hardware debugging tools that I have used in my projects.

  Are you sure? yes | no

Starhawk wrote 05/20/2015 at 21:39 point

Very very cool. Makes me wonder if this could be done with no microcontroller at all... there is often a certain intimidation type barrier-to-entry with those. I can do a little bit with PICAXE, for instance, but I've never done a thing with Arduino, because I have such a time wrapping my head around C-like stuff.

Bear in mind, though, that if you do use PICAXE -- unlike Arduino, it cannot be embedded in anything -- it's a purely-hobbyist system. You try to resell it inside of anything, RevEd gets the guys with suits and briefcases and nice shoes to come after you. Kind of a shame, really, but them's the rules... closed-source stuff, too, which is kind of a bother.

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates