Do IoT yourself in 20 minutes

In this post, I would like to show you the steps for controlling your first device via HTTP.

Requirements

Let’s start

“I would like my air conditioner to detect when I’m heading home, and turn itself on if the weather is hot”. This is a nice project and it’s totally feasible. But, instead of starting with this, let’s split the problem:

  • It’s not hard to create an app for our phones that “detects” when we are heading home, but it would be out of the scope of what I want to help you with.
  • There are different ways of detecting if the weather is hot or not. We could use the same phone app to consume this info from a web-service, or we could use a thermometer sensor on our Arduino board. We will go through the second option so we can include this in the scope of our project.
  • Before blowing up our air conditioner device (which is fairly expensive), why don’t we start with something simpler and cheaper? For this project we will be using a 9V fan. Since Arduino is capable of delivering 3.3V and 5V, we will need a relay and a 9V battery as well. This is intentional so we can emulate the behavior at the moment we want to connect a device that requires 110~220V (it’s just about changing the power source and the relay). Note: It is not recommended that you work on projects with higher voltages unless you are a professional. Not being cautious enough could result in serious injuries or worse.

Minimum Viable Product

Let’s start with a simpler version of our project. We have a temperature sensor and a fan. If the temperature is higher than a threshold, the fan starts. Take a look at the following sketch (you can run it, see the code and display the circuits if needed).

Connecting your device

Now we can wire the previous sketch over the Arduino ethernet shield. Our project will work exactly the same way, but we will be able to connect an ethernet cable to it.

Once that’s done, we are really not that far from our remotely controlled device. Our next steps would be:

  • To develop a WebServer for Arduino
  • To create a URL parser
  • To code the set of Handlers and the Dispatcher (so we can wire a URL with a piece of code)

It sounds like a lot of work, but let’s make things simpler with Nobel.
Nobel is a tiny code generator capable of writing an Arduino application that exposes an API based on a simple representation written in Swagger or RAML. I’ll be using Swagger for the example.

Installing Nobel

Installing Nobel is extremely easy. Just open a terminal and type: npm install -g nobel . That’s it.

Modeling the API

The API definition for our project is really simple. We have only one resource (the fan) and two actions (on and off) that we can represent with the HTTP methods POST and DELETE. You can write the Swagger code in any text editor. My favorite one is http://editor.swagger.io/#/ since it lets me validate the syntax and see documentation in real time. The following code turns out to be a fairly accurate Swagger representation of what we described on the last paragraph:

swagger: "2.0"
info:
  version: "0.0.1"
  title: TemperatureController
paths:
  /fan:
    post:
      description: |
        Turns the fan on
      responses:
        200:
          description: Successful response
    delete:
      description: |
        Turns the fan off
      responses:
        200:
          description: Successful response

Once we are sure that your API is correct, save this into a file. Let’s use the same name for this project: temperature-controller.yaml

Generating the code

Generating the code is almost as easy as installing nobel. On your terminal type: nobel -s temperature-controller.yaml -n temperatureController

You might want to check the complete documentation later but it is important that you pay attention to a detail if this is the first time you are working with Nobel: Have Nobel installing libraries for me.

Adding the desired logic

You will find the generated code on a folder with the project name, and 5 files inside. Open C_handlers.ino with your favorite text editor:

// Handlers
void fanHandler(WebServer &server, WebServer::ConnectionType verb, String uriParams, String queryParams) {
  switch (verb)
    {
    case WebServer::POST:
        server.httpSuccess();
        break;
    case WebServer::DELETE:
        server.httpSuccess();
        break;
    
    default:
        server.httpFail();
    }
}

All the API logic is distributed on the generated code so the remaining thing to do is to add the desired logic on each handler. For the POST case, we want to add the following code (before the server.httpSuccess() line):

float temperatureC = measure();
if (temperatureC > 24) {  // Setting this to 24 since the emulator sets a temperature of 24.71C
  digitalWrite(fan, HIGH);    
}

We will do it similarly for the DELETE case but we are only adding this line:

digitalWrite(fan, LOW);

We are almost done. As you can see on the code of the MVP, the measure function, and fan and temp variables are declared and initialized. This is the reason why the generated code also created the files B_Definitions.ino and D_Initialization.ino. Take a look at this section in the documentation for more details. For now, let’s add this code:

B_Definitions.ino


int fan = 9;   // Fan controlled by a Relay connected to the PIN 9
int temp = 0;  // Thermometer connected to the pin A0

float measure() {
  int reading = analogRead(temp);
  float voltage = reading * 5.0;
  voltage /= 1024.0; 
  return ((voltage - 0.5) * 100) ;
}

D_Initialization.ino (inside the setup function)


pinMode(fan, OUTPUT);    // initialize the digital pin as an output.

Follow these instructions to deploy and test your code and once you feel comfortable, save some money for a new air conditioner.

Leave a Reply

Your email address will not be published. Required fields are marked *