element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Design For A Cause 2021
  • Challenges & Projects
  • Design Challenges
  • Design For A Cause 2021
  • More
  • Cancel
Design For A Cause 2021
Blog VenTTracker #10 - Ventilation Monitor on Arduino IoT Cloud
  • Blog
  • Forum
  • Documents
  • Polls
  • Files
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: javagoza
  • Date Created: 2 May 2021 10:49 AM Date Created
  • Views 2566 views
  • Likes 9 likes
  • Comments 11 comments
  • arduino_iot_cloud
  • venttracker
  • wifinina
  • arduino_nano_33_iot
  • covid-19
  • window_sensor
  • natural ventilation
Related
Recommended

VenTTracker #10 - Ventilation Monitor on Arduino IoT Cloud

javagoza
javagoza
2 May 2021

This week we connected our window sensor to the cloud. We have designed a small demo application with a screen to display real-time data both on the device and in the cloud. The final version will work without the graphic display and in low power mode. We have also included the temperature reading provided by the IMU LSM6DDS3 housed in the Arduino NANO 33 IoT to have environmental data in the window.

 

image

  Design for A Cause 2021 the VenTTracker project

  01 - Intro and motivation. | 02 - Analyzing Window Types (I) | 03 - Analyzing Window Types (II) | 04 - Playing with the IMU | 05-Sliding Window Mock-up | 06 -  Window Sensor Prototype | 07 - Adjusting the window sensor | 08 - Trying to make a measuring device with the accelerometer | 09 - Checking and updating WiFiNINA Firmware | 10 - Ventilation Monitor on Arduino IoT Cloud | 11 - Wireless Environmental Monitor on Arduino Nano 33 IoT | 12 - Window Anomaly Detection. Edge Impulse & Arduino Nano 33 IoT | 14 - Environmental Monitor Revisited - Version 2 | 13 - Project wrap-up and Lessons learned

 

Tracking System for Classroom Ventilation Routines

A STEM project for classrooms

the VenTTracker project - VenTTracker #10 - Ventilation Monitor on Arduino IoT Cloud

 

image

 

The system in action:

 

You don't have permission to edit metadata of this video.
Edit media
x
image
Upload Preview
image

 

IoT over MQTT

 

We are going to use the arduino IoT Cloud service which is based on MQTT. MQTT is a widely used publish-subscribe messaging protocol in the Internet of Things. It runs on top of the TCP / IP protocol and is designed for connections to remote locations where a "small code footprint" is required or network bandwidth is limited. The goal is to provide a protocol that saves bandwidth and uses little battery power.

 

image

 

Architecture

 

Our routine ventilation monitor is composed of:

  • Devices:
    • Window sensors that record both the position of the window and the temperature in the window, as well as whether the window needs to be opened.
    • Environmental sensor to capture the environmental variables that concern us, such as the concentration of carbon dioxide in the room.
  • Software to define the behavior of our hardware.
  • Cloud application to store data or control devices remotely.

 

Devices

Our devices are built on the Arduino Nano 33 IoTArduino Nano 33 IoT board. They are the hardware that runs the software, reads sensors, controls actuators, and communicates with the Arduino IoT Cloud.

 

image

 

Things

Things are the digital twin of our hardware. When we create a new Thing, there are a few configurations that we need to do to get started.

Each thing has a linked physical device for which we have to define the credentials of the WIFI network to which it is going to connect and the variables that will be controlled or monitored with that device.

 

Variables

Variables are attributes that define the characteristics of a device. A variable can be 'read only' (RO) to indicate that Arduino Cloud IoT can read data but can not change the value of the variable. A variable could be designed as 'read and write' (RW) if Arduino Cloud IoT can also remotely change the value of the variable and send an event notification to the device.

 

Window Sensor Variables

 

  • CloudSwitch windowOpen: (RO) indicates if the window is open or closed
  • CloudSwitch windowAlert; (RW) can signal the window in alert state
  • CloudPercentage windowPosition; (RO) indicates if the window open percentage (0%, 25%, 50%, 75%, 100%)
  • CloudLocation windowLocation; (RO) indicates window geolocation coordinates
  • CloudTemperature windowTemp; (RO) indicates window sensor IMU temperature.

 

Dashboard

The dashboard is the cloud monitoring and control center! In the panel we have included several widgets linked to our variables

image

 

Dashboard Widgets

 

Is the window open? widget

"Is the window open?" widget tells us if the window is open or closed

image

 

"Window in ventilation alarm"  widget

"Window in ventilation alarm" allows us to put the sensor of that window in an alarm state or to know if it is still in an alarm state.

image

 

"% open" widget

"% open" allows us to know the degree of opening of the window in percentage.

image

 

"% opening vs time"  widget

The graph of "% opening vs time" allows us to graphically see the historical information of the degree of opening of the window in time.

image

 

"Temperature (ºC)" widget

The temperature widget allows us to view the last temperature reported by the sensor in ºC

image

 

"% temp vs time" widget

The graph of "% temp vs time" allows us to graphically see the historical information of the temperature reported by the window sensor over time.

image

 

"Window Geolocation" widget

The Window Geolocation widget shows the location of our window sensor device.

image

 

The Dashboard in Action

 

 

Window closed, with alarm state

image

 

 

image

 

Ventilation Alarm State Change

image

 

 

Window closed, no alarm state

 

image

image

 

 

Window 25% open

 

image

image

 

 

Window 50% open

 

image

image

Window 75% open

 

image

image

 

 

Window fully open

 

image

image

 

 

Download Historical Data

 

image

image

 

image

 

 

Step by Step creation of the Thing and Dashboard

The Create Environment

 

Go to https://store.arduino.cc/digital/create and select IoT Cloud

 

 

image

 

Create thing

 

image

Set up an Arduino Device

image

We install the Arduino Create Agent plugin

image

Run the installer

image

Accept the license

image

Specify the directory for the installation of the agent:

 

image

 

 

image

image

 

Accept the certificate

 

image

 

image

Back in your web browser, chrome for us.

Connect your Arduino NANO 33 IoT by USB

 

image

 

Configure your device

 

image

Name it

 

image

Let the agent communicate with your Arduino:

 

 

image

 

You are done

image

 

Your first Thing

 

image

Create your variables by adding them:

 

image

 

 

 

 

 

 

image

 

Add Variable

 

image

 

Add and Edit variables

image

 

 

Automatic Sketch Generation

 

image

 

/*

  Sketch generated by the Arduino IoT Cloud Thing "VT-C01-W02"

  https://create.arduino.cc/cloud/things/e7486f3d-9b68-4951-993e-2dd0c5284e0a

  Arduino IoT Cloud Variables description

  The following variables are automatically generated and updated when changes are made to the Thing

  CloudPercentage windowPosition;

  CloudContactSensor windowOpen;

  Variables which are marked as READ/WRITE in the Cloud Thing will also have functions

  which are called when their values are changed from the Dashboard.

  These functions are generated with the Thing and added at the end of this sketch.

*/

#include "thingProperties.h"

void setup() {

  // Initialize serial and wait for port to open:

  Serial.begin(9600);

  // This delay gives the chance to wait for a Serial Monitor without blocking if none is found

  delay(1500);

  // Defined in thingProperties.h

  initProperties();

  // Connect to Arduino IoT Cloud

  ArduinoCloud.begin(ArduinoIoTPreferredConnection);

    /*

     The following function allows you to obtain more information

     related to the state of network and IoT Cloud connection and errors

     the higher number the more granular information you’ll get.

     The default is 0 (only errors).

     Maximum is 4

*/

  setDebugMessageLevel(2);

  ArduinoCloud.printDebugInfo();

}

void loop() {

  ArduinoCloud.update();

  // Your code here

}

 

 

Serial monitor view

 

image

 

image

I do not feel safe uploading the credentials of my Wi-Fi network to the Internet so from now on we will work the sketch locally.

 

Open in full Editor the Sketch:

 

VT-C01-W02_may01a.ino tab

 

image

 

 

ReadMe.adoc tab

 

image

ThingProperties.h tab

image

 

Secret Tab

image

 

 

 

Download Sketch to local drive

 

image

Open in local Editor

image

 

Adding library ArduinoIoTCloud.h

 

 

image

 

image

Install all

Verify Sketch

 

The first compilation takes a long time.

Without having programmed a single line of code, this is what we have left for our program

 

Sketch uses 143844 bytes (54%) of program storage space. Maximum is 262144 bytes.

Global variables use 20592 bytes (62%) of dynamic memory, leaving 12176 bytes for local variables. Maximum is 32768 bytes.

 

We update the wifi credentials in the arduino_secrets.h file

 

#define SECRET_SSID ""

#define SECRET_PASS ""

 

Lets upload and run the sketch

 

image

 

 

Back to Arduino IoT Cloud

 

image

 

We already have our sensor connected to the Arduino IoT cloud

 

image

 

Create a Dashboard

image

 

 

 

 

 

 

Build dashboard

 

Add

 

image

 

image

 

image

View Dashboard

 

image

 

Adding a new variable. Let's add a variable for the window temperature

 

 

image

 

 

Adding a new device

 

image

 

The sketch changes, a new property is added

 

image

 

We have created a new variable and added it to our local Sketch. But the variable is not refreshed.

image

 

 

 

 

 

image

 

The demo code

 

#include "arduino_secrets.h"
/* 
  This is an example for testing the VenTTracker Window Sensor
  connecte to Arduino IoT Cloud.
  Displays a progress bar indicating the window openes on 
  a Monochrome OLED display based on SSD1306 drivers.
  This example is for a 128x32 pixel display using I2C to communicate
  3 pins are required to interface (two I2C and one reset).


  Lights LED according sensor events:
                       | LEFT LED  |  RIGHT LED  |
  WINDOW OPEN EVENT    |    OFF    |    OFF      |
  WINDOW CLOSED EVENT  |    ON     |    ON       |
  TO THE LEFT MOVEMENT |    ON     |    OFF      |
  TO THE RIGHT MOVEMENT|    ON     |    OFF      |


  Hardware. Pinout
    8 A4/SDA Analog ADC in; I2C SDA; SDA to SDA OLED Display
    9 A5/SCL Analog ADC in; I2C SCL to SCK OLED Display
    13 RST Digital In Active low reset input  RESET to push button. Other end to ground.
    14 GND Power Power Ground to Battery  - 
    15 VIN Power In Vin Power input VIN to Baterry  + 
    20 D2 Digital GPIO - to Open/Closed Reed Switches
    25 D7 Digital; Right LED with a 100 Ohm resitor to ground
    26 D8 Digital GPIO to Left LED with a 100 Ohm resitor to ground
    27 D9/PWM Digital GPIO to  Right Reed Switch. Other end to ground.
    28 D10/PWM Digital GPIO;  to Left Reed Switch. Other end to ground.


  Arduino IoT Cloud Thing "VT-CR01-WW01"
  https://create.arduino.cc/cloud/things/7c03b195-29d1-42ba-92e1-651a8e7d4010 


  Cloud Variables:


  CloudSwitch windowOpen: (RO) indicates if the window is open or closed
  CloudSwitch windowAlert; (RW) can signal the window in alert state
  CloudPercentage windowPosition; (RO) indicates if the window open percentage (0%, 25%, 50%, 75%, 100%)
  CloudLocation windowLocation; (RO) indicates window geolocation coordinates
  CloudTemperature windowTemp; (RO) indicates window sensor IMU temperature.


  Author: Enrique Albertos
  Date: 2021-05-01




*/


#include "thingProperties.h"
#include "SPI.h"
#include "Wire.h"
#include "SparkFunLSM6DS3.h"
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Wire.h>


#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels


int windowState = HIGH;


// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);


// Port connections
int leftSwitchPort = 10;      // switch to ground + internal pull-up resistor.
                              // Negative logic LOW when switch is closed
int rightSwitchPort = 9;      // switch to ground + internal pull-up resistor.
                              // Negative logic LOW when switch is closed
int leftLedPort = 8;          // positive logic. HIGH turn on the LED
int rightLedPort = 7;         // positive logic. HIGH turn on the LED
int openClosedSwitchPort = 2; // switch to ground + internal pull-up resistor.
                              // Negative logic LOW when switch is closed


typedef enum direction_t { RIGHT = 0x00, LEFT = 0xFF };
volatile direction_t lastWindowDirection = LEFT;


