How to Capture Temperature and Humidity Using the ESP8266 Weather Kit

In this post, I’ll show you how to set up the ESP8266 and how to capture temperature and humidity data using this device. For this project I followed the Uctronics user guide. To locate that, just type into Google, “UCTRONICS ESP8266 pdf user guide”, and it should be the first result.

Requirements

Here are the requirements:

  • Set up the ESP8266 and capture temperature and humidity data using this device.

Hardware Design

The following components are used in this project. You will need:

parts_for_esp8266

Here is the diagram of the hardware setup:

hardware_setup_esp8266PNG

Software Design

Software to read temperature and humidity comes from:
https://github.com/supprot/ArduCAM_esp8266- dht-thingspeak-logger.

Hardware Implementation

First, I did a test project to see if I can use an API to capture weather forecast data from the web on my OLED.

I downloaded and installed the Serial Driver available here: https://www.silabs.com/products/mcu/Pages/USBtoUARTBridgeVCPDrivers.aspx

device_driver_8266PNG

I installed the ESP8266 toolchain.

esp8266_toolchain

I selected the correct board NodeMCU 1.0 (ESP-12E Module): In the Arduino IDE, I went to Tools > Board: * > NodeMCU 1.0 (ESP-12E Module).

I set the correct port by going to Tools > Port and looking for a COM port labelled COM# (where # is a number).

I tested the setup of the Wifi Scanner. In the Menu of the Arduino IDE, I went to to File > Examples > ESP8266Wifi and select WiFiScan.

wifi_scan

I installed the libraries for the weather station: Sketch > Include Library… > Manage Libraries…

  • ESP8266 Weather Station Library
  • Json Streaming Parser Library
  • SSD1306 OLED Library

I opened the WeatherStationDemo example: Went to File > Examples > ESP8266 Weather Station >WeatherStationDemo and saved the new sketch with a new name.

I got the OpenWeatherMap API.

open_weather_map

I configured the weather station.

wx_station_demo

I connected the hardware.

esp8266_breadboard

I uploaded the firmware and ran the WeatherStation. The weather forecast and current weather outside were displayed on the OLED display as seen below.

Next, I collected and displayed temperature and humidity data in my home office. Here are the steps I took:

I set up Thingspeak.

thing_speak

I went to https://github.com/supprot/ArduCAM_esp8266- dht-thingspeak-logger and downloaded the code as a Zip file.

I adapted the settings to my needs.

I set up the hardware.

humidity_logger

I ran the temperature and humidity logger. Here are the results I got.

temp_results
humidity_results

Software Implementation

Here is the source code that you will need to load to your ESP8266 board. Where it says “xxxx”, that is where you enter your own values:

/**The MIT License (MIT)

Copyright (c) 2015 by Daniel Eichhorn

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

See more at http://blog.squix.ch
// Modified by Addison Sears-Collins
*/

#include <ESP8266WiFi.h>
#include <DHT.h>


/***************************
 * Begin Settings
 **************************/


const char* ssid     = "xxxx";
const char* password = "xxxx";

const char* host = "api.thingspeak.com";

const char* THINGSPEAK_API_KEY = "xxxx";

// DHT Settings
#define DHTPIN D6     // what digital pin we're connected to. If you are not using NodeMCU change D6 to real pin


// Uncomment whatever type you're using!
#define DHTTYPE DHT11   // DHT 11
//#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
//#define DHTTYPE DHT21   // DHT 21 (AM2301)

const boolean IS_METRIC = true;

// Update every 30 seconds. Min with Thingspeak is ~20 seconds
const int UPDATE_INTERVAL_SECONDS = 60;

/***************************
 * End Settings
 **************************/
 
// Initialize the temperature/ humidity sensor
DHT dht(DHTPIN, DHTTYPE);

void setup() {
  Serial.begin(115200);
  delay(10);

  // We start by connecting to a WiFi network

  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  
  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");  
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void loop() {      
    Serial.print("connecting to ");
    Serial.println(host);
    
    // Use WiFiClient class to create TCP connections
    WiFiClient client;
    const int httpPort = 80;
    if (!client.connect(host, httpPort)) {
      Serial.println("connection failed");
      return;
    }

    // read values from the sensor
    float humidity = dht.readHumidity();
    float temperature = dht.readTemperature(!IS_METRIC);
    
    // We now create a URI for the request
    String url = "/update?api_key=";
    url += THINGSPEAK_API_KEY;
    url += "&field1=";
    url += String(temperature);
    url += "&field2=";
    url += String(humidity);
    
    Serial.print("Requesting URL: ");
    Serial.println(url);
    
    // This will send the request to the server
    client.print(String("GET ") + url + " HTTP/1.1\r\n" +
                 "Host: " + host + "\r\n" + 
                 "Connection: close\r\n\r\n");
    delay(10);
    while(!client.available()){
      delay(100);
      Serial.print(".");
    }
    // Read all the lines of the reply from server and print them to Serial
    while(client.available()){
      String line = client.readStringUntil('\r');
      Serial.print(line);
    }
    
    Serial.println();
    Serial.println("closing connection");


  // Go back to sleep. If your sensor is battery powered you might
  // want to use deep sleep here
  delay(1000 * UPDATE_INTERVAL_SECONDS);
}

Video

How to Assemble the QWinOut DIY Radio-Controlled Quadcopter

In this post, I’ll show you how to assemble the QWinOut DIY Radio Controlled Quadcopter (450mm).

Requirements

Here are the requirements:

  • Assemble the quadcopter by following the instructional video below.
  • Register the drone with the Federal Aviation Administration (FAA).
  • Make a video of the flight.

Hardware Design

The following components are used in this system. They are all contained in the QWinout DIY Controlled Quadcopter Kit.

qwinout_quadcopter_parts_3

Spare Parts

Setup

Here are the steps for the hardware setup:

To begin, I secured the four plastic arms to the frame board with the screws. I used my fingers to tighten the screws, followed by a 5/64 in. long arm hex Allen key wrench.

qwinout_quadcopter_parts_2

I secured the motor on the motor mount of the arm with the screws. I used my fingers to tighten the screws, followed by a 3/32 in. long arm hex Allen key wrench.

qwinout_quadcopter_parts_1

I connected all four motors to the four Electronic Speed Controllers (ESCs). Black to black, red to red, and yellow to the middle wire.

qwinout_450mm_quadcopter_assembly (2)

I installed the KK Flight Controller on the board with the adhesive tape. I then connected the flight controller M1-M4 ports to the ESCs according to the sequence below. The arrow on the flight controller points to the front of the quadcopter.

qwinout_450mm_quadcopter_assembly (3)

Below is the direction that each motor should spin. Two motors will spin counterclockwise, and two motors will spin clockwise.

motor_spin_direction
qwinout_450mm_quadcopter_assembly (5)

Next, I installed batteries in the back of the Radio Link remote control. I then turned it on.

I then placed the aircraft horizontally. I turned off the PITCH knob switch by turning it counterclockwise. I used a 2.4mm flathead screwdriver to do this.

yaw_pitch_roll

I then connected the power of the aircraft. The flight controller light flashed quickly then slowly, indicating the neutral point signal was identified and saved. This completed the Transmitter Central Point Calibration.

I unplugged the power supply.

I turned on the PITCH knob by turning it clockwise 125 degrees.

I then did the Gyro direction correction. I turned off the ROLL knob switch by turning it counterclockwise.

yaw_pitch_roll_2

I then cut off the aircraft power supply. I turned the ROLL knob clockwise 125 degrees to turn it back on.

I then turned off the YAW knob by switching it counterclockwise all the way.

I pulled the throttle stick up to its highest position. I powered on the aircraft. I then pulled the remote control throttle back to its lowest point. This completed the calibration.

I turned the YAW knob switch clockwise 125 degrees to turn it back on.

Next, I unlocked the aircraft. I turned on the remote control, plugged in the quadcopter, and pushed the throttle stick (the button on the left) to the bottom right to unlock the aircraft.

I then checked the motor rotation direction to make sure motor 1 in the front left spun clockwise, motor 3 in the rear right spun clockwise, and the other two motors spun counterclockwise. To change the direction of a motor, I switched the black and yellow wires of motors 1 and 3 (any two of the three wires can be switched) because they were spinning counterclockwise.

Next, I secured the radio receiver behind the flight controller.

secure_radio_receiver

I then used the plastic cable ties to secure the ESC signal wires to the quadcopter.

I then secured the other frame board and the 4 arm groups with the screws.
I then added the parts to secure the propeller. There are two propellers that spin clockwise, and two propellers that spin counterclockwise. This video here helped me to determine which blade is clockwise and which blade is counterclockwise.

propeller_parts

Lastly, with the quadcopter assembled, I followed the “How to Fly a Drone: A Beginner’s Guide”, and I registered my drone with the FAA.

register_drone_at_faa

Implementation

qwinout_450mm_quadcopter_assembly (4)
qwinout_450mm_quadcopter_assembly (6)
You can also add the skid gear legs which I have linked to in the “Spare Parts” section of this post (see above)
qwinout_450mm_quadcopter_assembly (1)

Video

Here is the video of my quadcopter in action:

How to Develop an Arduino-Based Optical Tachometer

In this post, I’ll explain how to develop an Arduino-Based Optical Tachometer that measures the speed of a brushless propeller. The speed of the propeller must be measured using an IR Emitter/Detector pair using either Round Robin with Interrupts or Function Queue Scheduling. The RPMs (revolutions per minute) must be captured over time, downloaded to a Host, and graphed.

If you have ever driven a car or looked at the dashboard of a car, you have seen a tachometer. It is that meter on the other side of your speedometer that measures the rotation speed of your engine’s crankshaft in revolutions per minute (RPM). A tachometer is an instrument that measures the rotation speed of a shaft or disk, such as in a motor.

tachometer

Requirements

Here are the requirements I created for this project:

  • The system must execute on an Arduino.
  • The speed of a brushless propeller must be measured using an Infrared (IR) Emitter/Detector pair
  • The speed of a brushless propeller must be measured using Round Robin with Interrupts.
  • The revolutions per minute (RPMs) must be captured over time.
  • The RPMs must be downloaded to a Host.
  • Time vs. RPMs must be graphed.

Hardware Design

The following components are used in this project. You will need:

Here is the diagram of the hardware setup:

hardware_diagram_optical_tachometer

For the motor setup on the left of the image above, the current (when the transistor is “turned on”) goes from the 5V power supply, through the green wire, through the motor, and then down the yellow wire. It then passes through the collector towards the emitter, and then down to ground. If the transistor is shut off, it is no longer conducting. The residual peak current that would normally go through the transistor from the yellow wire needs somewhere to go. Instead of being forced through the non-conducting transistor (and potentially damaging it), the current redirects (shorts through the motor) and dissipates through the diode (from left to right through the diode in the schematic above) since diodes only allow current to travel in one direction.

optical_tachometer_arduino (1)
optical_tachometer_arduino (1)
optical_tachometer_arduino (2)
optical_tachometer_arduino (2)
optical_tachometer_arduino (3)

Troubleshooting Tips

  • There might be occasions where you start the motor (after you run the code in the Implementation section below), and the RPM readings start firing even though the propeller is nowhere near the IR emitter/receiver pair. If this happens to you, power the propeller/motor from a separate breadboard and Arduino.
    • You will also need to take out the pieces of code from the code below that pertain to the operation of the motor and upload that code in a separate sketch to the other Arduino (the one that will power the propeller). It is a pain in the butt to do all this and can take several extra hours or so of development time, but it will help solve this problem.
  • It is also helpful to cover the propeller blades with black electrical tape in case the IR emitter beam is passing right through the propeller blades.

Implementation

Here is the source code that you will need to load to your Arduino:

/**
 * In this program, we develop an Arduino-Based Optical Tachometer 
 * that measures the speed of a brushless propeller.
 * 
 * The Infrared LED is connected to pin 13.
 * The Infrared Phototransistor is connected to pin 2 (interrupts).
 * 
 * @version 1.0 2019-02-18
 * @author Addison Sears-Collins
 */
 
// Assign a name to the DC motor pin on the Arduino Uno
const unsigned int MOTOR_PIN = 3;

// Assign a name to the infrared LED pin on the Arduino Uno
const unsigned int IR_LED = 13;

// The number of blades on the propeller. Adjust accordingly.
const unsigned int BLADE_COUNT = 3;

// Volatile keyword is used with interrupts
// This variable is subject to change inside an interrupt
// service routine
volatile unsigned int break_number = 0;

// Flag used to stop the program
bool done = false;

// Used for capturing the time
unsigned long time;

// Used for capturing the rpm (revolutions per minute)
unsigned int rpm;

/**
 *  Function runs only once, after each powerup or reset of the Arduino Uno
 */
void setup() {

  // Open the serial port and set the data transmission rate to 9600 bits 
  // per second. 9600 is the default baud rate for Arduino Uno.
  Serial.begin(9600);

  // Show a welcome message as human-readable ASCII text
  Serial.println("PROPELLER RPM PROGRAM");
  Serial.println("This program transmits the time and RPM of a propeller.");
  Serial.println("Created by Addison Sears-Collins");
  Serial.println("");
  Serial.println("Press ! to end the program");
  Serial.println("");
  Serial.println("Please enter the desired speed of the motor.");
  Serial.println("Must be a value between 100 and 255.");
  Serial.println("");
  Serial.println("TIME, RPM");

  // The Infrared phototransistor is connected to pin 2.
  // Interrupt triggers when signal goes from HIGH to LOW
  attachInterrupt(digitalPinToInterrupt(2), isr_break_count, FALLING); 

  // Turn on the IR Led
  pinMode(IR_LED, OUTPUT);
  digitalWrite(IR_LED, HIGH);

  // Enable output for the motor
  pinMode(MOTOR_PIN, OUTPUT);

  break_number = 0;
  rpm = 0;  
 
}

/**
 *  Main function
 */
void loop() {

  display_time_and_rpm();
  
  start_motor();

  while(!done) {    

    // Update time and rpm every second
    delay(1000);

    // Don't process interrupts during this calculation
    noInterrupts();

    // Calculate the RPM. If a 3-blade propeller, 3 breaks
    // per second would yield 1 rpm, which is 60 rpm. 
    rpm = (60 * break_number) / BLADE_COUNT;

    // Display the time and rpm
    display_time_and_rpm();

    // End program if sentinel is entered 
    end_program();    
    
    break_number = 0;
    rpm = 0;

    // Restart interrupts
    interrupts();
  }
  
  // Do nothing
  while (true) {}
}

/**
  * This function starts the motor
  */
void start_motor() {

  // Wait for the user to enter the speed of the motor
  while (Serial.available() == 0){};

  // Activate the motor
  int speed = Serial.parseInt();
  if (speed >= 100 && speed <= 255) {
    analogWrite(MOTOR_PIN, speed);
  }
}

/**
  * Interrupt service routine.
  * This function counts the number of interrupts
  */
void isr_break_count() {

  break_number++;
  
}

/**
  * Function displays the time and rpm
  */
void display_time_and_rpm() {
  
  // Capture the time and covert to seconds
  time = millis() / 1000;

  // Display the time
  Serial.print(time); 
  Serial.print(" , ");
  // Println so the next line begins on a new line
  // Display the rpm
  Serial.println(rpm);   
}

/**
  * This function ends the program
  */
void end_program() {
  
  // Used for reading data from the serial monitor
  char ch;

  // Check to see if ! is available to be read
  if (Serial.available()) {     
  
    // Read the character
    // Serial.read() returns the first (oldest) character in the buffer 
    // and removes that byte of data from the buffer
    ch = Serial.read();    

    // End the program if an exclamation point is entered in the
    // serial monitor
    if (ch == '!') {
      done = true;  

      // Turn off the motor
      analogWrite(MOTOR_PIN, 0);

      // Turn off the IR LED
      digitalWrite(IR_LED, LOW);
      
      Serial.println("Finished recording RPM. Goodbye.");
    }
  }    
}

rpm_vs_time_2

Video