Hardware components | ||||||
| × | 2 | ||||
| × | 2 | ||||
| × | 3 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 2 | ||||
| × | 2 | ||||
Software apps and online services | ||||||
| ||||||
| ||||||
|
In this project, I will be creating a cloud-connected sensor network using the TI LaunchPad development ecosystem. I will create two sub-1GHz RF sensor nodes, which will read the data from their respective moisture, print the latest readings to an LCD screen, encode the readings into JSON, then transmit the JSON-encoded payload over the sub-1GHz radio.
A cloud gateway would then transmit the payload to IBM cloud using a free MQTT server. Once in the cloud the sensor data would be processed, so it can be visualized in a meaning way on a dashboard.
The sensor data would also be used to send signal back to the actuator via another MQTT server.
I am currently working to add weather data support to the project, so the actuator turning on/off is not solely based on moisture data rather it would also consider temperature, wind speed and rain forecast. In this way I will be able to ensure the project delivers maximum efficiency, cost saving and reliability.
// The AIR430BoostFCC library uses the SPI library internally. Energia does not
// copy the library to the output folder unless it is referenced here.
// The order of includes is also important due to this fact.
#include <SPI.h>
#include <AIR430BoostFCC.h>
#include <aJSON.h>
#include <LCD_Launchpad.h>
#include <Filter.h>
// -----------------------------------------------------------------------------
/**
* Global data
*/
const char analogPin = A7;
const char* mySensor = "M1";//M1 = Moisture Sensor 1 in short
LCD_LAUNCHPAD myLCD;
// -----------------------------------------------------------------------------
// Main
// Simple function for scrolling messages across the on-board LCD
void scrollText(String text)
{
Serial.println("System Initialising");
myLCD.displayText(text);
Serial.println(text);
delay(400);
while(text != ""){
myLCD.clear();
text = text.substring(1);
Serial.println(text);
myLCD.displayText(text);
delay(175);
}
}
// SETUP function for sketch
void setup()
{
// Setup serial for debug printing.
Serial.begin(9600);
Serial.println("\n");
// The radio library uses the SPI library internally, this call initializes
// SPI/CSn and GDO0 lines. Also setup initial address, channel, and TX power.
Radio.begin(0x01, CHANNEL_1, POWER_MAX);
// Configure the on-board LCD of the MSP430FR6989 LaunchPad
myLCD.init();
// Print welcome messages to the LCD screen
//String welcome = "Hello "+String(myName);
//scrollText(welcome);
// Print sensor type to the LCD screen
String sensorType = String("Moisture Sensor1");
scrollText(sensorType);
// Configure RED_LED, which will be used for visual notification of RF TX
pinMode(GREEN_LED, OUTPUT);
digitalWrite(GREEN_LED, LOW); // set the LED off
Serial.println("Setup Complete. Starting Radio");
}
// LOOP function for sketch
void loop()
{
//Blink LED & TX segment on LCD to signify start of new sensor reading + RF TX
digitalWrite(GREEN_LED, HIGH);
myLCD.showSymbol(LCD_SEG_TX, 1);
//***Exponential Filtering.*** Initialise all the readings to 0:
ExponentialFilter<float>FilteredData(40, 0);
int RawData = analogRead(analogPin);
FilteredData.Filter(RawData);
int SmoothData = FilteredData.Current();
// Encode sensor readings into JSON
/*Usual Desired JSON encoded format:
{
"d":{
"d":{
"Name":"MOhd",
"Sensor":"Moisture",
"Data": 1234
}
}
but in this case I avoided this format as only 60 byte max can be transferred over RF.
Therefore I have available space for addition sensor data.We can always add more detail to
the Raw data when in cloud.
*/
aJsonObject *msg = aJson.createObject();
//aJsonObject *d = aJson.createObject();
//aJson.addItemToObject(msg, "d", d);
aJson.addStringToObject(msg, "Arafat", mySensor);//s represents sensor in short
//int sensorValue = average;
aJson.addNumberToObject(msg, "D", SmoothData);// D2 represents data from moisture sensor 2 in short.
// Typecast JSON message to char array, delete JSON object, then send via via RF
char* payload = aJson.print(msg);
aJson.deleteItem(msg);
Radio.transmit(ADDRESS_BROADCAST, (uint8_t*)payload, 60);
// Print latest sensor readings to LCD
myLCD.displayText(" ");
myLCD.displayText(String( SmoothData));
// Print JSON-encoded payload to terminal, then free char array
Serial.print("TX (DATA): ");
Serial.println(payload);
free(payload);
// Transmission success! Toggle off LED & clear TX segment on LCD
digitalWrite(GREEN_LED, LOW);
myLCD.showSymbol(LCD_SEG_TX, 0);
// Go to LPM3 for 1 second
//sleepSeconds(1);
delay(250);
}
// The AIR430BoostFCC library uses the SPI library internally. Energia does not
// copy the library to the output folder unless it is referenced here.
// The order of includes is also important due to this fact.
#include <SPI.h>
#include <AIR430BoostFCC.h>
#include <aJSON.h>
#include <LCD_Launchpad.h>
#include <Filter.h>
// -----------------------------------------------------------------------------
/**
* Global data
*/
const char analogPin = A7;
const char* mySensor = "M2";
LCD_LAUNCHPAD myLCD;
// -----------------------------------------------------------------------------
// Main
// Simple function for scrolling messages across the on-board LCD
void scrollText(String text)
{
Serial.println("System Initialising");
myLCD.displayText(text);
Serial.println(text);
delay(400);
while(text != ""){
myLCD.clear();
text = text.substring(1);
Serial.println(text);
myLCD.displayText(text);
delay(175);
}
}
// SETUP function for sketch
void setup()
{
// Setup serial for debug printing.
Serial.begin(9600);
Serial.println("\n");
// The radio library uses the SPI library internally, this call initializes
// SPI/CSn and GDO0 lines. Also setup initial address, channel, and TX power.
Radio.begin(0x01, CHANNEL_1, POWER_MAX);
// Configure the on-board LCD of the MSP430FR6989 LaunchPad
myLCD.init();
// Print welcome messages to the LCD screen
//String welcome = "Hello "+String(myName);
//scrollText(welcome);
// Print sensor type to the LCD screen
String sensorType = String("Moisture Sensor2");
scrollText(sensorType);
// Configure RED_LED, which will be used for visual notification of RF TX
pinMode(GREEN_LED, OUTPUT);
digitalWrite(GREEN_LED, LOW); // set the LED off
Serial.println("Setup Complete. Starting Radio");
}
// LOOP function for sketch
void loop()
{
//Blink LED & TX segment on LCD to signify start of new sensor reading + RF TX
digitalWrite(GREEN_LED, HIGH);
myLCD.showSymbol(LCD_SEG_TX, 1);
//***Exponential Filtering.*** Initialise all the readings to 0:
ExponentialFilter<float>FilteredData(40, 0);
int RawData = analogRead(analogPin);
FilteredData.Filter(RawData);
int SmoothData = FilteredData.Current();
// Encode sensor readings into JSON
/*Usual Desired JSON encoded format:
{
"d":{
"d":{
"Name":"MOhd",
"Sensor":"Moisture",
"Data": 1234
}
}
but in this case I avoided this format as only 60 byte max can be transferred over RF.
Therefore I have available space for addition sensor data.We can always add more detail to the Raw data when in cloud.
*/
aJsonObject *msg = aJson.createObject();
//aJsonObject *d = aJson.createObject();
//aJson.addItemToObject(msg, "d", d);
aJson.addStringToObject(msg, "Arafat", mySensor);//s represents sensor in short
//int sensorValue = average;
aJson.addNumberToObject(msg, "D", SmoothData);// D2 represents data from moisture sensor 2 in short.
// Typecast JSON message to char array, delete JSON object, then send via via RF
char* payload = aJson.print(msg);
aJson.deleteItem(msg);
Radio.transmit(ADDRESS_BROADCAST, (uint8_t*)payload, 60);
// Print latest sensor readings to LCD
myLCD.displayText(" ");
myLCD.displayText(String( SmoothData));
// Print JSON-encoded payload to terminal, then free char array
Serial.print("TX (DATA): ");
Serial.println(payload);
free(payload);
// Transmission success! Toggle off LED & clear TX segment on LCD
digitalWrite(GREEN_LED, LOW);
myLCD.showSymbol(LCD_SEG_TX, 0);
// Go to LPM3 for 1 second
//sleepSeconds(1);
delay(300);
}
#include <SPI.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <aJSON.h>
// -----------------------------------------------------------------------------
/**
* Global data
*/
const char* myName = "Arafat";
const char* myActuator = "Pump";
const char pumpStatus = 19;
const char pumpControl = 18;
const char pumpRelay1 = 17;
char ssid[] = "maaislam"; // LenovoWIFI your network name also called SSID
char password[] = "123asdfgh"; // your network password
char server[] = "broker.hivemq.com"; // MQTTServer to use
WiFiClient wifiClient; // Connecting to MQTT broker via Wi-Fi
PubSubClient client(server, 1883, callback, wifiClient); // Initialize MQTT client
void callback(char* topic, byte* payload, unsigned int length) {
if ((char)payload[0] == '1') {
digitalWrite(pumpRelay1, HIGH);// Turn the Relay on (Note that LOW is the voltage level
digitalWrite(pumpControl, HIGH);
} else {
//digitalWrite(pumpRelay,LOW); // Turn the Relay off by making the voltage HIGH
digitalWrite(pumpControl, LOW);
digitalWrite(pumpRelay1, LOW);
}
Serial.print("Message arrived in topic: ");
Serial.println(topic);
delay(250);
Serial.print("Message:");
for (int i = 0; i < length; i++) {
Serial.println((char)payload[i]);
}
Serial.println();
// Switch on the LED if an 1 was received as first character
mqttPublish();
}
void mqttSubscribe()
{
// Reconnect if the connection was lost
if (!client.connected()) {
Serial.println("Disconnected. Reconnecting....");
client.connect("123asdfg_gateway2");
if(client.subscribe("maaislamPumpControl")) {
Serial.println("Subscription successfull");
}
}
// Check if any message were received
// on the subscribed topic
}
void mqttPublish()
{
// Encode Switch status into JSON before publishing
/* JSON encoded format sample:
{
"d":{
"d":{
"Name":"MOhd",
"Sensor":"Moisture",
"Data": 1234
}
}*/
aJsonObject *msg = aJson.createObject();
aJsonObject *d = aJson.createObject();
aJson.addItemToObject(msg, "d", d);
aJson.addStringToObject(d, "Name", myName);
aJson.addStringToObject(d, "Actuator", myActuator);
int switchState = digitalRead(pumpStatus);
aJson.addNumberToObject(d, "Data", switchState);
// Typecast JSON message to char array and delete JSON object
char* payload = aJson.print(msg);
//MQTT Publish
if ( client.publish("maaislamPumpStatus",(char*)payload))
{
digitalWrite(YELLOW_LED, HIGH);
Serial.println("MQTT Publish success!");
digitalWrite(YELLOW_LED, LOW);
//Serial print payload
Serial.println(payload);
free(payload);
}
else
{
Serial.println("MQTT Publish failed!");
}
aJson.deleteItem(msg);
}
void PinLedSetup()
{
//pin mode setup
pinMode(pumpRelay1, OUTPUT);
digitalWrite(pumpRelay1, LOW);
pinMode(pumpStatus, INPUT);
digitalWrite(pumpStatus, LOW);
pinMode(pumpControl, OUTPUT);
digitalWrite(pumpControl, LOW);
pinMode(RED_LED, OUTPUT); // RED LED Notifier for MQTT Receiption
digitalWrite(RED_LED, LOW);
pinMode(GREEN_LED, OUTPUT); // GREEN LED Notifier for Wi-Fi connected
digitalWrite(GREEN_LED, LOW);
pinMode(YELLOW_LED, OUTPUT); // YELLOW LED Notifier for MQTT Pub successful
digitalWrite(YELLOW_LED, LOW);
}
//
// -----------------------------------------------------------------------------
// Main
void setup()
{
PinLedSetup();
// Setup serial for debug printing.
Serial.begin(115200);
Serial.print("Attempting to connect to Network named: ");
// print the network name (SSID);
Serial.println(ssid);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
WiFi.begin(ssid, password);
while ( WiFi.status() != WL_CONNECTED) {
// print dots while we wait to connect
Serial.print(".");
delay(300);}
// Connected to Wi-Fi!
Serial.println("\nYou're connected to the network");
Serial.println("Waiting for an ip address");
// Wait for IP Address
while (WiFi.localIP() == INADDR_NONE) {
// print dots while we wait for an ip addresss
Serial.print(".");
delay(300);
}
Serial.println("\nIP Address obtained");
// We are connected and have an IP address. Print the WiFi status.
printWifiStatus();
}
void loop()
{
mqttSubscribe();
client.poll();
delay(250);
}
void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your WiFi IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print the received signal strength:
digitalWrite(GREEN_LED, HIGH); // Connected to WiFi LED
//delay(1000);
}
/* --COPYRIGHT--,BSD
* Copyright (c) 2015, Texas Instruments Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* --/COPYRIGHT--*/
/*******************************************************************************
*
* LCD_Launchpad.cpp
*
* Hardware abstraction layer for the FH-1138P Segmented LCD
* on MSP-EXP430FR6989 and MSP-EXP430FR4133
*
* February 2015
* E. Chen
*
* June 2015 StefanSch: Adopted for Energia
*
******************************************************************************/
#include "LCD_Launchpad.h"
#include "string.h"
//***** Defines ***************************************************************
// Define word access definitions to LCD memories
#ifndef LCDMEMW
#define LCDMEMW ((int*) LCDMEM) /* LCD Memory (for C) */
#endif
// Number of character positions in the display
#define LCD_NUM_CHAR 6
#if defined(__MSP430_HAS_LCD_C__)
//Change based on LCD Memory locations
#define pos1 9 /* Digit A1 begins at S18 */
#define pos2 5 /* Digit A2 begins at S10 */
#define pos3 3 /* Digit A3 begins at S6 */
#define pos4 18 /* Digit A4 begins at S36 */
#define pos5 14 /* Digit A5 begins at S28 */
#define pos6 7 /* Digit A6 begins at S14 */
// Memory locations for LCD characters
const uint8_t digit_loc[ LCD_NUM_CHAR ] =
{
pos1, // Position 1 = Digit A1
pos2, // Position 2 = Digit A2
pos3, // Position 3 = Digit A3
pos4, // Position 4 = Digit A4
pos5, // Position 5 = Digit A5
pos6 // Position 6 = Digit A6
};
const uint8_t symbol_loc[] [2] =
{
{ 2, 0x01}, // LCD_SEG_MARK,
{ 2, 0x02}, // LCD_SEG_R,
{ 2, 0x04}, // LCD_SEG_HEART,
{ 2, 0x08}, // LCD_SEG_CLOCK,
{ 4, 0x01}, // LCD_SEG_DOT3,
{ 4, 0x04}, // LCD_SEG_RADIO,
{ 6, 0x01}, // LCD_SEG_DOT2,
{ 6, 0x04}, // LCD_SEG_COLON2,
{ 8, 0x01}, // LCD_SEG_RX,
{ 8, 0x04}, // LCD_SEG_TX,
{ 10, 0x01}, // LCD_SEG_DOT1,
{ 10, 0x04}, // LCD_SEG_MINUS1,
{ 13, 0x10}, // LCD_SEG_BAT_POL,
{ 13, 0x20}, // LCD_SEG_BAT1,
{ 13, 0x40}, // LCD_SEG_BAT3,
{ 13, 0x80}, // LCD_SEG_BAT5,
{ 15, 0x01}, // LCD_SEG_DOT5,
{ 15, 0x04}, // LCD_SEG_DEG5,
{ 17, 0x10}, // LCD_SEG_BAT_ENDS,
{ 17, 0x20}, // LCD_SEG_BAT0,
{ 17, 0x40}, // LCD_SEG_BAT2,
{ 17, 0x80}, // LCD_SEG_BAT4,
{ 19, 0x01}, // LCD_SEG_DOT4,
{ 19, 0x04}, // LCD_SEG_COLON4,
};
// LCD memory map for numeric digits
const char digit[10][2] =
{
{0xFC, 0x28}, /* "0" LCD segments a+b+c+d+e+f+k+q */
{0x60, 0x20}, /* "1" */
{0xDB, 0x00}, /* "2" */
{0xF3, 0x00}, /* "3" */
{0x67, 0x00}, /* "4" */
{0xB7, 0x00}, /* "5" */
{0xBF, 0x00}, /* "6" */
{0xE4, 0x00}, /* "7" */
{0xFF, 0x00}, /* "8" */
{0xF7, 0x00} /* "9" */
};
// LCD memory map for uppercase letters
const char alphabetBig[26][2] =
{
{0xEF, 0x00}, /* "A" LCD segments a+b+c+e+f+g+m */
{0xF1, 0x50}, /* "B" */
{0x9C, 0x00}, /* "C" */
{0xF0, 0x50}, /* "D" */
{0x9F, 0x00}, /* "E" */
{0x8F, 0x00}, /* "F" */
{0xBD, 0x00}, /* "G" */
{0x6F, 0x00}, /* "H" */
{0x90, 0x50}, /* "I" */
{0x78, 0x00}, /* "J" */
{0x0E, 0x22}, /* "K" */
{0x1C, 0x00}, /* "L" */
{0x6C, 0xA0}, /* "M" */
{0x6C, 0x82}, /* "N" */
{0xFC, 0x00}, /* "O" */
{0xCF, 0x00}, /* "P" */
{0xFC, 0x02}, /* "Q" */
{0xCF, 0x02}, /* "R" */
{0xB7, 0x00}, /* "S" */
{0x80, 0x50}, /* "T" */
{0x7C, 0x00}, /* "U" */
{0x0C, 0x28}, /* "V" */
{0x6C, 0x0A}, /* "W" */
{0x00, 0xAA}, /* "X" */
{0x00, 0xB0}, /* "Y" */
{0x90, 0x28} /* "Z" */
};
LCD_LAUNCHPAD::LCD_LAUNCHPAD(void) {
}
void LCD_LAUNCHPAD::init()
{
LCDCCTL0 &= ~LCDON;
LCDCCTL0 = (LCDMX0 | LCDMX1
| LCDLP | LCDSON | LCDDIV_0 | LCDPRE_4);
LCDCPCTL0 |= 0xFFFC;
LCDCPCTL1 |= 0xFC3F;
LCDCPCTL2 |= 0x0FFF;
LCDCCTL0 &= ~LCDON;
LCDCVCTL &= ~(VLCDEXT | LCDREXT | LCDEXTBIAS |R03EXT);
// Set VLCD voltage to 3.20v
LCDCVCTL &= ~VLCD_15;
LCDCVCTL |= VLCD3;
// Enable charge pump and select internal reference for it
LCDCVCTL |= LCDCPEN;
LCDCVCTL &= ~VLCDREF_3;
LCDCVCTL |= VLCDREF_0;
LCDCCPCTL &= ~(LCDCPCLKSYNC);
LCDCCPCTL &= ~(LCDCPDIS7 | LCDCPDIS6 | LCDCPDIS5
| LCDCPDIS4 | LCDCPDIS3 |
LCDCPDIS2 | LCDCPDIS1 |
LCDCPDIS0);
LCDCCPCTL |= LCDCPCLKSYNC | 0;
// Clear LCD memory
LCDCMEMCTL |= LCDCLRM;
//Turn LCD on
LCDCCTL0 |= LCDON;
// //Serial.println("HERE!");
}
#endif /* defined(__MSP430_HAS_LCD_C__) */
#if defined(__MSP430_HAS_LCD_E__)
//Change based on LCD Memory locations
#define pos1 4 /* Digit A1 begins at S8 */
#define pos2 6 /* Digit A2 begins at S12 */
#define pos3 8 /* Digit A3 begins at S16 */
#define pos4 10 /* Digit A4 begins at S20 */
#define pos5 2 /* Digit A5 begins at S4 */
#define pos6 18 /* Digit A6 begins at S36 */
// Memory locations for LCD characters
const uint8_t digit_loc[ LCD_NUM_CHAR ] =
{
pos1, // Position 1 = Digit A1
pos2, // Position 2 = Digit A2
pos3, // Position 3 = Digit A3
pos4, // Position 4 = Digit A4
pos5, // Position 5 = Digit A5
pos6 // Position 6 = Digit A6
};
const uint8_t symbol_loc[] [2] =
{
{ 12, 0x01}, // LCD_SEG_MARK,
{ 12, 0x02}, // LCD_SEG_R,
{ 12, 0x04}, // LCD_SEG_HEART,
{ 12, 0x08}, // LCD_SEG_CLOCK,
{ 9, 0x01}, // LCD_SEG_DOT3,
{ 9, 0x04}, // LCD_SEG_RADIO,
{ 10, 0x01}, // LCD_SEG_DOT2,
{ 10, 0x04}, // LCD_SEG_COLON2,
{ 19, 0x01}, // LCD_SEG_RX,
{ 19, 0x04}, // LCD_SEG_TX,
{ 5, 0x01}, // LCD_SEG_DOT1,
{ 5, 0x04}, // LCD_SEG_MINUS1,
{ 12, 0x10}, // LCD_SEG_BAT_POL,
{ 12, 0x20}, // LCD_SEG_BAT1,
{ 12, 0x40}, // LCD_SEG_BAT3,
{ 12, 0x80}, // LCD_SEG_BAT5,
{ 3, 0x01}, // LCD_SEG_DOT5,
{ 3, 0x04}, // LCD_SEG_DEG5,
{ 13, 0x01}, // LCD_SEG_BAT_ENDS,
{ 13, 0x02}, // LCD_SEG_BAT0,
{ 13, 0x04}, // LCD_SEG_BAT2,
{ 13, 0x08}, // LCD_SEG_BAT4,
{ 11, 0x01}, // LCD_SEG_DOT4,
{ 11, 0x04}, // LCD_SEG_COLON4,
};
// LCD memory map for numeric digits
const char digit[10][2] =
{
{0xFC, 0x28}, /* "0" LCD segments a+b+c+d+e+f+k+q */
{0x60, 0x20}, /* "1" */
{0xDB, 0x00}, /* "2" */
{0xF3, 0x00}, /* "3" */
{0x67, 0x00}, /* "4" */
{0xB7, 0x00}, /* "5" */
{0xBF, 0x00}, /* "6" */
{0xE4, 0x00}, /* "7" */
{0xFF, 0x00}, /* "8" */
{0xF7, 0x00} /* "9" */
};
// LCD memory map for uppercase letters
const char alphabetBig[26][2] =
{
{0xEF, 0x00}, /* "A" LCD segments a+b+c+e+f+g+m */
{0xF1, 0x50}, /* "B" */
{0x9C, 0x00}, /* "C" */
{0xF0, 0x50}, /* "D" */
{0x9F, 0x00}, /* "E" */
{0x8F, 0x00}, /* "F" */
{0xBD, 0x00}, /* "G" */
{0x6F, 0x00}, /* "H" */
{0x90, 0x50}, /* "I" */
{0x78, 0x00}, /* "J" */
{0x0E, 0x22}, /* "K" */
{0x1C, 0x00}, /* "L" */
{0x6C, 0xA0}, /* "M" */
{0x6C, 0x82}, /* "N" */
{0xFC, 0x00}, /* "O" */
{0xCF, 0x00}, /* "P" */
{0xFC, 0x02}, /* "Q" */
{0xCF, 0x02}, /* "R" */
{0xB7, 0x00}, /* "S" */
{0x80, 0x50}, /* "T" */
{0x7C, 0x00}, /* "U" */
{0x0C, 0x28}, /* "V" */
{0x6C, 0x0A}, /* "W" */
{0x00, 0xAA}, /* "X" */
{0x00, 0xB0}, /* "Y" */
{0x90, 0x28} /* "Z" */
};
LCD_LAUNCHPAD::LCD_LAUNCHPAD(void) {
}
void LCD_LAUNCHPAD::init()
{
LCDCTL0 &= ~LCDON;
LCDPCTL0 |= 0xFFFF;
LCDPCTL1 |= 0x07FF;
LCDPCTL2 |= 0x00F0;
LCDCTL0 = (LCDMX0 | LCDMX1 | LCDSSEL_0
| LCDLP | LCDSON | LCDDIV_2);
// LCD Operation - Mode 3, internal 3.02v, charge pump 256Hz
LCDVCTL = (LCDREFEN| LCDCPEN | VLCD_6 |
LCDCPFSEL3 | LCDCPFSEL2 | LCDCPFSEL1 | LCDCPFSEL0);
// Clear LCD memory
LCDMEMCTL |= LCDCLRM | LCDCLRBM;
// Configure COMs and SEGs
// L0 = COM0, L1 = COM1, L2 = COM2, L3 = COM3
//LCD_E_setPinAsCOM( LCD_E_BASE, LCD_E_SEGMENT_LINE_0, );
//LCD_E_setPinAsCOM( LCD_E_BASE, LCD_E_SEGMENT_LINE_1, LCD_E_MEMORY_COM1 );
//LCD_E_setPinAsCOM( LCD_E_BASE, LCD_E_SEGMENT_LINE_2, LCD_E_MEMORY_COM2 );
//LCD_E_setPinAsCOM( LCD_E_BASE, LCD_E_SEGMENT_LINE_3, LCD_E_MEMORY_COM3 );
LCDM0W = 0x8421;
LCDBM0W = 0x8421;
// Select to display main LCD memory
LCDMEMCTL &= ~LCDDISP;
//LCDMEMCTL |= 0;
// Turn blinking features off
LCDBLKCTL &= ~(LCDBLKPRE2 | LCDBLKPRE1 | LCDBLKPRE0 | LCDBLKMOD_3);
LCDBLKCTL |= (LCDBLKPRE2 | LCDBLKMOD_0);
//Turn LCD on
LCDCTL0 |= LCDON;
}
#endif /* defined(__MSP430_HAS_LCD_E__) */
/*
* Display input string across LCD screen
*/
void LCD_LAUNCHPAD::displayText(String s)
{
LCD_LAUNCHPAD::displayText(s, 0);
}
void LCD_LAUNCHPAD::displayText(String s, char pos)
{
int length = s.length();
int i;
for (i=0; i<pos; i++)
{
showChar(' ', i);
}
for (i=pos; i<length; i++)
{
showChar(s.charAt(i-pos), i);
}
}
void LCD_LAUNCHPAD::displayText(char *s, char pos)
{
int length = strlen(s);
int i;
for (i=0; i<pos; i++)
{
showChar(' ', i);
}
for (i=pos; i<length; i++)
{
showChar(s[i-pos], i);
}
}
/*
* Scrolls input string across LCD screen from left to right
*/
void LCD_LAUNCHPAD::displayScrollText(char *s, unsigned int wait)
{
int length = strlen(s);
int i;
int x = 5;
char buffer[] = " ";
for (i=0; i<length+7; i++)
{
int t;
for (t=0; t<6; t++)
buffer[t] = ' ';
int j;
for (j=0; j<length; j++)
{
if (((x+j) >= 0) && ((x+j) < 6))
buffer[x+j] = s[j];
}
x--;
showChar(buffer[0], 0);
showChar(buffer[1], 1);
showChar(buffer[2], 2);
showChar(buffer[3], 3);
showChar(buffer[4], 4);
showChar(buffer[5], 5);
delay(wait);
}
}
size_t LCD_LAUNCHPAD::write(uint8_t c) {
static char position = 0;
if (c == '\n') {position = 0; return (c);}
if (c == '\r') {position = 0; return (c);}
if (position >= LCD_NUM_CHAR) position = 0;
LCD_LAUNCHPAD::showChar(c, position++);
return (c);
}
/*
* Displays input character at given LCD digit/position
* Only spaces, numeric digits, and uppercase letters are accepted characters
*/
void LCD_LAUNCHPAD::showChar(char c, int position)
{
position = digit_loc[position];
if (c >= 0 && c <= 9) c+= '0';
if (c >= 'a' && c <= 'z') c-= ('a' - 'A');
if (c == ' ')
{
// Display space
LCDMEM[position] = 0;
LCDMEM[position+1] = 0;
}
else if (c >= '0' && c <= '9')
{
// Display digit
LCDMEM[position] = digit[c-48][0];
LCDMEM[position+1] = digit[c-48][1];
}
else if (c >= 'A' && c <= 'Z')
{
// Display alphabet
LCDMEM[position] = alphabetBig[c-65][0];
LCDMEM[position+1] = alphabetBig[c-65][1];
}
else
{
// Turn all segments on if character is not a space, digit, or uppercase letter
LCDMEM[position] = 0xFF;
LCDMEM[position+1] = 0xFF;
}
}
/*
* Displays the given Symbol
*/
void LCD_LAUNCHPAD::showSymbol(char symbol, int status)
{
if (status)
LCDMEM[symbol_loc[symbol][0]] |= symbol_loc[symbol][1]; // switch on
else
LCDMEM[symbol_loc[symbol][0]] &= ~symbol_loc[symbol][1]; // switch off
}
/*
* Clears memories to all 6 digits on the LCD
*/
void LCD_LAUNCHPAD::clear()
{
#if defined(__MSP430_HAS_LCD_C__)
LCDCMEMCTL |= (LCDCLRM|LCDCLRBM);
#endif /* defined(__MSP430_HAS_LCD_C__) */
#if defined(__MSP430_HAS_LCD_E__)
LCDMEMCTL |= (LCDCLRM|LCDCLRBM);
LCDM0W = 0x8421;
LCDBM0W = 0x8421;
#endif /* defined(__MSP430_HAS_LCD_E__) */
}
[{"id":"2e2bc85.6e69438","type":"tab","label":"SensorDataManipulation","disabled":false,"info":""},{"id":"a74037fd.22229","type":"tab","label":"Pump_Control","disabled":false,"info":""},{"id":"8e39dbe1.c473b","type":"tab","label":"Weather Control (Future Dev.)","disabled":false,"info":""},{"id":"f4aa86c7.144588","type":"mqtt-broker","z":"","name":"","broker":"broker.hivemq.com","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""},{"id":"d083b646.6dc7d8","type":"ui_base","theme":{"name":"theme-custom","lightTheme":{"default":"#0094CE","baseColor":"#0094CE","baseFont":"-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif","edited":true,"reset":false},"darkTheme":{"default":"#097479","baseColor":"#097479","baseFont":"-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif","edited":true,"reset":false},"customTheme":{"name":"MY Custom Theme","default":"#4B7930","baseColor":"#2099d8","baseFont":"-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif","reset":false},"themeState":{"base-color":{"default":"#2099d8","value":"#2099d8","edited":true},"page-titlebar-backgroundColor":{"value":"#2099d8","edited":false},"page-backgroundColor":{"value":"#000000","edited":true},"page-sidebar-backgroundColor":{"value":"#000000","edited":true},"group-textColor":{"value":"#5db8e7","edited":false},"group-borderColor":{"value":"#2b2b2d","edited":true},"group-backgroundColor":{"value":"#2b2b2d","edited":true},"widget-textColor":{"value":"#ffffff","edited":true},"widget-backgroundColor":{"value":"#2099d8","edited":false},"widget-borderColor":{"value":"#2b2b2d","edited":true},"base-font":{"value":"-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif"}},"angularTheme":{"primary":"indigo","accents":"blue","warn":"red","background":"grey"}},"site":{"name":"My iot Dashboard","hideToolbar":"false","allowSwipe":"false","lockMenu":"false","allowTempTheme":"true","dateFormat":"DD/MM/YYYY","sizes":{"sx":48,"sy":48,"gx":6,"gy":6,"cx":6,"cy":6,"px":0,"py":0}}},{"id":"e318e60c.26e868","type":"ui_group","z":"","name":"Moisture Chart 2","tab":"6642d783.4c9c38","order":2,"disp":true,"width":"8","collapse":false},{"id":"630aa2ae.8c6cec","type":"ui_spacer","name":"spacer","group":"454c2947.1fa2c8","order":1,"width":1,"height":1},{"id":"6642d783.4c9c38","type":"ui_tab","z":"","name":"Moisture Details","icon":"dashboard","order":2,"disabled":false,"hidden":false},{"id":"b8708033.94d86","type":"ui_group","z":"","name":"Field Moisture Gauge","tab":"3a5681c6.69c0a6","order":3,"disp":true,"width":"6","collapse":false},{"id":"160544bc.95ef4b","type":"ui_group","z":"","name":"Field Moisture Level","tab":"3a5681c6.69c0a6","order":4,"disp":true,"width":"6","collapse":false},{"id":"973b4abf.8634a8","type":"ui_group","z":"","name":"Current Weather","tab":"3b35c1b2.64028e","order":4,"disp":true,"width":"6","collapse":false},{"id":"b5cb8ceb.ffc","type":"ui_group","z":"","name":"Hourly Weather Forecast","tab":"3b35c1b2.64028e","order":3,"disp":true,"width":"6","collapse":false},{"id":"c96008f2.e6b69","type":"ui_group","z":"","name":"Moisture Chart 1","tab":"6642d783.4c9c38","order":1,"disp":true,"width":"8","collapse":false},{"id":"3a5681c6.69c0a6","type":"ui_tab","z":"","name":"Pump Status ","icon":"dashboard","order":1,"disabled":false,"hidden":false},{"id":"bec8b727.033f","type":"ui_group","z":"","name":"Pump Status","tab":"3a5681c6.69c0a6","order":5,"disp":false,"width":"12","collapse":false},{"id":"3b35c1b2.64028e","type":"ui_tab","z":"","name":"Weather ","icon":"dashboard","order":3,"disabled":false,"hidden":false},{"id":"350b09af.e3ed46","type":"ui_group","z":"","name":"Moisture Sensor 1","tab":"3a5681c6.69c0a6","order":1,"disp":true,"width":"6","collapse":false},{"id":"9be2405.535364","type":"ui_group","z":"","name":"Moisture Sensor 2","tab":"3a5681c6.69c0a6","order":2,"disp":true,"width":"6","collapse":false},{"id":"a3dae5fe.27d948","type":"mqtt in","z":"2e2bc85.6e69438","name":"MQTT Receiver","topic":"SensorDataSaad","qos":"2","datatype":"auto","broker":"f4aa86c7.144588","x":142.74996948242188,"y":334.5000305175781,"wires":[["968f0139.ea5db","322ef2a1.623236"]]},{"id":"968f0139.ea5db","type":"json","z":"2e2bc85.6e69438","name":"","property":"payload","action":"","pretty":true,"x":318.7499694824219,"y":334.25001525878906,"wires":[["5be35248.b98b4c"]]},{"id":"43ae60ee.b38ee","type":"function","z":"2e2bc85.6e69438","name":"Get Moisture Reading 1","func":"\n//For Resistive Moisture Sensor\nmsg.payload = Number(msg.payload.D);\nmsg.payload =(msg.payload)*(100/1638);\nreturn msg;\n","outputs":1,"noerr":0,"x":242.37307739257812,"y":512.0951232910156,"wires":[["bb964cfb.c46db"]]},{"id":"6c7734c6.b4142c","type":"function","z":"2e2bc85.6e69438","name":"Pump on/off","func":"\n\nif (msg.payload < 25 )\n\n{\nmsg.payload = \"Moisture Low.So Pump is Turned ON\"\n}\nelse if (msg.payload >25 )\n{\n msg.payload = \"Moisture Normal. Pump Turned OFF\"\n}\n\nelse {\n return null;\n}\nreturn msg;\n","outputs":1,"noerr":0,"x":209.17143630981445,"y":984.7641334533691,"wires":[["8134b57a.9ea6f8","dc7df5c.1dcca08"]]},{"id":"8134b57a.9ea6f8","type":"rbe","z":"2e2bc85.6e69438","name":"Control","func":"rbe","gap":"","start":"","inout":"out","property":"payload","x":493.17156982421875,"y":982.9640502929688,"wires":[["73646a62.3c6c54"]]},{"id":"8ace368b.d24848","type":"ui_chart","z":"2e2bc85.6e69438","name":"MS2 Chart","group":"e318e60c.26e868","order":1,"width":"8","height":"5","label":"","chartType":"line","legend":"false","xformat":"auto","interpolate":"linear","nodata":"","dot":false,"ymin":"0","ymax":"100","removeOlder":"10","removeOlderPoints":"100","removeOlderUnit":"60","cutout":0,"useOneColor":false,"colors":["#1f75b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"outputs":1,"x":889.1517333984375,"y":572.380859375,"wires":[[]]},{"id":"8ccebab4.529508","type":"ui_gauge","z":"2e2bc85.6e69438","name":"MS Gauge","group":"b8708033.94d86","order":1,"width":"6","height":"5","gtype":"gage","title":"","label":"","format":"{{msg.payload.toFixed(0)}}%","min":0,"max":"100","colors":["#cf423f","#ff6800","#2099d8"],"seg1":"20","seg2":"40","x":718.9927978515625,"y":727.1427612304688,"wires":[]},{"id":"fdafb5f7.60c618","type":"ui_gauge","z":"2e2bc85.6e69438","name":"MS Wave","group":"160544bc.95ef4b","order":1,"width":"6","height":"5","gtype":"wave","title":"","label":"%","format":"{{value}}","min":0,"max":"100","colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","x":717.6594848632812,"y":802.6149291992188,"wires":[]},{"id":"bb964cfb.c46db","type":"smooth","z":"2e2bc85.6e69438","name":"","property":"payload","action":"mean","count":"10","round":"0","mult":"single","x":458.373104095459,"y":512.0950918197632,"wires":[["2c0338ac.ab6d58"]]},{"id":"73646a62.3c6c54","type":"ui_toast","z":"2e2bc85.6e69438","position":"bottom right","displayTime":"5","highlight":"","outputs":0,"ok":"OK","cancel":"","topic":"iot Dashboard","name":"","x":731.5714416503906,"y":982.9641094207764,"wires":[]},{"id":"5cd8e61b.4eccf8","type":"function","z":"2e2bc85.6e69438","name":"Get Moisture Reading 2","func":"\nmsg.payload = Number(msg.payload.D);\nmsg.payload =100- ((msg.payload-650)/(1340-650)*100);\nreturn msg;\n\n/*For Resistive Moisture Sensor\nmsg.payload = Number(msg.payload.d.Data);\nmsg.payload =(msg.payload)*(100/4095);\nreturn msg;\n*/","outputs":1,"noerr":0,"x":255.93026733398438,"y":573.7237854003906,"wires":[["301f7b80.bcf064"]]},{"id":"301f7b80.bcf064","type":"smooth","z":"2e2bc85.6e69438","name":"","property":"payload","action":"mean","count":"10","round":"0","mult":"single","x":469.93023681640625,"y":573.7237854003906,"wires":[["c8865255.80e26"]]},{"id":"2c0338ac.ab6d58","type":"function","z":"2e2bc85.6e69438","name":"Moisture Sensor 1","func":"global.set(\"MoistureSensor1\" ,msg.payload);\nreturn msg;","outputs":1,"noerr":0,"x":664.2500610351562,"y":511.69281005859375,"wires":[["8682f0da.de5138","3b72e2dd.de18d6"]]},{"id":"c8865255.80e26","type":"function","z":"2e2bc85.6e69438","name":"Moisture Sensor 2","func":"\n\nglobal.set(\"MoistureSensor2\" ,msg.payload);\nreturn msg;","outputs":1,"noerr":0,"x":661.4856567382812,"y":573.5929565429688,"wires":[["8ace368b.d24848","17e74f8b.a59f9"]]},{"id":"5187d824.8b6f8","type":"link in","z":"2e2bc85.6e69438","name":"","links":["eaf880d9.935aa"],"x":82.80160522460938,"y":512.6381530761719,"wires":[["43ae60ee.b38ee"]]},{"id":"eaf880d9.935aa","type":"link out","z":"2e2bc85.6e69438","name":"Sensor1 Data","links":["5187d824.8b6f8"],"x":580.3928833007812,"y":292.21429443359375,"wires":[]},{"id":"27f6b92d.59c9fe","type":"link out","z":"2e2bc85.6e69438","name":"Senson2 Data","links":["86d45bd0.78aae8"],"x":577.5357055664062,"y":370.9285888671875,"wires":[]},{"id":"86d45bd0.78aae8","type":"link in","z":"2e2bc85.6e69438","name":"","links":["27f6b92d.59c9fe"],"x":81.87312316894531,"y":571.0381164550781,"wires":[["5cd8e61b.4eccf8"]]},{"id":"8682f0da.de5138","type":"ui_chart","z":"2e2bc85.6e69438","name":"MS1 Chart","group":"c96008f2.e6b69","order":2,"width":"8","height":"5","label":"","chartType":"line","legend":"false","xformat":"auto","interpolate":"linear","nodata":"","dot":false,"ymin":"0","ymax":"100","removeOlder":"1","removeOlderPoints":"100","removeOlderUnit":"60","cutout":0,"useOneColor":false,"colors":["#1f75b4","#aec7e8","#ff7f0e","#008000","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"outputs":1,"x":888.39453125,"y":511.36669921875,"wires":[[]]},{"id":"2bf932b9.b1547e","type":"inject","z":"2e2bc85.6e69438","name":"Clock","topic":"","payload":"","payloadType":"date","repeat":"1","crontab":"","once":true,"onceDelay":0.1,"x":154.62498474121094,"y":802.5,"wires":[["eb13304a.60257"]]},{"id":"eb13304a.60257","type":"function","z":"2e2bc85.6e69438","name":"Average of Both Moisture Sensor Data","func":"var test = global.get(\"MoistureSensor1\")+global.get(\"MoistureSensor2\");\nmsg.payload = test/2;\nreturn msg;","outputs":1,"noerr":0,"x":429.875,"y":804,"wires":[["8ccebab4.529508","fdafb5f7.60c618","6c7734c6.b4142c"]]},{"id":"5be35248.b98b4c","type":"switch","z":"2e2bc85.6e69438","name":"Switch","property":"payload.Arafat","propertyType":"msg","rules":[{"t":"eq","v":"M1","vt":"str"},{"t":"eq","v":"M2","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":474.67852783203125,"y":334.9000244140625,"wires":[["eaf880d9.935aa"],["27f6b92d.59c9fe"]]},{"id":"b538f080.c1807","type":"comment","z":"2e2bc85.6e69438","name":"Global Variable","info":"Global Variable","x":670.3999938964844,"y":459.8499755859375,"wires":[]},{"id":"dc7df5c.1dcca08","type":"link out","z":"2e2bc85.6e69438","name":"","links":["7e9bda60.11e67c","13390a8a.b6dd15","d970573c.59f8e"],"x":450,"y":1051.6499633789062,"wires":[]},{"id":"3b72e2dd.de18d6","type":"ui_gauge","z":"2e2bc85.6e69438","name":"Moisture Sensor1","group":"350b09af.e3ed46","order":1,"width":"6","height":"5","gtype":"gage","title":"","label":"","format":"{{msg.payload.toFixed(0)}}%","min":0,"max":"100","colors":["#e10000","#e6e600","#008040"],"seg1":"20","seg2":"40","x":910.7779541015625,"y":461.27777099609375,"wires":[]},{"id":"17e74f8b.a59f9","type":"ui_gauge","z":"2e2bc85.6e69438","name":"Moisture Sensor2","group":"9be2405.535364","order":3,"width":"6","height":"5","gtype":"gage","title":"","label":"","format":"{{msg.payload.toFixed(0)}}%","min":0,"max":"100","colors":["#e10000","#e6e600","#008040"],"seg1":"20","seg2":"40","x":908.222412109375,"y":637.0556640625,"wires":[]},{"id":"de968a88.91464","type":"openweathermap in","z":"8e39dbe1.c473b","name":"Current Weather","wtype":"current","lon":"-0.3569340502747274","lat":"53.774493500000005","city":"","country":"","language":"en","x":184,"y":194,"wires":[["6641c5be.0c5324"]]},{"id":"80ac48f0.d84b48","type":"ui_template","z":"8e39dbe1.c473b","group":"973b4abf.8634a8","name":"icon","order":1,"width":"3","height":"2","format":"<div style=\"display: flex;height: 100%;justify-content: center;align-items: center;\">\n<i class=\"fa-4x wi wi-owm-{{msg.payload}}\"></i>\n</div>","storeOutMessages":true,"fwdInMessages":true,"templateScope":"local","x":901.0000610351562,"y":103.00000095367432,"wires":[[]]},{"id":"6641c5be.0c5324","type":"function","z":"8e39dbe1.c473b","name":"Splitter","func":"var icon = { payload:msg.payload.icon };\nvar detail = { payload:msg.payload.detail};\nvar tempc = { payload:msg.payload.tempc};\nvar humidity = { payload:msg.payload.humidity};\nvar windspeed = { payload:msg.payload.windspeed};\n\n\nreturn [ icon, detail, tempc, humidity, windspeed];","outputs":5,"noerr":0,"x":387.0000762939453,"y":195,"wires":[["80ac48f0.d84b48"],["7a6bb02f.b161e8"],["f27ce467.24658"],["1fe4bf05.222891"],["509e300.1c8e4d"]]},{"id":"7a6bb02f.b161e8","type":"ui_text","z":"8e39dbe1.c473b","group":"973b4abf.8634a8","order":2,"width":"3","height":"1","name":"Detail Weather","label":"","format":"{{msg.payload}}","layout":"row-right","x":930.0000610351562,"y":146.00000095367432,"wires":[]},{"id":"f27ce467.24658","type":"ui_text","z":"8e39dbe1.c473b","group":"b5cb8ceb.ffc","order":3,"width":"6","height":"1","name":"Temperature","label":"Temperature","format":"{{msg.payload}} °C","layout":"row-spread","x":919.9000091552734,"y":194.00000095367432,"wires":[]},{"id":"1fe4bf05.222891","type":"ui_text","z":"8e39dbe1.c473b","group":"973b4abf.8634a8","order":4,"width":"6","height":"1","name":"Humidity","label":"Humidity","format":"{{msg.payload}} %","layout":"row-spread","x":907.9000091552734,"y":236.00000286102295,"wires":[]},{"id":"769fcdf1.d304dc","type":"openweathermap in","z":"8e39dbe1.c473b","name":"Weather Forecast","wtype":"forecast","lon":"-0.3569340502747274","lat":"53.774493500000005","city":"","country":"","language":"en","x":193.9000129699707,"y":405.8000030517578,"wires":[["e4046d0b.d09798"]]},{"id":"e4046d0b.d09798","type":"function","z":"8e39dbe1.c473b","name":"Splitter","func":"var msg1 = { payload:msg.payload[0].weather[0].icon };\nvar msg2 = { payload:msg.payload[0].weather[0].description};\nvar msg3 = { payload:msg.payload[0].main.temp};\nvar msg4 = { payload:msg.payload[0].main.humidity};\nvar msg5 = { payload:msg.payload[0].wind.speed};\n\n\nreturn [ msg1, msg2, msg3, msg4, msg5];","outputs":5,"noerr":0,"x":384.0000991821289,"y":405.8000030517578,"wires":[["55d3db3a.334114"],["315f73ba.6899f4"],["6851733b.e50ce4"],["d04fc99.da85fb8"],["501627eb.588418"]]},{"id":"6851733b.e50ce4","type":"ui_text","z":"8e39dbe1.c473b","group":"973b4abf.8634a8","order":3,"width":"6","height":"1","name":"Temperature","label":"Temperature","format":"{{msg.payload}} °C","layout":"row-spread","x":919.7999649047852,"y":453.80000591278076,"wires":[]},{"id":"d04fc99.da85fb8","type":"ui_text","z":"8e39dbe1.c473b","group":"b5cb8ceb.ffc","order":4,"width":"6","height":"1","name":"Humidity","label":"Humidity","format":"{{msg.payload}} %","layout":"row-spread","x":911.7999649047852,"y":501.80000591278076,"wires":[]},{"id":"315f73ba.6899f4","type":"ui_text","z":"8e39dbe1.c473b","group":"b5cb8ceb.ffc","order":2,"width":"3","height":"1","name":"Detail Weather","label":"","format":"{{msg.payload}} ","layout":"row-right","x":931.9000091552734,"y":403.80000400543213,"wires":[]},{"id":"55d3db3a.334114","type":"ui_template","z":"8e39dbe1.c473b","group":"b5cb8ceb.ffc","name":"icon","order":1,"width":"3","height":"2","format":"<div style=\"display: flex;height: 100%;justify-content: center;align-items: center;\">\n<i class=\"fa-4x wi wi-owm-{{msg.payload}}\"></i>\n</div>","storeOutMessages":true,"fwdInMessages":true,"templateScope":"local","x":902.9000091552734,"y":345.80000352859497,"wires":[[]]},{"id":"509e300.1c8e4d","type":"ui_text","z":"8e39dbe1.c473b","group":"973b4abf.8634a8","order":4,"width":"6","height":"1","name":"Wind Speed","label":"Wind Speed","format":"{{msg.payload}} m/s","layout":"row-spread","x":919.1000099182129,"y":276.99999237060547,"wires":[]},{"id":"501627eb.588418","type":"ui_text","z":"8e39dbe1.c473b","group":"b5cb8ceb.ffc","order":4,"width":"6","height":"1","name":"Wind Speed","label":"Wind Speed","format":"{{msg.payload}} m/s","layout":"row-spread","x":922.1000099182129,"y":548.9999923706055,"wires":[]},{"id":"322ef2a1.623236","type":"debug","z":"2e2bc85.6e69438","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":424.49998474121094,"y":204.8000030517578,"wires":[]},{"id":"af036b41.96e118","type":"mqtt in","z":"a74037fd.22229","name":"Status signal","topic":"maaislamPumpStatus","qos":"2","datatype":"auto","broker":"f4aa86c7.144588","x":337.344482421875,"y":344.7555236816406,"wires":[["11ece5e.107b49a"]]},{"id":"11ece5e.107b49a","type":"json","z":"a74037fd.22229","name":"","property":"payload","action":"","pretty":false,"x":609.344482421875,"y":345.55552673339844,"wires":[["ae7d6592.b3f43"]]},{"id":"ae7d6592.b3f43","type":"function","z":"a74037fd.22229","name":"Converter","func":"\nif ( msg.payload.d.Data == 1){\n \n msg.payload = \"Pump ON\"; \n}\nelse if (msg.payload.d.Data === 0)\n{\n msg.payload = \"Pump OFF\";\n}\nelse {\n return null;\n}\nreturn msg;","outputs":1,"noerr":0,"x":330.67779541015625,"y":477.08888244628906,"wires":[["66710d7d.184004","a6918717.de2cf8"]],"info":"This function takes the Data item from json \nand converts it to boolean form."},{"id":"be20885c.1eb95","type":"mqtt out","z":"a74037fd.22229","name":"Control Signal","topic":"maaislamPumpControl","qos":"2","retain":"","broker":"f4aa86c7.144588","x":727.4222412109375,"y":223.1110076904297,"wires":[]},{"id":"d970573c.59f8e","type":"link in","z":"a74037fd.22229","name":"","links":["dc7df5c.1dcca08"],"x":253.755615234375,"y":220.02207946777344,"wires":[["4ee1f73a.5e2f68"]]},{"id":"4ee1f73a.5e2f68","type":"change","z":"a74037fd.22229","name":"","rules":[{"t":"change","p":"payload","pt":"msg","from":"Moisture Low.So Pump is Turned ON","fromt":"str","to":"1","tot":"num"},{"t":"change","p":"payload","pt":"msg","from":"Moisture Normal. Pump Turned OFF","fromt":"str","to":"0","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":383.12225341796875,"y":221.31101989746094,"wires":[["be20885c.1eb95"]]},{"id":"1a73ea89.b1e675","type":"ui_text","z":"a74037fd.22229","group":"bec8b727.033f","order":1,"width":"5","height":"2","name":"cog","label":"","format":"<font color={{msg.color}} ><i class=\"{{msg.class}}\"style=\"font-size:24px;\"></i></font>","layout":"row-right","x":781.9000244140625,"y":513.2000122070312,"wires":[]},{"id":"66710d7d.184004","type":"function","z":"a74037fd.22229","name":"Cog Icon","func":"\nmsg.class = \n(msg.payload == \"Pump ON\")?\"fa fa-cog fa-spin fa-5x fa-fw\":\"fa fa-cog fa-5x fa-f\";\n//Shows a staic or spinning cof icon based on the message\n\n\n\nmsg.color = \n(msg.payload == \"Pump ON\")?\"lime\":\"red\";// Changes color of the cog based on the message\n\nreturn msg;\n","outputs":1,"noerr":0,"x":589.2000122070312,"y":510.2000274658203,"wires":[["1a73ea89.b1e675"]]},{"id":"a6918717.de2cf8","type":"function","z":"a74037fd.22229","name":"Status Text","func":"\nswitch (msg.payload) {\n\ncase \"Pump ON\" : // if incoming message is \"Pump ON\"\n msg.color = \"lime\";// change message text color.\n msg.payload = \"Pump ON\";// show message\n msg.size = \"8\";// increase message font size.\n break;\n \ncase \"Pump OFF\" : // if incoming message is \"Pump OFF\"\n msg.color = \"red\"; // change message text color.\n msg.payload = \"Pump OFF\"; // show message.\n msg.size = \"8\"; // increase message font size.\n break;\n \n}\n\nreturn msg;","outputs":1,"noerr":0,"x":600.2000122070312,"y":456.2000274658203,"wires":[["a6afa763.bfc078"]]},{"id":"a6afa763.bfc078","type":"ui_text","z":"a74037fd.22229","group":"bec8b727.033f","order":3,"width":"6","height":"2","name":"text","label":"","format":"<font color= {{msg.color}} size= {{msg.size}}> {{msg.payload}} </font>","layout":"row-left","x":784.2000122070312,"y":457.2000274658203,"wires":[]}]
/*
*
* This example demonstrates usage of the AIR430BoostETSI library which uses
* the 430Boost-CC110L AIR Module BoosterPack created by Anaren Microwave, Inc.
* and available through the TI eStore, for the European Union.
*/
#include <AIR430BoostFCC.h>
#include <SPI.h>
#include <WiFi.h>
#include <PubSubClient.h>
// -----------------------------------------------------------------------------
/**
* Global data
*/
unsigned char rxData[60]; // Data to read from radio RX FIFO (60 bytes MAX.)
char ssid[] = "maaislam"; // LenovoWIFI your network name also called SSID
char password[] = "123asdfgh"; // your network password
char server[] = "broker.hivemq.com"; // MQTTServer to use
WiFiClient wifiClient; // Connecting to MQTT broker via Wi-Fi
PubSubClient client(server, 1883, callback, wifiClient); // Initialize MQTT client
// -----------------------------------------------------------------------------
// RF packet received!
void printRxData()
{
// If RF data received, print diagnostic info to Serial Monitor & Publish over MQTT
Serial.print("RX (DATA, RSSI, LQI, CRCBIT): ");
Serial.print("(");
Serial.print((char*)rxData);
Serial.print(", ");
Serial.print(Radio.getRssi());
Serial.print(", ");
Serial.print(Radio.getLqi());
Serial.print(", ");
Serial.print(Radio.getCrcBit());
Serial.println(")");
// Publish latest RF payload to the cloud via MQTT, Blink Yellow LED if successful
if(client.publish("SensorDataSaad",(char*)rxData)) {
digitalWrite(YELLOW_LED, HIGH);
Serial.println("MQTT Publish success!");
digitalWrite(YELLOW_LED, LOW);
} else {
Serial.println("MQTT Publish failed!");
}
}
void callback(char* topic, byte* payload, unsigned int length) {
// Not used
}
//
// -----------------------------------------------------------------------------
// Main
void setup()
{
//Setup LED for example demonstration purposes.
pinMode(RED_LED, OUTPUT); // RED LED Notifier for subGHz RF Rx
digitalWrite(RED_LED, LOW);
pinMode(GREEN_LED, OUTPUT); // GREEN LED Notifier for Wi-Fi connected
digitalWrite(GREEN_LED, LOW);
pinMode(YELLOW_LED, OUTPUT); // YELLOW LED Notifier for MQTT Pub successful
digitalWrite(YELLOW_LED, LOW);
pinMode(PUSH1, INPUT); // Configure PUSH1. Used to decide how we will connect to Wi-Fi
// Setup serial for debug printing.
Serial.begin(115200);
Serial.print("Attempting to connect to Network named: ");
// print the network name (SSID);
Serial.println(ssid);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
WiFi.begin(ssid, password);
while ( WiFi.status() != WL_CONNECTED) {
// print dots while we wait to connect
Serial.print(".");
delay(300);}
// Connected to Wi-Fi!
Serial.println("\nYou're connected to the network");
Serial.println("Waiting for an ip address");
// Wait for IP Address
while (WiFi.localIP() == INADDR_NONE) {
// print dots while we wait for an ip addresss
Serial.print(".");
delay(300);
}
Serial.println("\nIP Address obtained");
// We are connected and have an IP address. Print the WiFi status.
printWifiStatus();
// ATTEMPT TO INITIALIZE CC110L SUBGHz RADIO
// The radio library uses the SPI library internally, this call initializes
// SPI/CSn and GDO0 lines. Also setup initial address, channel, and TX power.
Radio.begin(0x01, CHANNEL_1, POWER_MAX);
}
void loop()
{
// Reconnect to MQTT Broker if the connection was lost
if (!client.connected()) {
Serial.println("Disconnected. Reconnecting to MQTT Broker");
client.connect("123asdfg_gateway1");
Serial.println("Connected to MQTT Broker!");
}
// Turn on the receiver and listen for incoming data. Timeout after 1 seconds.
// The receiverOn() method returns the number of bytes copied to rxData.
if (Radio.receiverOn(rxData, 60, 1000) > 0)
{
/**
* Data has been received and has been copied to the rxData buffer provided
* to the receiverOn() method. At this point, rxData is available. See
* printRxData() for more information.
*/
digitalWrite(RED_LED, HIGH);
printRxData(); // RX debug information
digitalWrite(RED_LED, LOW);
}
// Ping MQTT broker to maintain connection
client.poll();
}
void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your WiFi IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print the received signal strength:
digitalWrite(GREEN_LED, HIGH); // Connected to WiFi LED
}
#pragma once
/*
* Implements a simple linear recursive exponential filter.
* See: http://www.statistics.com/glossary&term_id=756 */
template<class T> class ExponentialFilter
{
// Weight for new values, as a percentage ([0..100])
T m_WeightNew;
// Current filtered value.
T m_Current;
public:
ExponentialFilter(T WeightNew, T Initial)
: m_WeightNew(WeightNew), m_Current(Initial)
{ }
void Filter(T New)
{
m_Current = (100 * m_WeightNew * New + (100 - m_WeightNew) * m_Current + 50)/100;
}
void SetWeight(T NewWeight)
{
m_WeightNew = NewWeight;
}
T GetWeight() const { return m_WeightNew; }
T Current() const { return (m_Current + 50)/100; }
void SetCurrent(T NewValue)
{
m_Current = NewValue*100;
}
};
// Specialization for floating point math.
template<> class ExponentialFilter<float>
{
float m_fWeightNew;
float m_fCurrent;
public:
ExponentialFilter(float fWeightNew, float fInitial)
: m_fWeightNew(fWeightNew/100.0), m_fCurrent(fInitial)
{ }
void Filter(float fNew)
{
m_fCurrent = m_fWeightNew * fNew + (1.0 - m_fWeightNew) * m_fCurrent;
}
void SetWeight(float NewWeight)
{
m_fWeightNew = NewWeight/100.0;
}
float GetWeight() const { return m_fWeightNew*100.0; }
float Current() const { return m_fCurrent; }
void SetCurrent(float fNewValue)
{
m_fCurrent = fNewValue;
}
};
/* --COPYRIGHT--,BSD
* Copyright (c) 2015, Texas Instruments Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* --/COPYRIGHT--*/
/*******************************************************************************
*
* LCD_Launchpad.h
*
* Hardware abstraction layer for the FH-1138P Segmented LCD
* on MSP-EXP430FR6989 and MSP-EXP430FR4133
*
* February 2015
* E. Chen
*
* June 2015 StefanSch: Adopted for Energia
*
******************************************************************************/
#ifndef LCD_LAUNCHPAD_H_
#define LCD_LAUNCHPAD_H_
#include "Energia.h"
enum LCD_ICONS {
LCD_SEG_MARK,
LCD_SEG_R,
LCD_SEG_HEART,
LCD_SEG_CLOCK,
LCD_SEG_DOT3,
LCD_SEG_RADIO,
LCD_SEG_DOT2,
LCD_SEG_COLON2,
LCD_SEG_RX,
LCD_SEG_TX,
LCD_SEG_DOT1,
LCD_SEG_MINUS1,
LCD_SEG_BAT_POL,
LCD_SEG_BAT1,
LCD_SEG_BAT3,
LCD_SEG_BAT5,
LCD_SEG_DOT5,
LCD_SEG_DEG5,
LCD_SEG_BAT_ENDS,
LCD_SEG_BAT0,
LCD_SEG_BAT2,
LCD_SEG_BAT4,
LCD_SEG_DOT4,
LCD_SEG_COLON4,
};
class LCD_LAUNCHPAD : public Print {
public:
LCD_LAUNCHPAD();
void init();
void displayText(String s);
void displayText(String s, char pos);
void displayText(char* s, char pos);
void displayScrollText(char* s, unsigned int wait);
void showChar(char, int);
void showSymbol(char symbol, int status);
void clear(void);
virtual size_t write(uint8_t c);
//virtual size_t write(const uint8_t *buffer, size_t size);
using Print::write; // pull in write(str) and write(buf, size) from Print
};
#endif /* LCD_LAUNCHPAD_H_ */
Comments