I wanted to dabble with BLE and learn a bit:
- Can you hack together in your garage an antenna and RF section that will work at 2.4GHz?
- If it works, who good/bad will it be?
- What is hand soldering QFN packages like? Many BLE devices are only available in CSP or QFN48.
If you want to make IoT and Wearable devices that can be controlled from your phone/tablet/whatever, ZigBee is a neat mesh networking technology; but it’s not in any phones. Bluetooth (and more recently) Bluetooth Low Energy is in all of them. It’s easy to write a BLE control app write yourself using the Cocoa frameworks or download one like the excellent LightBlue for iPhone:
Make a Board
So, I broke out Eagle and designed a PCB around the Nordic nRF51822 chip, basing the design on a reference from the Nordic data sheet,
I picked the Nordic device because:
- There aren’t many catalogue BLE devices around yet
- It’s Cortex M0. No need to learn ARC (CSR).
- The CPU is integrated into the SoC (unlike the TI device)
The nRF51822 worked great, but it wasn’t all good. More on that later…
My Eagle board design is on GitHub here.
The most challenging part was the 2.4GHz antenna design. The key decisions were:
- Pi network or balun
- Chip antenna or the “real thing”
Since I wanted some RF experience, I picked both of the harder options i.e. pi network and PCB strip antenna.
This whole project was brought to you by app notes…. the best I found
The STM32F1xx has some neat features that allow you to cross-couple timers in interesting ways.
In the last post on timers, I synchronized 2 timers by using a master-slave configuration where the master resets the slave on every cycle. This time I use 2 cross-coupled channels of one timer in order to measure a PWM train frequency and mark:space ratio.
The trick to measure PWM is to use one counter to measure the period and the second to measure mark time, the latter reset by the first period counter on every cycle:
Here’s how it works:
The pulse train is applied to the pin of Timer 1 channel 1 (T1C1)
T1C1 edge detector outputs rising and falling edge signals as shown below.
The MUXs are cleverly designed so that you can use the edge signals from one channel
This post pulls together the work from prior posts on the timers, ADC, DMA and GPIU for the STM32F372.
The idea is to get the MCU to do periodic ADC measurements and store the results away on its own without needing the CPU to intervene. This means no interrupts or polling, just the peripheral blocks working together on their own. This type of design is becoming more and more common in the low power world where the CPU and its subsystem is kept asleep, leaving the peripherals to do their job with the CPU only woken when some control needs doing.
The demo works like this:
Timer 2 is set up to produce a PWM train with a 5 second period. I use 2 channels in the same counter with the same mark:space ratio settings so that the first can drive the ADC whilst the second flashes an LED so that I know something is happening…
Timer2 has a nice feature where you can set it to send a Trigger Event at each Update Event (UEV). Here I set the UEV to be when the counter spills over the period
For this demo I used 3 of the counter timers on the STM32F372 to generate pulse trains of differing frequencies, made more interesting by adding 2 things:
(1) Chaining of timers using synchronization. Surprisingly, even when 2 timers driven by the onboard clock of the F372 are started at the same time, within 30 secs they have often drifted apart by as much as 500mS. This could be caused by differing path lengths on the SoC. The problem can be solved by using the on-board triggering mechanism which allows one timer to generate triggers that will drive another at selectable events. I used this feature to reset the second timer to the first on every cycle, thereby minimizing drift.
(2) Generating a periodic interrupt using the CortexM3 core SYSTICK clock. The SYSTICK clock only has a couple of configuration registers and is much simpler than the CTC Timers. Easy.
The programmers’ models for the timers used in the STM32F1xx and F37x series are similar. I guess ST reused the same IP blocks… There
Though many eval boards come with an embedded JTAG-USB interface, I still like to use a separate purpose-built JTAG debug box.
If you pick the right one:
- It can be used with many boards and SoCs. Once set up, one debug toolchain works for many projects.
- You can use it to debug MCUs on bread-boarded projects. You will need to make a hacked SWD cable like the one I show in this post.
- Not that expensive. I picked up a Segger JTAG EDU on a home-use deal for $60. I remember the early days at ARM when we first launched our “EmbeddedICE” box; the price then was over $1K….Today you can get some very cheap $20 knock offs from China on EBay and AliExpress. These may or may not work, but I believe it not worth my time to rely on dodgy tools with questionable software.
- It works natively with Mac OSX. At least the Segger version does. I don’t need to run Fusion, Parallels or Virtual Box.
- Does not require special USB drivers etc. The Mac version works by looking like a TCP device and speaking IP.
- Supported directly under Eclipse. Again no special driver required
- Supports SWD or full JTAG
(1) Connection to the target
The first thing you will need is a SWD cable. I made one out of some 20 core ribbon cable and a 20 pin IDC box connector. The ARM documentation on SWD pinouts is highly ambiguous since they talk about the pins to a “connector”. What’s a connector? Do they mean the plug (male) or socket (female)? I figured out the Segger pin out by using a Salaea Logic Analyzer:
(2) Get the Segger software tools working
On a Mac, this is as simple as starting the JLinkExe terminal application in the Segger Application folder. Don’t try and use the JLinkGDBServer app from terminal.
If all is well, JLinkExe reports something like this:
Note how JLinkExe switched automatically to SWD. This works most of the time, but not always. It depends on whether your target device is “known” to the box or not. If it is not known, you can fix this by
I used a header board for an STM MEMS evaluation kit in order to take a look at some common MEMS sensors:
- LPS301: Pressure and temperature sensor
- LG3D20: Gyroscope
- LSM303DLHC: Accelerometer and magnetometer
The header was an STEVAL-MKI124V1 which is designed to work with an STM motherboard evaluation system. I took a shortcut and used it with an ARM MBED board featuring an NXP LPC1768 MBED.
Hook-up using I2C was trivial:
The schematic for the evaluation board is here:
The orientation of the sensors on the board is like this:
MBED-based code I write to drive the I2C is on the MBED website here
The code sets up each of the sensors and then provides a continuous output of temperature, pressure and orientation. Rather than optimize for performance or efficiency, the code here is intended to show clearly how to access the sensors.
An interesting twist was to use the linear accelerometer to find the vector of the earth’s gravitational field (i.e. down) and to use that to make a tilt-adjusted compass. Algorithm
Quick and simple project to make an adapter PCB to use a QFP packaged MCU on a traditional through-hole breadboard.
I ended up making a double-sided PCB to support 2 different QFP sizes. One side set up for 48 pins, the other for 32pins. Usage is to populate one side or the other, not both….
Simple pin-out to two standard 24-pin headers. No on board components such as decoupling capacitors.
Here is the board in action on a breadboard and loaded up with a 48-pin STM32F100C8:
Eagle files for the board are on GitHub here.
I have found that basic example code from MCU suppliers is often too complex. Vendors want to write one example for their entire product range, so you often end up with a spaghetti of code and linker script that weaves in CMSIS, USB, drivers for fancy peripherals and whatever else. Even if you wanted to strip it down to basics, you would have to deal with multiple file dependencies in a web of directories that make the job harder than it should be.
For new board bring up, once I have shown sign of life using low level JTAG (see this post), the next thing I like is the simplest possible software set-up that I can get working.
Nice theory. Where do I download some code? I was surprised at how much I had to search to find anything useful. So this post has a simple example I made for a new STM32F100C8 board. It should work or at least help for many CortexM0 or M3 MCUs.
In the below diagram, the pieces of code we need to supply for this simple approach are in blue:
There are countless
Powering up a new board design or even skiing off-piste with an eval board without vendor-suppled code? This post shows a way to look for first signs of life without depending on working debug toolchain or working target software.
I use a Segger JTAG probe that I covered in a previous post.
Some recent eval boards like the one for Nordic Micro’s nRF51822 ship with an on-board USB debug connection that has a USB-JTAG decoder chip on board. This board uses the same Segger driver as their JTAG box embedded in the decoder, so the below approach should also work.
Segger JLINK application driver has a series of useful commands for examining directly addresses in memory:
- mem Read memory. Syntax: mem , (hex)
- mem8 Read 8-bit items. Syntax: mem8 , (hex)
- mem16 Read 16-bit items. Syntax: mem16 , (hex)
- mem32 Read 32-bit items. Syntax: mem32 , (hex)
Since many MCUs have a factory-programmed ID register, you can use JTAG to read this value and check for signs of life.
To start with, I target a STM32F100C8. This MCU has a register at 1FFFF7E0 hex containing a 16-bit value with the flash size of the MCU. This is covered in the STM32F100 programming manual on
I was looking for a way to test the frequency response of a new oscilloscope.
Analog Devices has a nice IC that can produce a digitally synthesized sine wave of frequency between 0 and about 70 MHz. AD9850 link is here.
The quickest way to throw together a prototype was using an MBED platform. My code is here
What made things even easier was the availability of ready-to-go evaluation boards from China on Ebay for less than $5. This is the one I used.
This design is limited to about 40MHz if you want a clean signal without aliasing.
Frequency and phase are set by a 40-bit command that has:
- 32-bit frequency setting
- 5-bit phase setting
- 1-bit power up/down
- 2-bits factory debug access
Output frequency is given by: fOUT = (frq × CLKIN)/(2^32)
where frq is the 32-bit frequency and CLKIN is the frequency of the on-board crystal (125MHz in this case) So, for example 0x147AE148 is 10MHz.
Frequency resolution has a step size of 29KHz with the 125MHz clock.
You can also change phase in increments of 180°, 90°, 45°, 22.5°, 11.25° or any combination thereof using
Most NSOutlineView examples I have seen are not that helpful since you spend time trying to figure out how the data model behind the example works rather than seeing how to use the framework itself. Yes, the data model is critical, however if you don’t understand the framework then you won’t be able to write a controller to feed the view or the model…
So. I have tried instead to get started by boiling this all down to the simplest possible configuration.
Before the Memory Leak Police get on to me, the below is not written for memory management beauty but rather to demonstrate the framework; so, the reader is left to figure out the releases. I know I generate lots of objects…and also that I violate MVC….
But, can you make it simpler than this..?
Power up Interface Builder, drop an NSOutlineView into a window, hook up the delegates and outlets like you would for NSTableView. That’s it.
Here is what’s going on in the code.
In Method#1, I hard-wire the code
Outline views are great for displaying hierarchical data because they allow the user to drill down into the parts of the dataset that are the most interesting.
A common place where they show up is in file handling windows. So. My last example in this column will be a directory browser. To build an outline view, all you have to do is create the view in Interface Builder, hook it up to your code and implement 4 specific delegate methods. Simple really.
It turns out that unless you try and understand some of what NSOutlineView does behind the scenes, the chances of actually hooking up your data right are remote… If you have a bug, what tends to happen is that you either get an exception/crash or nothing happens. And since much of the inner workings take place beneath the hood inside runtime, it’s not as if you can put a breakpoint inside the NSOutlineView to see what’s going on. It can take many NSLogs in your code to get some visibility.