Skip to content

Instantly share code, notes, and snippets.

@bboyho
Last active December 20, 2021 01:05
Show Gist options
  • Save bboyho/e5f5d292648fec768126f7c126d3a5dc to your computer and use it in GitHub Desktop.
Save bboyho/e5f5d292648fec768126f7c126d3a5dc to your computer and use it in GitHub Desktop.
/*
HTU21D Humidity Sensor Example Code
By: Nathan Seidle
SparkFun Electronics
Date: September 15th, 2013
License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license).
Uses the HTU21D library to display the current humidity and temperature
Open serial monitor at 9600 baud to see readings. Errors 998 if not sensor is detected. Error 999 if CRC is bad.
Hardware Connections (Breakoutboard to Arduino):
-VCC = 3.3V
-GND = GND
-SDA = A4 (use inline 330 ohm resistor if your board is 5V)
-SCL = A5 (use inline 330 ohm resistor if your board is 5V)
*/
#include <Wire.h>
// digital I/O pins
const byte STAT1 = 13;
boolean STAT1_blink = HIGH;
#include "SparkFunHTU21D.h" // include HTU21D library
//Create an instance of the object
HTU21D myHumidity;
float temp_C = 0.00;
float temp_F = 0.00;
float humd = 0.00;
#include <SFE_MicroOLED.h> // Include the SFE_MicroOLED library
#define PIN_RESET 7
#define DC_JUMPER 1
MicroOLED oled(PIN_RESET, DC_JUMPER); // I2C declaration
#include "SparkFunBME280.h"
BME280 mySensor;
float bme280_temp_C = 0.00;
float bme280_temp_F = 0.00;
float bme280_humidity = 0.00;
float bme280_pressure = 0.00;
float bme280_altitude_meters = 0.00;
float bme280_altitude_feet = 0.00;
#include <SparkFunCCS811.h>
#define CCS811_ADDR 0x5B //Default I2C Address
CCS811 myCCS811(CCS811_ADDR);
int co2 = 400;
int tvoc = 0;
#include "SparkFun_VL53L1X.h"
//Optional interrupt and shutdown pins.
#define SHUTDOWN_PIN 2
#define INTERRUPT_PIN 3
SFEVL53L1X distanceSensor;
//Uncomment the following line to use the optional shutdown and interrupt pins.
//SFEVL53L1X distanceSensor(Wire, SHUTDOWN_PIN, INTERRUPT_PIN);
int distance = 0;
int prevDistance = 0;
int currentDistance = 0;
float distanceInches = 0.00;
float distanceFeet = 0.00;
#include <SparkFun_Qwiic_Button.h>
QwiicButton button;
uint8_t brightness = 100; //The brightness to set the LED to when the button is pushed
//Can be any value between 0 (off) and 255 (max)
boolean buttonState = false; //set button low, so not pressing.
//keep track if button press when held down
//boolean prev_buttonState = false;
//boolean current_buttonState = false;
//unsigned long buttonMillis = 0;
boolean incrementMode = true;
///////////////////////////////
// Display Mode Page Control //
///////////////////////////////
// This enum defines all of our display modes and their order.
enum t_displayModes {
DISPLAY_HTU21D,
DISPLAY_BME280_1,
DISPLAY_BME280_2,
DISPLAY_CCS811_1,
DISPLAY_CCS811_2,
DISPLAY_VL53L1X,
DISPLAY_CUBE
};
const int NUM_DISPLAY_MODES = 7; // Number of values defined in enum above
volatile int displayMode = NUM_DISPLAY_MODES - 1; // Keeps track of current display page
const unsigned long DISPLAY_UPDATE_RATE = 5000; // Cycle display every 5 seconds
unsigned long lastDisplayUpdate = 0; // Stores time of last display update
unsigned long lastLEDUpdate = 0; // Stores time of last LED update
unsigned long currentMillis = 0; // Stores time of last display update
boolean activity = true; //used to keep track of movement or button press
const unsigned long noActivityMillis = NUM_DISPLAY_MODES * (DISPLAY_UPDATE_RATE + 1000); //used to compare amount of time when no activity to turn of screen
unsigned long lastActivityMillis = 0;
float percentage = 0; //store percent for progress bar
int progressWidth = 0; // Width of progress bar depends on the [% * (64 pixels wide)]
int progressY = 0; //location of the progress bar at the botton of the microOLED
int SCREEN_WIDTH = oled.getLCDWidth();
int SCREEN_HEIGHT = oled.getLCDHeight();
float d = 3;
float px[] = {
-d, d, d, -d, -d, d, d, -d
};
float py[] = {
-d, -d, d, d, -d, -d, d, d
};
float pz[] = {
-d, -d, -d, -d, d, d, d, d
};
float p2x[] = {
0, 0, 0, 0, 0, 0, 0, 0
};
float p2y[] = {
0, 0, 0, 0, 0, 0, 0, 0
};
float r[] = {
0, 0, 0
};
#define SHAPE_SIZE 600
// Define how fast the cube rotates. Smaller numbers are faster.
// This is the number of ms between draws.
//#define ROTATION_SPEED 0
void setup()
{
Serial.begin(115200);
Serial.println("HTU21D, BME280, CCS811, VL53LlX, Qwiic Button, microOLED Example!");
pinMode(STAT1, OUTPUT); //Status LED Blue
delay(100);
myHumidity.begin();// Wire.begin() is in HTU21D library
delay(100);
mySensor.beginI2C();//join BME280
delay(100);
myCCS811.begin();//join CCS811
//Wire.setClock(400000); // Set clock speed to be the fastest for better communication (fast mode)
delay(100);
if (distanceSensor.begin() != false) //Begin returns 0 on a good init
{
Serial.println("Sensor failed to begin. Please check wiring. Freezing...");
while (1)
;
}
Serial.println("Sensor online!");
if (button.begin() == false) {
Serial.println("Device did not acknowledge! Freezing.");
while (1);
}
oled.begin(); // Initialize the OLED
oled.clear(ALL); // Clear the display's internal memory
oled.display(); // Display what's in the buffer (splashscreen)
delay(1000); // Delay 1000 ms
oled.clear(PAGE); // Clear the buffer.
//Quick test to check how many characters can go across screen
//oled.clear(ALL); // Clear the display's internal memory
//oled.setCursor(0, 0); // Set cursor to top-left
//oled.setFontType(0); // Smallest font
//oled.print(F("123456789;")); // Print, max is 10 characters across, 5x7-pixel characters
//oled.display(); // Display what's in the buffer (splashscreen)
//delay(10000); // Delay 1000 ms
}
void loop()
{
humd = myHumidity.readHumidity();
temp_C = myHumidity.readTemperature();
temp_F = temp_C * (9.0 / 5.0) + 32.0;
bme280_temp_C = mySensor.readTempC();
bme280_temp_F = mySensor.readTempF();
bme280_humidity = mySensor.readFloatHumidity();
bme280_pressure = mySensor.readFloatPressure();
bme280_altitude_meters = mySensor.readFloatAltitudeMeters();
bme280_altitude_feet = mySensor.readFloatAltitudeFeet();
if (myCCS811.dataAvailable())
{
//If so, have the sensor read and calculate the results.
//Get them later
myCCS811.readAlgorithmResults();
}
co2 = myCCS811.getCO2();
tvoc = myCCS811.getTVOC();
distanceSensor.startRanging(); //Write configuration bytes to initiate measurement
while (!distanceSensor.checkForDataReady())
{
delay(1);
}
distance = distanceSensor.getDistance(); //Get the result of the measurement from the sensor
distanceSensor.clearInterrupt(); distanceSensor.stopRanging();
currentDistance = distance;
distanceInches = distance * 0.0393701;
distanceFeet = distanceInches / 12.0;
buttonState = button.isPressed();
//get time based on how long the Arduino has been running
currentMillis = millis();
// Displaying °C and °F with a scroll bar
// Another method of updating display:
// The display will cycle itself every DISPLAY_UPDATE_RATE seconds
if ( (currentMillis >= (lastDisplayUpdate + DISPLAY_UPDATE_RATE + 1000)) || (buttonState == true) )
{
if (incrementMode == true) {
// Increment displayMode, next time through a new page will be displayed:
displayMode = (displayMode + 1) % NUM_DISPLAY_MODES;
}
else {
//incrementMode == false
// Decrement displayMode, next time through a previous page will be displayed:
if (displayMode > 0) {
displayMode = (displayMode - 1) % NUM_DISPLAY_MODES;
}
else {
displayMode = NUM_DISPLAY_MODES - 1;
}
}
// Update lastDisplayTime, so we don't come back for DISPLAY_UPDATE_RATE seconds
lastDisplayUpdate = currentMillis;
}
//check to see if something got in front of the ToF sensor or if there is a button press
if ( (abs(currentDistance - prevDistance) > 100) || (buttonState == true) ) {
activity = true;
lastActivityMillis = currentMillis;
}
if (buttonState == true) {
button.LEDon(brightness);
}
else {
//no button press
button.LEDoff();
}
if (activity == true && (( currentMillis - lastActivityMillis ) < noActivityMillis)) {
// display
oled.clear(PAGE); // Clear the display
updateDisplay();
displayProgressBar(); // Draws a progress bar at the bottom of the screen
oled.display();
if (currentMillis >= lastLEDUpdate + 1000) {
STAT1_blink = !STAT1_blink;
digitalWrite(STAT1, STAT1_blink); //Blink stat LED
lastLEDUpdate = currentMillis;
}
}
else
{
//if nothing got in front of the ToF sensor, don't display anything
oled.clear(PAGE); // Clear the display}
oled.display();
digitalWrite(STAT1, false); //Blink stat LED
activity = false;
}
prevDistance = currentDistance;
Serial.print(F("Time on: "));
Serial.println(millis());
Serial.print(F("HTU21D Temperature: "));
Serial.print(temp_C, 1);
Serial.print(F("°C, "));
Serial.print(temp_F, 1);
Serial.print(F("°F"));
Serial.print(F("\tHumidity: "));
Serial.print(humd, 1);
Serial.println(F("%RH"));
Serial.print(F("BME280 Temperature: "));
Serial.print(bme280_temp_C, 2);
Serial.print(F("°C, "));
Serial.print(bme280_temp_F, 2);
Serial.print(F("°F "));
Serial.print(F("\tHumidity: "));
Serial.print(bme280_humidity, 2);
Serial.print("%RH");
Serial.print(F("\tPressure: "));
Serial.print(bme280_pressure / 100, 0);
Serial.print("hPa");
Serial.print(F("\tAlt: "));
Serial.print(bme280_altitude_meters / 1000, 3);
Serial.print(F("km, "));
Serial.print(bme280_altitude_feet, 1);
Serial.println(F("ft"));
Serial.print(F("CCS811 CO2: "));
Serial.print(co2);
Serial.print(F(",\ttVOC: "));
Serial.println(tvoc);
Serial.print(F("VL53L1X Distance: "));
Serial.print(distance);
Serial.print(F("m, "));
Serial.print(distanceFeet, 2);
Serial.println(F("ft"));
Serial.print(F("Qwiic Button Status: "));
Serial.println(buttonState);
Serial.println();
//delay(1000);
}//end loop
void updateDisplay() {
switch (displayMode)
{
case DISPLAY_HTU21D:
displayHTU21D();
break;
case DISPLAY_BME280_1:
displayBME280_1();
break;
case DISPLAY_BME280_2:
displayBME280_2();
break;
case DISPLAY_CCS811_1:
displayCCS811_1();
break;
case DISPLAY_CCS811_2:
displayCCS811_2();
break;
case DISPLAY_VL53L1X:
displayVL53L1X();
break;
case DISPLAY_CUBE:
drawCube();
break;
}
}
void displayHTU21D() {
oled.setFontType(0); // Smallest font
oled.setCursor(16, 0); // Set cursor to top-middle
oled.print(F("HTU21D")); // Print
oled.setFontType(1); // medium font
oled.setCursor(0, 8); // Set cursor to top-ish
oled.print(F(" C"));
oled.setCursor(0, 8); // Set cursor to top-ish
oled.print(String(temp_C, 2)); // Print temp, assuming that it is within room temp in tens
oled.setCursor(0, 21); // Set cursor to middle-ish
oled.print(F(" F"));
oled.setCursor(0, 21); // Set cursor to middle-ish
oled.print(String(temp_F, 2));// Print temp, assuming that it is within room temp in tens
oled.circle(50, 9, 1); //"degree" sign after output values
oled.circle(50, 22, 1); //"degree" sign after output values
oled.setCursor(0, 34); // Set cursor to bottom-ish
oled.print(F(" %RH"));
oled.setCursor(0, 34); // Set cursor to bottom-ish
oled.print(String(humd, 1)); // Print humid, assuming that it is within room temp in tens
}
void displayBME280_1() {
oled.setFontType(0); // Smallest font
oled.setCursor(16, 0); // Set cursor to top-middle
oled.print(F("BME280")); // Print
oled.setFontType(1); // medium font
oled.setCursor(0, 8); // Set cursor to middle-ish
oled.print(F(" C"));
oled.setCursor(0, 8); // Set cursor to top-ish
oled.print(String(bme280_temp_C, 2)); // Print temp, assuming that it is within room temp in tens
oled.setCursor(0, 21); // Set cursor to middle-ish
oled.print(F(" F"));
oled.setCursor(0, 21); // Set cursor to middle-ish
oled.print(String(bme280_temp_F, 2));// Print temp, assuming that it is within room temp in tens
oled.circle(50, 9, 1); //"degree" sign after output values
oled.circle(50, 22, 1); //"degree" sign after output values
oled.setCursor(0, 34); // Set cursor to bottom-ish
oled.print(F(" %RH"));
oled.setCursor(0, 34); // Set cursor to middle-ish
oled.print(String(bme280_humidity, 1)); // Print humid, assuming that it is within room temp in tens
/*
oled.setCursor(0, 8); // Set cursor to top-left
oled.print(); // Print
oled.print("Pa"); // Print
oled.setCursor(0, 16); // Set cursor to middle-ish
oled.print(); // Print temp, assuming that it is within room temp in tens
oled.print(" ft"); // Print
*/
}
void displayBME280_2() {
oled.setFontType(0); // Smallest font
oled.setCursor(16, 0); // Set cursor to top-middle
oled.print(F("BME280")); // Print
oled.setFontType(1); // medium font
oled.setCursor(0, 8); // Set cursor to top-ish
oled.print(F(" hPa"));
oled.setCursor(0, 8); // Set cursor to top-ish
if ((bme280_pressure / 100) < 1000) {
oled.print(F(" ")); //Print space
}
oled.print(String(bme280_pressure / 100, 0)); // Print pressure, assuming that it is within room temp in tens
oled.setCursor(0, 21); // Set cursor to middle-ish
oled.print(F(" km"));
oled.setCursor(0, 21); // Set cursor to middle-ish
oled.print(String(bme280_altitude_meters / 1000, 3)); // Print altitude, assuming that it is within room temp in tens
oled.setCursor(0, 34); // Set cursor to middle-ish
oled.print(F(" ft"));
oled.setCursor(0, 34); // Set cursor to middle-ish
if (bme280_altitude_feet < 10) {
oled.print(F(" ")); // Print space
}
else if (bme280_altitude_feet >= 10 && bme280_altitude_feet < 100) {
oled.print(F(" ")); // Print space
}
else if (bme280_altitude_feet >= 100 && bme280_altitude_feet < 1000) {
oled.print(F(" ")); // Print space
}
else if (bme280_altitude_feet >= 1000 && bme280_altitude_feet < 10000) {
oled.print(F(" ")); // Print space
}
//bme280_altitude_feet >= 10000
oled.print(String(bme280_altitude_feet, 0));// Print altitude, assuming that it is within room temp in tens
}
void displayCCS811_1() {
oled.setFontType(0); // Smallest font
oled.setCursor(16, 0); // Set cursor to top-left
oled.print(F("CCS811")); // Print
oled.setFontType(1); // medium font
oled.setCursor(21, 8); // Set cursor to middle-ish
oled.print(F("CO"));
oled.setFontType(0); // small font
oled.setCursor(37, 12); // Set cursor to middle-ish
oled.print(F("2"));
oled.setFontType(2); // medium font
if (co2 < 1000) {
oled.setCursor(16, 21); // Set cursor to middle-ish
}
else if (co2 >= 1000) {
oled.setCursor(11, 21); // Set cursor to middle-ish
}
oled.print(String(co2)); // Print CO2, assuming that it is within room temp in tens
}
void displayCCS811_2() {
oled.setFontType(0); // Smallest font
oled.setCursor(16, 0); // Set cursor to top-left
oled.print(F("CCS811")); // Print
oled.setFontType(1); // medium font
oled.setCursor(16, 8); // Set cursor to middle-ish
oled.print(F("tVOC"));
oled.setFontType(2); // medium font
if (tvoc < 10) {
oled.setCursor(26, 21); // Set cursor to middle-ish
}
else if (tvoc >= 10 && tvoc < 100) {
oled.setCursor(21, 21); // Set cursor to middle-ish
}
else if (tvoc >= 100 && tvoc < 1000) {
oled.setCursor(16, 21); // Set cursor to middle-ish
}
else if (tvoc >= 1000) {
oled.setCursor(11, 21); // Set cursor to middle-ish
}
oled.print(String(tvoc));// Print tVOC, assuming that it is within room temp in tens
}
void displayVL53L1X() {
oled.setFontType(0); // Smallest font
oled.setCursor(14, 0); // Set cursor to top-middle
oled.print(F("VL53L1X")); // Print
//assuming readings isn't bigger than 4 digits (5 digits if no decimal point)
oled.setFontType(1); // medium font
oled.setCursor(0, 8); // Set cursor to top-ish
oled.print(F(" mm")); // Print distance
oled.setCursor(0, 8); // Set cursor to top-ish
if (distance < 10) {
oled.print(F(" ")); // Print space
}
else if (distance >= 10 && distance < 100) {
oled.print(F(" ")); // Print space
}
else if (distance >= 100 && distance < 1000) {
oled.print(F(" ")); // Print space
}
else if (distance >= 1000) {
oled.print(F(" ")); // Print space
}
oled.print(distance); // Print distance
oled.setCursor(0, 21); // Set cursor to middle-ish
oled.print(F(" in")); // Print distance
oled.setCursor(0, 21); // Set cursor to middle-ish
if (distanceInches < 10) {
oled.print(F(" ")); // Print space
oled.print(distanceInches, 2); // Print distance
}
else if (distanceInches >= 10 && distanceInches < 100) {
oled.print(distanceInches, 2); // Print distance
}
else if (distanceInches >= 100 && distanceInches < 1000) {
oled.print(distanceInches, 1); // Print distance
}
oled.setCursor(0, 34); // Set cursor to bottom-ish
oled.print(F(" ft")); // Print distance
oled.setCursor(0, 34); // Set cursor to bottom-ish
if (distanceFeet < 10) {
oled.print(F(" ")); // Print space
}
oled.print(distanceFeet); // Print distance
}
void drawCube() {
r[0] = r[0] + 10 * PI / 180.0; // Add a degree
r[1] = r[1] + 10 * PI / 180.0; // Add a degree
r[2] = r[2] + 10 * PI / 180.0; // Add a degree
if (r[0] >= 360.0 * PI / 180.0) r[0] = 0;
if (r[1] >= 360.0 * PI / 180.0) r[1] = 0;
if (r[2] >= 360.0 * PI / 180.0) r[2] = 0;
for (int i = 0; i < 8; i++)
{
float px2 = px[i];
float py2 = cos(r[0]) * py[i] - sin(r[0]) * pz[i];
float pz2 = sin(r[0]) * py[i] + cos(r[0]) * pz[i];
float px3 = cos(r[1]) * px2 + sin(r[1]) * pz2;
float py3 = py2;
float pz3 = -sin(r[1]) * px2 + cos(r[1]) * pz2;
float ax = cos(r[2]) * px3 - sin(r[2]) * py3;
float ay = sin(r[2]) * px3 + cos(r[2]) * py3;
float az = pz3 - 150;
p2x[i] = SCREEN_WIDTH / 2 + ax * SHAPE_SIZE / az;
p2y[i] = SCREEN_HEIGHT / 2 + ay * SHAPE_SIZE / az;
}
for (int i = 0; i < 3; i++)
{
oled.line(p2x[i], p2y[i], p2x[i + 1], p2y[i + 1]);
oled.line(p2x[i + 4], p2y[i + 4], p2x[i + 5], p2y[i + 5]);
oled.line(p2x[i], p2y[i], p2x[i + 4], p2y[i + 4]);
}
oled.line(p2x[3], p2y[3], p2x[0], p2y[0]);
oled.line(p2x[7], p2y[7], p2x[4], p2y[4]);
oled.line(p2x[3], p2y[3], p2x[7], p2y[7]);
}
// This function draws a line at the very bottom of the screen showing how long
// it'll be before the screen updates.
// Based on Jim's micro OLED code used in the Photon SIK KIT => [ https://github.com/sparkfun/Inventors_Kit_For_Photon_Experiments/blob/master/11-OLEDApps/Code/02-WeatherForecast/WeatherApp.ino ]
void displayProgressBar() {
// Use lastDisplayUpdate's time, the time Arduino has been running
// (since we do not have an RTC, Internet, or GPS), and the total time
// per page (DISPLAY_UPDATE_RATE) to calculate what portion
// of the display bar needs to be drawn.
percentage = (float)(currentMillis - lastDisplayUpdate) / (float)DISPLAY_UPDATE_RATE;
//for debugging progress bar
//SerialUSB.println(currentMillis);
//SerialUSB.println(lastDisplayUpdate);
//SerialUSB.println(DISPLAY_UPDATE_RATE);
//SerialUSB.println(percentage);
//SerialUSB.println(oled.getLCDWidth());
// Mutliply that value by the total lcd width to get the pixel length of our line
progressWidth = percentage * oled.getLCDWidth();
// the y-position of our line should be at the very bottom of the screen:
progressY = oled.getLCDHeight() - 1;
// First, draw a blank line to clear any old lines out:
oled.line(0, progressY, oled.getLCDWidth(), progressY, BLACK, NORM);
// Next, draw our line:
oled.line(0, progressY, progressWidth, progressY);
//oled.display(); // Update the display, this is already called after we exit this function
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment