Uploaded by sajibnet

Embedded Project Documentation Team Anonymous Final

advertisement
Weather Station Project
Signal name: ANO wind direction, ANO wind Speed
Team Anonymous
Mohammad Ahsan Nazmul
MD Mahmadul Hasan
Technical document
April 2023
Course name : Embedded System
Software Engineering Program 2023
Table of contens
1 Hardware ........................................................................................................... 3
2 Software............................................................................................................. 4
2.1 Code Explanation ....................................................................................... 4
2.2 Verification ................................................................................................ 6
Whole Code ............................................................................................................. 8
1 Hardware
The purpose of this project is to gain foundational knowledge in embedded systems and
create a functional weather station, with the aim of successfully completing the course.
we believe that this project will add value to our portfolio and enhance our
understanding of the subject matter. The primary objective is to measure wind direction
and wind speed using the weather station.
To create a weather station project that can measure wind direction and speed, the
following hardware components were used:
o Breadboard - It provides a platform to connect different components of the
project together without the need for soldering. It is a convenient way to create
circuits and prototypes.
o LCD Display 16x2 - It displays the measured values of wind direction and
speed. It is a standard display module.
o Arduino Mega - It is a microcontroller board that provides the processing power
for the project. It receives data from the sensors and uses the data to calculate the
wind direction and speed. It then displays the measured values on the LCD
screen.
o Keypad 4x4 - It is used to input values. We used it to display different values on
the display. It is a standard keypad with four rows and four columns.
o Ethernet module - It enables the weather station to connect to the internet and
share the measured data. It is a network module that allows the weather station
to communicate with the broker (Raspberry Pi ) and send message to database.
o Wires , Connectors, Resistors – Besides We used wires, 1 resistor and different
connector cables to make the connection.
2 Software
We have used mainly Arduino IDE and it’s Libraries to do the coding. Besides this we
have also practiced with www.tinkercad.com website at the beginning to get an idea of
the circuit board. We have used C++ Programming Language for the project.
o Arduino IDE - This is a software development environment used to write and
upload code to the Arduino microcontroller. It is the main software used to
program the microcontroller. It can be downloaded from the official Arduino
website and is available for free.
o Arduino libraries - These are pre-written code modules that provide a set of
functions to make programming the microcontroller easier. There are many
libraries available for Arduino that can be downloaded and included in the code.
The following libraries are used for this project:
1. LiquidCrystal.h - This library provides functions to control the LCD display.
2. Keypad.h - This library provides functions to read inputs from the keypad.
3. Ethernet.h - This library used to enable the Arduino Mega to connect to the internet
and communicate with other devices using the W5100 Ethernet module
4. ArduinoJson.h - The ArduinoJson library is used to manipulate JSON (JavaScript
Object Notation) data, which is a lightweight data format often used for web
application
5. TimerOne.h – This is used to set up and manage timers on the microcontroller.
6. PubSubClient.h – This is used to implement the MQTT (Message Queuing
Telemetry Transport) protocol. This library allows the Arduino Mega to publish and
subscribe to topics on an MQTT broker.
2.1
Code Explanation
Part 1: At beginning the code imports libraries and declares variables for various
components used in the project, including Ethernet, MQTT, LCD display, keypad, and
ArduinoJson.
It also defines the pin connections for the LCD display and keypad, sets up keypad
button press initial conditions, and initializes variables for wind speed and direction.
In addition, it sets up the MQTT client object with the required parameters, such as the
IP address of the MQTT server, port number, client ID, username, and password.
Finally, it defines the input and output MQTT topic names for receiving and sending
data.
Part 2:
In the Setup() section we used fetch_IP() function to initialize Ethernet connection.
Connect_MQTT_server() function is called to connect to the MQTT server.
The LCD is initialized with 16 columns and 2 rows. Pin A2 is set as an input. The
variables related to wind speed calculation are initialized to 0.
The pulseCountFunction() function is attached as an interrupt service routine to the
signal input pin (pin 2) with a trigger condition of a rising edge.
The timerInterruptFunction() function is attached as an interrupt service routine to the
Timer1 interrupt, which is set to trigger every 1 second.
Using this two interrupt we calculated the windFrequency and the calculated the
Wind speed using formula as
windSpeed = -0.24 + windFrequency * 0.699;
Part 3:
The main loop of the program reads the keypad input (1,2 or 3) to determine whether to
display wind direction, speed, or both on the LCD. It then reads the wind direction and
map it in 360 degree values and shows the direction using a range of respective degree
values.
wind speed is calculated based on the number of pulses received from Arduino mega
pin 2 within 1 second and using timer interrupt function . Then we calculated the
frequency and speed as follows:
void timerInterruptFunction() {
timeCount++;
if (timeCount >= 19) { // Perform wind speed calculation every 5 seconds
windFrequency = pulseCount / 10; // Multiply pulse count by 2 to get frequency in Hz
pulseCount = 0; // Reset pulse count
windSpeed = -0.24 + windFrequency * 0.699; // Calculate wind speed using equation
timeCount = 0; // Reset time counter
}
}
If the MQTT client is connected to the broker, it sends the wind direction and speed
data to the broker using the send_MQTT_message() function. If the client is not
connected, it attempts to reconnect to the broker.
The send_MQTT_message() function is responsible for formatting and sending the
wind direction and speed data to the broker using MQTT protocol.
Callback function is used for receiving MQTT messages and printing them to the Serial
Monitor and LCD
2.2
Pic:1
Pic-2
Verification
Picture 1 and 2 showing wind direction and wind speed sent to the server.
Pic:3
Picture of the Weather station board
Whole Code
#include <Ethernet.h>
#include <PubSubClient.h>
#include <TimerOne.h>
// incluide Ethernet library W5100
// include MQTT library
//timer function
#include <Keypad.h>
#include <LiquidCrystal.h>
#include <ArduinoJson.h>
//-----------------------------------------------------------------LiquidCrystal lcd(12, 11, 35, 34, 33, 32);// LCD display pin connection
//--------keypad settings---------const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte rowPins[ROWS] = { 38, 39, 40, 41 };
byte colPins[COLS] = { 42, 43, 44, 45 };
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
//-------button press conditions---------------volatile boolean buttonPressed1 = false;
volatile boolean buttonPressed2 = false;
volatile boolean buttonPressed3 = false;
// Define variables
String windDirection;
bool displayDirection;
bool displaySpeed;
bool displayBoth;
int degree_Value;
volatile unsigned long pulseCount;
volatile unsigned long windFrequency;
float windSpeed;
unsigned long timeCount;
// Define pin numbers
const int signalInputPin = 2;
EthernetClient ethClient;// Ethernet object variable
static uint8_t mymac[6] = { 0x44,0x76,0x58,0x10,0x00,0x62 };
// -------- MQTT settings-----------unsigned int Port = 1883;
byte server[] = { 10,6,0,21 };
char* deviceId
char* clientId
// MQTT port number
// TAMK IP
= "esdevice23";// * set your device id (will be the MQTT client username)
= "escg223"; // * set a random string (max 23 chars, will be the MQTT client id)
char* deviceSecret = "tamk";
// * set your device secret (will be the MQTT client password)
// MQTT Server settings
void callback(char* topic, byte* payload, unsigned int length); // subscription callback for received MQTTT
messages
PubSubClient client(server, Port, callback, ethClient); // mqtt client
// MQTT topic names
#define inTopic
"ICT4_in_2020" // * MQTT channel where data are received
#define outTopic "ICT4_out_2020" // * MQTT channel where data is send
// ---------------- Main SETUP section-----------------------------void setup() {
Serial.begin(9600);
// Serial monitor baudrate = 9600
Serial.println("Start 20.1.2023"); // print to serial monitor
delay(500);
fetch_IP(); // initialize Ethernet connection
Connect_MQTT_server(); // connect to MQTT server
lcd.begin(16, 2);
pinMode(A2, INPUT);
//wind speed void setup
pulseCount = 0;
windFrequency = 0;
windSpeed = 0.0;
timeCount = 0;
// Attach interrupt function to signal input pin
attachInterrupt(digitalPinToInterrupt(signalInputPin), pulseCountFunction, RISING);//counting pulse on
rising
// Set up timer for 1 second intervals
Timer1.initialize(1000000);
Timer1.attachInterrupt(timerInterruptFunction);
//These two intterupt helps to calculate the frequency
}
void loop(){
// Check if 1,2 or 3 button is pressed to switch between wind direction, speed display or both
char key = keypad.getKey();
if(key == '1'){
buttonPressed1 = true;
buttonPressed2 = false;
buttonPressed3 = false;
} else if(key == '2'){
buttonPressed1= false;
buttonPressed2 = true;
buttonPressed3 = false;
} else if(key == '3'){
buttonPressed1= false;
buttonPressed2 = false;
buttonPressed3 = true;
} else {
buttonPressed1= false;
buttonPressed2 = false;
buttonPressed3 = false;
}
//-------------------------------------//
if(buttonPressed1 == true){
displayDirection = true;
displaySpeed = false;
displayBoth = false;
} else if(buttonPressed2 == true){
displayDirection = false;
displaySpeed = true;
displayBoth = false;
} else if(buttonPressed3 == true){
displayDirection = false;
displaySpeed = false;
displayBoth = true;
}
//---- Read wind direction and speed from sensors and display on LCD--lcd.setCursor(20, 1);
lcd.print("1-Dir 2-Spd 3-Both");
float analog_Value = analogRead(A2);
float voltage_Value = 5 * analog_Value / 1023;
if (voltage_Value < 1.2) {
degree_Value = 0;
} else{
degree_Value = ((voltage_Value - 1.2) / 3.8) * 360;
}
if (displayDirection == true) {
lcd.setCursor(0, 0);
if (voltage_Value <= 1.19) {
windDirection = "Loading....";
} else if (degree_Value >= 337.5 || (degree_Value > -1 && degree_Value <= 22.4)) {
windDirection = "North";
} else if (degree_Value > 22.4 && degree_Value <= 67.5) {
windDirection = "North East";
} else if (degree_Value > 67.5 && degree_Value <= 112.5) {
windDirection = "East";
} else if (degree_Value > 112.5 && degree_Value <= 157.5) {
windDirection = "South East";
} else if (degree_Value > 157.5 && degree_Value <= 202.5) {
windDirection = "South";
} else if (degree_Value > 202.5 && degree_Value <= 247.5) {
windDirection = "South West";
} else if (degree_Value > 247.5 && degree_Value <= 292.5) {
windDirection = "West";
} else {
windDirection = "North West";
}
lcd.clear(); // clear the display before printing new data
lcd.setCursor(0, 0);
lcd.print("Dir : ");
lcd.print(windDirection);
lcd.setCursor(0, 1);
lcd.print(degree_Value);
lcd.print(" degrees");
lcd.setCursor(20, 1);
lcd.print("1-Dir 2-Spd 3-Both");
} else if (displaySpeed == true){
lcd.clear(); // clear the display before printing new data
lcd.setCursor(0, 0);
lcd.print("Wind Speed: ");
lcd.setCursor(0, 1);
lcd.print("Freq: ");
lcd.setCursor(7, 1);
lcd.print(windFrequency);
lcd.setCursor(13, 1);
lcd.print("Hz");
lcd.setCursor(13, 0);
lcd.print(windSpeed);
lcd.setCursor(20, 1);
lcd.print("1-Dir 2-Spd 3-Both");
} else if (displayBoth == true){
lcd.clear(); // clear the display before printing new data
lcd.setCursor(0, 0);
lcd.print("Dir : ");
lcd.print(degree_Value);
lcd.setCursor(0, 1);
lcd.print("Wind Speed: ");
lcd.setCursor(13, 1);
lcd.print(windSpeed);
lcd.setCursor(20, 1);
lcd.print("1-Dir 2-Spd 3-Both");
}
// ----------------------Send MQTT message to broker----------------------------------------------if (client.connected()){
const char* windDirections = windDirection.c_str();
send_MQTT_message(degree_Value,windSpeed);// call MQTT routine function
} else {
client.connect(clientId, deviceId, deviceSecret);// Reconnect if connection is lost
Serial.println("No, re-connecting" );
}
// Delay before checking again
delay(1000);
}
// -------GET IP number from DHCP server-----------void fetch_IP(void){
byte rev=1;
rev=Ethernet.begin(mymac);// get IP number
Serial.print( F("\nW5100 Revision ") );
if (rev == 0){
Serial.println( F( "Failed to access Ethernet controller" ) );
}
Serial.println( F( "Setting up DHCP" ));
Serial.print("Connected with IP: ");
Serial.println(Ethernet.localIP());
}
// ----------MQTT Routines--------------------void send_MQTT_message(int dir, float spd){ // Send MQTT message
char bufa[50];
char fufa[50];
char sufa[50];
int timeDelay = 1000; // This is for adjust the time delay of MQTT + JSON transferring
if (displayDirection == true){
const size_t bufferSize = JSON_OBJECT_SIZE(2) + 30;
StaticJsonDocument<bufferSize> jsonDoc;
jsonDoc["S_name1"] = "ANO Wind Direction";
jsonDoc["S_value1"] = dir;
String jsonStr;
serializeJson(jsonDoc, jsonStr);
char message[jsonStr.length() + 10];
sprintf(message, "IOTJS=%s", jsonStr.c_str());
Serial.println( message );
client.publish(outTopic,message);
delay(timeDelay);
} else if (displaySpeed == true){
const size_t bufferSize = JSON_OBJECT_SIZE(2) + 30;
StaticJsonDocument<bufferSize> jsonDoc;
jsonDoc["S_name1"] = "ANO Wind Speed";
jsonDoc["S_value1"] = spd;
String jsonStr;
serializeJson(jsonDoc, jsonStr);
char message[jsonStr.length() + 10];
sprintf(message, "IOTJS=%s", jsonStr.c_str());
// create message with header and data
Serial.println( message );
client.publish(outTopic,message);
delay(timeDelay);
} else if (displayBoth == true) {
// --------Adding wind direction here---------------const size_t bufferSize = JSON_OBJECT_SIZE(2) + 30;
StaticJsonDocument<bufferSize> jsonDoc;
jsonDoc["S_name1"] = "ANO Wind Direction";
jsonDoc["S_value1"] = dir;
String jsonStr;
serializeJson(jsonDoc, jsonStr);
char message[jsonStr.length() + 10];
sprintf(message, "IOTJS=%s", jsonStr.c_str());
// create message with header and data
Serial.println(message);
client.publish(outTopic, message);
//--------------- Adding wind speed here----------------jsonDoc.clear(); // Clear the previous data from the JSON document
delay(500);
StaticJsonDocument<bufferSize> jsonDoc2;
jsonDoc2["S_name1"] = "ANO Wind Speed";
jsonDoc2["S_value1"] = spd;
String jsonStr2;
serializeJson(jsonDoc2, jsonStr2);
char message2[jsonStr2.length() + 10];
sprintf(message2, "IOTJS=%s", jsonStr2.c_str());
// create message with header and data
Serial.println( message2 );
client.publish(outTopic,message2);
delay(timeDelay);
}
}
// -------------------MQTT server connection -------------------------------void Connect_MQTT_server(){
Serial.println(" Connecting to MQTT" );
Serial.print(server[0]); Serial.print(".");
// Print MQTT server IP number to Serial monitor
Serial.print(server[1]); Serial.print(".");
Serial.print(server[2]); Serial.print(".");
Serial.println(server[3]);
// delay(500);
if (!client.connected()){
// check if allready connected
if (client.connect(clientId, deviceId, deviceSecret)){ // connection to MQTT server
Serial.println(" Connected OK " );
client.subscribe(inTopic);
// subscript to in topic
} else{
Serial.println(client.state());
}
}
}
// ------------------Receive incoming MQTT message ----------------------------void callback(char* topic, byte* payload, unsigned int length){
char* receiv_string;
// copy the payload content into a char*
receiv_string = (char*) malloc(length + 1);
memcpy(receiv_string, payload, length);
// copy received message to receiv_string
receiv_string[length] = '\0';
Serial.println( receiv_string );
free(receiv_string);
}
//------------------- Interrupt function to count pulses--------------------------void pulseCountFunction() {
pulseCount++;
}
//----------- Interrupt function to calculate wind frequency on every seconds-----void timerInterruptFunction() {
timeCount++;
if (timeCount >= 10) { // when 10 seconds is elapsed we calculate the frequency
windFrequency = pulseCount / 10; // frequency is calculated from (total number of pulse)/ elasped
time(every 10 sec)
pulseCount = 0; // Reset pulse count
windSpeed = -0.24 + windFrequency * 0.699; // Calculate wind speed using equation
timeCount = 0; // Reset time counter
}
}
Download