Display sensor values

Updated on 31 August 2021
dev board Adafruit Feather Bluefruit
chip nRF52
chip VEML6075
chip Si7021
features LiPo UV temperature humidity
This tutorial is more than 1 year old. If the steps below do not work, then please check the latest versions and the documentations of the individual tools used.

Before starting

Code

Download code display-sensors.ino
#include <Arduino.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SharpMem.h>
#include <Wire.h>
#include "Adafruit_VEML6075.h"
#include "Adafruit_Si7021.h"

Adafruit_VEML6075 uv = Adafruit_VEML6075();
Adafruit_Si7021 sensor = Adafruit_Si7021();

#define SHARP_SCK  12
#define SHARP_MOSI 13
#define SHARP_SS   7

#define VBAT_PIN          (A7)

// 3.0V ADC range and 12-bit ADC resolution = 3000mV/4096
#define VBAT_MV_PER_LSB   (0.73242188F)

// 2M + 0.806M voltage divider on VBAT = (2M / (0.806M + 2M))
#define VBAT_DIVIDER      (0.71275837F)

// Compensation factor for the VBAT divider
#define VBAT_DIVIDER_COMP (1.403F)

Adafruit_SharpMem display(SHARP_SCK, SHARP_MOSI, SHARP_SS, 144, 168);

#define BLACK 0
#define WHITE 1

// toggle true or false to enable serial console debug messages
bool debug = false;

struct SensorValues {
  int vbat_raw;
  uint8_t vbat_per;
  float vbat_mv;

  float uvindex;
  float uva;
  float uvb;

  float humidity;
  float temperature;
};

void setup(void) {
  if (debug) {
      Serial.begin(115200);
  }

  initDisplay();
  initUVSensor();
  initTempHumiditySensor();
  initBatt();
}

void loop(void) {
  SensorValues v = getSensorValues();

  display.clearDisplay();

  displayBatt(v.vbat_raw, v.vbat_per, v.vbat_mv);
  displayUV(v.uvindex, v.uva, v.uvb);
  displayTempHumidity(v.temperature, v.humidity);

  display.refresh();
  delay(4000);
}

void initDisplay(void) {
  display.begin();

  display.setRotation(0);
  display.setTextSize(2);
  display.setTextColor(BLACK);

  display.clearDisplay();
}

void initUVSensor(void) {
  if (!uv.begin() && debug) {
    Serial.println("Failed to communicate with VEML6075 sensor, check wiring?");
  }
  if (debug) {
    Serial.println("Found VEML6075 sensor");
  }
}

void initTempHumiditySensor(void) {
  if (!sensor.begin() && debug) {
    Serial.println("Failed to communicate with Si7021 sensor, check wiring?");
  }
  if (debug) {
    Serial.println("Found Si7021 sensor");
  }
}

void initBatt(void) {
  analogReference(AR_INTERNAL_3_0);
  analogReadResolution(12);  // Can be 8, 10, 12 or 14
  delay(1);
}

uint8_t mvToPercent(float mvolts) {
    uint8_t battery_level;

    if (mvolts >= 3000) {
      battery_level = 100;
    } else if (mvolts > 2900) {
      battery_level = 100 - ((3000 - mvolts) * 58) / 100;
    } else if (mvolts > 2740) {
      battery_level = 42 - ((2900 - mvolts) * 24) / 160;
    } else if (mvolts > 2440) {
      battery_level = 18 - ((2740 - mvolts) * 12) / 300;
    } else if (mvolts > 2100) {
      battery_level = 6 - ((2440 - mvolts) * 6) / 340;
    } else {
      battery_level = 0;
    }

    return battery_level;
}

void displayBatt(int vbat_raw, uint8_t vbat_per, float vbat_mv) {
  if (debug) {
    Serial.print("ADC = ");
    Serial.print(vbat_raw * VBAT_MV_PER_LSB);
    Serial.print(" mV (");
    Serial.print(vbat_raw);
    Serial.print(") ");
    Serial.print("LIPO = ");
    Serial.print(vbat_mv);
    Serial.print(" mV (");
    Serial.print(vbat_per);
    Serial.print("%)");
  }
}

void displayUV(float uvindex, float uva, float uvb) {
  if (debug) {
    Serial.print(", UV Index: ");
    Serial.print(uvindex, 2);
    Serial.print(", UVA: ");
    Serial.print(uva, 2);
    Serial.print(", UVB: ");
    Serial.print(uvb, 2);
  }

  display.setCursor(10, 10);
  display.println("UV index");
  display.setCursor(10, 30);
  display.println(uvindex, 0);

  display.setCursor(10, 65);
  display.print("UVA ");
  display.println(uva, 0);

  display.setCursor(10, 85);
  display.print("UVB ");
  display.println(uvb, 0);
}

void displayTempHumidity(float temperature, float humidity) {
  if (debug) {
    Serial.print(" Temperature: ");
    Serial.print(temperature, 2);
    Serial.print("°C, Humidity: ");
    Serial.print(humidity, 2);
    Serial.println(" RH%");
  }

  display.setCursor(10, 120);
  display.print("Temp ");
  display.print(temperature, 0);
  display.println(" C");

  display.setCursor(10, 140);
  display.print("Hum ");
  display.print(humidity, 0);
  display.println(" RH%");
}

SensorValues getSensorValues(void) {
  int vbat_raw = analogRead(VBAT_PIN);

  SensorValues v = {
    vbat_raw,
    mvToPercent(vbat_raw * VBAT_MV_PER_LSB),
    (float)vbat_raw * VBAT_MV_PER_LSB * VBAT_DIVIDER_COMP,

    uv.readUVI(),
    uv.readUVA(),
    uv.readUVB(),

    sensor.readHumidity(),
    sensor.readTemperature()
  };

  return v;
}

Makefile

BOARD?=adafruit:nrf52:feather52832
PORT?=/dev/tty.SLAB_USBtoUART
BUILD=build
# Arduino CLI version 0.14.0 is used.

.PHONY: default lint all flash clean

default: lint all flash clean

lint:
	cpplint --extensions=ino --filter=-legal/copyright *.ino

all:
	arduino-cli compile --fqbn $(BOARD) --output-dir $(BUILD) ./

flash:
	adafruit-nrfutil dfu genpkg --dev-type 0x0052 --application $(BUILD)/*.hex dfu-package.zip
	adafruit-nrfutil dfu serial --package dfu-package.zip -p $(PORT) -b 115200

clean:
	rm -rf build
	rm dfu-package.zip

Prototype

A photo of the actual setup.

Display sensor values prototype

Schematic

Wire up the hardware accordingly

Display sensor values schematic

Serial console

Serial output from the firmware.

Display sensor values serial console

Description

Display UV and temperature / humidity sensor values with a LiPo.

Hardware used:

  1. Adafruit Bluefruit nRF52 breakout board
  2. Adafruit SHARP Memory Monochrome Display Breakout 168x144 pixels
  3. Adafruit UV sensor VEML 6075 breakout board
  4. Adafruit Temperature/Humidity sensor Si7021 breakout board
  5. LiPo 1200mAh 3.7V

References