Last active
May 4, 2020 14:38
-
-
Save justind000/d515c6f8190b9d7192bda25220f5552b to your computer and use it in GitHub Desktop.
Helium - uFire Project with E-paper display
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Prior to compiling, install the following libraries: | |
Isolated EC Probe Interface v1.2.1 | |
Isolated ISE Probe Interface v1.2.0 | |
ArduinoJson v6.14.1 | |
ESP32_LoRaWAN https://github.com/HelTecAutomation/ESP32_LoRaWAN | |
click links below in the #include section | |
Follow directions to install the development repository here: | |
https://github.com/Heltec-Aaron-Lee/WiFi_Kit_series | |
Select Wireless Stick Lite from the Board list in the Tools menu | |
and select the appropriate options from the Tools menu | |
*/ | |
#include <ESP32_LoRaWAN.h> | |
#include <uFire_EC.h> // http://librarymanager/All#Isolated_EC_Probe_Interface | |
#include <uFire_pH.h> // http://librarymanager/All#Isolated_ISE_Probe_Interface | |
#include <uFire_ORP.h> // http://librarymanager/All#Isolated_ISE_Probe_Interface | |
#include <ArduinoJson.h> // http://librarymanager/All#ArduinoJson | |
#include "paper.h" | |
// license for Heltec ESP32 LoRaWAN | |
uint32_t license[4] = { 0x93401581, 0x1DC4DF49, 0x1637CA6F, 0x1D40CA9F }; | |
// OTAA para | |
uint8_t DevEui[] = { }; | |
uint8_t AppEui[] = { }; | |
uint8_t AppKey[] = { }; | |
// ABP para | |
uint8_t NwkSKey[] = {}; | |
uint8_t AppSKey[] = {}; | |
uint32_t DevAddr; | |
// configure our device for the Helium LoRaWAN network | |
DeviceClass_t loraWanClass = CLASS_A; // Class A = a battery operated device | |
uint32_t appTxDutyCycle = 21600000; // how often to wake-up, take and send a measurement, in ms | |
bool overTheAirActivation = true; // We want to use over the air activation rather than ABP https://www.lairdconnect.com/support/faqs/what-difference-between-abp-and-otaa | |
bool loraWanAdr = false; // we don't want to use Adaptive Data Rate https://www.thethingsnetwork.org/docs/lorawan/adaptive-data-rate.html | |
bool isTxConfirmed = false; // we also don't want to use confirmed transmissions | |
uint8_t appPort = 2; // always 2 | |
uint8_t confirmedNbTrials = 8; // the number of re-transmits, this isn't used with isTxConfirmed = false, but the library still wants to know | |
uint8_t debugLevel = LoRaWAN_DEBUG_LEVEL; // how much extra data the library can print on serial to debug connection issues, this is set in the Tools menu | |
LoRaMacRegion_t loraWanRegion = ACTIVE_REGION; // For the US, we must use US915, it's set in the Tools menu | |
#define VEXT_PIN 21 // the board's VExt pin, used to power our sensors | |
#define BATT_VOLTAGE_PIN 13 // the Heltec board allows you to read the lithium battery voltage without any extra hardware or wires | |
// ArduinoJson library variables | |
// https://arduinojson.org/v6/assistant/ | |
const size_t capacity = JSON_OBJECT_SIZE(5) + 10; | |
DynamicJsonDocument payload(capacity); | |
// uFire sensor classes | |
uFire_EC ec; | |
uFire_pH ph; | |
uFire_ORP orp; | |
static void prepareTxFrame(uint8_t port) | |
{ | |
// this is called to prepare the payload, so encode our `payload` object into MsgPack here | |
// figure out how bit it is and set the appropriate variables | |
serializeMsgPack(payload, appData); | |
appDataSize = measureMsgPack(payload);//AppDataSize max value is 64 | |
} | |
void setup() | |
{ | |
// init the board | |
pinMode(VEXT_PIN, OUTPUT); | |
digitalWrite(VEXT_PIN, LOW); | |
delay(800); | |
// ::begin everything | |
Serial.begin(115200); | |
display.init(); | |
Wire.begin(32, 33); //32=sda, 33=scl | |
SPI.begin(SCK, MISO, MOSI, SS); | |
ec.begin(); | |
ph.begin(); | |
orp.begin(0x3e); // use a non-default i2c address | |
// take all our sensor measurements | |
payload["bV"] = ReadVoltage(BATT_VOLTAGE_PIN) * 2.3857143; | |
payload["t_C"] = ec.measureTemp(); | |
payload["ec_mS"] = ec.measureEC(ec.tempC); | |
payload["ph"] = ph.measurepH(ec.tempC); | |
payload["orp"] = orp.measuremV(); | |
// print things for us to see | |
serializeJsonPretty(payload, Serial); | |
displayMeasurements(ec.mS, "mS", ph.pH, "pH", orp.mV, "ORP", ec.tempC, "C"); | |
// start the LoRa radio | |
Mcu.init(SS, RST_LoRa, DIO0, DIO1, license); | |
// set the device state, which is used in loop() to figure out what to do next | |
deviceState = DEVICE_STATE_INIT; | |
} | |
void loop() | |
{ | |
switch ( deviceState ) | |
{ | |
case DEVICE_STATE_INIT: | |
{ | |
LoRaWAN.init(loraWanClass, loraWanRegion); | |
break; | |
} | |
case DEVICE_STATE_JOIN: | |
{ | |
LoRaWAN.join(); | |
break; | |
} | |
case DEVICE_STATE_SEND: | |
{ | |
prepareTxFrame( appPort ); | |
LoRaWAN.send(loraWanClass); | |
deviceState = DEVICE_STATE_CYCLE; | |
break; | |
} | |
case DEVICE_STATE_CYCLE: | |
{ | |
// Schedule next packet transmission | |
txDutyCycleTime = appTxDutyCycle + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND ); | |
LoRaWAN.cycle(txDutyCycleTime); | |
deviceState = DEVICE_STATE_SLEEP; | |
break; | |
} | |
case DEVICE_STATE_SLEEP: | |
{ | |
// the device will then go to sleep and we want current use to be as low as possible | |
low_power(); | |
LoRaWAN.sleep(loraWanClass, debugLevel); | |
break; | |
} | |
default: | |
{ | |
deviceState = DEVICE_STATE_INIT; | |
break; | |
} | |
} | |
} | |
void low_power() { | |
// go to sleep: | |
// change pins to input | |
// turn off power to sensors and radio | |
digitalWrite(VEXT_PIN, HIGH); | |
pinMode(VEXT_PIN, INPUT); | |
pinMode(5, INPUT); | |
pinMode(14, INPUT); | |
pinMode(15, INPUT); | |
pinMode(16, INPUT); | |
pinMode(17, INPUT); | |
pinMode(19, INPUT); | |
pinMode(27, INPUT); | |
pinMode(32, INPUT); | |
pinMode(33, INPUT); | |
} | |
// a more accurate ADC read to within 1% | |
// https://github.com/HelTecAutomation/Heltec_ESP32/blob/master/examples/ESP32/ADC_Read_Voltage/ADC_Read_Accurate/ADC_Read_Accurate.ino | |
double ReadVoltage(byte pin) { | |
double reading = analogRead(pin); | |
return -0.000000000000016 * pow(reading, 4) + 0.000000000118171 * pow(reading, 3) - 0.000000301211691 * pow(reading, 2) + 0.001109019271794 * reading + 0.034143524634089; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <GxEPD2_BW.h> // click to install: http://librarymanager/All#GxEPD2 | |
#include <GxEPD2_3C.h> | |
#include <Fonts/FreeSans9pt7b.h> | |
#include <Fonts/FreeSansBold9pt7b.h> | |
#include <Fonts/FreeSansBold18pt7b.h> | |
GxEPD2_BW<GxEPD2_290, GxEPD2_290::HEIGHT> display(GxEPD2_290(/*CS*/ 18, /*DC*/ 10, /*RST*/ 9, /*BUSY*/ 12)); | |
void displayMeasurements(float measure1, String unit1, float measure2, String unit2, float measure3, String unit3, float measure4, String unit4) | |
{ | |
display.setRotation(0); | |
display.setTextColor(GxEPD_BLACK); | |
// measurement 1 | |
display.setFont(&FreeSansBold18pt7b); | |
int16_t mtbx1, mtby1; uint16_t mtbw1, mtbh1; | |
display.getTextBounds((String)measure1, 0, 0, &mtbx1, &mtby1, &mtbw1, &mtbh1); | |
uint16_t mx1 = ((display.width() - mtbw1) / 2) - mtbx1; | |
uint16_t my1 = 60; | |
// unit 1 | |
display.setFont(&FreeSans9pt7b); | |
int16_t utbx1, utby1; uint16_t utbw1, utbh1; | |
display.getTextBounds(unit1, 0, 0, &utbx1, &utby1, &utbw1, &utbh1); | |
uint16_t ux1 = ((display.width() - utbw1) / 2) - utbx1; | |
uint16_t uy1 = my1 + 20; | |
// measurement 2 | |
display.setFont(&FreeSansBold18pt7b); | |
int16_t mtbx2, mtby2; uint16_t mtbw2, mtbh2; | |
display.getTextBounds((String)measure2, 0, 0, &mtbx2, &mtby2, &mtbw2, &mtbh2); | |
uint16_t mx2 = ((display.width() - mtbw2) / 2) - mtbx2; | |
uint16_t my2 = 120; | |
// unit 2 | |
display.setFont(&FreeSans9pt7b); | |
int16_t utbx2, utby2; uint16_t utbw2, utbh2; | |
display.getTextBounds(unit2, 0, 0, &utbx2, &utby2, &utbw2, &utbh2); | |
uint16_t ux2 = ((display.width() - utbw2) / 2) - utbx2; | |
uint16_t uy2 = my2 + 20; | |
// measurement 3 | |
display.setFont(&FreeSansBold18pt7b); | |
int16_t mtbx3, mtby3; uint16_t mtbw3, mtbh3; | |
display.getTextBounds((String)measure3, 0, 0, &mtbx3, &mtby3, &mtbw3, &mtbh3); | |
uint16_t mx3 = ((display.width() - mtbw3) / 2) - mtbx3; | |
uint16_t my3 = 180; | |
// unit 3 | |
display.setFont(&FreeSans9pt7b); | |
int16_t utbx3, utby3; uint16_t utbw3, utbh3; | |
display.getTextBounds(unit3, 0, 0, &utbx3, &utby3, &utbw3, &utbh3); | |
uint16_t ux3 = ((display.width() - utbw3) / 2) - utbx3; | |
uint16_t uy3 = my3 + 20; | |
// measurement 4 | |
display.setFont(&FreeSansBold18pt7b); | |
int16_t mtbx4, mtby4; uint16_t mtbw4, mtbh4; | |
display.getTextBounds((String)measure4, 0, 0, &mtbx4, &mtby4, &mtbw4, &mtbh4); | |
uint16_t mx4 = ((display.width() - mtbw4) / 2) - mtbx4; | |
uint16_t my4 = 240; | |
// unit 4 | |
display.setFont(&FreeSans9pt7b); | |
int16_t utbx4, utby4; uint16_t utbw4, utbh4; | |
display.getTextBounds(unit4, 0, 0, &utbx4, &utby4, &utbw4, &utbh4); | |
uint16_t ux4 = ((display.width() - utbw4) / 2) - utbx4; | |
uint16_t uy4 = my4 + 20; | |
display.setFullWindow(); | |
display.fillScreen(GxEPD_WHITE); | |
display.setCursor(25, 15); | |
display.setFont(&FreeSansBold9pt7b); | |
display.println("uFire LLC"); | |
if (measure1) | |
{ | |
display.setCursor(mx1, my1); | |
display.setFont(&FreeSansBold18pt7b); | |
display.println(measure1); | |
display.setFont(&FreeSans9pt7b); | |
display.setCursor(ux1, uy1); | |
display.print(unit1); | |
} | |
if (measure2) | |
{ | |
display.setCursor(mx2, my2); | |
display.setFont(&FreeSansBold18pt7b); | |
display.println(measure2); | |
display.setFont(&FreeSans9pt7b); | |
display.setCursor(ux2, uy2); | |
display.print(unit2); | |
} | |
if (measure3) | |
{ | |
display.setCursor(mx3, my3); | |
display.setFont(&FreeSansBold18pt7b); | |
display.println(measure3); | |
display.setFont(&FreeSans9pt7b); | |
display.setCursor(ux3, uy3); | |
display.print(unit3); | |
} | |
if (measure4) | |
{ | |
display.setCursor(mx4, my4); | |
display.setFont(&FreeSansBold18pt7b); | |
display.println(measure4); | |
display.setFont(&FreeSans9pt7b); | |
display.setCursor(ux4, uy4); | |
display.print(unit4); | |
} | |
display.setCursor(1, uy4 + 30); | |
display.display(false); | |
display.hibernate(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment