Skip to content

Instantly share code, notes, and snippets.

@kikermo
Last active June 27, 2019 08:21
Show Gist options
  • Save kikermo/054ced4c2cc2e0f67f784ccf538e1727 to your computer and use it in GitHub Desktop.
Save kikermo/054ced4c2cc2e0f67f784ccf538e1727 to your computer and use it in GitHub Desktop.
Simple script to read a soil moisture with an Adafruit Feather nfr52840
#include <bluefruit.h>
#include <Adafruit_LittleFS.h>
#include <InternalFileSystem.h>
#include <Arduino.h>
uint32_t vbat_pin = PIN_VBAT; // A7 for feather nRF52832, A6 for nRF52840
int moistureSensorPin = A0;
#define DEBUG_MODE true
#define SAMPLE_PERIOD 10000 // Spacing between sample extraction in miliseconds
#define TX_POWER (6) // 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)
BLEDis bledis; // device information
BLEBas blebas; // battery
BLEService bleEnvService = BLEService(ENVIROMENTAL_SERVICE_UUID);
BLECharacteristic bleHumidityC = BLECharacteristic(HUMIDITY_CHARACTERISTIC_UUID);
// Sensors
const int SENSOR_EN_PIN = 13;
void setup() {
pinMode(SENSOR_EN_PIN, OUTPUT);
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();
bleHumidityC.setProperties(CHR_PROPS_NOTIFY);
bleHumidityC.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS);
bleHumidityC.setFixedLen(1);
bleHumidityC.begin();
bleHumidityC.write(0);
// Set up and start advertising
startAdv();
}
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() {
// 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);
uint8_t moistureVal = analogRead(moistureSensorPin);
bleHumidityC.notify8(moistureVal);
digitalWrite(SENSOR_EN_PIN, HIGH);
logMoistureSensor(moistureVal);
delay(SAMPLE_PERIOD);
}
// 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("%");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment