Who needs breadboards? With the new SOMRT1061 development board’s Qwiic connector, adding off-the-shelf I2C devices and libraries to your prototypes has never been easier!
You might not have noticed it in our recent NNDK release notes, but we’ve been hard at work retooling our I2C library to make use of the friendly Wire interface commonly used by other microcontroller platforms. Why? Because with the release of our new SOMRT1061 development kit and its Qwiic I2C connector, it’s now possible to buy a device from a popular website like SparkFun and have it running on your NetBurner device in minutes! Your next ARM-powered Industrial IoT project can come together faster than ever with a wide assortment of affordable, reusable, plug-and-play modules.
The Project
What’s the best way to demonstrate these new capabilities? Let’s keep it as simple as possible: this tutorial combines our Earthquake WebClient example that makes use of our elegant ParsedJsonDataSet library, with new Qwiic I2C examples for an OLED Display and a 12-button Keypad, both from SparkFun. A little bit of glue code to push the data where we want it, a few inputs and outputs, and we’re done!
Code in this blog post and associated GitHub repository are copyright NetBurner, Inc, and covered by the NetBurner license: see the NNDK license that came with your product for more details. Some included files are provided by SparkFun and have their own copyright notices. Arduino is a trademark of Arduino SA, but this tutorial contains no Arduino code: the included Arduino.h file enables compatibility with common libraries only, and is named as such only to enable that compatibility. The NetBurner logo included in this project’s 3D files is a trademark of NetBurner.
Getting Started with Qwiic
Qwiic is an open standard created by SparkFun to easily connect I2C devices without breadboards or soldering.
In this example, we’ll use their 1.3″ Qwiic OLED Display and 12-button Qwiic Keypad, but you can theoretically use any Qwiic product in their catalogue. If we don’t have an example for it, our examples can be used as a guide for implementing the product’s library in your NetBurner project. We’ve done our best to make the Wire object as close as possible to other platforms, and make a compatibility layer for the most common objects and functions found in Arduino.h. Advanced components may require more work, like audio codecs, radios, or sensors, but the foundation is here!
3D Printed Project Box
To really bring a proof-of-concept home in a nice way, we’ve also put together a 3D-printable enclosure for our SOMRT1061 dev kit that exposes all the ports, plus cutouts for the screen and keypad we’ll be using. It’s made in the highly-customizable OpenSCAD with the help of the YAPP project box library, so we hope you’ll find it useful in a variety of ways! The cutouts for the header pins are ready to use, just commented out in favor of the screen and keypad cutouts we’ll be using for this post. Please use and modify to your heart’s content!
Bill of Materials
- Qty 1: SOMRT1061 Dev Kit (Dev Board, SOMRT1061 on carrier board, USB cable, Ethernet cable)
- Qty 1: SparkFun 1.3″ Qwiic OLED Display
- Qty 1: SparkFun 12-button Qwiic Keypad
- Qty 2: Qwiic cables (ideally 100mm)
For the 3D printed enclosure:
- The enclosure itself (see the Readme on GitHub)
- Qty 8: Heat-set M3 inserts for plastic
- Qty 4: M3x4 socket-cap screws
- Qty 3: M3x8 socket-cap screws
- Qty 9: 1-inch long cut sections of clear 1.75mm plastic filament, and clear glue (optional)
- If printing with the default OpenSCAD settings with the outputWifi option set to true (for the optional NBEXP-WIFI-INIR WiFi expansion module):
- Qty 1: M3x20 socket-cap screw
- Qty 1: the 11mm printed cylindrical spacer in the 3D file
- Otherwise, print and generate an STL with outputWifi set to false and use:
- Qty 1: an additional M3x8 socket-cap screw
- No spacer needed
- Soldering iron or other heated tip for the M3 inserts
- Appropriate hex key or bit for the M3 screws
The Code
Please download the code from our GitHub repository and copy-paste the files onto a new NetBurner project created with NBEclipse and configured with your SOMRT1061’s IP address.
To summarize, the real glue holding this project together is a compatibility layer that implements common APIs that these Qwiic and other Wire I2C devices expect. So for example we have a file called Arduino.h which just contains thin wrappers over standard NetBurner function calls:
// Arduino.h
// NetBurner "Arduino Compatibility" Shim
#ifndef _NB_ARDUINO
#define _NB_ARDUINO
#include
#include
#include
#include
#include
#include
#include
typedef bool boolean;
typedef uint8_t byte;
#define PI 3.1415926535
static inline void delay(int x)
{
if (x > (1000/TICKS_PER_SECOND)) { OSTimeDly(x/TICKS_PER_SECOND+1); }
else for (volatile int i = 0; i < x*100000; i++);
}
static inline int min(const int a, const int b) {
return a < b ? a : b;
}
static inline int max(const int a, const int b) {
return a > b ? a : b;
}
static inline long map(long x, long in_min, long in_max, long out_min, long out_max)
{
long outD = (out_max - out_min);
long inR = (x - in_min);
long inD = (in_max - in_min);
return outD*inR/inD+out_min;
}
static inline unsigned long millis() {
return Secs*1000;
}
class String : public NBString
{
public:
String(){};
/**
* @brief Construct a new NBString object from an existing NBString object
*
* @param str Existing NBString object
*/
String(const NBString &str) :NBString(str) {};
/**
* @brief Construct a new NBString object from a substring of an existing NBString object.
*
* @param str Existing NBString object
* @param pos Starting position to copy
* @param len Ending position to copy
*/
String(const NBString &str, size_t pos, size_t len = npos) :NBString(str,pos,len) {};
/**
* @brief Construct a NBString object from a character string (null terminated array of characters)
*
* @param s String to initialize object
*/
String(const char *s) :NBString(s) {};
/**
* @brief Construct a NBString object from a character string up to the specified amount
*
* @param s String to initialize object
* @param n Number of characters to copy
*/
String(const char *s, size_t n) : NBString(s,n){};
String(uint32_t v) {siprintf("%lu",v); };
String(uint16_t v) {siprintf("%u",v); };
String(uint8_t v) {siprintf("%u",v); };
String(int32_t v) {siprintf("%ld",v); };
String(int16_t v) {siprintf("%d",v); };
};
#define HEX (16)
#define DEC (10)
#define OCT (8)
#define BIN (2)
class Print
{
size_t handle_unum(uint32_t v, int base)
{
NBString s;
switch(base)
{
case 16: s.siprintf("%lX",v); break;
case 10: s.siprintf("%ld",v); break;
case 8: s.siprintf("%lo",v); break;
case 2: s.siprintf("%b",v); break;
default:return 0;
}
return print((const NBString)s); // (uint8_t *)s.c_str(),s.length()
}
size_t handle_inum(int32_t v, int base)
{
if(v<0)
{
return write((uint8_t)'-')+handle_unum((uint32_t)-v,base);
}
return handle_unum((uint32_t)v,base);
}
public:
virtual size_t write(uint8_t c)=0; // Pure virtual, must be implemented precisely by children
virtual size_t write(const uint8_t *buffer, size_t size=0){ size_t i=0; while(i
And a few more header files to implement some other expected variables:
// src/avr/pgmspace.h
// shim for ARM
#define PROGMEM
#define pgm_read_byte *
// src/pgmspace.h
// shim for non-ARM
#define PROGMEM
#define pgm_read_byte *
And believe it or not, with those files in place it’s now easy to copy-paste I2C Wire code examples into our project! SparkFun’s qwiic_* cpp and h files can live next to our main.cpp file in the src folder, and resources like qw_* headers, bitmaps, and fonts can live in the src/res subfolder.
Obviously there’s a lot to a complete program, so review the complete code on GitHub, but here’s a short overview of the functions necessary to initialize and use the I2C Wire interface and Qwiic devices; this program simply displays keypad characters on the OLED display:
// main.cpp
#include
#include
#include
#include
#include
#include "res/qwiic_resdef.h"
// ...snip...
SerialIf Serial;
TwoWire Wire;
Qwiic1in3OLED myOLED;
QwiicFont *pFont;
KEYPAD key;
// ...snip...
void UserMain(void *pd)
{
init();
Wire.begin();
myOLED.begin();
key.begin();
while (1) {
uint8_t rv=key.getButton();
key.updateFIFO();
if (rv>0) {
myOLED.erase();
myOLED.setCursor(0, 0);
myOLED.print((char)rv);
myOLED.display();
}
OSTimeDly(1);
}
}
Flashing the Complete Program
Primary network interface configured for DHCP MAC Address = 00:03:f4:12:34:56 Type "A" to abort boot Application: QwiicBlogExample NNDK Revision: 3.5.2 Time Set Running OLED Earthquake example OLED begin success. Keypad begin success. Keypad is connected. Got 4 quakes: 0 ago - 4.9 4 km E of Limones, Panama 1 ago - 5.6 13 km SE of Manaca Civil, Panama 2 ago - 5.7 5 km SSE of Puerto Armuelles, Panama 4 ago - 4.6 70 km SW of Cañete, ChileDon’t forget to connect up your Qwiic keypad and screen! Qwiic (and I2C) are usually daisy chainable in any orientation, so multiple devices can be connected in a row:
3D Printing
Time to make a nice project box for your prototype!
Check out the 3d-printed-enclosure subfolder on GitHub for the printable files. You can try loading the STL into a slicer directly, but we suggest opening the SCAD file in OpenSCAD and poking around first. There are also test-sample files available, which you can use as calibration examples to test your printer and OpenSCAD settings on a smaller model before copying those settings to the larger model, saving time and plastic.
Case Assembly
Here are all of the necessary parts laid out:
After a successful print that passes a fit check, we start by installing the heat-set inserts with a soldering iron or other hot tip set to about 300 degrees Celsius. (PLA plastic melts at about 210 degrees C, but we also need to heat up the brass insert in a timely manner.) The taller posts can be installed with a regular-tipped iron. Shorter posts may benefit from the tip applied sideways to avoid hitting the plastic underneath, or by using a specialized tip for the purpose:
The cut pieces of clear filament are inserted into the light tubes and optionally secured with a dot of clear glue:
The button posts can also be installed through the hollow flanges labeled RST and IRQ. The button caps snap-fit onto the ends of the posts, so if the fit is slightly off they can be sanded or glued to attach securely, or reprinted with different settings based on your printer:
The 3D printed straps can then be screwed in place with short M3 screws to hold the Qwiic keypad and screen:
Almost done! Connect another Qwiic wire between the lid components and the Dev Board. The cable can either be connected through the outside and routed in through the WiFi slot, or it can be looped back around directly inside the enclosure base using the extra space in the Qwiic cutout:
If using the WiFi module, it can now be installed above the Qwiic connector. The 11mm 3D printed spacer can be used to support the space between both circuit boards. Note that the WiFi module takes extra power, so it may be a good time to check if your computer’s USB port provides enough power, and switch ports or use an external charger if not:
And we’re ready to put it all together! Fold the top half on top of the bottom half, routing the Qwiic wire underneath the WiFi module as you go. You can place the long M3 screw underneath to hold things in place if you want. The two halves should fit neatly together with no forcing or pinched cables:
Finally the bottom screws can be secured:
And you’re done! Plug in power and Ethernet, and the most recent data from USGS.gov will appear. Press 8 to scroll “down”, 2 to scroll “up”, and # to get new data:
Wrap-up
Not only is the SOMRT1061 an exciting new platform with tons of capability packed into a small package, we’ve also loaded the SOMRT1061 Development Kit full of ways to quickly and easily bring your ideas to life. Whether it’s the convenient Qwiic I2C system, onboard A2D, easy WiFi header, USB OTG ports, RTC, multiple CAN and UARTs, the fun RGB LED, or the flexible develop-prototype-production SOMRT1061 form factor, we hope NetBurner’s new products empower you like never before.
If you have any questions or feedback about this blog post or our products, please check out our Forums or contact us at [email protected] or [email protected] !







