Skip to main content

Week 3: Arduino to screen and posting to API

Recap

Last week we built RESTful clients to connect to our server and request data from sensors dotted around the classroom. We added setInterval functions to capture dynamic data over time, and briefly explored how JavaScript handles asynchronous and unpredictable interactions.

What you may not have worked out is that the server we used was not actually connected to the sensors. Instead, each of the sensors was connected to another client computer like yours – except these clients were sending data to the server using HTTP (POST).

Today

We are going to focus on sending data from our Arduino through Node.js, firstly directly to the browser where it can be visualised and then to an API where it will be stored and accessible across the network.

Exercise 1: Send Arduino data to a browser

In this part of the workshop, we will be aiming to control the RGB colour of a web page using three dials on an Arduino; one each for red, green, and blue.

We will build up to this in stages, some of which should be familiar from previous workshops.

Project Structure

Before we start, it is a good idea to create a new directory and project structure:

├── projectName/ (CHANGE THIS)
     ├── client/
     │   └── index.html
     ├── server/
     │   ├── package.json
     │   └── app.js
     └── hardware/

1. Wire up three potentiometers to three analog pins

Connect three potentiometers as shown in the diagram below.

3 Potentiometers

2. Upload the Arduino code

The Arduino code reads each of the three analog pins and sends the values to the serial port.

#define r A0
#define g A1
#define b A2

void setup() {
  Serial.begin( 9600 );
  pinMode( r, INPUT );
  pinMode( g, INPUT );
  pinMode( b, INPUT );
}

void loop() {
  Serial.print( map( analogRead( r ), 0, 1023, 0, 255 ) );
  Serial.print( ',' );
  Serial.print( map( analogRead( g ), 0, 1023, 0, 255 ) );
  Serial.print( ',' );
  Serial.print( map( analogRead( b ), 0, 1023, 0, 255 ) );
  Serial.println();
  delay( 50 );
}

This can be saved in your hardware folder.

Open your serial monitor and you will see 3 comma separated values being printed on each line. Change the potentiometer positions and you should see the values changing.

The Arduino sketch is reading values from three potentiometers, representing red, green, and blue. The resistance (determined by the position) is shifted into the range 0-255 (from the default 0-1023 provided by the analogRead() function). These values are combined, separated by a comma, and delimited with a new line character.

255,0,0		red
0,255,0		green
0,0,255		blue
255,255,255	white
128,128,128	grey
3. Read SerialPort from Node.js

In order to get our potentiometer values into a browser, we need to first read them using Node.js.

Like many of the problems we need to solve in Node.js, there is a library to help. In this case we will use two new libraries for handling the serial port data (serialport and cli-serial-selector) and one library that we have used before (socket.io). We can install all three libraries at once using the following command:

npm install serialport cli-serial-selector socket.io

**Windows serial port hack**
Windows handles the serial ports slightly differently to macOS and Linux. Follow the directions below in order to use the required `serialport` package on a Windows computer.
- Run `CMD.exe` as _Administrator_
- Type `npm install --global --production windows-build-tools` and hit `↵ Return`
- Type `npm install serialport --build-from-source` and hit `↵ Return`
- Probably reboot (because Windows)

4. Open Atom and Add Project Folder

Open Atom and got to File > Add Project Folder. Add the entire project directory so you can see the server and client folders in the left hand project explorer.

5. Write the server code

We will now go through the code together to get the serial port values printed to the command line interface and ultimately sent through to the browser.

Create and open an empty JavaScript file in atom called app.js.

6. Copy and paste the client code

Here is the simple client code that changes the background colour of the HTML <body> tag. Copy this into an HTML file in the client directory.

<html>
  <head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.7.3/socket.io.js"></script>
    <script>
			var socket = io.connect( 'http://127.0.0.1:4503' );
			socket.on( 'connect', function() {
				document.body.style.backgroundColor = 'black';
			} );
			socket.on( 'rgb', function ( values ) {
				document.body.style.backgroundColor = 'rgb( ' + values.r + ', ' + values.g + ', ' + values.b + ' )';
			} );
		</script>
	</head>
	<body>
	</body>
</html>

Exercise 2: Send Arduino data to API

We have created a path for digitised data from potentiometers to be transmitted from the Arduino to your browser, via serial, Node.js, and socket.io. All of this communication has taken place just on a local machine. If we want to share this data, it would need to be uploaded to an API.

To do this we will use data from a light-dependent resistor (LDR, also known as a photoresistor).

Send test data to our API (HTTP Client)

Before we send (or POST) data to the API using code, we can send some test data using an HTTP client which has a graphical user interface. Download and open the Advanced Rest Client and add the following details. Make sure you change the path to your own name:

Rest client configuration

To see if your data has been POSTed successfully, open the following URL:
http://lab.arts.local:2020/

This URL only works when connected to the UAL WiFi

Send test data to our API (Node.js script)

Now open Atom and create a new JavaScript file that we will use to send some test data. Create the file in the server directory and call it publish-test-data.js or something similar.

Paste the code below into that file.

var request = require( 'request' );

request.post( {
    url: 'http://lab.arts.local:2020/api/tom/test',
    headers: {
        'Content-Type': 'application/json'
    },
    body: JSON.stringify( { value: Math.random() } )
} );

Open the CLI/terminal and cd into the server directory. Install the request library using npm:

npm install request

Now run the node file and you should see random data is published to the API:

node publish-test-data.js

Sending sensor data to our API

Next we will now connect a sensor (LDR) to our Arduino, send the sensor values to the serial port where they are read by our Node.js script and POSTed to the API.

It will be useful to create a new JavaScript file in the server directory for this part.

1. Connect a light dependent resistor

Follow these instructions.

Once completed, open the serial monitor and check that you can see the values changing based upon the light that is hitting the LDR.

2. Read SerialPort from Node.js

Modify the code you have written in the previous exercise to read the values from the serial port and output them to the CLI. Remember that we are now only receiving one value from the Arduino instead of three comma separated values.

3. Send this data to the API

You have now accessed the values from the serial port and displayed them in the CLI. Next you will need to send this data to an API. To achieve this combine the code you have just written with the code from publish-test-data.js.