Assignment 6 Update

With the wires back on the fan motor, I confirmed that code works in two ways: 1) when the humidity sensor detects that the average humidity is less than 50% the fan turns on, and 2) when the average humidity is less than 50% the fan turns off. Next, with condition 2 as the base conditions, I needed to test if the fan will turn on when the humidity sensor detects that the average humidity has increased to above 50%.

With my first version of the code, the fan was not responding the way I wanted to the humidity sensor readings.

This second version of the code using millis() was successful:

#include <DHT.h>
#include <DHT_U.h>
#define DHTPIN 2        // sensor DHT22 data connected to Arduino pin 2
#define DHTTYPE DHT22  // using sensor DHT22
DHT dht(DHTPIN, DHTTYPE);  //dht library
int chk;
int humid; //stores humidity


//data smoothing
const int numReadings = 5;
int humReadings [numReadings];
int humReadIndex = 0;
int humTotal = 0;
int humAverage = 0;
int inputPin = 2; //put dht 222 sensor pin here
//detecting sensor change
int last;
//response to sensor change


//for fan and motor
int speedPin = 5;
int dir1 = 4;
int dir2 = 3;
int mSpeed = 0;
unsigned long lastReadTime = 0;

void setup() {
  // put your setup code here, to run once:
  //pins for fan and motot
  pinMode(speedPin, OUTPUT);
  pinMode(dir1, OUTPUT);
  pinMode(dir2, OUTPUT);


  //dht sensor
  dht.begin();

//data smoothing for humidity
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    //tempReadings[thisReading] = 0;
    humReadings[thisReading] = 0;
  }
  Serial.begin(9600);

  lastReadTime = millis();
}

void loop() {
  //delay(1000);

  if ((millis() - lastReadTime) >= 10000UL) {
    //Serial.println(lastReadTime); //used to check millis 
    //Serial.println(millis());//used to check millis
    lastReadTime = millis();
    humid = dht.readHumidity();
    Serial.println(humid); //prints the current sensor reading
    humTotal = humTotal - humReadings[humReadIndex];
    humReadings[humReadIndex] = humid;
    humTotal = humTotal + humReadings [humReadIndex];
    humReadIndex = humReadIndex + 1;
    if (humReadIndex >= numReadings) {
      humReadIndex = 0;
    }
    humAverage = humTotal / numReadings;
    Serial.println(humAverage);

  }


  if (humAverage > 50)
  {
    digitalWrite(dir1, HIGH);
    digitalWrite(dir2, LOW);
    analogWrite(speedPin, 225);
  }else
  {
    digitalWrite(dir1,HIGH);
    digitalWrite(dir2,LOW);
    analogWrite(speedPin, 0);
  }
}

I started in a room with humidity readings less than 50 (no fan motion). I turned on hot water in the bathroom, and after a few minutes, moved the sensor and fan into that room. As the sensor’s humidity reading rose, so did the average humidity reading. Once the average humidity reading rose above 50, the fan began to turn. Then I moved the sensor and fan back into the original room, and waited for the average humidity to fall. When the average humidity fell below 50 again, the fan motor turned off.

Note on power and troubleshooting:

I originally had both the fan and the humidity sensor connected to the rail. This worked the first time I tried it, but the sensor began to send back 0 readings after a few test runs. I had to connect the DHT22 sensor to the arduino and the fan to the rail (with 5V power supply connected to 9V battery) for both the sensor and the fan to work properly. My clue was that the LED light on the power supply started bright and dimmed as the code started running.

Assignment 6 – Jud

Description:

This circuit turns the data that the sound sensor gets into an angle based off of a moving average of the amplitude of the data received. The data from the sensor captures the raw sound waves from the air and sends them to the arduino which has a very spiky and unsmooth nature. In addition, the data transitions for increasing to decreasing very rapidly so a traditional filter or tracking the change in the data does not work well at all. Instead, I have implemented a moving average method where the code tracks a certain number of data points, calculates the max and min of the data, and then uses the difference between these values as the new data. This is then multiplied by some multiplier to increase the variance and translated into an angle for a servo to travel to. The algorithm for calculating the angle works wonders while the servo isn’t connected, however, as depicted in the video, the noise of the servo creates an uncontrollable feedback look that results in the servo moving out of control. Regardless, the system responds to noise in the way that it should translating a noise in the environment into an angle for the servo to move to.

Video:

Code:

#include <Servo.h>

//Define Accelerometer Variables for pins
#define MICROPHONE    A0
#define SERVO_PIN     9

Servo servo;

double servoAngle = 0;

double alpha = 0.9;
double multiplier = 5;

//Array to hold data for moving average calculation
double speakerData[100]; // {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

double speakerLevel = 0;
double prevSpeakerLevel = 0;
double maxSpeakerLevel = 200;
double minSpeakerLevel = 50;


void setup() {
  //Setup pins as inputs
  pinMode(MICROPHONE, INPUT);

  //Create servo object
  servo.attach(SERVO_PIN);
  
}

void loop() {

  //Update moving average array
  for (int i = (sizeof(speakerData)/sizeof(speakerData[0]) - 1); i >= 0; i--) {
    if (i != 0) {
      speakerData[i] = speakerData[i - 1];
    }
    else {
      speakerData[i] = analogRead(MICROPHONE);
    }
  }

  double MIN = findMin();
  double MAX = findMax();

  speakerLevel = MAX - MIN;
  speakerLevel = multiplier*(alpha*speakerLevel + (1 - alpha)*prevSpeakerLevel);  //Filter data

  //Put upper and lower bounds on data
  if (speakerLevel >= maxSpeakerLevel) {
    speakerLevel = maxSpeakerLevel;
  }
  else if (speakerLevel <= minSpeakerLevel) {
    speakerLevel = minSpeakerLevel;
  }

  servoAngle = 180*(speakerLevel - minSpeakerLevel)/(maxSpeakerLevel - minSpeakerLevel);
  servo.write((int) servoAngle);

  prevSpeakerLevel = speakerLevel;
  
}

int findMin() {
  double minimum = 0;
  for (int i = 0; i < sizeof(speakerData)/sizeof(speakerData[0]); i++) {
    if (speakerData[i] < minimum || i == 0) {
      minimum = speakerData[i];
    }
  }
  return minimum;
}

int findMax() {
  double maximum = 0;
  for (int i = 0; i < sizeof(speakerData)/sizeof(speakerData[0]); i++) {
    if (speakerData[i] > maximum) {
      maximum = speakerData[i];
    }
  }
  return maximum;
}

 

Assignment 6 – James Kyle

Daylight Level Indicator:

For this assignment, I have made a theoretical daylight level sensor. The inspiration for this comes from my lab being in the basement of Ansys. We have no windows down there so I can easily get sucked into work and stay there for hours without realizing what time of day it is and/or whether it is time to pack up and call it a day. This daylight level indicator is meant to solve this problem by sensing the amount of daylight coming from outside and physically turning a dial to show the time of day. Theoretically, this dial would take the shape of a circle with night and day images on either side. The servo would turn to the appropriate position to indicate how close the sun is to setting or rising depending on the level of light outside and the time of day.

#include <Servo.h>


int hours = 0;

const int measurementNumber = 20;
int measurementCount = 0;
int lightMeasurements[measurementNumber];
const int lightLevel = A0; //Light level pin (photoresistor pin)

int lightBottomBound = 0;
int lightTopBound = 0;


Servo myServo;
int SERVOPIN = 9;



void setup() {

  pinMode(lightLevel, INPUT);

  myServo.attach(9);

}

void loop() {

  //Update measurement counter
  if (measurementCount < measurementNumber) {
    measurementCount += 1;
  } else {
    measurementCount = 0;
  }


  //Update light level average
  int lightLevelSum = 0;
  for (int i = 1; i < measurementNumber; i++) {
    lightLevelSum += lightMeasurements[i];
  }

  int lightLevelAverage = lightLevelSum / measurementNumber;



  //Update light level measurements
  int currentLightLevel = analogRead(lightLevel);
  lightMeasurements[measurementCount] = currentLightLevel;




  //Change bounds if light level is outside of bounds
  if (lightLevelAverage < lightBottomBound) {
    lightBottomBound = lightLevelAverage;
  }

  if (lightLevelAverage > lightTopBound) {
    lightTopBound = lightLevelAverage;
  }


  //Write to servo
  int servoAngle = map(lightLevelAverage, lightBottomBound, lightTopBound, 0, 180);
  myServo.write(servoAngle);


  delay(1000);

}