Category Archives: Bluetooth Low Energy

Micro:bit, MakeCode, & Extensions

Micro:bit

Over the past five years I’ve been an active developer for and user of the micro:bit, a low-cost platform designed by a non-profit organization (and partners) with the goal to “Inspire every child to create their best digital future.”

An overview of the mico:bit (from https://microbit.org/get-started/user-guide/overview/)

I use the micro:bit for summer camp activities and have worked on supporting some K-12 modules. Most of my activities are geared towards novices, who benefit from block-based visual programming languages.

MakeCode

MakeCode, developed by Microsoft, is web based development environment that supports a block-based visual programming language. MakeCode supports a variety of platforms, including the micro:bit.

& Extensions

One of the great features of MakeCode is the ability for people in the user community to create “Extensions”. Extensions allow developers to create new sets of blocks that others can use. This allows the platform to grow beyond the originally expected uses and beyond the limited ability of individual companies/organizations to meet all of requests from micro:bit users.

I originally created an extension to support curricular development. Washington University’s Institute for School Partnership (ISP) wanted to pilot test some new modules for their mySci curriculum (used in over 200 schools). The ISP was willing to share the curricular materials that resulted from our collaboration, which can be found here. And here’s a video of it in use:

mySci Module Demo

My part in this was developing the support for an appropriate temperature sensor. I chose to use the Dallas Semiconductors (now Analog) DS18B20. One of the first problems we encountered in early testing was inconsistent temperature readings! A little research led to Chris Petrich’s great resource for counterfeit DS18B20s. Afterward, we started using DS18B20s from authorized resellers (YourDuino.com, which was sold) and the inaccuracy problems disappeared. Although I haven’t tried them, I expect the AdaFruit sensor/resistor combo to be a great choice: https://www.adafruit.com/product/381.

I created a MakeCode block specifically for the DS18B20 to make it really easy to collect accurate temperatures. My original version required connecting three wires and a resistor, but I created a second version that can work with just two connection. Both version were added to the list of official “MakeCode Extensions”:

  • The documentation for the original version, DSTemp, is available on the MakeCode site (or at my GitHub repo).
  • The documentation for the 2-wire version, DSTemp-2wire, is also available on the MakeCode site (or at my GitHub repo). It includes step-by-step instructions to “make” the sensor (i.e., how to wire it).
Parts needed to create a simple DS18B20 setup (2-wire version)
Assembled, user-friendly DS18B20 sensor

Extensive Extensions

My work to support the ISP was a great introduction to the micro:bit MakeCode ecosystem. I’ve gone on to develop several other Extensions with varying degrees of complexity. There are a variety of things about MakeCode development that are a good fit for me:

  • Creating blocks for novices requires careful thought about semantics and novice programmers.
  • Extensions require a variety of low-level concepts, like memory management, embedded systems concepts, operating systems concepts, etc.
  • C++ is used at the hardware level, but TypeScript is used for most of the API level that is exposed for MakeCode users. The mix of the two requires a variety of programming skills.
  • The scope of the MakeCode extensions is modest and can fit my schedule.
  • Due to prior industry-focused projects for consumer electronics, I had already worked with the processor line used in the micro:bit (Nordic Semiconductor’s nRF51 and nRF52) before the micro:bit was released. Since the prior work was focused on Bluetooth Low Energy “gadgets”, I already had a deep knowledge of some aspects of the micro:bit hardware, which has been beneficial for my micro:bit work.

I’ve continued to develop extensions that extend the micro:bit in a variety of ways.

My Extensions

DSTemp & DSTemp-2wire

DSTemp official page (or at my GitHub repo)
DSTemp 2-wire officia page (or at my GitHub repo)

As detailed above, these are the two that started my journey into micro:bit MakeCode extensions.

BLE HID

Official page (my GitHub repo)

BLE stands for Bluetooth Low Energy (which the micro:bit’s radio can do) and HID stands for Human Interface Device. This extension allows the micro:bit to act like a programmable bluetooth keyboard, mouse, media controller, game pad, or a combination of them. Here’s a brief demo of some of the ways it can be used:

This extension was originally created in response to a request on a MakeCode forum: “Steering Wheel with McroBit?” [sic], where a micro:bit user wanted to know if they could use their micro:bit as a steering wheel controller. Since I had been working with Bluetooth Low Energy on the Nordic platform long before the micro:bit, my reaction was “Why not???”. The desire / value of this sort of support came up among users, members of the Microbit Education Foundation team, and members of the Microsoft team, such as here and here. Those posts were before the release of the second version of the micro:bit, which was much better suited to supporting this sort of feature due to a combination of additional memory, a better Bluetooth interface, and a faster processor. Of course, it still took moderate effort to make this sort of support available to MakeCode users and reasonably easy to use.

This is my most elaborate extension so far. It required substantial “reengineering” of the underlying runtime (i.e., some mild hacks to do things that were not well supported). This is also one of the one’s I’m the most proud of, but not because of the tech skills involved in creating it…because of the potential uses.

Soon after releasing the initial version of it, it was already being explored as a tool to prototype and create low-cost assistive technology. Thanks to Loreto Dumitrescu, who put together a workshop to share this work! The slides from the workshop can be found here — they include a full walk-through of the concepts and creating/configuring an assistive device. Loreto’s build instructions for a hand-based switch can be found here. And build instructions for my minor variation, which uses a foot based switch, can be found here.

Time & Date

Official page (my GitHub repo)

For several years I helped with summer camp activities that created wearables based on the MakeCode Watch example. These are really great activities: Minimal and cheap materials, easy to assemble, neither too time consuming nor too short, and kids can express their style/personality. The downside was the micro:bit didn’t have blocks to represent “wall-clock time”. And the process of actually showing time by counting seconds was too complex for a novice-friendly camp activity.

In addition to the watch activity, I realized that my continuing interest in data logging and science activities could really benefit from wall-clock time (without the expense of an external hardware real-time clock module). Consequently, I created a set of blocks to support a software based real-time clock. There are definitely some limitations, like losing the time on reset and being dependent on modest clock accuracy of the micro:bit (v1 is pretty good, but v2 can drift by ~4-5 seconds per day).

This extension was a lot of fun to think about. It required both careful consideration of the semantics of representing and interacting with wall-clock time as well as understanding the underlying microprocessor clock facilities.

Button Clicks

Official page (my GitHub repo)

An educator using the micro:bit wanted the ability to detect double clicks and was having trouble coming up with a suitable solution (they solicited ideas via the micro:bit developer Slack).

Since the micro:bit just has two buttons, detecting different types of clicks can substantially improve the ability to interact with it. I wanted the ability to distinguish single clicks, double clicks, and long presses (holds) to support my BLE HID extension. Specifically, I wanted to be able to quickly create media remote controls. For example, I wanted a single click of Button A to be play/pause. A single click of Button B to be next track. A double click of Button A to be volume down; A double click of Button B to be volume up. And holding Button A would be rewind while holding Button B would be fast forward.

Detecting different types of clicks requires tracking the timing of events (when a button is pressed and released, how long it has been since it was released, etc.). A lot of the subtle details of click detection are well-explored in the embedded systems community, especially for consumer electronics, but are not well known to the typical micro:bit audience. Although there is benefit in end users trying to replicate the double-click detection on their own, it seemed like: a) the limited buttons were an impediment to some users’ ability to create things and b) the knowledge needed to support click detection was beyond what could reasonably be expected of many micro:bit users…. so I created a library to simplify the process that’s sufficient for many needs.

(Display) Rotate

Official page (my GitHub repo)

I’ve heard that some K-12 educators want to show how accelerometers are used in cell phones to control the display orientation. Although the micro:bit has some support for rotating its display, this was not well supported in MakeCode. This extension (with the help of updates from the Microbit Education Foundation team — Thanks Martin!) provides a block to change the display orientation and create satisfying examples that rotate dynamically in response to the orientation of the micro:bit.

Air Quality: SEN55

SEN55 official page (or at my GitHub repo)

I was searching for an interesting source of data for my data logging projects as well as a sensor that could help me learn a bit more about PCB manufacturing (specifically, testing JLCPCB’s PCB Assembly — I plan to release the board design as open source too. It’s relatively cheap to manufacture). The Sensirion SEN55 seems like a good fit:

  • It provides the type of data that should be collected over a long term.
  • It provides multiple types of data: Temperature, Relative Humidity, Particle Mass Concentrations, and data on Volatile and Oxidizing gases.
  • It’s got a really simple (I2C) interface, but still has some interfacing challenges (requires 5V power and I2C isn’t accessible via the ring connectors).

BLE Log Access

Pending review for official extension (or at my GitHub repo)

My current work is again focused on data logging applications. The newest version of the micro:bit (v2) includes support for a “data logger“. The data logger blocks allow the micro:bit to accumulate data from long-running experiments/projects, like tracking the temperature in a stream over a week or the sunlight in a school classroom over a few days. It stores the data on the micro:bit. In order to retrieve the data, the micro:bit needs to be connected to a computer. When connected, the micro:bit shows up as a USB drive and users retrieve the data by opening a file on the drive.

