Skip to content

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

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);
}

Video

From Vimeo

Sound Waves from George Gally (Radarboy) on Vimeo.

From Youtube

3D Models


Last update: November 3, 2022