Skip to content

Instantly share code, notes, and snippets.

@mristau
Created February 19, 2018 10:35
Show Gist options
  • Save mristau/8fe061636f4f0376e1ef8817ce1c2fec to your computer and use it in GitHub Desktop.
Save mristau/8fe061636f4f0376e1ef8817ce1c2fec to your computer and use it in GitHub Desktop.
#include <SPI.h>
#include <BLEPeripheral.h>
#include <nrf_sdm.h>
#include <nrf_soc.h>
#include <WInterrupts.h>
#define BAUDRATE 38400
#define BUTTON_PIN 29 // Active Low Button on my Board at this pin
#define INTERRUPT_PIN 19 // Active High Interrupt from Lis2de12 accelerometer
#define BATTERY_PIN A2 // LiPo charging circuit output of battery voltage
#define DEVICE_NAME "BLE-Test Device"
#define DescriptorUUID "2901"
#define BatteryLevelServiceUUID "180F"
#define BatteryLevelCharUUID "2A19"
BLEPeripheral blePeripheral = BLEPeripheral();
BLEService batteryLevelService = BLEService(BatteryLevelServiceUUID);
BLEUnsignedCharCharacteristic batteryLevelChar = BLEUnsignedCharCharacteristic(BatteryLevelCharUUID, BLERead | BLENotify);
BLEDescriptor batteryLevelDescriptor = BLEDescriptor(DescriptorUUID, "Battery Level 0 - 100%");
volatile bool buttonPressed = false;
volatile bool accelInterrupt = false;
uint8_t checkForSoftDevice() {
uint8_t check;
sd_softdevice_is_enabled(&check);
return check;
}
void constLat() {
//NRF_POWER_MODE_CONSTLAT, /**< Constant latency mode. See power management in the reference manual. */
if (checkForSoftDevice() == 1) {
// SoftDevice enabled
sd_power_mode_set(NRF_POWER_MODE_CONSTLAT);
} else {
// No SoftDevice
NRF_POWER->TASKS_CONSTLAT = 1;
}
}
void lowPower() {
//NRF_POWER_MODE_LOWPWR /**< Low power mode. See power management in the reference manual. */
if (checkForSoftDevice() == 1) {
// SoftDevice enabled
sd_power_mode_set(NRF_POWER_MODE_LOWPWR);
} else {
// No SoftDevice
NRF_POWER->TASKS_LOWPWR = 1;
}
}
void powerOff() {
if (checkForSoftDevice() == 1) {
// SoftDevice enabled
sd_power_system_off();
} else {
// No SoftDevice
NRF_POWER->SYSTEMOFF = 1;
}
}
void buttonHandler() {
buttonPressed = true;
}
void accelHandler() {
accelInterrupt = true;
}
/*
* The sketch uses BLEPeripheral to create an environmental sensor service and defines pressure, temperature,
* and elevation characteristics as well as a battery service to monitor the battery voltage level via a battery
* level characteristic. A resistor divider needs to be added to any analog pin so the voltage can be sampled
* between 0 and the 3V3 of the board (27K/100K will do) such that the ADC will read 0 at 0 V and 4095 at
* 4.2 V of LiPo battery voltage.
*/
void updateBatteryLevel() {
float VBAT;
int16_t level = analogRead(BATTERY_PIN);
// (127.0f/100.0f) = ((R1+R2) / R2)
VBAT = (127.0f/100.0f) * 3.30f * ((float)level)/4095.0f; // convert to the LiPo battery voltage
Serial.print("VBAT = "); Serial.println(VBAT, 2);
// 3600 equals to 3.7V of a LiPo battery which is the nominal Voltage, so all above 3.7V will be 100%
level = constrain(level, 0, 3600);
// 3200 equals to 3.3V of a LiPo, as the chip will turn off at ~3.3V i'm mapping that to 0%
uint8_t batteryLevel = map(level, 3200, 3600, 0, 100);
batteryLevelChar.setValue((uint8_t)batteryLevel); // set the battery level characteristic value
}
void blePeripheralConnectHandler(BLECentral& central) {
Serial.print(F("Connected event, central: "));
Serial.println(central.address());
}
void blePeripheralDisconnectHandler(BLECentral& central) {
Serial.print(F("Disconnected event, central: "));
Serial.println(central.address());
}
void setupBLE() {
Serial.println("Setup BLE Peripheral");
blePeripheral.setLocalName(DEVICE_NAME);
blePeripheral.setAdvertisedServiceUuid(batteryLevelService.uuid());
blePeripheral.setAdvertisingInterval(100);
blePeripheral.setAppearance(0x0000);
blePeripheral.setConnectable(true);
blePeripheral.setDeviceName(DEVICE_NAME);
blePeripheral.addAttribute(batteryLevelService);
blePeripheral.addAttribute(batteryLevelChar);
blePeripheral.addAttribute(batteryLevelDescriptor);
// assign event handlers for connected, disconnected to peripheral
blePeripheral.setEventHandler(BLEConnected, blePeripheralConnectHandler);
blePeripheral.setEventHandler(BLEDisconnected, blePeripheralDisconnectHandler);
// begin initialization
blePeripheral.begin();
}
void setup() {
Serial.begin(BAUDRATE);
delay(2000);
setupBLE();
pinMode(INTERRUPT_PIN, INPUT);
pinMode(BATTERY_PIN, INPUT);
analogReadResolution(12); // take advantage of 12-bit ADCs
pinMode(BUTTON_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), buttonHandler, FALLING);
attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), accelHandler, RISING);
NRF_GPIO->PIN_CNF[INTERRUPT_PIN] &= ~((uint32_t)GPIO_PIN_CNF_SENSE_Msk);
NRF_GPIO->PIN_CNF[INTERRUPT_PIN] |= ((uint32_t)GPIO_PIN_CNF_SENSE_High << GPIO_PIN_CNF_SENSE_Pos);
}
void loop() {
blePeripheral.poll();
updateBatteryLevel();
if (buttonPressed) {
// Button press will shutdown the nRF, choose the right function for your usage
buttonPressed = false;
powerOff();
// lowPower();
// constLat();
}
if (accelInterrupt) {
accelInterrupt = false;
}
delay(1000);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment