Final Project¶
potivia¶
in the final two weeks , I worked with my collogue Mohamed Almoawdah in building an indoor air monitoring system that could be easily implemented in ascetic way ,
so we tried to build an air mentoring system blended within a palnt pot , and we name it potovia!
electronics¶
I started with the fist element in the circuit which was MQ-5 gas sensor .This sensor is useful for detecting gas leaks (in home and industry). the sensor is sensitive (can detect) co2 , CO , SO2..etc , which all may considered as harmful gasses
I used adafruite blue feather as MICRO-CONROLLER to the circuit
..
the first step I did was to connect to wires from adafruit to the breadboard
gnd (adafruit)>>>> negative sign in the breadboard 3v (adafruit)>>>>> positive sign ,thi step is esntitial that we way I can as much sensors as I can to same circut
then I linked the gnd (from the sesnor )>>>negative sign of the board vcc (from the sensor)>>>> positive sign of the board A0 (FROM THE SESNOR)>>>>> A0 ANALOG in the adafruit
to have more insight in the process please refer to my 7th week assignment
secondly
I linked the soil moister sensor to the adafruit as followed vcc >> postive gnd>> negative A0>> A1
the soil moister sensor is linked as the other sensor but the olny diffrence is digital analog. and the fact that the soil moister need to adjusted, because left alone the soil mister will only give numbers high or low depending the soil status so what I did is I adjusted the numbers with an if statment to control the result so if the soil was moistred enough it will display wet of not dry will the output
code¶
since my microntroller have an already built in tempreture sensor and humidity I used the code from thier website and added it to my code , detials on the refrences
#include <SPI.h>
#include <MQ135.h>
#define soilSensor2 A1
int goodMoisture = 300;
// SPDX-License-Identifier: MIT
//
#include <Adafruit_APDS9960.h>
#include <Adafruit_BMP280.h>
#include <Adafruit_LIS3MDL.h>
#include <Adafruit_SHT31.h>
#include <Adafruit_Sensor.h>
#include <PDM.h>
#include <bluefruit.h>
#include <Adafruit_LittleFS.h>
#include <InternalFileSystem.h>
// BLE Service
BLEDfu bledfu; // OTA DFU service
BLEDis bledis; // device information
BLEUart bleuart; // uart over ble
BLEBas blebas; // battery
Adafruit_APDS9960 apds9960; // proximity, light, color, gesture
Adafruit_BMP280 bmp280; // temperautre, barometric pressure
Adafruit_LIS3MDL lis3mdl; // magnetometer
Adafruit_SHT31 sht30; // humidity
uint8_t proximity;
uint16_t r, g, b, c;
float temperature, pressure, altitude;
float magnetic_x, magnetic_y, magnetic_z;
float accel_x, accel_y, accel_z;
float gyro_x, gyro_y, gyro_z;
float humidity;
int32_t mic;
extern PDMClass PDM;
short sampleBuffer[256]; // buffer to read samples into, each sample is 16-bits
volatile int samplesRead; // number of samples read
#include <SPI.h>
#define DUST_SENSOR_PIN_PM10 A3 //Must be the pins that
#define DUST_SENSOR_PIN_PM25 A2 //support interrupts
#define INTERVAL_COUNTDOWN 1000
#define INTERVAL_READ 30000
#include <KarserDSM501.h>
// ISRs forward declaration
void pm10_handleInterrupt();
void pm25_handleInterrupt();
// init pm10 and pm25 instances
KarserDSM501 pm10(DUST_SENSOR_PIN_PM10, pm10_handleInterrupt);
KarserDSM501 pm25(DUST_SENSOR_PIN_PM25, pm25_handleInterrupt);
// handle ISRs
void pm10_handleInterrupt() { pm10.handleInterrupt(); }
void pm25_handleInterrupt() { pm25.handleInterrupt(); }
unsigned long timer = 0;
void setup()
{
Serial.println("Feather Sense Sensor Demo");
// initialize the sensors
apds9960.begin();
apds9960.enableProximity(true);
apds9960.enableColor(true);
bmp280.begin();
lis3mdl.begin_I2C();
sht30.begin();
int sensorValue1 = analogRead(soilSensor2);
pinMode(A0,INPUT);
Serial.begin(9600);
Serial.println("Feather Sense Sensor Demo");
// initialize the sensors
apds9960.begin();
apds9960.enableProximity(true);
apds9960.enableColor(true);
bmp280.begin();
lis3mdl.begin_I2C();
sht30.begin();
Serial.begin(115200);
#if CFG_DEBUG
// Blocking wait for connection when debug mode is enabled via IDE
while ( !Serial ) yield();
#endif
Serial.println("Bluefruit52 BLEUART Example");
Serial.println("---------------------------\n");
// Setup the BLE LED to be enabled on CONNECT
// Note: This is actually the default behavior, but provided
// here in case you want to control this LED manually via PIN 19
Bluefruit.autoConnLed(true);
// Config the peripheral connection with maximum bandwidth
// more SRAM required by SoftDevice
// Note: All config***() function must be called before begin()
Bluefruit.configPrphBandwidth(BANDWIDTH_MAX);
Bluefruit.begin();
Bluefruit.setTxPower(4); // Check bluefruit.h for supported values
//Bluefruit.setName(getMcuUniqueID()); // useful testing with multiple central connections
Bluefruit.Periph.setConnectCallback(connect_callback);
Bluefruit.Periph.setDisconnectCallback(disconnect_callback);
// To be consistent OTA DFU should be added first if it exists
bledfu.begin();
// Configure and Start Device Information Service
bledis.setManufacturer("Adafruit Industries");
bledis.setModel("Bluefruit Feather52");
bledis.begin();
// Configure and Start BLE Uart Service
bleuart.begin();
// Start BLE Battery Service
blebas.begin();
blebas.write(100);
// Set up and start advertising
startAdv();
Serial.println("Please use Adafruit's Bluefruit LE app to connect in UART mode");
Serial.println("Once connected, enter character(s) that you wish to send");
}
void loop()
{
int sv=analogRead(A0);
Serial.print("AQI=");
Serial.print(sv);
Serial.print("ppm");
Serial.println(" ");
bleuart.write("AQI=");
char svchar[16];
itoa(sv, svchar, 10);
bleuart.write(svchar);
bleuart.write("ppm");
bleuart.write(" ");
bleuart.write('\n');
int sensorValue1 = analogRead(soilSensor2);
if (sensorValue1 < goodMoisture){
Serial.println("wet");
bleuart.write("Soil condition: wet");
bleuart.write('\n');
} else {
Serial.println("dry");
bleuart.write("Soil condition: dry");
bleuart.write('\n');
}
proximity = apds9960.readProximity();
while (!apds9960.colorDataReady()) {
delay(5);
}
apds9960.getColorData(&r, &g, &b, &c);
temperature = bmp280.readTemperature();
pressure = bmp280.readPressure();
altitude = bmp280.readAltitude(1013.25);
lis3mdl.read();
magnetic_x = lis3mdl.x;
magnetic_y = lis3mdl.y;
magnetic_z = lis3mdl.z;
sensors_event_t accel;
sensors_event_t gyro;
sensors_event_t temp;
accel_x = accel.acceleration.x;
accel_y = accel.acceleration.y;
accel_z = accel.acceleration.z;
gyro_x = gyro.gyro.x;
gyro_y = gyro.gyro.y;
gyro_z = gyro.gyro.z;
humidity = sht30.readHumidity();
samplesRead = 0;
Serial.println("---------------------------------------------");
Serial.print("Temperature: ");
Serial.print(temperature);
Serial.println(" C");
Serial.print(" ");
bleuart.write("Temperature: ");
char temperaturechar[16];
itoa(temperature, temperaturechar, 10);
bleuart.write(temperaturechar);
bleuart.write(" C");
bleuart.write(" ");
bleuart.write('\n');
Serial.print("Humidity: ");
Serial.print(humidity);
Serial.println(" %");
delay(1000);
bleuart.write("Humidity: ");
char humiditychar[16];
itoa(humidity, humiditychar, 10);
bleuart.write(humiditychar);
bleuart.write(" ");
bleuart.write('\n');
if (!pm10.isReady() && (millis() >= timer + INTERVAL_COUNTDOWN)) {
Serial.println("DSM501 warm up: " + String(pm10.getReadyCountdown()));
timer += INTERVAL_COUNTDOWN;
} else if (millis() >= timer + INTERVAL_READ) {
timer += INTERVAL_READ;
Serial.println("pm10: "+String(pm10.readPM())+" pm2.5: "+String(pm25.readPM()));
delay (1000) ;
}
bleuart.write("DSM501 warm up: ");
String dsm = String(pm10.readPM());
char dsmchar[16];
dsm.toCharArray(dsmchar, 10);
bleuart.write(dsmchar);
bleuart.write('\n');
}
void startAdv(void)
{
// Advertising packet
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
Bluefruit.Advertising.addTxPower();
// Include bleuart 128-bit uuid
Bluefruit.Advertising.addService(bleuart);
// Secondary Scan Response packet (optional)
// Since there is no room for 'Name' in Advertising packet
Bluefruit.ScanResponse.addName();
/* Start Advertising
* - Enable auto advertising if disconnected
* - Interval: fast mode = 20 ms, slow mode = 152.5 ms
* - Timeout for fast mode is 30 seconds
* - Start(timeout) with timeout = 0 will advertise forever (until connected)
*
* For recommended advertising interval
* https://developer.apple.com/library/content/qa/qa1931/_index.html
*/
Bluefruit.Advertising.restartOnDisconnect(true);
Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
}
// callback invoked when central connects
void connect_callback(uint16_t conn_handle)
{
// Get the reference to current connection
BLEConnection* connection = Bluefruit.Connection(conn_handle);
char central_name[32] = { 0 };
connection->getPeerName(central_name, sizeof(central_name));
Serial.print("Connected to ");
Serial.println(central_name);
}
/**
* Callback invoked when a connection is dropped
* @param conn_handle connection where this event happens
* @param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h
*/
void disconnect_callback(uint16_t conn_handle, uint8_t reason)
{
(void) conn_handle;
(void) reason;
Serial.println();
Serial.print("Disconnected, reason = 0x"); Serial.println(reason, HEX);
}
the final result in the serial looked like
then we thought about how we gonna display all these data , accourding to our design lcd is not practical , hence we thought about displaying all these data in AN app detial in my collgue mohammed page
and also we thought about linking led pixels around 60 pices to circuit and the soil moister specifically , to reflect the statues of the plant and the result was really satisficing. if the soil moister eeading were wet the led pixel will turn in green if dry red
and the final project code after linking the data from the serial to the app looked like this
2D and 3D Modeling¶
Add here your modeling and design.
Some other section¶
This is an updated text.
Materials¶
Qty | Description | Price | Link | Notes |
---|---|---|---|---|
1 | Material one | 22.00 $ | http://amazon.com/test | Order many |
1 | Material two | 22.00 $ | http://amazon.com/test | |
1 | Material three | 22.00 $ | http://amazon.com/test | |
1 | Material five | 22.00 $ | http://amazon.com/test | |
1 | Material eight | 22.00 $ | http://amazon.com/test | |
1 | Material twelve | 22.00 $ | http://amazon.com/test | |
1 | Material eleven | 22.00 $ | http://amazon.com/test |
Useful links¶
Code Example¶
Use the three backticks to separate code.
#include <SPI.h>
#include <MQ135.h>
#define soilSensor2 A1
int goodMoisture = 300;
// SPDX-License-Identifier: MIT
//
#include <Adafruit_APDS9960.h>
#include <Adafruit_BMP280.h>
#include <Adafruit_LIS3MDL.h>
#include <Adafruit_SHT31.h>
#include <Adafruit_Sensor.h>
#include <PDM.h>
#include <bluefruit.h>
#include <Adafruit_LittleFS.h>
#include <InternalFileSystem.h>
// BLE Service
BLEDfu bledfu; // OTA DFU service
BLEDis bledis; // device information
BLEUart bleuart; // uart over ble
BLEBas blebas; // battery
Adafruit_APDS9960 apds9960; // proximity, light, color, gesture
Adafruit_BMP280 bmp280; // temperautre, barometric pressure
Adafruit_LIS3MDL lis3mdl; // magnetometer
Adafruit_SHT31 sht30; // humidity
uint8_t proximity;
uint16_t r, g, b, c;
float temperature, pressure, altitude;
float magnetic_x, magnetic_y, magnetic_z;
float accel_x, accel_y, accel_z;
float gyro_x, gyro_y, gyro_z;
float humidity;
int32_t mic;
extern PDMClass PDM;
short sampleBuffer[256]; // buffer to read samples into, each sample is 16-bits
volatile int samplesRead; // number of samples read
#include <SPI.h>
#define DUST_SENSOR_PIN_PM10 A3 //Must be the pins that
#define DUST_SENSOR_PIN_PM25 A2 //support interrupts
#define INTERVAL_COUNTDOWN 1000
#define INTERVAL_READ 30000
#include <KarserDSM501.h>
// ISRs forward declaration
void pm10_handleInterrupt();
void pm25_handleInterrupt();
// init pm10 and pm25 instances
KarserDSM501 pm10(DUST_SENSOR_PIN_PM10, pm10_handleInterrupt);
KarserDSM501 pm25(DUST_SENSOR_PIN_PM25, pm25_handleInterrupt);
// handle ISRs
void pm10_handleInterrupt() { pm10.handleInterrupt(); }
void pm25_handleInterrupt() { pm25.handleInterrupt(); }
unsigned long timer = 0;
void setup()
{
Serial.println("Feather Sense Sensor Demo");
// initialize the sensors
apds9960.begin();
apds9960.enableProximity(true);
apds9960.enableColor(true);
bmp280.begin();
lis3mdl.begin_I2C();
sht30.begin();
int sensorValue1 = analogRead(soilSensor2);
pinMode(A0,INPUT);
Serial.begin(9600);
Serial.println("Feather Sense Sensor Demo");
// initialize the sensors
apds9960.begin();
apds9960.enableProximity(true);
apds9960.enableColor(true);
bmp280.begin();
lis3mdl.begin_I2C();
sht30.begin();
Serial.begin(115200);
#if CFG_DEBUG
// Blocking wait for connection when debug mode is enabled via IDE
while ( !Serial ) yield();
#endif
Serial.println("Bluefruit52 BLEUART Example");
Serial.println("---------------------------\n");
// Setup the BLE LED to be enabled on CONNECT
// Note: This is actually the default behavior, but provided
// here in case you want to control this LED manually via PIN 19
Bluefruit.autoConnLed(true);
// Config the peripheral connection with maximum bandwidth
// more SRAM required by SoftDevice
// Note: All config***() function must be called before begin()
Bluefruit.configPrphBandwidth(BANDWIDTH_MAX);
Bluefruit.begin();
Bluefruit.setTxPower(4); // Check bluefruit.h for supported values
//Bluefruit.setName(getMcuUniqueID()); // useful testing with multiple central connections
Bluefruit.Periph.setConnectCallback(connect_callback);
Bluefruit.Periph.setDisconnectCallback(disconnect_callback);
// To be consistent OTA DFU should be added first if it exists
bledfu.begin();
// Configure and Start Device Information Service
bledis.setManufacturer("Adafruit Industries");
bledis.setModel("Bluefruit Feather52");
bledis.begin();
// Configure and Start BLE Uart Service
bleuart.begin();
// Start BLE Battery Service
blebas.begin();
blebas.write(100);
// Set up and start advertising
startAdv();
Serial.println("Please use Adafruit's Bluefruit LE app to connect in UART mode");
Serial.println("Once connected, enter character(s) that you wish to send");
}
void loop()
{
int sv=analogRead(A0);
Serial.print("AQI=");
Serial.print(sv);
Serial.print("ppm");
Serial.println(" ");
bleuart.write("AQI=");
char svchar[16];
itoa(sv, svchar, 10);
bleuart.write(svchar);
bleuart.write("ppm");
bleuart.write(" ");
bleuart.write('\n');
int sensorValue1 = analogRead(soilSensor2);
if (sensorValue1 < goodMoisture){
Serial.println("wet");
bleuart.write("Soil condition: wet");
bleuart.write('\n');
} else {
Serial.println("dry");
bleuart.write("Soil condition: dry");
bleuart.write('\n');
}
proximity = apds9960.readProximity();
while (!apds9960.colorDataReady()) {
delay(5);
}
apds9960.getColorData(&r, &g, &b, &c);
temperature = bmp280.readTemperature();
pressure = bmp280.readPressure();
altitude = bmp280.readAltitude(1013.25);
lis3mdl.read();
magnetic_x = lis3mdl.x;
magnetic_y = lis3mdl.y;
magnetic_z = lis3mdl.z;
sensors_event_t accel;
sensors_event_t gyro;
sensors_event_t temp;
accel_x = accel.acceleration.x;
accel_y = accel.acceleration.y;
accel_z = accel.acceleration.z;
gyro_x = gyro.gyro.x;
gyro_y = gyro.gyro.y;
gyro_z = gyro.gyro.z;
humidity = sht30.readHumidity();
samplesRead = 0;
Serial.println("---------------------------------------------");
Serial.print("Temperature: ");
Serial.print(temperature);
Serial.println(" C");
Serial.print(" ");
bleuart.write("Temperature: ");
char temperaturechar[16];
itoa(temperature, temperaturechar, 10);
bleuart.write(temperaturechar);
bleuart.write(" C");
bleuart.write(" ");
bleuart.write('\n');
Serial.print("Humidity: ");
Serial.print(humidity);
Serial.println(" %");
delay(1000);
bleuart.write("Humidity: ");
char humiditychar[16];
itoa(humidity, humiditychar, 10);
bleuart.write(humiditychar);
bleuart.write(" ");
bleuart.write('\n');
if (!pm10.isReady() && (millis() >= timer + INTERVAL_COUNTDOWN)) {
Serial.println("DSM501 warm up: " + String(pm10.getReadyCountdown()));
timer += INTERVAL_COUNTDOWN;
} else if (millis() >= timer + INTERVAL_READ) {
timer += INTERVAL_READ;
Serial.println("pm10: "+String(pm10.readPM())+" pm2.5: "+String(pm25.readPM()));
delay (1000) ;
}
bleuart.write("DSM501 warm up: ");
String dsm = String(pm10.readPM());
char dsmchar[16];
dsm.toCharArray(dsmchar, 10);
bleuart.write(dsmchar);
bleuart.write('\n');
}
void startAdv(void)
{
// Advertising packet
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
Bluefruit.Advertising.addTxPower();
// Include bleuart 128-bit uuid
Bluefruit.Advertising.addService(bleuart);
// Secondary Scan Response packet (optional)
// Since there is no room for 'Name' in Advertising packet
Bluefruit.ScanResponse.addName();
/* Start Advertising
* - Enable auto advertising if disconnected
* - Interval: fast mode = 20 ms, slow mode = 152.5 ms
* - Timeout for fast mode is 30 seconds
* - Start(timeout) with timeout = 0 will advertise forever (until connected)
*
* For recommended advertising interval
* https://developer.apple.com/library/content/qa/qa1931/_index.html
*/
Bluefruit.Advertising.restartOnDisconnect(true);
Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
}
// callback invoked when central connects
void connect_callback(uint16_t conn_handle)
{
// Get the reference to current connection
BLEConnection* connection = Bluefruit.Connection(conn_handle);
char central_name[32] = { 0 };
connection->getPeerName(central_name, sizeof(central_name));
Serial.print("Connected to ");
Serial.println(central_name);
}
/**
* Callback invoked when a connection is dropped
* @param conn_handle connection where this event happens
* @param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h
*/
void disconnect_callback(uint16_t conn_handle, uint8_t reason)
{
(void) conn_handle;
(void) reason;
Serial.println();
Serial.print("Disconnected, reason = 0x"); Serial.println(reason, HEX);
}
Gallery¶
Video¶
From Vimeo¶
Sound Waves from George Gally (Radarboy) on Vimeo.