volatile int8_t encoderPosition =  0; // don't know where is our encoder, we'll need an absolute reference
// let's assume we are in closed position and window opens from left to right
volatile bool encoderChangePending = false;
volatile bool openCloseChangePending = true;
unsigned long lastLeftSwitchDebounceTime = 0; // the last time the input left encoder pin was toggled
unsigned long debounceDelay = 150; // the debounce time


#define LOGO_HEIGHT   32
#define LOGO_WIDTH    64
//  logo 8 pixels per Byte Little Endian Horizontal
static const unsigned char PROGMEM logoDesignForACause[] ={
0x00, 0x00, 0x0F, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xC0, 0x01, 0xFE, 0x00, 0x00,
0x00, 0x00, 0xFF, 0xF8, 0x07, 0xFF, 0x80, 0x00, 0x00, 0x03, 0xFF, 0xFC, 0x1F, 0xFF, 0xE0, 0x00,
0x00, 0x07, 0xFF, 0xFE, 0x3F, 0xFF, 0xF0, 0x00, 0x00, 0x0F, 0xFF, 0xFE, 0x3F, 0xFF, 0xFC, 0x00,
0x00, 0x1F, 0xF9, 0xFE, 0x3F, 0xEF, 0xFC, 0x00, 0x00, 0x3F, 0xF0, 0x3E, 0x3E, 0x07, 0xFE, 0x00,
0x00, 0x7F, 0xE0, 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x80, 0xF0, 0x0F, 0x10, 0xFF, 0x80, 0x00, 0xFF, 0x83, 0xFC, 0x3F, 0xC0, 0xFF, 0xC0,
0x01, 0xFF, 0x07, 0x1E, 0x70, 0xE0, 0x7F, 0xC0, 0x01, 0xFF, 0x0E, 0x07, 0xE0, 0x60, 0x7F, 0xE0,
0x03, 0xFF, 0x0C, 0x03, 0xC4, 0x30, 0x7F, 0xE0, 0x03, 0xFE, 0x0C, 0xE1, 0x8E, 0x30, 0x3F, 0xE0,
0x07, 0xFF, 0x0C, 0x03, 0x86, 0x30, 0x7F, 0xF0, 0x07, 0xFF, 0x0C, 0x03, 0xC4, 0x70, 0x7F, 0xF0,
0x0F, 0xFF, 0x8E, 0x07, 0xE0, 0x60, 0xFF, 0xF8, 0x1F, 0xFF, 0x87, 0xBE, 0x79, 0xE0, 0xFF, 0xFC,
0x1F, 0xFF, 0xC3, 0xF8, 0x3F, 0x81, 0xFF, 0xFC, 0x3F, 0xFF, 0xE0, 0x60, 0x06, 0x03, 0xFF, 0xFE,
0x7F, 0xFF, 0xF8, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x3F, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x1F, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFE, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x06, 0x30, 0x07, 0xFF, 0xFF,
0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF
};


#define TITLE_HEIGHT   32
#define TITLE_WIDTH    112
// title logo 8 pixels per Byte Little Endian Horizontal
static const unsigned char PROGMEM designChallengeTitle[] ={
0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00,
0x01, 0x80, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00,
0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0xC0, 0x00, 0x00, 0x00, 0x67, 0x3C, 0x79, 0x1F, 0x3E, 0x0F,
0x3C, 0xD0, 0x38, 0x18, 0xCF, 0x11, 0x1C, 0x78, 0x63, 0x7E, 0xD9, 0x9F, 0x3E, 0x0F, 0x6E, 0xF0,
0x6C, 0x18, 0x1F, 0xBB, 0x36, 0x7C, 0x63, 0x66, 0xC9, 0xB3, 0x37, 0x06, 0x66, 0xE0, 0x0C, 0x18,
0x01, 0xBB, 0x72, 0xCC, 0x63, 0x7E, 0xE1, 0xB3, 0x37, 0x06, 0x66, 0xC0, 0x3C, 0x18, 0x07, 0xBB,
0x38, 0xFC, 0x63, 0x7E, 0x79, 0xB3, 0x37, 0x06, 0x66, 0xC0, 0x7C, 0x18, 0xDF, 0xBB, 0x1E, 0xFC,
0x67, 0x60, 0x1D, 0xB3, 0x37, 0x06, 0x66, 0xC0, 0xCC, 0x18, 0xD9, 0xBB, 0x06, 0xC0, 0x66, 0x66,
0xDD, 0x9F, 0x37, 0x06, 0x66, 0xC0, 0xEC, 0x0D, 0xD9, 0xBB, 0x76, 0xEC, 0x7C, 0x3C, 0xF9, 0x9F,
0x37, 0x06, 0x7C, 0xC0, 0x7C, 0x0F, 0x9F, 0x9F, 0x3E, 0x78, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0E, 0x10, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F,
0x30, 0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xB0, 0x00,
0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0xBF, 0x1E, 0x66, 0x38,
0xB8, 0xF8, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x3F, 0x3F, 0x66, 0x7D, 0xF8, 0xF9,
0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x33, 0x03, 0x66, 0xCC, 0xCD, 0x99, 0xB0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x33, 0x1F, 0x66, 0xFC, 0xCD, 0x9B, 0xF8, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x31, 0xB3, 0x3B, 0x66, 0xE1, 0xCD, 0x9B, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x39, 0xB3, 0x33, 0x66, 0xC4, 0xCD, 0x99, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B,
0xB3, 0x37, 0x66, 0xEC, 0xCC, 0xF9, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x33, 0x3F,
0x66, 0x7C, 0xCC, 0xF9, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF8,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};


// double buffer for the display
GFXcanvas1 canvas(SCREEN_WIDTH, SCREEN_HEIGHT); // 128x32 pixel canvas


void isrFallingLeftSwitchPort();      // ISR for leftSwitchPort
void isrChangeOpenClosedSwitchPort(); // ISR for open/close switches




LSM6DS3 IMU(I2C_MODE, 0x6A);


void setup() {


  // Initialize serial and wait for port to open:
  Serial.begin(9600);
  // This delay gives the chance to wait for a Serial Monitor without blocking if none is found
  delay(5000); 
  setupAccelerometer();
  // Defined in thingProperties.h
  initProperties();


  // Connect to Arduino IoT Cloud
  ArduinoCloud.begin(ArduinoIoTPreferredConnection);
  
  /*
     The following function allows you to obtain more information
     related to the state of network and IoT Cloud connection and errors
     the higher number the more granular information you’ll get.
     The default is 0 (only errors).
     Maximum is 4
 */
  setDebugMessageLevel(4);
  ArduinoCloud.printDebugInfo();


  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32
    Serial.println(F("SSD1306 allocation failed"));
    for (;;)
      ; // Don't proceed, loop forever
  }


  // set port switches with internal 20K pull up resistors
  pinMode(leftSwitchPort, INPUT_PULLUP);
  pinMode(rightSwitchPort, INPUT_PULLUP);
  pinMode(openClosedSwitchPort, INPUT_PULLUP);


  // set debugging LEDs ports
  pinMode(leftLedPort, OUTPUT);
  pinMode(rightLedPort, OUTPUT);
  pinMode(LED_BUILTIN, OUTPUT);


  blinkLogo(designChallengeTitle, TITLE_WIDTH, TITLE_HEIGHT);
  blinkLogo(logoDesignForACause, LOGO_WIDTH, LOGO_HEIGHT);
  // detect falling edges the switch chages from open to closed. It is negative
  // logic
  attachInterrupt(digitalPinToInterrupt(leftSwitchPort),
                  isrFallingLeftSwitchPort, FALLING);


  // detect switch chages from open to closed. It is negative logic
  attachInterrupt(digitalPinToInterrupt(openClosedSwitchPort),
                  isrChangeOpenClosedSwitchPort, CHANGE);


}


