////////////////////////////////////////////////////////////////////////////////
// Name: SmellyUno-V02 //
// Platform: Arduino UNO Rev3 //
// Created by: HARB rboek2@gmail.com july 2018 GPL copyrights //
// Robot: http://robotigs.com/robotigs/includes/bots_header.php?idbot=8 //
// An Arduino is used to measure air pollution. //
////////////////////////////////////////////////////////////////////////////////
// SET PRECOMPILER OPTIONS *****************************************************
// Initialse conditional compiling, uncomment to include, comment to exclude -
// Do comment for runtime versions
//#define RS232 //Uncomment to include Serial Monitor sections
// #ifdef RS232 //Only include these lines if the variable has been defined
// Define the needed header files for the precompiler, no charge if not used -
#include <LiquidCrystal.h> //Default in IDE, by Tom Igoe
// Define Arduino board pins -------------------------------------------------
#define buzActPin 9 //Define which I/O pin connects the activ white BUZZER
#define buttonPin 12 //Define which DIO pin connects yellow BUTTON
#define ledRedPin 10 //3 Colour LED, which pin connects PWM red LED
#define ledGrePin 13 //3 Colour LED, to which pin connects PWM green LED
#define ledBluPin 11 //3 Colour LED to which pin connects PWM blue LED
#define MQ2 A1 //Define to which pin connect orange ADC GAS
#define MQ3 A0 //Define to which pin connect orange ADC GAS
#define MQ5 A3 //Define to which pin connect orange ADC GAS
#define MQ9 A2 //Define to which pin connect orange ADC GAS
#define d4 2 //Data line pin LCD
#define d5 3 //Data line pin LCD
#define d6 4 //Data line pin LCD
#define d7 5 //Data line pin LCD
#define en 6 //Enable pin LCD
#define rs 7 //Register Select pin LCD
//DEFINE VARIABLES -----------------------------------------------------------
bool ledOnBoardVal = LOW; //You can chose HIGH-on or LOW-off for LED_BUILTIN
bool ButtonVal = LOW; //You can chose HIGH-on or LOW-off for BUTTON
byte ButtonCycle = 0; //Cycle between 4 display options BUTTON
word LCDcounter = 5000; //Used to make it less nervous LCD
word counter = 0; //Used to effectivly count down LCD
byte msWait = 1; //Test your patience during the test LED
byte brillance = 0; //Brightness of any color, just to test PWM LED
word valMQ2 = 0; //Value as measured by MQ2 sensor GAS
word valMQ3 = 0; //Value as measured by MQ3 sensor GAS
word valMQ5 = 0; //Value as measured by MQ5 sensor GAS
word valMQ9 = 0; //Value as measured by MQ9 sensor GAS
String Request = ""; //Create receive string WIFI
String command = ""; //Create receive string WIFI
String html = ""; //HTML Response preapaired WIFI
unsigned int bodyLength; //HTML answer length WIFI
//Initialize OBJECTS ---------------------------------------------------------
LiquidCrystal lcd(rs, en, d4, d5, d6, d7); //Initialize LCD
//END OF PRECOMPILER OPTIONS ---------------------------------------------------
void setup() { //Setup runs once ***********************************************
disable_jtag(); //Disable to free port C, enabled by default JTAG
Serial.begin(57600); //Nothing more needed for the Serial Monitor WIFI
pinMode(ledRedPin, OUTPUT); //Make the LED connection output RED LED
pinMode(ledGrePin, OUTPUT); //Make the LED connection output GREEN LED
pinMode(ledBluPin, OUTPUT); //Make the LED connection output BLUE LED
pinMode(LED_BUILTIN, OUTPUT); //Arduino boards contain an onboard BUILTIN LED
pinMode(buzActPin, OUTPUT); //Make the connection output ACTIV BUZZER
pinMode(buttonPin, INPUT_PULLUP); //Pull up to 5Vdc BUTTON
//Start objects --------------------------------------------------------------
lcd.begin(16, 2); //Set up the LCD's number of columns and rows LCD
//Test hardware and software -------------------------------------------------
test_LEDs(); //PWM fade in and fade out for all 4 LED
#if defined(RS232) //Only compiled in if it must be included CONDITIONAL
Serial.println("Setup done"); //Print a message to test the SERIAL MONITOR
#endif //End of compiling CONDITIONAL
beep(1); //Create a test beep (x5ms) with KY-012 active BUZZER
}//--(end setup )---------------------------------------------------------------
void loop() { //KEEP ON RUNNING THIS LOOP FOREVER ******************************
valMQ2 = analogRead(MQ2); //Read the gas concentration of sensor MQ2
valMQ3 = analogRead(MQ3); //Read the gas concentration of sensor MQ3
valMQ5 = analogRead(MQ5); //Read the gas concentration of sensor MQ5
valMQ9 = analogRead(MQ9); //Read the gas concentration of sensor MQ9
checkButton(); //Check if the yellow button is being pressed BUTTON
showLCD(); //Show 1 sensor at LCD
refreshAnswer(); //Replace the old answer by a new one WIFI
http_check(); //See if we received a http request and reply if so WIFI
analyzeRequest(); //Change settings if requested by user WIFI
toggle_ledOnBoard(); //Toggles the LED_BUILTIN on or off on-board LED
} //End of void loop() //KEEP ON RUNNING THIS LOOP FOREVER
void refreshAnswer(void) { //Replace the old answer by a new one WIFI **********
html = String(valMQ2); //Start with a fresh string and enter a value WIFI
html += " "; //All response values are separated by a blank space WIFI
html += String(valMQ3); //Add another value to the response WIFI
html += " "; //All response values are separated by a blank space WIFI
html += String(valMQ5); //Add another value to the response WIFI
html += " "; //All response values are separated by a blank space WIFI
html += String(valMQ9); //Add another value to the response WIFI
bodyLength = html.length(); //Calculate the number of characters to sent WIFI
} //Exit refreshAnswer ---------------------------------------------------------
void http_check(void) { //See if we received a http request and reply if so WIFI
Request = ""; //Reset receive string by making it empty WIFI
while (Serial.available() > 0){ //Check if any request is made WIFI
Request = String(Request + Serial.readString()); //Read incoming WIFI
} //End of if (Serial.available() > 0) Entire block has been read WIFI
if (Request != "") { //Did I really receive a request? WIFI
Serial.println("HTTP/1.1 200 OK"); //Start answer to the request WIFI
Serial.println("Connection: close"); //Close after html is finished WIFI
Serial.print("Content-Length: "); //Finish html after amount of chars WIFI
Serial.println (bodyLength); //Name the amount of calculated characters WIFI
Serial.println("Content-Type: text/html"); //Needed to be compatible WIFI
Serial.println(" /n \n"); //Needed to end the headers WIFI
Serial.println(html); //Broadcast the message to be shown in browser WIFI
Serial.println(); //Any HTTP response ends with another blank line WIFI
Serial.println(); //Any HTTP response ends with another blank line WIFI
} //End of if (inStri <> "") The request has been answered WIFI
} //Exit http_check ------------------------------------------------------------
void analyzeRequest(void) { //Change settings if requested by user WIFI ********
if (Request != "") { //Did we receive any request WIFI
command = Request.substring(7, 10); //Extract the command from request WIFI
if (command == "prg"){ //Command selects the mode: 0=OFF 1=ON 2=AUTO WIFI
//prgVal1 = Request.substring(11, 12); //Filter the command number WIFI
} //End of if (command == "prg"){ Command selects the mode WIFI
} //End of if (Request != "") Finished processing requests WIFI
} //Exit analyzeRequest --------------------------------------------------------
void checkButton(void) { //Check if the yellow button is being pressed BUTTON **
ButtonVal = digitalRead(buttonPin); //High by default INPUT_PULLUP BUTTON
if (ButtonVal == LOW) { //Low if pressed BUTTON
counter = 0; //Refresh LCD immediately after relasing BUTTON
while (digitalRead(buttonPin) == LOW){ //Wait unil released BUTTON
} //Released BUTTON
ButtonCycle++; //Show next menu item invoked by BUTTON
if (ButtonCycle > 3){ //Only 4 smelly sensors exist (1-4) BUTTON
ButtonCycle = 0; //So cycle back if top had been reached BUTTON
} //Cycle now contains the appropiate value BUTTON
//delay (50); //If main loop is short, a debouncing pause is needed BUTTON
} //End of (ButtonVal == LOW) End of pressed BUTTON
} //Exit checkButton -----------------------------------------------------------
void showLCD(void) { //Show 1 sensor at LCD ************************************
if (counter == 0) { //Counter was introduced against a nevous display LCD
switch (ButtonCycle) { //So what do you want to see at the display LCD
case 0: //Cycle is being pressed by user BUTTON
lcd.setCursor(0, 0); //Position curcor at screen to write LCD
lcd.print(ButtonCycle+1); //Print a message to the LCD
lcd.print("=LPG met pro bu"); //Print a message to the LCD
lcd.setCursor(0, 1); //Position curcor at screen to write LCD
lcd.print("105 < "); //Print a message to the LCD
lcd.print(valMQ2); //Print a message to the LCD
lcd.print(" < 135 "); //Print a message to the LCD
break; //Jump to the end of this SWITCH
case 1: //Cycle is being pressed by user BUTTON
lcd.setCursor(0, 0); //Position curcor at screen to write LCD
lcd.print(ButtonCycle+1); //Print a message to the LCD
lcd.print("=Alcohol Benzin"); //Print a message to the LCD
lcd.setCursor(0, 1); //Position curcor at screen to write LCD
lcd.print("75 < "); //Print a message to the LCD
lcd.print(valMQ3); //Print a message to the LCD
lcd.print(" < 105 "); //Print a message to the LCD
break; //Jump to the end of this SWITCH
case 2: //Cycle is being pressed by user BUTTON
lcd.setCursor(0, 0); //Position curcor at screen to write LCD
lcd.print(ButtonCycle+1); //Print a message to the LCD
lcd.print("=LPG met pro bu"); //Print a message to the LCD
lcd.setCursor(0, 1); //Position curcor at screen to write LCD
lcd.print("250 < "); //Print a message to the LCD
lcd.print(valMQ5); //Print a message to the LCD
lcd.print(" < 360 "); //Print a message to the LCD
break; //Jump to the end of this SWITCH
case 3: //Cycle is being pressed by user BUTTON
lcd.setCursor(0, 0); //Position curcor at screen to write LCD
lcd.print(ButtonCycle+1); //Print a message to the LCD
lcd.print("=LPG met CO "); //Print a message to the LCD
lcd.setCursor(0, 1); //Position curcor at screen to write LCD
lcd.print("70 < "); //Print a message to the LCD
lcd.print(valMQ9); //Print a message to the LCD
lcd.print(" < 140 "); //Print a message to the LCD
break; //Jump to the end of this switch
default: //If NO button case matched, then perform default case BUTTON
break; //Jump to the end of this SWITCH
} //End of switch (ButtonCycle) So what you want to see at the display LCD
counter = LCDcounter; //Reset counter to initial value
}else{ //Counter is not zero yet
counter--;
} //End of (counter == 0) {
} //Exit showLCD(void) { //Show 1 sensor at LCD --------------------------------
void test_LEDs(void){ //PWM fade in and fade out for all 4 LED *****************
while (brillance<255){
analogWrite(ledGrePin, brillance); //Set LED to desired PWM value GREEN
brillance++;
delay (msWait);
}
while (brillance>0){
analogWrite(ledGrePin, brillance); //Set LED to desired PWM value GREEN
brillance--;
delay (msWait);
}
analogWrite(ledGrePin, 0); //Set LED to desired PWM value = off GREEN
while (brillance<255){
analogWrite(ledBluPin, brillance); //Set LED to desired PWM value BLUE
brillance++;
delay (msWait);
}
while (brillance>0){
analogWrite(ledBluPin, brillance); //Set LED to desired PWM value BLUE
brillance--;
delay (msWait);
}
analogWrite(ledBluPin, 0); //Set LED to desired PWM value = off BLUE
digitalWrite(ledRedPin, HIGH); //Set LED to desired value DIO RED LED
delay (500);
digitalWrite(ledRedPin, LOW); //Set LED to desired PWM value DIO RED LED
} //Exit test_LEDs -------------------------------------------------------------
void beep(uint8_t ms) { //Create a test beep (x5ms) with KY-012 active BUZZER **
digitalWrite(buzActPin,HIGH); //Turn buzzer on
while (ms > 0){ //Timer of the duration of the beep
delay(5); //Wait milliseconds
ms--; //Countdown untill we reached zero
} //Timer of the duration of the beep has been counted down to zero
digitalWrite(buzActPin,LOW); //Turn annoying buzzer off as fast as you can
} //Exit beep ------------------------------------------------------------------
void toggle_ledOnBoard(void){ //Toggles the LED_BUILTIN on-board LED on or off *
ledOnBoardVal = !ledOnBoardVal; //Toggle value
digitalWrite(LED_BUILTIN, ledOnBoardVal); //Set Arduino boards onboard LED
} //Exit toggle_ledBin ---------------------------------------------------------
void disable_jtag(void) { //Disable jtag to free port C, enabled by default ****
#if defined(JTD) //Not all AVR controller include jtag
MCUCR |= ( 1 << JTD ); //Write twice to disable
MCUCR |= ( 1 << JTD ); //So stutter once
#endif //End of conditional compiling
} //Exit jtag_disable ----------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
// PIN ALLOCATIONS TABLE ARDUINO UNO //
// Board -Atmel- PIN - IDE - Function - Connection ALT //
// //
// CONNECTIONS RAILS TOP LEFT: DIGITAL PWM<~> ******************************* //
// SCL - 28 - PC5 -19/A5- ADC5/SCL/PCINT13 - TWI //
// SDA - 27 - PC4 -18/A4- ADC4/SDA/PCINT12 - TWI //
// AREF - 21 - REF - - AREF - //
// GND - 22 - GND - - GND - //
// 13 - 19 - PB5 - 13 - SCK/PCINT5 - LED_BUITIN + GREEN LED SPI //
// 12 - 18 - PB4 - 12 - MISO/PCINT4 - BUTTON SPI //
// ~11 - 17 - PB3 - 11 - MOSI/OC2A/PCINT3 - BLUE LED PWM //
// ~10 - 16 - PB2 - 10 - SS/OC1B/PCINT2 - RED LED PWM //
// ~9 - 15 - PB1 - 9 - OC1A/PCINT1 - BUZZER PWM //
// 8 - 14 - PB0 - 8 - PCINT0/CLK0/ICP1 - DIO //
// //
// CONNECTIONS RAILS TOP RIGHT: DIGITAL PWM<~> ****************************** //
// 7 - 13 - PD7 - 7 - PCINT23/AIN1 - LCD RC DIO //
// ~6 - 12 - PD6 - 6 - PCINT22/OCA0/AIN0 - LCD EN PWM //
// ~5 - 11 - PD5 - 5 - PCINT21/OC0B/T1 - LCD D7 PWM //
// ~4 - 6 - PD4 - 4 - PCINT20/XCK/T0 - LCD D6 PWM //
// ~3 - 5 - PD3 - 3 - PCINT19/OC2B/INT1 - LCD D5 INT //
// ~2 - 4 - PD2 - 2 - PCINT18/INT0 - LCD D4 INT //
// TX->1 - 3 - PD1 - 1 - PCINT17/TXD - Serial monitor + WIFI TXD //
// RX<-0 - 2 - PD0 - 0 - PCINT16/RCD - Serial Monitor + WIFI RCD //
// //
// CONNECTIONS RAILS BOTTOM LEFT: POWER ************************************* //
// 5V - 7 - VCC - - VCC - VCC //
// RES - 1 - RES - - PCINT14/RESET - RES //
// 3.3V - - - - - //
// 5V - - - - - //
// GND - - - - - //
// GND - - - - - //
// Vin - - - - - Feeded from breadboard //
// //
// CONNECTIONS RAILS BOTTOM RIGHT: ANALOG IN ******************************** //
// A0 - 23 - PC0 -A0/14- ADC0/PCINT8 - MQ3 ADC //
// A1 - 24 - PC1 -A1/15- ADC1/PCINT9 - MQ2 ADC //
// A2 - 25 - PC2 -A2/16- ADC2/PCINT10 - MQ9 ADC //
// A3 - 26 - PC3 -A3/17- ADC3/PCINT12 - MQ5 ADC //
// A4 - 27 - PC4 -A4/18- ADC4/SDA/PCINT12 - TWI //
// A5 - 28 - PC5 -A5/19- ADC5/SCL/PCINT13 - TWI //
////////////////////////////////////////////////////////////////////////////////
// EEPROM MEMORY MAP: //
// Start End Number Description //
// 0000 0000 1 Never use this memory location to be AVR compatible //
////////////////////////////////////////////////////////////////////////////////
//345678911234567892123456789312345678941234567895123456789612345678971234567898
////////////////////////////////////////////////////////////////////////////////
// FUSES (can always be altered by using the STK500) //
// On-Chip Debug Enabled: off (OCDEN=0) //
// JTAG Interface Enabled: off (JTAGEN=0) //
// Preserve EEPROM mem through the Chip Erase cycle: On (EESAVE = 0) //
// Boot Flash section = 2048 words, Boot startaddr=$3800 (BOOTSZ=00) //
// Boot Reset vector Enabled, default address=$0000 (BOOTSTR=0) //
// CKOPT fuse (operation dependent of CKSEL fuses (CKOPT=0) //
// Brown-out detection level at VCC=2,7V; (BODLEVEL=0) //
// Ext. Cr/Res High Freq.; Start-up time: 16K CK + 64 ms (CKSEL=1111 SUT=11) //
// LOCKBITS (are dangerous to change, since they cannot be reset) //
// Mode 1: No memory lock features enabled //
// Application Protect Mode 1: No lock on SPM and LPM in Application Section //
// Boot Loader Protect Mode 1: No lock on SPM and LPM in Boot Loader Section //
////////////////////////////////////////////////////////////////////////////////