13. Applications and implications¶
This week I worked on interpreting the data sent by an Arduino or a similar device and show them in some kind of user interface.
To get started, I used Processing, which is a very simple and easys-to-learn java-based platform you can do a lot with.
A second aproach I did using Python, a very popular and powerful programming language.
Sensors and Arduino¶
For a little project dealing with the display of sensor data, I chose the following input devices:
The Arduino and Processing will communicate using the Serial interface.
Serial Communication¶
Within the Setup function, I need to start communication first.
#include <Wire.h>
[...]
void setup(){
Serial.begin(9600);
Wire.begin();
}
Now I can print the stuff I want to communicate to the Serial interface.
RTC¶
With the DS1307 I have an RTC module that delivers an accurate time measurement. This module requires 5V, GND as well as two analog pins, A4 and A5 in my case.
To be able to use it easily, I download a library for it as well.
Extracting it to the library folder of my Arduino IDE is enough to be able to use it like this:
#include <RTClib.h>
RTC_DS1307 RTC;
After including the library and creating a RTC to work with, I need to
RTC.begin();
if (! RTC.isrunning()){
Serial.println("RTC is NOT running!");// This will reflect the time that your sketch was compiled
RTC.adjust(DateTime(__DATE__, __TIME__));
}
within the setup().
This serves the purpose of checking if the clock works. Eventually, wrong connections will lead to errors here, but I did not have any problems with it.
Within the loop, I use it as follows:
DateTime now = RTC.now();
if (now.second() != seconds){
Serial.print(now.month(), DEC);
Serial.print('/');
Serial.print(now.day(), DEC);
Serial.print('/');
Serial.println(now.year(), DEC);
Serial.print(doubleDigit(now.hour()), DEC);
Serial.print(':');
Serial.print(doubleDigit(now.minute()), DEC);
Serial.print(':');
Serial.println(doubleDigit(now.second()), DEC);
seconds = now.second();
}
Firstly, I need to create a DateTime variable that stores the current values I read by calling RTC.now().
I store the current seconds-value inside a variable, to change the values only when a new second started and to reduce the computing.
If it is at the time to print new values to it, I print the date and the time after one another, divided by a new line.
int doubleDigit(int x){
if (x < 10){
Serial.print(0);
}
return x;
}
The function “doubleDigit()” is a quick helper that makes single digit number have a 0 in front of them, the guarantee correct formating.
Temperature and Humidity Sensor¶
This sensor can display realtime temperature and ambient humidity.
It simply needs to be connected to 5V, GND and an Arduino pin.
It is possible to read the raw data, too, but there is a library called
The content of the .zip will be extracted to my library folder of the Arduino IDE.
#include <dht_nonblocking.h>
#define DHT_SENSOR_TYPE DHT_TYPE_11
#define DHT_SENSOR_PIN 7
Firstly, in the Arduino code, I need to include the library I just downloaded and to define the sensor type, which varies depending which sensor you are using. Then I define the pin the sensor is connected to and I’m ready to go!
float temp;
float hum;
if(dht_sensor.measure(&temp, &hum)){
Serial.println(temp, 1);
Serial.println(hum, 1);
}
In the loop, I’m holding temperature and humidity in float variables. With the measure function I now read the sensor inputs and print the result to the Serial interface.
And that is pretty much it for this sensor.
Light Dependent Resistor¶
When plugging 5V, GND and an analog Arduino pin to the light sensor, it can send a value between 0 (bright) and 1024 (dark).
#define LIGHT A2
int lightVal = 0;
String lightText = "";
I start by defining the pin to use and creating two variable holding the value and the string to send to the Serial interface.
Afterwards I read the value from the pin and interpret it!
lightVal = analogRead(LIGHT);
if(lightVal <= 1024){
lightText = "Very Dark!";
}
if(lightVal <= 800){
lightText = "Dark!";
}
if(lightVal <= 600){
lightText = "Sun is Up!";
}
if(lightVal <= 400){
lightText = "Bright!";
}
if(lightVal <= 200){
lightText = "Very Bright!";
}
Serial.println(lightText);
Since a mere number isn’t that easy to interpret when talking about lighting and brightness, I decided to translate it into simple words.
I’m not yet sure about which value represents what brightness, these values are just estimated.
Water Level Sensor¶
This water level sensor changes its’ value depending on how wet it is.. or so.
Depending on how much of its’ surface is covered, the value rises. I’m trying that kind of sensor for the first time, though.
5V, GND and an analog Arduino pin have to be connected to it.
It is kind of realtime, but using it to measure the water level is not as immediate as I was hoping. The sensor takes a while to dry until it sends the value it should send. Still I tried using it for the interface test.
#define WATERLEVEL A3
int waterVal = 0;
String waterLvl = "";
I define the pin, set some variables, exactly as I did for the light sensor.
Here, I again decided to interpret the values in text to make it easier to understand.
waterVal = analogRead(WATERLEVEL);
if(waterVal >= 0){
waterLvl = "Empty!";
}
if(waterVal > 100){
waterLvl = "Low!";
}
if(waterVal > 200){
waterLvl = "Medium!";
}
if(waterVal > 300){
waterLvl = "Max!";
}
Serial.println(waterLvl);
And that’s it for the water level sensor!
Processing¶
Processing’s user interface, and the language itself seems very similar to the Arduino IDE. As always, imports and variable declarations happen at the top.
import processing.serial.*;
Serial myPort;
String date = "";
String time = "";
String temp = "";
String lastTemp = "";
String hum = "";
String lastHum = "";
String light = "";
String water = "";
PFont f;
void setup() {
size(640, 400);
printArray(Serial.list()); // List all the available serial port
myPort = new Serial(this, Serial.list()[0], 9600); // Open the port you are using at the rate you want
}
The serial communication is important to find the data the arduino will send. As you can see above, the Serial variable will need the COM port of the Arduino. For me it is COM4, although i take the very first child of the Serial.list array. That happens because no other COM port is available.
Additionally, the different variables are used to save the prints and the PFont is essential to bring text to the surface.
void draw() {
frameRate(5);
while (myPort.available() > 0) {
ReadInput();
DrawInputs();
}
}
Inside my draw function, I set the framerate rather low and insert a while-loop, running as long as there is a serial port available.
The function ReadInput(); does what it says, as you can see here:
void ReadInput(){
date = myPort.readStringUntil('\n');
time = myPort.readStringUntil('\n');
temp = myPort.readStringUntil('\n');
hum = myPort.readStringUntil('\n');
light = myPort.readStringUntil('\n');
water = myPort.readStringUntil('\n');
print(date);
print(time);
println(temp);
println(hum);
println(light);
println(water);
}
For this part, it is important to know in which order and format the data is sent from the Arduino.
For the purpose of staying as simple as possible, I sent every data as a String and divided the different sensors inputs by a “println” (\n).
This way, I can read the string from my serial port until a \n appears.
So I read the chunks one by one and save the values to the String variables I prepared for them.
The prints in the second half of the function are for debugging only and can be ignored.
The next step in the draw loop is to draw the inputs read.
void DrawInputs(){
background(255);
f = createFont("Arial",16,true);
textFont(f,36);
fill(0);
textAlign(CENTER, TOP);
text(date, width/3, 50);
text(time, width/3*2, 50);
if(temp != "0.0\n"){
lastTemp = temp;
}
text(CutFloats(lastTemp) + "°", width/3, 150);
if(hum != "0.0\n"){
lastHum = hum;
}
text(CutFloats(lastHum) + "%", width/3*2, 150);
text(light, width/3, 250);
text(water, width/3*2, 250);
}
I set the background to be white (255) and set my Font, using fill(0) to make it black. I align the text and start by printing date and time, with the x positions depending on the window’s width and the y position as 50.
As I occured errors using temperature and humidity values as floats, I kept them strings. I wrote the small function CutFloats, to have the “\n” removed from the String. This way I can write a “°” or a “%” behind each of the values. I also check if I am receiving a 0.0, which is the default value of the sensor. If yes, the last value measured should be displayed for another measurement interval.
String CutFloats(String tmp){
if(tmp != null && tmp.length() >= 4) tmp = tmp.substring(0, (tmp.length()-1));
return tmp;
}
Lastly, the strings I sent describing light intensity and water level are written into the scene. It then looks like this.
In another approach I switched from simply writing the brightness on the screen to setting the brightness of the background equal to the measured light intensity.
Parsing the value to an int was a bit tricky, because you have to get rid off the “\n” before you can transform it. Mapping it to a value between 0 and 255 made it possible to use it for the given purpose.