Initial commit

parents
.pio
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"platformio.platformio-ide"
]
}
{
"files.associations": {
"array": "cpp",
"*.tcc": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"deque": "cpp",
"unordered_map": "cpp",
"unordered_set": "cpp",
"vector": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"functional": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"fstream": "cpp",
"initializer_list": "cpp",
"iomanip": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"limits": "cpp",
"memory": "cpp",
"new": "cpp",
"ostream": "cpp",
"numeric": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"cinttypes": "cpp",
"utility": "cpp",
"typeinfo": "cpp"
}
}
\ No newline at end of file
This directory is intended for project header files.
A header file is a file containing C declarations and macro definitions
to be shared between several project source files. You request the use of a
header file in your project source file (C, C++, etc) located in `src` folder
by including it, with the C preprocessing directive `#include'.
```src/main.c
#include "header.h"
int main (void)
{
...
}
```
Including a header file produces the same results as copying the header file
into each source file that needs it. Such copying would be time-consuming
and error-prone. With a header file, the related declarations appear
in only one place. If they need to be changed, they can be changed in one
place, and programs that include the header file will automatically use the
new version when next recompiled. The header file eliminates the labor of
finding and changing all the copies as well as the risk that a failure to
find one copy will result in inconsistencies within a program.
In C, the usual convention is to give header files names that end with `.h'.
It is most portable to use only letters, digits, dashes, and underscores in
header file names, and at most one dot.
Read more about using header files in official GCC documentation:
* Include Syntax
* Include Operation
* Once-Only Headers
* Computed Includes
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
This directory is intended for project specific (private) libraries.
PlatformIO will compile them to static libraries and link into executable file.
The source code of each library should be placed in a an own separate directory
("lib/your_library_name/[here are source files]").
For example, see a structure of the following two libraries `Foo` and `Bar`:
|--lib
| |
| |--Bar
| | |--docs
| | |--examples
| | |--src
| | |- Bar.c
| | |- Bar.h
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
| |
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |
| |- README --> THIS FILE
|
|- platformio.ini
|--src
|- main.c
and a contents of `src/main.c`:
```
#include <Foo.h>
#include <Bar.h>
int main (void)
{
...
}
```
PlatformIO Library Dependency Finder will find automatically dependent
libraries scanning project source files.
More information about PlatformIO Library Dependency Finder
- https://docs.platformio.org/page/librarymanager/ldf.html
This is a README file that explains the final project.
The essence of this project is create an embedded IOT system for monitoring temperature and humidity conditions
that will connect to the internet via MQTT protocol and report anomalous weather conditions.
Refer to final Project template for more details about the embedded system
void setup_wifi()
connects the system to the internet
const char* ssid = "myssid";
const char* password = "mypassword";
replace the values there with your personal ssid and password in order to connect to the internet
#define MQTT_SERIAL_PUBLISH_CH "myLine/input"
#define MQTT_SERIAL_SUBSCRIBE_CH "myLine/output"
this is the line that we are publishing, and are subrcibed to
it can be replace with a different value, however the same change must be made to the low on node red
void reconnect()
reconnect the system to the internet suppose there is a break in connection while publishing/subscribing
publishSerialData()
publishes data to the subscribed mqtt port
bool isH()
takes a input of type float and checks if the values
satisfies the conditions for an anomalous humidity.
returns true if true and false otherwise.
bool isT()
takes a input of type float and checks if the values
satisfies the conditions for an anomalous temperature.
returns true if true and false otherwise.
std::string convert()
takes an input of data type float and converts it to string
useful for publishing float values across the internet
float setnum()
sets a random number using the clock time as the seed
returns a value of type float. this is the anomalous
temperature/humidity level that is sent across the internet
float setIndex(float h, float t)
sets a random value of type float based on the random humidity
and temperature levels. this value represents the heat index that
is sent across the internet
void sleep()
this function serves the purpose of minimizing power consumption
this function is called from the user interface on node red via a button
when called, the esp32 device is put into a "deep sleep"
per protocol, and because it is not turned off in deep sleep, wi-fi and
bluetooth has to be specifically turned off.
more so, only sending the device into deep sleep without turning off bluetooth
or wi-fi does not actually minimize power consumption.
these are pre-defined under the header files "esp_err.h" and "esp_task.h"
esp_err_t esp_bluedroid_disable();
esp_err_t esp_bt_controller_disable();
esp_err_t esp_wifi_stop();
they are used in the sleep() function to turn of the bluetooth and wifi in the esp
void wakeUp()
this function "wakes" the esp32 device and reports the source of trigger that woke it up
by the program, the esp can be awoken by using a touch pin (literally touching the pin)
or through the user interface, by clicking on the wake button
void emitSound()
this is the function that controls the buzzer in alarm mode.
in order to light the LED simultaneously with the buzzer, the function also controls
the LED light. esentially it sends a high signal to the buzzer and led pins, then delays for
a set time (passed into the function) and then sends a low signal.
void callback()
this is the function that is called when there is data to be received from the
user interface on node red.
the date received is in bytes so we first convert it to readable form.
std::string output(reinterpret_cast<const char *>(payload), length);
analyze the data and call various functions based on data
evalOutput(output);
void evalOutput()
takes an input of type string and calls calls various if it meets certain conditions
if input = true, sets alarm mode to active using a flag; flag = true
if input = false, sets alarm mode to inactive using a flag; flag = false
if input = sleep, invokes sleep function
if input = arise, invokes wake up function
void setOdd()
this block of code sets odd temepratures and is called every 50 seconds
setnum() for temp. and humidity as well as setIndex() for heat level
are called here.
isH() and isT() are called here to check if the climate values are abnormal
emitSound() is also called if anomalous temeperatures are recorded
void measureTemp()
this function:
- measures and records the temperature from the humidity/temperature sensor
- computes a value for heat index
- makes sure values are read from sensor or outputs an error message
this function does the most work (calls the most functions) thus it is used to
simulate CPU usage.
srtTime = millis() and stpTime = millis() are called at the beginning and end of the function
respectively to record the time which is then scaled to simulate CPU usage. the logic is that
time taken for this function will vary since every five seconds it
calls additional functions. thus the variance in time will give some variance in CPU usage
void getCPUusage()
computes the CPU usage using values from the
measureTemp() function and scales it to reflect CPU usage
publishes values to node red
Credits:
/*
Deep Sleep with Touch Wake Up
=====================================
This code displays how to use deep sleep with
a touch as a wake up source and how to store data in
RTC memory to use it over reboots
This code is under Public Domain License.
Author:
Pranav Cherukupalli <cherukupallip@gmail.com>
*/
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
monitor_speed = 115200
lib_deps =
# RECOMMENDED
# Accept new functionality in a backwards compatible manner and patches
knolleary/PubSubClient @ ^2.8
# RECOMMENDED
# Accept new functionality in a backwards compatible manner and patches
adafruit/DHT sensor library @ ^1.4.0
# Accept new functionality in a backwards compatible manner and patches
adafruit/Adafruit Unified Sensor @ ^1.1.4
#include <Arduino.h>
#include "DHT.h"
#include <WiFi.h>
#include <PubSubClient.h>
#include <string>
#include <iostream>
#include <sstream>
#include "esp_err.h"
#include "esp_task.h"
bool flag;
#define LED_PIN1 32
#define LED_PIN2 26
#define BUZZER_PIN 33
#define DHTPIN 22
#define DHTTYPE DHT11
#define interval 50000
#define fract 60
#define threshold 40
DHT dht(DHTPIN, DHTTYPE);
// Update these with values suitable for your network.
const char* ssid = "Springforte Lead";
const char* password = "12345678";
const char* mqtt_server = "test.mosquitto.org";
#define mqtt_port 1883
#define MQTT_SERIAL_PUBLISH_CH "myLine/input"
#define MQTT_SERIAL_SUBSCRIBE_CH "myLine/output"
WiFiClient wifiClient;
PubSubClient client(wifiClient);
void setup_wifi() {
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
randomSeed(micros());
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
} //setup_wifi()
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Create a random client ID
String clientId = "ESP32Client-";
clientId += String(random(0xffff), HEX);
// Attempt to connect
//if (client.connect(clientId.c_str(),MQTT_USER,MQTT_PASSWORD))
if (client.connect(clientId.c_str()) )
{
Serial.println("connected");
// subscribe
client.subscribe(MQTT_SERIAL_SUBSCRIBE_CH);
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
} //reconnect()
void publishSerialData(const char *serialData){
if (!client.connected()) {
reconnect();
}
Serial.println(String("publishing: ") + serialData);
client.publish(MQTT_SERIAL_PUBLISH_CH, serialData);
} //publishSerialData()
//returns true for odd levels of humidity
bool isH(float num) {
if(num<30 || num>75)
return true;
else
return false;
} //bool isH()
//returns true for odd temperature levels
bool isT(float num) {
if(num<27 || num>40)
return true;
else
return false;
} //bool isT
std::string convert (float number){
std::ostringstream buff;
buff<<number;
return buff.str();
} //convert()
float setnum() {
srand((unsigned) time(0));
float randomNumber = (float) rand()/RAND_MAX;
//( static_cast <float> (rand()/100.0) );
return randomNumber*100;
} //setnum()
float setIndex(float h, float t) {
float nI = dht.computeHeatIndex(t, h, false);
return nI;
} //setIndex()
void sleep() {
publishSerialData("Going to sleep now. Zzzzzzz.");
delay(1000);
esp_err_t esp_bluedroid_disable();
esp_err_t esp_bt_controller_disable();
esp_err_t esp_wifi_stop();
Serial.flush(); //send out anything that might be in serial.
esp_deep_sleep_start();
} //sleep()
void wakeUp() {
//enable bluetooth
esp_err_t esp_bluedroid_enable();
esp_sleep_wakeup_cause_t reason;
reason = esp_sleep_get_wakeup_cause();
switch(reason)
{
case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",reason); break;
}
Serial.println(reason);
publishSerialData("Awake...");
} //wakeUp()
void emitSound(unsigned long timeHighMs, unsigned long timeLowMs, unsigned long count)
{
Serial.println("if we got here, that means my piezzo is not working");
for(int i=0;i<count;i++) {
digitalWrite(BUZZER_PIN, HIGH); digitalWrite(LED_PIN1, HIGH);
delay(timeHighMs);//wait for 1ms
digitalWrite(BUZZER_PIN, LOW); digitalWrite(LED_PIN1, LOW);
delay(timeLowMs);//wait for 1ms
}
} //emitsound()
void evalOutput (std::string str) {
if(str == "true") {
flag = true;
digitalWrite(LED_PIN2, HIGH);
publishSerialData("Alarm State: ACTIVE");
}
if(str == "false") {
flag = false;
digitalWrite(LED_PIN2, LOW);
publishSerialData("Alarm State: INACTIVE");
}
if(str == "sleep")
sleep();
if(str == "arise")
wakeUp();
}
std::string output;
void callback(char* topic, byte *payload, unsigned int length) {
Serial.println("-------new message from broker-----");
Serial.print("channel:");
Serial.println(topic);
Serial.print("data:");
Serial.write(payload, length);
Serial.println();
//collect incoming data and analyze
std::string output(reinterpret_cast<const char *>(payload), length);
evalOutput(output);
} //callback()
void setOdd() {
float newh = setnum();
float newt = setnum();
float newhI = setIndex(newh, newt);
if(newhI>100) { //scale it if greater than 100
//newhI = fmod(newhI, 100);
Serial.print("this is the heat index");
Serial.println(newhI);
newhI = newhI/6;
std::string newsI = convert(newhI);
newsI = newsI + "H";
publishSerialData(newsI.c_str());
}
if(isH(newh)) {
std::string newsh = convert(newh);
newsh = newsh + "%";
publishSerialData("WARNING: unusual humidity levels");
//client.publish(MQTT_SERIAL_PUBLISH_CH, "WARNING: unusual humidity levels");
publishSerialData(newsh.c_str());
//Serial.print("newh: "); Serial.println(newh);
if(flag)
emitSound(1000, 1000, 1);
else {
digitalWrite(LED_PIN1, HIGH);
delay(1000);
digitalWrite(LED_PIN1, LOW);
}
}
if(isT(newt)) {
std::string newst = convert(newt);
newst = newst + "°C";
publishSerialData("WARNING: unusual temperature levels");
publishSerialData(newst.c_str());
//Serial.print("newt: "); Serial.println(newt);
if(flag)
emitSound(1000, 1000, 1);
else {
digitalWrite(LED_PIN1, HIGH);
delay(1000);
digitalWrite(LED_PIN1, LOW);
}
}
}
unsigned long srtTime; //startTime
unsigned long stpTime; //stopTime
unsigned long lastcTime; //last time an odd temperature was set
float count = 0.00; //to control how climate levels are published
void measureTemp() {
//the most work is done in this block of code. collect CPU usage here
srtTime = millis();
float h = dht.readHumidity();
delay(300);
float t = dht.readTemperature();
delay(300);
float f = dht.readTemperature(true);
delay(300);
// Check if any reads failed and exit early (to try again).
if (isnan(h) || isnan(t) || isnan(f)) {
Serial.println(F("Failed to read from DHT sensor!"));
return;
}
// Compute heat index in Fahrenheit (the default)
//float hif = dht.computeHeatIndex(f, h);
// Compute heat index in Celsius (isFahreheit = false)
float hic = dht.computeHeatIndex(t, h, false);
//simulating anomalous temperatures
//sets a random temperature every 50 seconds
if(millis() > lastcTime + interval) {
lastcTime = millis();
setOdd();
}
//publish exact recorded temperatures if time interval is not up
else {
if(fmod(count, 2) == 0) {
std::string sh = convert(h);
sh = sh + "%";
std::string st = convert(t);
st = st + "°C";
std::string shic = convert(hic);
shic = shic + "H";
publishSerialData(sh.c_str());
publishSerialData(st.c_str());
publishSerialData(shic.c_str());
}
count += 0.5;
}
/*
Serial.print(F("Humidity: "));
Serial.print(h);
Serial.print(F("% Temperature: "));
Serial.print(t);
Serial.print(F("°C "));
Serial.print(f);
Serial.print(F("°F Heat index: "));
Serial.print(hic);
Serial.print(F("°C "));
Serial.print(hif);
Serial.println(F("°F"));
*/
stpTime = millis();
} //measureTemp()
void getCPUusage() {
float oldU = 0.00;
long diff = (stpTime - srtTime) / 100;
if(diff > diff + (oldU/fract) || diff < diff - (oldU/fract)) {
std::string usage = convert(diff);
usage = usage + "U";
publishSerialData(usage.c_str());
}
oldU = diff;
}
void setup() {
//initialize pins
pinMode(LED_PIN1, OUTPUT);
pinMode(LED_PIN2, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
esp_sleep_enable_touchpad_wakeup(); //configure touchpad as a wakeup source
touchAttachInterrupt(T2, wakeUp, threshold); //setup interrupt on touch pad 2
Serial.begin(115200);
Serial.setTimeout(500); //wait for serial data
setup_wifi();
client.setServer(mqtt_server, mqtt_port);
client.setCallback(callback);
reconnect();
Serial.setTimeout(5000);
Serial.println("before dht begin");
dht.begin();
//publishSerialData("false");
}
bool state;
void loop() {
if(state) {
measureTemp();
getCPUusage();
}
client.loop();
if (Serial.available())
{
String str = Serial.readStringUntil('\n');
publishSerialData(str.c_str());
if(str == "S" || str == "s") {
publishSerialData("initializing...");
publishSerialData("measuring...");
state = true;
}
}
}
This directory is intended for PlatformIO Unit Testing and project tests.
Unit Testing is a software testing method by which individual units of
source code, sets of one or more MCU program modules together with associated
control data, usage procedures, and operating procedures, are tested to
determine whether they are fit for use. Unit testing finds problems early
in the development cycle.
More information about PlatformIO Unit Testing:
- https://docs.platformio.org/page/plus/unit-testing.html
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment