Hardware components | ||||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
Software apps and online services | ||||||
| ||||||
| ||||||
|
In this step, we will connect Water Level Sensor HW-038 but in order to recognize the possible water leak.
So firstly we have to connect the sensor to our schema that was built in previous part of this tutorial series:
The connection scheme is (Resistors are not required, but they allow to avoid interference):
To get it working we need to write some code. In order to make the logic that we want, we need to use Arduino interrupts. In our case, we will use attachInterrupt() function with mode CHANGE to get information about value statuses (rising/falling). Our interruption function will set the flag that signaling is water leaking or not.
// in the global scope
#define water_level_sensor_pin 35
int water_level_changed = 0;
void setup() {
...
pinMode(water_level_sensor_pin, INPUT);
attachInterrupt(digitalPinToInterrupt(water_level_sensor_pin), water_level_alarm, CHANGE);
}
void water_level_alarm(void) {
water_level_changed = true;
}
void loop() {
...
if (water_level_changed) {
tb.sendTelemetryInt("Water level", digitalRead(water_level_sensor_pin));
water_level_changed = false; }
...
}
Now let's upload code to your controller (Ctrl+U Or upload icon).
After the upload is done, we can add a widget for displaying the potential water leakage — the alarm widget on ThingsBoard.
If you want to also create alarms you can use this guide, and to display them please follow this instruction.Step 2
Now, we will gonna connect the light level sensor to our schema, it is the most simple part of this tutorial as it not requires an additional library or something else.
The connection scheme is:
In the code below, we read the analogue pin value and simply send it to our ThingsBoard widget.
// in the global scope
#define light_sensor_pin 32
int light_level = 0;
void loop() {
...
float R_light = analogRead(light_sensor_pin);
float lux = (250.0 / (0.0037 * R_light)) - 50.0;
Serial.println(lux);
tb.sendTelemetryFloat("Light level", lux);
...
}
Upload the code to your controller (Ctrl+U Or upload icon).
And finally let's add a widget to your ThingsBoard dashboard, to do this follow the next steps:
1. Go to Dashboards groups > All.
2. Select dashboard in the list or create a new one, click on "Open dashboard" button.
3. Click on Edit button at the right bottom.
4. Click on Add new widget button > Create new widget.
5. Select Analogue gauges.
6. Select Radial gauge.
7. Add datasource (by selecting your device and telemetry key from it) and click on Add button.
8. In order to change the widget style you can use Advanced tab.
9. Now you can see the widget on your dashboard
If you have done all well, you see the values from the sensor in your ThingsBoard dashboard widget.
Code ListingYou can find it in the attached files.
ResultWas this article useful? Place a comment below!
#include <WiFi.h>
#include <MQUnifiedsensor.h>
#include <ThingsBoard.h>
const char* ssid = "YOUR_SSID";
const char* password = "YOUR_PASSWORD";
#define TOKEN "YOUR_DEVICE_TOKEN"
#define THINGSBOARD_SERVER "thingsboard.cloud"
// Initialize ThingsBoard client
WiFiClient espClient;
// Initialize ThingsBoard instance
ThingsBoard tb(espClient);
// the Wifi radio's status
int status = WL_IDLE_STATUS;
//Definitions
#define placa "ESP-32"
#define Voltage_Resolution 3.3
#define pin 34 //Analog input 0 of your arduino
#define type "MQ-135" //MQ135
#define ADC_Bit_Resolution 12 // For arduino UNO/MEGA/NANO
#define RatioMQ135CleanAir 3.6//RS / R0 = 3.6 ppm
double CO2 = (0);
MQUnifiedsensor MQ135(placa, Voltage_Resolution, ADC_Bit_Resolution, pin, type);
#define water_level_sensor_pin 35
int water_level_changed = 0;
#define light_sensor_pin 33
void setup()
{
Serial.begin(9600);
if(Serial) Serial.println("Serial is open");
WiFi.begin(ssid, password);
Serial.print("Connecting");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.print("Connected, IP address: ");
Serial.println(WiFi.localIP());
//Set math model to calculate the PPM concentration and the value of constants
MQ135.setRegressionMethod(1); //_PPM = a*ratio^b
MQ135.init();
Serial.print("Calibrating please wait.");
float calcR0 = 0;
for(int i = 1; i<=10; i ++)
{
MQ135.update(); // Update data, the arduino will be read the voltage on the analog pin
calcR0 += MQ135.calibrate(RatioMQ135CleanAir);
Serial.print(".");
}
MQ135.setR0(calcR0/10);
Serial.println(" done!.");
if(isinf(calcR0)) {Serial.println("Warning: Conection issue founded, R0 is infite (Open circuit detected) please check your wiring and supply"); while(1);}
if(calcR0 == 0){Serial.println("Warning: Conection issue founded, R0 is zero (Analog pin with short circuit to ground) please check your wiring and supply"); while(1);}
/***************************** MQ CAlibration ********************************************/
MQ135.serialDebug(false);
pinMode(water_level_sensor_pin, INPUT);
attachInterrupt(digitalPinToInterrupt(water_level_sensor_pin), water_level_alarm, CHANGE);
}
void water_level_alarm(void) {
water_level_changed = true;
}
void loop()
{
if (!tb.connected()) {
// Connect to the ThingsBoard
Serial.print("Connecting to: ");
Serial.print(THINGSBOARD_SERVER);
Serial.print(" with token ");
Serial.println(TOKEN);
if (!tb.connect(THINGSBOARD_SERVER, TOKEN)) {
Serial.println("Failed to connect");
return;
}
}
if (water_level_changed) {
tb.sendTelemetryInt("Water level", digitalRead(water_level_sensor_pin));
water_level_changed = false;
}
MQ135.update(); // Update data, the arduino will be read the voltage on the analog pin
MQ135.setA(110.47); MQ135.setB(-2.862);
CO2 = MQ135.readSensor();
MQ135.setA(605.18); MQ135.setB(-3.937);
float CO = MQ135.readSensor();
MQ135.setA(77.255); MQ135.setB(-3.18);
float Alcohol = MQ135.readSensor();
MQ135.setA(44.947); MQ135.setB(-3.445);
float Toluene = MQ135.readSensor();
MQ135.setA(102.2 ); MQ135.setB(-2.473);
float NH4 = MQ135.readSensor();
MQ135.setA(34.668); MQ135.setB(-3.369);
float Acetone = MQ135.readSensor();
float R_light = analogRead(light_sensor_pin);
float lux = (250.0 / (0.0037 * R_light)) - 50.0;
Serial.println(lux);
Serial.print("CO2: ");
Serial.println(CO2);
Serial.print("Light level: ");
Serial.println(lux);
Serial.println("Sending data...");
tb.sendTelemetryFloat("CO2", CO2);
tb.sendTelemetryFloat("CO", CO);
tb.sendTelemetryFloat("Alcohol", Alcohol);
tb.sendTelemetryFloat("Toluene", Toluene);
tb.sendTelemetryFloat("NH4", NH4);
tb.sendTelemetryFloat("Acetone", Acetone);
tb.sendTelemetryFloat("Light level", lux);
tb.loop();
delay(1000); //Sampling frequency
}
{
"title": "Air Quality",
"image": null,
"mobileHide": false,
"mobileOrder": null,
"configuration": {
"description": "",
"widgets": {
"11a80b8e-e962-de17-dc1c-cc1543aebf2c": {
"isSystemType": true,
"bundleAlias": "charts",
"typeAlias": "basic_timeseries",
"type": "timeseries",
"title": "New widget",
"image": null,
"description": null,
"sizeX": 8,
"sizeY": 5,
"config": {
"datasources": [
{
"type": "entity",
"name": null,
"entityAliasId": "4bf9b60c-91d0-61e1-ec10-d1bdca48100d",
"filterId": null,
"dataKeys": [
{
"name": "CO2",
"type": "timeseries",
"label": "CO2",
"color": "#2196f3",
"settings": {
"excludeFromStacking": false,
"hideDataByDefault": false,
"disableDataHiding": false,
"removeFromLegend": false,
"showLines": true,
"fillLines": false,
"showPoints": false,
"showPointShape": "circle",
"pointShapeFormatter": "var size = radius * Math.sqrt(Math.PI) / 2;\nctx.moveTo(x - size, y - size);\nctx.lineTo(x + size, y + size);\nctx.moveTo(x - size, y + size);\nctx.lineTo(x + size, y - size);",
"showPointsLineWidth": 5,
"showPointsRadius": 3,
"tooltipValueFormatter": "",
"showSeparateAxis": false,
"axisTitle": "",
"axisPosition": "left",
"axisTicksFormatter": "",
"thresholds": [
{
"thresholdValueSource": "predefinedValue"
}
],
"comparisonSettings": {
"showValuesForComparison": true,
"comparisonValuesLabel": "",
"color": ""
}
},
"_hash": 0.019369294834221784
},
{
"name": "Alcohol",
"type": "timeseries",
"label": "Alcohol",
"color": "#f44336",
"settings": {
"excludeFromStacking": false,
"hideDataByDefault": false,
"disableDataHiding": false,
"removeFromLegend": false,
"showLines": true,
"fillLines": false,
"showPoints": false,
"showPointShape": "circle",
"pointShapeFormatter": "var size = radius * Math.sqrt(Math.PI) / 2;\nctx.moveTo(x - size, y - size);\nctx.lineTo(x + size, y + size);\nctx.moveTo(x - size, y + size);\nctx.lineTo(x + size, y - size);",
"showPointsLineWidth": 5,
"showPointsRadius": 3,
"tooltipValueFormatter": "",
"showSeparateAxis": false,
"axisTitle": "",
"axisPosition": "left",
"axisTicksFormatter": "",
"thresholds": [
{
"thresholdValueSource": "predefinedValue"
}
],
"comparisonSettings": {
"showValuesForComparison": true,
"comparisonValuesLabel": "",
"color": ""
}
},
"_hash": 0.10773096272975002
},
{
"name": "CO",
"type": "timeseries",
"label": "CO",
"color": "#ffc107",
"settings": {
"excludeFromStacking": false,
"hideDataByDefault": false,
"disableDataHiding": false,
"removeFromLegend": false,
"showLines": true,
"fillLines": false,
"showPoints": false,
"showPointShape": "circle",
"pointShapeFormatter": "var size = radius * Math.sqrt(Math.PI) / 2;\nctx.moveTo(x - size, y - size);\nctx.lineTo(x + size, y + size);\nctx.moveTo(x - size, y + size);\nctx.lineTo(x + size, y - size);",
"showPointsLineWidth": 5,
"showPointsRadius": 3,
"tooltipValueFormatter": "",
"showSeparateAxis": false,
"axisTitle": "",
"axisPosition": "left",
"axisTicksFormatter": "",
"thresholds": [
{
"thresholdValueSource": "predefinedValue"
}
],
"comparisonSettings": {
"showValuesForComparison": true,
"comparisonValuesLabel": "",
"color": ""
}
},
"_hash": 0.16983810931760046
},
{
"name": "NH4",
"type": "timeseries",
"label": "NH4",
"color": "#607d8b",
"settings": {
"excludeFromStacking": false,
"hideDataByDefault": false,
"disableDataHiding": false,
"removeFromLegend": false,
"showLines": true,
"fillLines": false,
"showPoints": false,
"showPointShape": "circle",
"pointShapeFormatter": "var size = radius * Math.sqrt(Math.PI) / 2;\nctx.moveTo(x - size, y - size);\nctx.lineTo(x + size, y + size);\nctx.moveTo(x - size, y + size);\nctx.lineTo(x + size, y - size);",
"showPointsLineWidth": 5,
"showPointsRadius": 3,
"tooltipValueFormatter": "",
"showSeparateAxis": false,
"axisTitle": "",
"axisPosition": "left",
"axisTicksFormatter": "",
"thresholds": [
{
"thresholdValueSource": "predefinedValue"
}
],
"comparisonSettings": {
"showValuesForComparison": true,
"comparisonValuesLabel": "",
"color": ""
}
},
"_hash": 0.8795072817187648
},
{
"name": "Acetone",
"type": "timeseries",
"label": "Acetone",
"color": "#607d8b",
"settings": {
"excludeFromStacking": false,
"hideDataByDefault": false,
"disableDataHiding": false,
"removeFromLegend": false,
"showLines": true,
"fillLines": false,
"showPoints": false,
"showPointShape": "circle",
"pointShapeFormatter": "var size = radius * Math.sqrt(Math.PI) / 2;\nctx.moveTo(x - size, y - size);\nctx.lineTo(x + size, y + size);\nctx.moveTo(x - size, y + size);\nctx.lineTo(x + size, y - size);",
"showPointsLineWidth": 5,
"showPointsRadius": 3,
"tooltipValueFormatter": "",
"showSeparateAxis": false,
"axisTitle": "",
"axisPosition": "left",
"axisTicksFormatter": "",
"thresholds": [
{
"thresholdValueSource": "predefinedValue"
}
],
"comparisonSettings": {
"showValuesForComparison": true,
"comparisonValuesLabel": "",
"color": ""
}
},
"_hash": 0.06822020169930765
},
{
"name": "Toluene",
"type": "timeseries",
"label": "Toluene",
"color": "#9c27b0",
"settings": {
"excludeFromStacking": false,
"hideDataByDefault": false,
"disableDataHiding": false,
"removeFromLegend": false,
"showLines": true,
"fillLines": false,
"showPoints": false,
"showPointShape": "circle",
"pointShapeFormatter": "var size = radius * Math.sqrt(Math.PI) / 2;\nctx.moveTo(x - size, y - size);\nctx.lineTo(x + size, y + size);\nctx.moveTo(x - size, y + size);\nctx.lineTo(x + size, y - size);",
"showPointsLineWidth": 5,
"showPointsRadius": 3,
"tooltipValueFormatter": "",
"showSeparateAxis": false,
"axisTitle": "",
"axisPosition": "left",
"axisTicksFormatter": "",
"thresholds": [
{
"thresholdValueSource": "predefinedValue"
}
],
"comparisonSettings": {
"showValuesForComparison": true,
"comparisonValuesLabel": "",
"color": ""
}
},
"_hash": 0.8240666057673744
}
]
}
],
"timewindow": {
"realtime": {
"timewindowMs": 60000
}
},
"showTitle": true,
"backgroundColor": "#fff",
"color": "rgba(0, 0, 0, 0.87)",
"padding": "8px",
"settings": {
"shadowSize": 4,
"fontColor": "#545454",
"fontSize": 10,
"xaxis": {
"showLabels": true,
"color": "#545454"
},
"yaxis": {
"showLabels": true,
"color": "#545454",
"tickDecimals": 2
},
"grid": {
"color": "#545454",
"tickColor": "#DDDDDD",
"verticalLines": true,
"horizontalLines": true,
"outlineWidth": 1
},
"stack": false,
"tooltipIndividual": false,
"showTooltip": true,
"timeForComparison": "previousInterval",
"xaxisSecond": {
"axisPosition": "top",
"showLabels": true
},
"comparisonEnabled": false,
"smoothLines": true,
"tooltipCumulative": false
},
"title": "CO2",
"dropShadow": true,
"enableFullscreen": true,
"titleStyle": {
"fontSize": "16px",
"fontWeight": 400
},
"useDashboardTimewindow": true,
"displayTimewindow": true,
"showTitleIcon": false,
"iconColor": "rgba(0, 0, 0, 0.87)",
"iconSize": "24px",
"titleTooltip": "",
"enableDataExport": true,
"widgetStyle": {},
"showLegend": true,
"legendConfig": {
"direction": "column",
"position": "bottom",
"sortDataKeys": false,
"showMin": false,
"showMax": false,
"showAvg": true,
"showTotal": false
}
},
"row": 0,
"col": 0,
"id": "11a80b8e-e962-de17-dc1c-cc1543aebf2c"
},
"12d74d94-f73a-83d4-b708-6b4a4d7ad5f0": {
"isSystemType": true,
"bundleAlias": "analogue_gauges",
"typeAlias": "radial_gauge_canvas_gauges",
"type": "latest",
"title": "New widget",
"image": null,
"description": null,
"sizeX": 6,
"sizeY": 5,
"config": {
"datasources": [
{
"type": "entity",
"name": null,
"entityAliasId": "4bf9b60c-91d0-61e1-ec10-d1bdca48100d",
"filterId": null,
"dataKeys": [
{
"name": "Light level",
"type": "timeseries",
"label": "Light level",
"color": "#2196f3",
"settings": {},
"_hash": 0.9444290605775362
}
]
}
],
"timewindow": {
"realtime": {
"timewindowMs": 60000
}
},
"showTitle": true,
"backgroundColor": "rgb(255, 255, 255)",
"color": "rgba(0, 0, 0, 0.87)",
"padding": "8px",
"settings": {
"startAngle": 45,
"ticksAngle": 270,
"showBorder": true,
"defaultColor": "#ffffff",
"needleCircleSize": 10,
"highlights": [],
"showUnitTitle": true,
"colorPlate": "#ffffff",
"colorMajorTicks": "#444",
"colorMinorTicks": "#666",
"minorTicks": 10,
"valueInt": 3,
"highlightsWidth": 15,
"valueBox": true,
"animation": true,
"animationDuration": 500,
"animationRule": "cycle",
"colorNeedleShadowUp": "rgba(255, 255, 255, 0)",
"numbersFont": {
"family": "Roboto",
"size": 18,
"style": "normal",
"weight": "500",
"color": "#616161"
},
"titleFont": {
"family": "Roboto",
"size": 24,
"style": "normal",
"weight": "500",
"color": "#888"
},
"unitsFont": {
"family": "Roboto",
"size": 22,
"style": "normal",
"weight": "500",
"color": "#616161"
},
"valueFont": {
"family": "Segment7Standard",
"size": 36,
"style": "normal",
"weight": "normal",
"shadowColor": "rgba(0, 0, 0, 0.49)",
"color": "#444"
},
"minValue": -20,
"colorNeedleShadowDown": "rgba(188,143,143,0.45)",
"colorValueBoxRect": "#888",
"colorValueBoxRectEnd": "#666",
"colorValueBoxBackground": "#babab2",
"colorValueBoxShadow": "rgba(0,0,0,1)",
"maxValue": 1000
},
"title": "Light level (Lux)",
"dropShadow": true,
"enableFullscreen": true,
"titleStyle": {
"fontSize": "16px",
"fontWeight": 400
},
"showTitleIcon": false,
"iconColor": "rgba(0, 0, 0, 0.87)",
"iconSize": "24px",
"titleTooltip": "Light level (Lux)",
"enableDataExport": true,
"widgetStyle": {},
"showLegend": false,
"titleIcon": ""
},
"row": 0,
"col": 0,
"id": "12d74d94-f73a-83d4-b708-6b4a4d7ad5f0"
},
"8b62ff45-cf96-5002-555a-a610115b545e": {
"isSystemType": true,
"bundleAlias": "alarm_widgets",
"typeAlias": "alarms_table",
"type": "alarm",
"title": "New widget",
"image": null,
"description": null,
"sizeX": 10.5,
"sizeY": 6.5,
"config": {
"timewindow": {
"realtime": {
"interval": 1000,
"timewindowMs": 86400000
},
"aggregation": {
"type": "NONE",
"limit": 200
}
},
"showTitle": true,
"backgroundColor": "rgb(255, 255, 255)",
"color": "rgba(0, 0, 0, 0.87)",
"padding": "4px",
"settings": {
"enableSelection": true,
"enableSearch": true,
"displayDetails": true,
"allowAcknowledgment": true,
"allowClear": true,
"displayPagination": true,
"defaultPageSize": 10,
"defaultSortOrder": "-createdTime",
"enableSelectColumnDisplay": true,
"enableStickyAction": false,
"enableFilter": true,
"enableStickyHeader": true
},
"title": "New Alarms table",
"dropShadow": true,
"enableFullscreen": true,
"titleStyle": {
"fontSize": "16px",
"fontWeight": 400,
"padding": "5px 10px 5px 10px"
},
"useDashboardTimewindow": false,
"showLegend": false,
"alarmSource": {
"type": "entity",
"name": null,
"entityAliasId": "4bf9b60c-91d0-61e1-ec10-d1bdca48100d",
"filterId": null,
"dataKeys": [
{
"name": "createdTime",
"type": "alarm",
"label": "Created time",
"color": "#2196f3",
"settings": {
"useCellStyleFunction": false,
"cellStyleFunction": "",
"useCellContentFunction": false,
"cellContentFunction": ""
},
"_hash": 0.021092237451093787
},
{
"name": "type",
"type": "alarm",
"label": "Type",
"color": "#f44336",
"settings": {
"useCellStyleFunction": false,
"cellStyleFunction": "",
"useCellContentFunction": false,
"cellContentFunction": ""
},
"_hash": 0.7323586880398418
},
{
"name": "severity",
"type": "alarm",
"label": "Severity",
"color": "#ffc107",
"settings": {
"useCellStyleFunction": false,
"useCellContentFunction": false
},
"_hash": 0.09927019860088193
},
{
"name": "status",
"type": "alarm",
"label": "Status",
"color": "#607d8b",
"settings": {
"useCellStyleFunction": false,
"cellStyleFunction": "",
"useCellContentFunction": false,
"cellContentFunction": ""
},
"_hash": 0.6588418951443418
},
{
"name": "Water level",
"type": "timeseries",
"label": "Water level",
"color": "#9c27b0",
"settings": {
"columnWidth": "0px",
"useCellStyleFunction": false,
"cellStyleFunction": "",
"useCellContentFunction": false,
"cellContentFunction": "",
"defaultColumnVisibility": "visible",
"columnSelectionToDisplay": "enabled",
"columnExportOption": "onlyVisible"
},
"_hash": 0.7204241527272135
}
]
},
"alarmSearchStatus": "ANY",
"alarmsPollingInterval": 5,
"showTitleIcon": false,
"titleIcon": "more_horiz",
"iconColor": "rgba(0, 0, 0, 0.87)",
"iconSize": "24px",
"titleTooltip": "",
"widgetStyle": {},
"displayTimewindow": true,
"actions": {},
"alarmStatusList": [],
"alarmSeverityList": [
"CRITICAL"
],
"alarmTypeList": [],
"searchPropagatedAlarms": false,
"datasources": []
},
"row": 0,
"col": 0,
"id": "8b62ff45-cf96-5002-555a-a610115b545e"
}
},
"states": {
"default": {
"name": "Air Quality",
"root": true,
"layouts": {
"main": {
"widgets": {
"11a80b8e-e962-de17-dc1c-cc1543aebf2c": {
"sizeX": 12,
"sizeY": 6,
"row": 0,
"col": 0
},
"12d74d94-f73a-83d4-b708-6b4a4d7ad5f0": {
"sizeX": 6,
"sizeY": 6,
"row": 0,
"col": 12
},
"8b62ff45-cf96-5002-555a-a610115b545e": {
"sizeX": 12,
"sizeY": 5,
"row": 6,
"col": 0
},
"cd052af7-efa9-2e58-8197-0b406f3723e7": {
"sizeX": 12,
"sizeY": 3,
"row": 6,
"col": 12
},
"32311d7a-cfd7-23ea-a3f1-7687a79e7cb5": {
"sizeX": 12,
"sizeY": 2,
"row": 9,
"col": 12
},
"a03a3244-2944-55f8-35fe-df348de691ed": {
"sizeX": 6,
"sizeY": 6,
"row": 0,
"col": 18
}
},
"gridSettings": {
"backgroundColor": "#eeeeee",
"columns": 24,
"margin": 10,
"backgroundSizeMode": "100%"
}
}
}
}
},
"entityAliases": {
"4bf9b60c-91d0-61e1-ec10-d1bdca48100d": {
"id": "4bf9b60c-91d0-61e1-ec10-d1bdca48100d",
"alias": "Alias",
"filter": {
"type": "singleEntity",
"resolveMultiple": false,
"singleEntity": {
"entityType": "DEVICE",
"id": "d62db230-25b5-11ec-a9e6-556e8dbef35c"
}
}
}
},
"filters": {},
"timewindow": {
"hideInterval": false,
"hideAggregation": false,
"hideAggInterval": false,
"hideTimezone": false,
"selectedTab": 0,
"realtime": {
"realtimeType": 0,
"timewindowMs": 60000,
"quickInterval": "CURRENT_DAY",
"interval": 1000
},
"aggregation": {
"type": "NONE",
"limit": 25000
}
},
"settings": {
"stateControllerId": "entity",
"showTitle": false,
"showDashboardsSelect": true,
"showEntitiesSelect": true,
"showDashboardTimewindow": true,
"showDashboardExport": true,
"toolbarAlwaysOpen": true
}
},
"name": "Air Quality"
}
Comments