V1.0
ESP32 Gateway
#define DEBUG
#include "DebugUtils.h"
#include "src/lora/lora.h"
#include "src/eink/eink.h"
#include "src/gps/gps.h"
long lastSendTime = 0;
int interval = 2000;
int count = 0;
char count_string[] = {'0', '0', '0','\0'};
void setup() {
#ifdef DEBUG
SerialUSB.begin(9600);
while (!SerialUSB) { }
#endif
DEBUG_TITLE("Start Oak: With GPS, LoRa and E-ink...");
if(!initLora()) {
DEBUG_PRINT("LoRa init failed. Check your connections.");
}
// initGPS();
}
void loop() {
if (millis() - lastSendTime > interval) {
// count
sprintf(count_string, "%d", ++count);
DEBUG_PRINT(count_string);
String sensorData = String(count);
// E-ink
if (!initEink()) {
DEBUG_TITLE("E-ink initialization failed");
}
clearEink();
setEink();
displayEink(0, 50, count_string);
// LoRa send
sendMessage(sensorData);
lastSendTime = millis();
interval = random(2000) + 1000;
}
// LoRa receive
receiveMessage();
}
Makefile
BOARD?=arduino:samd:mzero_bl
PORT := $(shell ls /dev/cu.usbmodem*)
.PHONY: default lint all flash clean
default: all flash clean
lint:
cpplint --extensions=ino --filter=-legal/copyright *.ino
all:
arduino-cli compile --fqbn $(BOARD) ./
flash:
arduino-cli upload -p $(PORT) --fqbn $(BOARD)
clean:
rm -r build
Serial console
#include <bluefruit.h>
#include "Adafruit_VEML6075.h"
int redPin = PIN_A1;
int greenPin = PIN_A2;
int bluePin = PIN_A3;
const int ENSensorPin = 15;
Adafruit_VEML6075 uv = Adafruit_VEML6075();
uint8_t uvindexvalue = 0x42;
float readUVIndexValue = 0.0;
/* GATT Services https://www.bluetooth.com/specifications/gatt/services/
Name: Environmental Sensing
Uniform Type Identifier: org.bluetooth.service.environmental_sensing
Assigned Number: 0x181A
Specification: GSS
*/
#define UUID16_SVC_ENVIRONMENTAL_SENSING 0x181A
/* GATT Characteristics https://www.bluetooth.com/specifications/gatt/characteristics/
Name: UV Index
Uniform Type Identifier: org.bluetooth.characteristic.uv_index
Assigned Number: 0x2A76
Specification: GSS
*/
#define UUID16_CHR_UV_INDEX 0x2A76
BLEService ess = BLEService(UUID16_SVC_ENVIRONMENTAL_SENSING);
BLECharacteristic uvic = BLECharacteristic(UUID16_CHR_UV_INDEX);
BLEDis bledis; // DIS (Device Information Service) helper class instance
// Advanced function prototypes
void startAdv(void);
void setupESService(void);
void connect_callback(uint16_t conn_handle);
void disconnect_callback(uint16_t conn_handle, uint8_t reason);
void setup() {
Serial.begin(115200);
while (!Serial) delay(10);
pinMode(ENSensorPin, OUTPUT);
digitalWrite(ENSensorPin, LOW);
Serial.println("Starting Palm design verification test");
Serial.println("-------------------------------------\n");
Serial.println("Test 1/14: It expects display GREEN LED");
displayLEDColor(0, 255, 0);
delay(1000);
Serial.println("Test 2/14: It expects display YELLOW LED");
displayLEDColor(255, 255, 0);
delay(1000);
Serial.println("Test 3/14: It expects display ORANGE LED");
displayLEDColor(255, 50, 0);
delay(1000);
Serial.println("Test 4/14: It expects display RED LED");
displayLEDColor(255, 0, 0);
delay(1000);
Serial.println("Test 5/14: It expects display PURPLE LED");
displayLEDColor(255, 0, 255);
delay(1000);
Serial.println("Test 6/14: It expects display no color on the LED");
displayLEDColor(0, 0, 0);
delay(1000);
digitalWrite(ENSensorPin, HIGH);
Serial.println("Test 7/14: It expects the Sensor VEML6075 to be disabled");
delay(1000);
digitalWrite(ENSensorPin, LOW);
delay(100);
int returnValue = uv.begin();
if (!returnValue) {
Serial.println("Test 8/14: It expects to error if sensor is not found");
}
Serial.println("Test 9/14: It expects the Sensor VEML6075 to be enabled");
Serial.println("Test 10/14: It expects to initialise the nRF52 module");
Bluefruit.begin();
Bluefruit.setName("TestPalm@Hutscape");
Bluefruit.Periph.setConnectCallback(connect_callback);
Bluefruit.Periph.setDisconnectCallback(disconnect_callback);
bledis.setManufacturer("Adafruit Industries");
bledis.setModel("Bluefruit Feather52");
bledis.begin();;
setupESService();
startAdv();
Serial.println("Test 11/14: It expects to start advertising");
}
void loop() {
digitalToggle(LED_RED); // blinking RED LED indicates reading UV sensor
readUVIndexValue = uv.readUVI();
uvindexvalue = round(abs(readUVIndexValue));
Serial.print("Test 12/14: It expects to read UV Index value: ");
Serial.println(uvindexvalue);
displayLED(uvindexvalue);
if (Bluefruit.connected()) {
// Note: We use .indicate instead of .write!
// If it is connected but CCCD is not enabled
// The characteristic's value is still updated although indicate is not sent
if (uvic.indicate(&uvindexvalue, sizeof(uvindexvalue))) {
Serial.print("Test 13/14: It expects to update UV Index value: ");
Serial.println(uvindexvalue);
} else {
Serial.println("Test 14/14: It errors when indicate is not set");
}
}
delay(2000);
}
void displayLEDColor(int red, int green, int blue) {
analogWrite(redPin, red);
analogWrite(greenPin, green);
analogWrite(bluePin, blue);
}
void displayLED(uint8_t uvindexvalue) {
if (uvindexvalue <= 2) {
// UV Index <= 2, display GREEN or no color alerts
displayLEDColor(0, 255, 0);
} else if (uvindexvalue >= 3 && uvindexvalue <= 5) {
// UV Index is from 3 to 5, display YELLOW
displayLEDColor(255, 255, 0);
} else if (uvindexvalue >= 6 && uvindexvalue <= 7) {
// UV Index is from 6 to 7, display ORANGE
displayLEDColor(255, 50, 0);
} else if (uvindexvalue >= 8 && uvindexvalue <= 10) {
// UV Index is from 8 to 10, display RED
displayLEDColor(255, 0, 0);
} else {
// UV Index is above 11, display PURPLE
displayLEDColor(255, 0, 255);
}
}
void startAdv(void) {
// Advertising packet
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
Bluefruit.Advertising.addTxPower();
// Include HTM Service UUID
Bluefruit.Advertising.addService(ess);
// Include Name
Bluefruit.Advertising.addName();
/* Start Advertising
* - Enable auto advertising if disconnected
* - Interval: fast mode = 20 ms, slow mode = 152.5 ms
* - Timeout for fast mode is 30 seconds
* - Start(timeout) with timeout = 0 will advertise forever (until connected)
*
* For recommended advertising interval
* https://developer.apple.com/library/content/qa/qa1931/_index.html
*/
Bluefruit.Advertising.restartOnDisconnect(true);
// in unit of 0.625 ms
Bluefruit.Advertising.setInterval(32, 244);
// number of seconds in fast mode
Bluefruit.Advertising.setFastTimeout(30);
// 0 = Don't stop advertising after n seconds
Bluefruit.Advertising.start(0);
}
void setupESService(void) {
// Configure the Environmental Sensing service
// See: https://www.bluetooth.com/wp-content/uploads/Sitecore-Media-Library/Gatt/Xml/Characteristics/org.bluetooth.characteristic.uv_index.xml
// Supported Characteristics:
// Name UUID Requirement Properties
// ---------------------------- ------ ----------- ----------
// UV Index 0x2A76 Mandatory Read
ess.begin();
// Note: You must call .begin() on the BLEService before calling .begin() on
// any characteristic(s) within that service definition.. Calling .begin() on
// a BLECharacteristic will cause it to be added to the last BLEService that
// was 'begin()'ed!
// Configure the UV Index characteristic
// See:https://www.bluetooth.com/wp-content/uploads/Sitecore-Media-Library/Gatt/Xml/Characteristics/org.bluetooth.characteristic.uv_index.xml
// Properties = Indicate
// Min Len = 1
// Max Len = 1
// B0 = UINT8 - UV Index measurement unitless
uvic.setProperties(CHR_PROPS_INDICATE);
uvic.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS);
uvic.setFixedLen(1);
uvic.setCccdWriteCallback(cccd_callback); // Optionally capture CCCD updates
uvic.begin();
uvic.write(&uvindexvalue, sizeof(uvindexvalue));
}
void connect_callback(uint16_t conn_handle) {
// Get the reference to current connection
BLEConnection* connection = Bluefruit.Connection(conn_handle);
char central_name[32] = { 0 };
connection->getPeerName(central_name, sizeof(central_name));
Serial.print("Connected to ");
Serial.println(central_name);
}
/**
* Callback invoked when a connection is dropped
* @param conn_handle connection where this event happens
* @param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h
*/
void disconnect_callback(uint16_t conn_handle, uint8_t reason) {
(void) conn_handle;
(void) reason;
Serial.println("Disconnected");
Serial.println("Advertising!");
}
void cccd_callback(uint16_t conn_hdl,
BLECharacteristic* chr, uint16_t cccd_value) {
// Display the raw request packet
Serial.print("CCCD Updated: ");
// Serial.printBuffer(request->data, request->len);
Serial.print(cccd_value);
Serial.println("");
// Check the characteristic this CCCD update is associated with in case
// this handler is used for multiple CCCD records.
if (chr->uuid == uvic.uuid) {
if (chr->indicateEnabled(conn_hdl)) {
Serial.println("UV Index Measurement 'Indicate' enabled");
} else {
Serial.println("UV Index Measurement 'Indicate' disabled");
}
}
}
Makefile
.PHONY: lint compile upload clean
lint:
cpplint --extensions=ino --filter=-legal/copyright *.ino
compile:
arduino-cli compile --fqbn adafruit:nrf52:feather52832 ./
upload:
adafruit-nrfutil dfu genpkg --dev-type 0x0052 --application ./.*.hex dfu-package.zip
adafruit-nrfutil dfu serial --package dfu-package.zip -p /dev/tty.SLAB_USBtoUART -b 115200
clean:
rm -f .*.elf
rm -f .*.hex
rm -f *.zip
flash: lint compile upload clean
Serial console