Scott Hanselman

Arduino 101 with an Intel Edison - Hooking up JSON to an LCD Screen

March 10, '15 Comments [20] Posted in Hardware | Open Source
Sponsored By
Playing with Arduino and Nightscout

Hanselminutes and CodeNewbie are teaming up to produce two new podcast episodes a week for the month of March, featuring incredible makers in the hardware space. There will be new content every weekday in March, so bookmark http://www.marchisformakers.com and join us!

  • CodeNewbie is the most supportive community of programmers and people learning to code. Tune in every week for stories about people on their coding journey.
  • Hanselminutes: Fresh Air for Developers is a weekly talk show that brings interesting people together to talk about the web, culture, education, technology and more.

Our hashtag for this event is #MarchIsForMakers and YOU, Dear Reader, can help us out by being our Street Team.

Share our website http://marchisformakers.com!

...with friends, kids, teachers, family, anyone you think my be benefit from learning about hardware and today's maker culture.

This is Week 2! At the end of March we'll have as many as 10 great podcasts, amazing guests, Live Google Hangouts, blog posts, Twitter Chats on Wednesdays, and a huge collection of links and projects for you to explore.


Please note that I'm learning. I'm sure some of you are fantastic experts, while others are working on Hello World. If you find errors, naïve or otherwise, in my code or solution, DO let me know in the comments and I'll update this post with notes and asides so we can all learn!

I wanted to learn a little about Arduino this week. It's an huge and enthusiastic community based around an open-source electronics platform. The hardware is small and relatively inexpensive, and it brings hardware hacking to folks (like myself) that may not feel up to doing really low level electronics work. There or stackable "shields" you can plug on top and easily add new features, screens, sensors, and more.

Arduino_Uno_-_R3

There's lots of different choices for Arduino development, including some more interesting versions like the Intel Edison with Arduino Breakout Board. The Intel Edison supports not just Arduino, but also can run a full version of Yocto Linux, and can run Python and node.js. I have an older Arduino Atmega328 which was like $12.99, but I wanted a more flexible option that included on board Wi-Fi. Getting Wi-Fi connectivity is kind of a hassle if it's not built in.

The Arduino Yún is a great choice, but I figured I'd spend more for the Edison and get a lot more options. I also got the "Seeed Studio Grove Starter Kit." This is a cool Arduino Shield that lets me (and the kids) attached sensors, buttons, screens, and lots of other stuff without soldering!

intel-lot-edition-gen2

I download the Arduino software, but also found that Intel now has a complete Integrated IoT Windows 64 Installer that will get everything you need to get started with the Intel Edison. It makes it REALLY easy to start.

I tried a few small "Sketches" out, turning on a light with a button press, and such.

image

But I wanted to make something more interesting to me personally. I'm a Type 1 Diabetic, and I wear an insulin pump and Dexcom Continuous Glucose Meter. They are connected to the cloud via a project called Nightscout.  Nightscout takes my sugar values and pushes them into Azure, where they are available via a JSON web service.

NOTE: I've put my Arduino Sketch on GitHub here. https://github.com/shanselman/NightscoutArduinoPlayground

Nightscout has a /pebble endpoint that is used to feed the Pebble Watch Face and show folks their blood sugar on their wrist. I thought it would be cool to hook up an Arduino to get my blood sugar from the cloud and display it on an LCD. It'll show the current value, change the background to green/yellow/red to display risk, and then a custom character to show trends (flat, up, down, etc).

The JSON the Nightscout service returns looks like this, but I just want the "sgv" value and the "direction."

{
status: [{
now: 1426017007130
}],
bgs: [{
sgv: "102",
bgdelta: 2,
trend: 4,
direction: "Flat",
datetime: 1426016912000,
filtered: 115232,
unfiltered: 118368,
noise: 1,
rssi: 191,
battery: "59"
}]
}

I needed to bring in three libraries to achieve my goal. Remember I want to:

  • Connect to my Wi-Fi network
  • Download some JSON and parse it
  • Display values on an LCD screen

So I needed:

As with all problems when you're learning new things, you'll want to break them down one at a time.

I wanted to just display a string on the LCD, that was easy, there's lots of examples online in the Arduino community.

lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Hello World");

Connecting to Wi-Fi was pretty easy also:

while (status != WL_CONNECTED) {
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(ssid, pass);

// wait 3 seconds for connection:
lcd.setCursor(0, 0);
lcd.print("Waiting...");
delay(3000);
}

When doing an HTTP call (given the libraries I was learning about) it's pretty low level. Constrained memory Arduinos (not like the Edison) don't seem to have SSL support, nor do they have high-level HTTP libraries. I had to craft the HTTP headers manually:

lcd.print("Connecting...");
if (client.connect(server, 80)) {
lcd.clear();
lcd.print("Server connected");
// Make a HTTP request:
client.println("GET /pebble HTTP/1.1");
client.println("Host: hanselsugars");
client.println("Connection: close");
client.println();
}

Then I spin through the HTTP Response looking for the start of the JSON, and store it away. At this point I'm wondering if I'm doing it wrong. It isn't very robust.

boolean jsonFound = false;
int bytes = 0;
while (client.available()) {
char c = client.read();
//look for first {, yes it could be in a cookie but I'm thinking positively.
if (c == '{') jsonFound = true;
if (!jsonFound) continue;

stringBuffer[bytes++] = c;
if (bytes >= MAXBUFFER) break; //that's all we have room for or we're done
}

Then once I've got the stringBuffer, I use the aJSON library to get the values I need. This isn't pretty, but it's how you use this library.

I also added a little bit to turn the color of the screen red/green/yellow.

if (root != NULL) {
aJsonObject* bgs = aJson.getObjectItem(root, "bgs");
if (bgs != NULL) {
aJsonObject* def = aJson.getArrayItem(bgs, 0);
if (def != NULL) {
aJsonObject* sgv = aJson.getObjectItem(def, "sgv");
String bg = sgv->valuestring;
int bgInt = bg.toInt();
if (bgInt > 180) lcd.setRGB(255, 0, 0);
if (bgInt > 150 && bgInt <= 180) lcd.setRGB(255, 255, 0);
if (bgInt <= 150) lcd.setRGB(0, 255, 0);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Glucose (mg/dl)");
lcd.setCursor(0, 1);
lcd.print(bg);
}

I also created some custom characters to show trends, based on a string (pretending to be an enum) that comes back from the JSON service. For example, an up arrow:

byte SingleUp[8] = {
B00000,
B00100,
B01110,
B10101,
B00100,
B00100,
B00100,
B00000
};

All the questionable code is up at https://github.com/shanselman/NightscoutArduinoPlayground

At this point I'm confused/learning about a few things:

  • It runs for a while and then stops.
    • I don't know what state it's in.
    • I would like it to call out to the web service every 5 min and update the LCD. I suspect I am not managing Wi-Fi connection state correctly (as in, not at all).
    • So the question is, how does one take a working prototype and turn it into a real appliance that can run forever?
  • I'm reusing the stringBuffer which is a bad idea. I need to clear it out.
  • Sometimes the Custom Characters are corrupted on the screen.
    • No idea why. It works 8 out of 10 times. Perhaps it's an Edison bug or a SeeedStudio bug.

When I get it working reliably, I'd like to 3D Print a case and mount it somewhere. :)

Arduino for Visual Studio

One other thing I found out, there's a fantastic add-in for Visual Studio that will give you a great Arduino Development Environment inside of Visual Studio. It includes simple debugging, breakpoints, a nice serial monitor and more. I'm still finding debugging to be challenging as local watches and step over isn't supported, but it's vastly superior to the tiny Arduino IDE.

Visual Micro - Arduino for Visual Studio

Arduino Emulator

Don't have an Arduino or a breadboard? Check out http://123d.circuits.io online. It's amazing. It's an Arduino Circuit Simulator online. Check this out!

image

You can setup boards, write code, and practice in software before you test it out on hardware.

image

Don't forget, visit http://marchisformakers.com, tell your friends and tweet us at #MarchIsForMakers!


Sponsor: Big thanks to Aspose for sponsoring the blog feed this week! Are you working with Files? Aspose.Total for .NET has all the APIs you need to create, manipulate and convert Microsoft Office documents and many other formats in your applications. Start a free trial today.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb
Tuesday, 10 March 2015 22:22:16 UTC
I am goin g to start with something simpler, and looks like I will build cool desktop lamp ;)
Wednesday, 11 March 2015 01:15:24 UTC
I'm pretty sure "while (client.available())" is where the problem is. If I understand correctly, "available" only indicates there are bytes that have already arrived from the server, so "!available()" is not the same as "done".

If that's right, then you'd need to completely change "loop" to be a state machine. While the socket is connected, you'd want to read available data and then return. Only process the data when the socket is disconnected. Note that you should send the "Connection: close" header so that the server will actually close the socket.

Reliable HTTP connection management is quite a bit more complex. For a truly reliable client, you'd have to implement some form of no-response timeout at least to avoid the half-open problem.
Wednesday, 11 March 2015 01:17:58 UTC
Thanks Stephen! Interesting, I will need to look into it more because that specific line actually CAME in the library examples for the Wifi.h. Perhaps I am doing it wrong. http://arduino.cc/en/Reference/ClientAvailable
Scott Hanselman
Wednesday, 11 March 2015 02:22:14 UTC
I don't have an Intel Edison or a Wi-Fi shield for Arduino but Could I use a Raspberry Pi instead for the Wi-Fi component?
Sara
Wednesday, 11 March 2015 04:52:53 UTC
Hey Scott how can we download the March Is For Makers podcasts as MP3? I can't see the option.
Tom
Wednesday, 11 March 2015 05:09:14 UTC
The Galileo is a little bit of a wacky Arduino since it's really an Intel processor running Linux, and not a little AVR microcontroller running code bare metal (like the Arduino Uno, Leonardo, etc.). You probably want to check out the Galileo forums to see what folks do for debugging, getting robust wifi code, etc. Using the Arduino ethernet library examples could be painful since those examples are really simple and not super robust (they need to run on a CPU with only 2 kilobytes of memory and 32 kilobytes of program space so they don't have much space for error handling, etc).

Since you're using a Galileo and it has a full Linux environment available you might look into putting all the complex logic like talking to web services, parsing text, etc. into a process you run yourself in Linux. Something like a python, node.js, etc. script that talks to the web service and sends/receives data with the Arduino sketch would be a lot easier and save you the pain of writing all the code to do HTTP requests, etc. I'm not sure off-hand what ways you can use to communicate between the Arduino sketch and your own scripts, but check the Galileo forums to see if there are some examples.

And yep a Raspberry Pi could work to do something like query a web service and display data on a small LCD. Here's an example of how to use python on a Raspberry Pi to talk to an LCD.
Tony
Wednesday, 11 March 2015 13:50:01 UTC
One of the benefits of Arduino was that his processor was real time , so it was better than OS based processors that cant work for real time applications , so I wounder after installing linux if Arduino lost its cause of being the real time processor
Sam
Wednesday, 11 March 2015 15:18:42 UTC
Wouldn't it be a little simpler with Galileo or Yun if you move your cloud web request say to a simple Python script which would also parse the response and send data to the Arduino controller simple sketch that would display it on LCD.

Then crontab your python script to run every 5-10 mins.

Something similar to what the following guy did:
www.jeremyblum.com/2014/01/06/epaper-weather-station/

I was able to replicate this ePaper project on Yun and it works without any issues so far...
Alex S
Wednesday, 11 March 2015 15:58:22 UTC
It's usually obvious when the Cloud-to-Butt extension has worked its magic but this had me wondering for a couple of seconds:
[...] I wear an insulin pump and Dexcom Continuous Glucose Meter. They are connected to my butt via a project called Nightscout.
Tim Burga
Wednesday, 11 March 2015 17:54:47 UTC
Sara - Sure, but a Raspberry Pi is a more capable machine. You could use a higher-level language like Python to call out. Then get a LCD screen like this, specific to the Pi: http://www.adafruit.com/product/1115

Tom - They are all at either hanselminutes.com or at codenewbie.org/podcast

Tony - This is an Edison, is that very different from a Galileo? Yes, I totally get that I'm using an overpowered Intel as an Arduino (my other Arduino is being used on another project). I should probably have used a YUN, or as you rightfully say, used a higher level language. Thanks for your comment!

Alex - Yes it likely would! I should take a look and see if there are Python libraries for the LCD screen I'd like to use. I realize this could be a simple script, but I also wanted to see how it works on a Arduino using their lower level constructs.
Scott Hanselman
Wednesday, 11 March 2015 19:27:27 UTC
Right, for pure Arduino sketch it's really tough nut to crack sometimes, especially with that amount of memory available on controller side.

Also you wouldn't need python library for LCD as it would still stay at the Arduino controller side and you just need to modify/minify your Arduino c-program to be able to get data from Python script somehow and display it... (Sorry if it's not a clear explanation, I am really bad at it)
Alex S
Wednesday, 11 March 2015 20:56:12 UTC
Great work!

I'm sad you didn't use ArduinoJson instead of aJson :-(

Maybe next time ;-)
Wednesday, 11 March 2015 21:59:16 UTC
Benoit - Hey! I tried! I did, it was my first choice. I couldn't figure out how to get the "sgv" value from https://hanselsugars.azurewebsites.net/pebble so I gave up. Ideas?
Scott Hanselman
Thursday, 12 March 2015 06:47:47 UTC
Hi Scott,

love the #MarchIsForMakers initiative!
Definitely sparked my intereset in the maker game (again) and I unburied my Arduino kit yesterday.

Out of personal interest: did you run the Arduino IDE on one of your High DPI machines? I did so on my Yoga 2 Pro and the experience is very poor. Any ideas, advice on that?
Thursday, 12 March 2015 09:18:28 UTC
Scott, I figured out why you couldn't use ArduinoJson.
The Nightscout data is not standard JSON per se as it doesn't have quotes around object's member names.
Unfortunately ArduinoJson doesn't support this yet, but soon it should.
Thursday, 12 March 2015 19:37:53 UTC
Scott, thanks for pointing to the simulator website! That saved me from buying (and probably burning) my first circuits :)
Azat Sattarov
Sunday, 22 March 2015 13:23:58 UTC
You might be interested in a simpler way of getting the odd value from a JSON string in straight C... http://www.codeproject.com/Articles/885389/jRead-an-in-place-JSON-element-reader

You could get the sgv and direction values with 2 calls:

int sgv= jRead_int( jsonBuffer, "{'bgs' [0 {'sgv'");

char direction[32]; jRead_string( jsonBuffer, "{'bgs' [0 {'direction'", direction, 32 );

Yours,
TonyWilk
TonyWilk
Thursday, 02 April 2015 13:21:49 UTC
You might be interested in trying the Netduino (http://www.netduino.com/). Someone gave a talk on it at our .NET User Group lately and I think you could write C# and debug from Visual Studio, which was pretty amazing!
Jeffrey Bridgman
Saturday, 04 April 2015 10:17:31 UTC
Great work!
Thursday, 23 April 2015 19:03:13 UTC
Hi!

Thank you for this great review and the interesting pointers.

Similar to Visual Micro for Visual Studio on Windows, there's embedXcode for Xcode that runs on Mac OS X.

It supports both the Wiring / Arduino framework and native applications for Yocto on the Intel Edison board.

Learn more at http://embedxcode.weebly.com
Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.