Data logging greatly extends the ability of the micro:bit for a lot of STEM applications, but removing it and connecting it to a computer to retrieve the data could be a hinderance for some applications.

My current work is two parts:

  1. A new set of blocks (just one block actually). The current version of the work can be added by using this URL for the extension: https://github.com/bsiever/microbit-pxt-blelog . The block will make the micro:bit appear as a Bluetooth device. (Currently this only works with the beta version of MakeCode: here)
  2. A corresponding set of libraries to retrieve the data. So far, I have created a Web Bluetooth library (here: https://github.com/bsiever/microbit-webblelog). This will allow applications to retrieve the data over Bluetooth. The example includes a simple webpage to retrieve the data and save it as a CSV file (here).

This approach allows longer running data collection, live viewing of data in long running tasks, and deeper “embedding” of the micro:bit. It also has better association of the data with “wall-clock time”, which is really important for many long running data collection tasks. For example, temperature-based work is often strongly influenced by the time of day. Having a clear association between the time of day and each data sample can be helpful.

Longer term plans include development of a mobile app to retrieve/graph the data (Flutter!?!).

Morse Code

Morse official page (or at my GitHub repo)

Thanks to work from others and the possible combination of Morse Code with my BLE HID extension, I decided to try creating an extension that supports keying in, encoding, and decoding Morse code. It also works well with the button press/release semantics provided by the Button Clicks extension described above.

Loreto has developed a great example “two button keyboard”, which can be used as assistive tech for those who are unable to use a regular keyboard. It combined 3D printing, the Morse Code extension and the BLE HID extension. The build details can be found here: Microbit: 2 Button Morse Typewriter.

Flash Storage Access

Not an official extension (my GitHub repo)

In response to a MakeCode Forum post from @mwest226, I created a prototype extension that provides users with access to Flash-based storage with get/put operations that store key/value pairs (strings only). @mwest226 also pointed out memory leaks in my work — thanks!

If there’s sufficient interest I may clean this up and submit it as an official extension, but MWest’s fork may be a better candidate for an official extension!

i2c Pins

Not an official extension (my GitHub repo)

This extension allows the pins used for i2c communication to be redirected. This is especially valuable in some hardware devices that connect to the board via the “holes” (or even alligator clips), which are not the default locations for i2c signals. The Python APIs provided the ability to redirect i2c pins, but MakeCode did not — some accessory developers needed this ability for accessories that did not use an edge connector. (Thanks to MakeKit for inspiring/sponsoring/testing this work)

This is not approved as an official extension because it may have side effects that are not obvious to end users, especially with the V1 micro:bit where it will disable use of the built in accelerometer. None the less, it is stable and there are products that rely on it. Products can include it as a dependency in their custom blocks so end users are not bothered with adding an unofficial extension.

Related (not an Extension)

My GitHub repo

In order to support projects that interact with the micro:bit, I’ve created a WebUSB library that lets simple webpages connect to the micro:bit (over USB) and interact with it via serial communication. Several projects (and at least one company) have adopted this library. After recent changes in the interface chip on the micro:bit v2.2, which changed USB enumeration slightly, I migrated this to be a user-friendly wrapper around DAP.js.

SIGCSE 2016 IoT Workshop

Thanks for participating in our Workshop. Feel free to contact us at any time either via e-mail or connect with us on LinkedIn:

Bill Siever Michael Rogers
bsiever@gmail.com mprogers@mac.com
View Bill Siever's profile on LinkedIn View Bill Siever's profile on LinkedIn

Please download these files:

  1. SIGCSE.zip: SIGCSE Simblee Examples Library
    (GitHub Repository)
  2. Simblee-PulseSensorAmped.zip: Simblee Pulse Sensor Library
    (GitHub Repository)
  3. SimbleeForMobile-BarGraph.zip: Simblee Bar Graph Library
    (GitHub Repository)
  4. SIGCSE_IoT_Exercises.pdf: Guide to the exercises

Please help SIGCSE evaluate workshops by completing this survey at the end of our session:

https://www.surveymonkey.com/r/WFNRGJY

Logging events with on Nordic’s nRF series via Seger’s J-Link Real-Time Terminal

One of the most most common debugging techniques is “logging”, or creating a history of what happens while code runs.  Logging can be especially difficult in embedded systems, which often lack a natural way to log events, like a console.  Commonly UARTs are used to log messages via a serial port, but this approach can consume significant run-time that may undermine the timing constraints of the software. It also requires the use of additional pins to support development.

I’ve found it especially difficult to debug applications using Nordic’s Bluetooth Low Energy products (nRF family).  Fortunately, due to some helpful hints by fellow Nordic developers (Thanks Jeremy) and great products from Segger, I’ve got a solution that suits my needs fairly well. Segger’s Real-Time Terminal is a perfect solution to the problem. I’ve taken the example’s provided by Segger and made a package from them (easier to configure on multiple projects). I’ve also added some wrapper functions that provide additional data I find helpful when debugging.

The following explains how to setup a logger for the nRF series of chips, but assumes that:

  1. You are using a Segger J-Link (I’m using the J-Link CortexM)
  2. You are using Keil MDK v5 or later,which uses Software Packs.

This guide is broken into three distinct phases:

  1. Installing the Logging Package and updating the Keil’s IDE to easily connect to Segger’s Log Viewer
  2. Configuring a project to use the Logging functions
  3. A quick demo of actual use

 

Installing the Logging Package and updating the Keil

These steps should only need to be performed once.

    1. Install the latest version of Segger’s J-Link: https://www.segger.com/jlink-software.html?step=1&file=JLink_496a.

 

  1. Install the Software Package I created for Logging
    1. Download Siever.Segger_RTT_Logger.1.0.1.pack. (It works with any system that Segger’s RTT supports, not just Nordic)
    2. Double click on the package. It should automatically install via Keil’s Package Installer.
  2. Update Keil’s Tools menu to allow easy access to the Log Viewer (which is the window you will use to view log messages).
    1. Open Keil.
    2. Select Tools → Customize Tools Menu... from the menu:

      1_AddCustomEntry
    3. Add a new entry for the Log Viewer. When done it should look something like:
      2_LogViewerEntryDetails

      There are a few things to notice here:

      • I typed Log Viewer in the first available slot. This will be the name of the new item on the Tools menu.
      • The Command is the JLinkRTTViewer.exe. Verify that the path is correct for your installation.
      • Note that Run Independent is checked.

    The Tools menu should now have a new item that will be used to launcher the Log Viewer.


Configuring a project to use the Logging functions

You will need to do this for each project on which you want to use these logging functions.

    1. Open the Project
    2. Select the Logger Package for inclusion in the project. Select Project → Manage → Select Software Packs...:

      1_AddPack
    3. Select the newly added Logger Package and set the version to fixed:

      2_SelectPackToAdd_1.0.1

 

  1. Add the Pack to the Run-Time Environment. Select Project → Manage → Run-Time Environment...:

    3_AddPackToRunTime
  2. Ensure that the package will be included at Run-Time. Expand it and make sure it is selected:

    4_ExpandLoggerPackAndSelect_1.0.1
  3. The package will need to be enabled via a define. Add the define to the project’s Preprocessor Symbols.
    1. Select Project → Options For Target...:

      OptionsForTarget
    2. Navigate to the C/C++ tab and add RTT_LOG_ENABLED to the Defines:

      AddDefine

Demo of Use

In order to use the logging functions you will need to add calls to the logging functions to your code. You can use primitive functions provided by Segger, but I choose to use my own wrappers. In order to use my wrappers you will need to include the header file:


6_AddIncludeWhereNeeded

and insert calls into your code. I’ve provided three functions that each have printf semantics (and each call Segger’s SEGGER_RTT_vprintf()). My functions are:

loge(…)
Used for logging run-time errors (shown in red)
logw(…)
Used for logging warnings (shown in yellow)
logi(…)
Used for logging general information (shown in white)

Here are some examples in code:


7_AddLogMessages
I generally start a debugging session and then launch the Log Viewer via the item added to the Tools menu:


3_UpdatesMenu Launching

The Log Viewer you will ask how it should connect to a debugger session. When being run with an existing debugging session just indicate it should connect to the debugging session:


4_LaunchSettings

Here’s an example of the log generated by the three examples shown above:


RunAndDebug

Notice that:

  • The different warning styles are color coded.
  • The log macros I’ve created insert the file name and line number. This does consume additional flash memory, so don’t get too carried away with log messages.
  • Currently I have all log messages going to the tab for Terminal 0. It would be easy to update the approach to include different messages to different terminal tabs for different modules.

Disclaimers

This work is provided as-is with no warranty or guarantee of any sort. I’m new to Segger’s RTT and haven’t done any review of performance issues. I’m also new to CMSIS Packages and haven’t verified that I’ve followed all appropriate package conventions. At this point this is an alpha version, but any input or suggestions are welcome. The log macros were made for my needs when I developed them and may not suite other’s needs. The formatting used for them could certainly be improved.

Credits

The package includes unmodified code provided by Segger at: http://download.segger.com/J-Link/RTT/RTT_Implementation_141217.zip. Code by Segger includes a copyright notice, but they have given me permission to share the package.