void loop() {
  ArduinoCloud.update();
  windowLocation =  Location(41.652785957455f,  -0.8729272143593402f);
  windowOpen = !windowState;
  windowTemp = IMU.readTempC();
  if (windowState == HIGH) {
    windowPosition = 0;
  } else {
    windowPosition = (encoderPosition + 1) * 25;
  }
  // if there is a new event from the encoder acknowledge it and do pending
  // actions
  if (encoderChangePending) {
    encoderChangePending = false;
    // turn on left led when window direction is LEFT
    digitalWrite(leftLedPort, lastWindowDirection == LEFT);
    // and turn on right led when window direction is RIGHT
    digitalWrite(rightLedPort, lastWindowDirection == RIGHT);
    // log encoder position to serial port
    Serial.println(encoderPosition); 
    if (windowState == LOW) {
      drawProgressBar(encoderPosition);
    } else {
      drawLogo(logoDesignForACause, LOGO_WIDTH, LOGO_HEIGHT);
    }   
  }
  if (openCloseChangePending) {
    openCloseChangePending = false;
        // Light LEDs when window closed
    digitalWrite(leftLedPort, windowState);
    digitalWrite(rightLedPort, windowState);
    if (windowState == LOW) {
      drawProgressBar(encoderPosition);
      windowAlert = false;
    } else {
      drawProgressBar(-1);
    }
  }
  if(windowAlert){ // blink leds
    digitalWrite(leftLedPort, true);
    digitalWrite(rightLedPort, true);
    delay(400);
    digitalWrite(leftLedPort, false);
    digitalWrite(rightLedPort, false);
    delay(400);
  }
  
}


void setupAccelerometer() {
  IMU.begin();
}








void onWindowAlertChange() {
  Serial.print("On Window Change\n");
  if(windowAlert) {
    digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
    displayOpenWindow();
  } else { 
    digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW

  }
  
}




/**
  Interrupt Service Routine for Falling Edge in Left Switch Port
*/
void isrFallingLeftSwitchPort() {
  if ((millis() - lastLeftSwitchDebounceTime) > debounceDelay) {
    if (digitalRead(rightSwitchPort) == HIGH) {
      if (encoderPosition > 0) {
        encoderPosition--;
      }
      lastWindowDirection = LEFT;
    } else {
      if (encoderPosition < 3) {
        encoderPosition++;
      }
      lastWindowDirection = RIGHT;
    }
    lastLeftSwitchDebounceTime = millis();
    encoderChangePending = true;
  }
}


/**
  Interrupt Service Routine for Changing Edge in Open Close Switches
  when the window is closed light the two LEDS
*/
void isrChangeOpenClosedSwitchPort() {
  windowState = !digitalRead(openClosedSwitchPort);
  if ((millis() - lastLeftSwitchDebounceTime) > debounceDelay) {
    encoderPosition = 0;
    openCloseChangePending = true;
    lastLeftSwitchDebounceTime = millis();
  }
}


/**
* Print the progress bar
*/
void drawProgressBar(const int counter) {
  display.clearDisplay();
  canvas.fillScreen(BLACK);
  canvas.setCursor(0, 0);
  canvas.setTextSize(2);
  canvas.print((counter+1)*25);
  canvas.print("% ");
  canvas.print(IMU.readTempC(),1);
  canvas.print("C");
  for(int i = 0; i < 4; ++i) {
    canvas.drawRect(i * SCREEN_WIDTH / 4, SCREEN_HEIGHT / 2,SCREEN_WIDTH /4 , SCREEN_HEIGHT / 2 , WHITE  );
  }  
  for (int i = 0 ; i <= counter;++i) {
      canvas.fillRect(i * SCREEN_WIDTH / 4+3, SCREEN_HEIGHT / 2 + 4,SCREEN_WIDTH /4 -6, SCREEN_HEIGHT / 2 -8, WHITE  );
  }
  display.drawBitmap(0, 0, canvas.getBuffer(), 128, 32, WHITE,
                     BLACK); // Copy to screen
  display.display();
}


/**
* Print the progress bar
*/
void displayOpenWindow() {
  display.clearDisplay();
  canvas.fillScreen(BLACK);
  canvas.setCursor(0, 0);
  canvas.setTextSize(2);
  canvas.println("  PLEASE,");
  canvas.print(  "   OPEN ");
  display.drawBitmap(0, 0, canvas.getBuffer(), 128, 32, WHITE,
                     BLACK); // Copy to screen
  display.display();
}




/**
  Send a logo to the Display and center it and wait 1 second
*/
void drawLogo(const unsigned char* logo, const int width, const int height ) {
  display.clearDisplay();
  display.drawBitmap(
    (display.width()  - width ) / 2,
    (display.height() - height) / 2,
    logo, width, height, 1);
  display.display();
}


/**
  blinks a logo on the display
*/
void blinkLogo(const unsigned char* logo, const int width, const int height) {
    // After reset blink the logo
  display.clearDisplay();
  drawLogo(logo, width, height);
  //Invert and restore display, pausing in-between
  display.invertDisplay(true);
  delay(1000);
  display.invertDisplay(false);
  delay(2000);
}

 

Summary

It has been very easy to connect our sensor to the Arduino IoT cloud. The entire process including the documentation has not taken more than an hour of work.

To do the full demo we wanted to have connected three window sensors but the free plan did not allows us to connect more than one device or manage more than 5 cloud variables without upgrading to a paid plan.

 

UPDATE 2021/05/03

Arduino announced changes to their plans for the Arduino IoT Cloud:

Free PLAN:

  • 2 Things
  • Unlimited dashboards
  • 100 Mb to store sketches
  • 1 day data retention
  • 200s/day of compilation time

 

Entry PLAN ($ 2.99/month):

  • 10 Things
  • Unlimited dashboards
  • Unlimited storage for sketches
  • 15 days data retention
  • Unlimited compilation time
  • APIs
  • Over the Air Updates

 

 

Next Steps

  • Prepare our sensor to be able to configure it via bluetooth
  • Train a Machine learning model that allows us to detect anomalies in the movement of the window to warn of the need for window maintenance.
  • Get started with the design of our environmental sensor.

 

VenTTracker Blogs
VenTTracker #01 - Intro and motivation.
VenTTracker #02 - Analyzing window types.
VenTTracker #03 - Analyzing window types II
VenTTracker #04 - Playing with the IMU
VenTTracker #05 - Sliding Window Mock-up
VenTTracker #06 - Window Sensor Prototype
VenTTracker #07 - Adjusting the window sensor
VenTTracker #08 - Trying to make a measuring device with the accelerometer
VenTTracker #09 - Checking and updating WiFiNINA Firmware
VenTTracker #10 - Ventilation Monitor on Arduino IoT Cloud
VenTTracker #11 - Wireless Environmental Monitor on Arduino Nano 33 IoT
VenTTracker #12 - Window Anomaly Detection. Edge Impulse & Arduino Nano 33 IoT
VenTTracker #14 (aka #11 bis) - Environmental Monitor Revisited - Version 2
VenTTracker #13 - Project wrap-up and Lessons learned

 

 

<< Previous VenTTracker BlogNext VenTTracker Blog  >>
VenTTracker #09 - Checking and updating WiFiNINA FirmwareVenTTracker #11 - Wireless Environmental Monitor on Arduino Nano 33 IoT
  • Sign in to reply

Top Comments

  • DAB
    DAB over 4 years ago +2
    Very good write up for the process. DAB
  • skruglewicz
    skruglewicz over 4 years ago +2
    Very nice blog. Plenty of great research information ..thank you
  • leeccd
    leeccd over 4 years ago +2
    Very informative blog, thanks!
  • ilvyanyatka
    ilvyanyatka over 4 years ago in reply to javagoza

    Even with these limitations it still looks like a great deal for Arduino projects. When they will add ESP32 support it will be just perfect.

    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • javagoza
    javagoza over 4 years ago in reply to ilvyanyatka

    Version 2.0 of the Arduino IDE is still in beta. I had some problem loading unofficial libraries from zips and with other boards that are not Arduino and are not supported yet. And also some small problems with the editor that are solved like everything in computing by restarting the Arduino IDE. In general I'm happy, you can also keep the latest version 1.8.x without uninstalling so if you have a problem you can go back to the other one. Version 2 does not yet have the serial plotter and when you have two projects open it gets mixed up with the serial ports, but Arduino releases new versions often and they correct many problems.

    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • ilvyanyatka
    ilvyanyatka over 4 years ago

    Wow, thank you so much for such a detailed instruction!

    Additional thank you for the information about Arduino IDE 2.0 in your status.

    I will definitely check them both out!

    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • leeccd
    leeccd over 4 years ago

    Very informative blog, thanks!

    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • javagoza
    javagoza over 4 years ago in reply to skruglewicz

    Thanks! I hope that helps. Despite the lack of help documentation within the Arduino IoT Cloud portal, it is quite intuitive, although I had to finish reading the getting started guides on the Arduino portal to understand some terms.

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
>
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube