Skip to content

Instantly share code, notes, and snippets.

@kikermo
Created September 1, 2019 23:18
Show Gist options
  • Select an option

  • Save kikermo/a1e9efdff97187b62d34185fa14be35e to your computer and use it in GitHub Desktop.

Select an option

Save kikermo/a1e9efdff97187b62d34185fa14be35e to your computer and use it in GitHub Desktop.
#include <bluefruit.h>
#include <Arduino.h>
#include "Timer.h"
uint32_t vbat_pin = PIN_VBAT; // A7 for feather nRF52832, A6 for nRF52840
int moistureSensorPin = A0;
const int IRRIGATION_VALVE_PIN = 12;
const int SENSOR_EN_PIN = 13;
#define DEBUG_MODE false // Enables or disable serial comunication
#define SAMPLE_PERIOD 10000 // Spacing between sample extraction in miliseconds
#define TX_POWER (4) // Transmission power in dBm (check bluefruit.h)
// BATTERY CONSTANTS
#define VBAT_MV_PER_LSB (0.73242188F) // 3.0V ADC range and 12-bit ADC resolution = 3000mV/4096
#define VBAT_DIVIDER (0.5F) // 150K + 150K voltage divider on VBAT
#define VBAT_DIVIDER_COMP (2.0F) // Compensation factor for the VBAT divider 2
#define REAL_VBAT_MV_PER_LSB (VBAT_DIVIDER_COMP * VBAT_MV_PER_LSB)
// BLE
#define ENVIROMENTAL_SERVICE_UUID (0x181A)
#define HUMIDITY_CHARACTERISTIC_UUID (0x2A6F)
#define IRRIGATION_CHARACTERISTIC_UUID (0x5fb7d2ba33894732adc0b50a46ba4a7f) // 5fb7d2ba-3389-4732-adc0-b50a46ba4a7f
BLEDis bledis; // device information
BLEBas blebas; // battery
BLEService bleEnvService = BLEService(ENVIROMENTAL_SERVICE_UUID);
BLECharacteristic bleHumidityC = BLECharacteristic(HUMIDITY_CHARACTERISTIC_UUID);
BLECharacteristic bleIrrigationChar = BLECharacteristic(IRRIGATION_CHARACTERISTIC_UUID);
Timer timer;
void setup() {
pinMode(SENSOR_EN_PIN, OUTPUT);
pinMode(IRRIGATION_VALVE_PIN, OUTPUT);
digitalWrite(SENSOR_EN_PIN, LOW);
digitalWrite(IRRIGATION_VALVE_PIN, LOW);
if (DEBUG_MODE) {
Serial.begin(115200);
while ( !Serial ) delay(10); // for nrf52840 with native usb
Serial.println("Greenhouse Monitor");
Serial.println("---------------------------\n");
}
Bluefruit.autoConnLed(true);
Bluefruit.configPrphBandwidth(BANDWIDTH_MAX);
Bluefruit.begin();
Bluefruit.setTxPower(TX_POWER); // Check bluefruit.h for supported values
Bluefruit.setName("Greenhouse Monitor");
Bluefruit.Periph.setConnectCallback(deviceConnectedCallback);
Bluefruit.Periph.setDisconnectCallback(deviceDisconnectedCallback);
// Configure and Start Device Information Service
bledis.setManufacturer("Kikermo Industries");
bledis.setModel("Bluefruit Feather52");
bledis.begin();
// Start BLE Battery Service
blebas.begin();
blebas.write(100);
// Start GreenHouse Service
bleEnvService.begin();
// Configure humidity characteristic
bleHumidityC.setProperties(CHR_PROPS_NOTIFY);
bleHumidityC.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS);
bleHumidityC.setFixedLen(1);
bleHumidityC.begin();
bleHumidityC.write(0);
// Configure irrigation characteristic
bleIrrigationChar.setProperties(CHR_PROPS_WRITE);
bleIrrigationChar.setPermission(SECMODE_NO_ACCESS, SECMODE_OPEN);
bleIrrigationChar.setFixedLen(1);
bleIrrigationChar.setWriteCallback(irrigationValveCallback);
bleIrrigationChar.begin();
// Set up and start advertising
startAdv();
// Set up timer
int sensorReadEvent = timer.every(SAMPLE_PERIOD, readSensorsCallback, 0);
}
void startAdv(void) {
// Advertising packet
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
Bluefruit.Advertising.addTxPower();
// Include bleuart 128-bit uuid
Bluefruit.Advertising.addService(bleEnvService);
// Secondary Scan Response packet (optional)
// Since there is no room for 'Name' in Advertising packet
Bluefruit.ScanResponse.addName();
Bluefruit.Advertising.restartOnDisconnect(true);
Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
}
void loop() {
timer.update();
}
void readSensorsCallback(void* context) {
// Battery Reading
float vbat_mv = readVBAT();
uint8_t vbat_per = mvToPercent(vbat_mv);
blebas.notify(vbat_per);
logBatteryResult(vbat_mv, vbat_per);
//Sensor reading
digitalWrite(SENSOR_EN_PIN, HIGH);
delay(500);
uint8_t moistureVal = analogRead(moistureSensorPin);
bleHumidityC.notify8(moistureVal);
digitalWrite(SENSOR_EN_PIN, LOW);
logMoistureSensor(moistureVal);
}
// callback invoked when the connection is established
void deviceConnectedCallback(uint16_t connectionHandle) {
// Get the reference to current connection
BLEConnection* connection = Bluefruit.Connection(connectionHandle);
char deviceName[32] = { 0 };
connection->getPeerName(deviceName, sizeof(deviceName));
if (!DEBUG_MODE) {
return;
}
Serial.print("Connected to ");
Serial.println(deviceName);
Serial.print("Enabling Sensors");
}
/**
Callback invoked when a connection is dropped
*/
void deviceDisconnectedCallback(uint16_t connectionHandle, uint8_t reason) {
(void) connectionHandle;
(void) reason;
if (!DEBUG_MODE) {
return;
}
Serial.println();
Serial.println("Disconnected");
Serial.println("Disabling Sensors");
}
float readVBAT(void) {
float raw;
// Set the analog reference to 3.0V (default = 3.6V)
analogReference(AR_INTERNAL_3_0);
// Set the resolution to 12-bit (0..4095)
analogReadResolution(12); // Can be 8, 10, 12 or 14
// Let the ADC settle
delay(1);
// Get the raw 12-bit, 0..3000mV ADC value
raw = analogRead(vbat_pin);
// Set the ADC back to the default settings
analogReference(AR_DEFAULT);
analogReadResolution(10);
// Convert the raw value to compensated mv, taking the resistor-
// divider into account (providing the actual LIPO voltage)
// ADC range is 0..3000mV and resolution is 12-bit (0..4095)
return raw * REAL_VBAT_MV_PER_LSB;
}
uint8_t mvToPercent(float mvolts) {
if (mvolts < 3300)
return 0;
if (mvolts < 3600) {
mvolts -= 3300;
return mvolts / 30;
}
mvolts -= 3600;
return 10 + (mvolts * 0.15F ); // thats mvolts /6.66666666
}
void logBatteryResult(float vbatMv, uint8_t vbatPer) {
if (!DEBUG_MODE) {
return;
}
Serial.print("LIPO = ");
Serial.print(vbatMv);
Serial.print(" mV (");
Serial.print(vbatPer);
Serial.println("%)");
}
void logMoistureSensor(uint8_t moistureVal) {
if (!DEBUG_MODE) {
return;
}
uint8_t moisturePer = moistureVal * 100 / 256;
Serial.print("Soil moisture = ");
Serial.print(moisturePer);
Serial.println("%");
}
void irrigationValveCallback(uint16_t conn_hdl, BLECharacteristic* chr, uint8_t* data, uint16_t len) {
Serial.print("Irrigation Value = ");
Serial.println(data[0]);
boolean irrigationEnabled = data[0] > 0;
digitalWrite(IRRIGATION_VALVE_PIN, (irrigationEnabled) ? HIGH : LOW);
if (!DEBUG_MODE) {
return;
}
Serial.println((irrigationEnabled) ? "Valve open" : "Valve closed");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment