First commit of the connected mailbox app
This commit is contained in:
parent
3254117798
commit
e4a258ba3b
17
src/app/BoardConfig.cpp
Normal file
17
src/app/BoardConfig.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
#include "BoardConfig.h"
|
||||
|
||||
BoardConfig::BoardConfig( const Pin ExternalInt,
|
||||
const Pin LDOEnable,
|
||||
const Pin BattVSensEnable,
|
||||
const Pin NRFCe,
|
||||
const Pin SwitchVSensEnable,
|
||||
const Pin NRFCs,
|
||||
const Pin MOSI,
|
||||
const Pin MISO,
|
||||
const Pin SCK,
|
||||
const Pin BattAnalogVSens,
|
||||
const Pin SwitchAnalogVSens
|
||||
):ExternalInt(ExternalInt), LDOEnable(LDOEnable), BattVSensEnable(BattVSensEnable), NRFCe(NRFCe), SwitchVSensEnable(SwitchVSensEnable), NRFCs(NRFCs), MOSI(MOSI), MISO(MISO), SCK(SCK), BattAnalogVSens(BattAnalogVSens), SwitchAnalogVSens(SwitchAnalogVSens)
|
||||
{
|
||||
|
||||
}
|
44
src/app/BoardConfig.h
Normal file
44
src/app/BoardConfig.h
Normal file
@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Author : Anatole SCHRAMM-HENRY
|
||||
* Created the : 08/09/2022
|
||||
* This class encapsulates the various configuration values for the board like the Pin Mapping for instance.
|
||||
*/
|
||||
#ifndef BOARDCONFIG_H
|
||||
#define BOARDCONFIG_H
|
||||
|
||||
#include "definition.h"
|
||||
|
||||
class BoardConfig
|
||||
{
|
||||
public:
|
||||
BoardConfig(
|
||||
const Pin ExternalInt = D2_EXTERNAL_INT,
|
||||
const Pin LDOEnable = D4_LDO_EN,
|
||||
const Pin BattVSensEnable = D5_BAT_V_SENS_EN,
|
||||
const Pin NRFCe = D6_NRF_CE,
|
||||
const Pin SwitchVSensEnable = D7_SWITCH_V_SENS_EN,
|
||||
const Pin NRFCs = D10_NRF_CS,
|
||||
const Pin MOSI = D11_MOSI,
|
||||
const Pin MISO = D12_MISO,
|
||||
const Pin SCK = D13_SCK,
|
||||
const Pin BattAnalogVSens = A0_BAT_V_SENS,
|
||||
const Pin SwitchAnalogVSens = A1_SWITCH_V_SENS
|
||||
);
|
||||
|
||||
const Pin ExternalInt;
|
||||
const Pin LDOEnable;
|
||||
const Pin BattVSensEnable;
|
||||
const Pin NRFCe;
|
||||
const Pin SwitchVSensEnable;
|
||||
const Pin NRFCs;
|
||||
const Pin MOSI;
|
||||
const Pin MISO;
|
||||
const Pin SCK;
|
||||
const Pin BattAnalogVSens;
|
||||
const Pin SwitchAnalogVSens;
|
||||
|
||||
protected:
|
||||
private:
|
||||
};
|
||||
|
||||
#endif //BOARDCONFIG_H
|
109
src/app/MBPeripherals.cpp
Normal file
109
src/app/MBPeripherals.cpp
Normal file
@ -0,0 +1,109 @@
|
||||
#include "MBPeripherals.h"
|
||||
|
||||
void defaultExtIntIsr(void){}
|
||||
|
||||
MBPeripherals::MBPeripherals(const BoardConfig &boardConfig, void (*extIntIsr)(void)): _boardConfig(boardConfig), _NRF(boardConfig.NRFCe, boardConfig.NRFCs)
|
||||
{
|
||||
if(!extIntIsr)
|
||||
_extIntIsr = &(defaultExtIntIsr); //We provide a default ISR
|
||||
}
|
||||
|
||||
uint8_t MBPeripherals::init()
|
||||
{
|
||||
uint8_t toReturn(0);
|
||||
//We initialize needed IOs :
|
||||
pinMode(_boardConfig.ExternalInt, INPUT);
|
||||
pinMode(_boardConfig.LDOEnable, OUTPUT);
|
||||
_3V3PowerRail(OFF);
|
||||
pinMode(_boardConfig.SwitchVSensEnable, INPUT_PULLUP);
|
||||
pinMode(_boardConfig.BattVSensEnable, OUTPUT);
|
||||
digitalWrite(_boardConfig.BattVSensEnable, LOW);
|
||||
|
||||
//Unused pins are set as inputs with internal pullup enabled to reduce power consumption during sleep
|
||||
pinMode(0,INPUT_PULLUP);
|
||||
//pinMode(1,INPUT_PULLUP); TX pin for serial
|
||||
pinMode(6,INPUT_PULLUP);
|
||||
pinMode(7,INPUT_PULLUP);
|
||||
pinMode(8,INPUT_PULLUP);
|
||||
pinMode(9,INPUT_PULLUP);
|
||||
pinMode(10,INPUT_PULLUP);
|
||||
pinMode(11,INPUT_PULLUP);
|
||||
pinMode(12,INPUT_PULLUP);
|
||||
pinMode(A2,INPUT_PULLUP);
|
||||
pinMode(A3,INPUT_PULLUP);
|
||||
pinMode(A4,INPUT_PULLUP);
|
||||
pinMode(A5,INPUT_PULLUP);
|
||||
pinMode(A6,INPUT_PULLUP);
|
||||
pinMode(A7,INPUT_PULLUP);
|
||||
|
||||
//We check that every external devices are responding
|
||||
_3V3PowerRail(ON);
|
||||
toReturn |= _NRF.begin();
|
||||
_3V3PowerRail(OFF);
|
||||
|
||||
attachInterrupt(digitalPinToInterrupt(_boardConfig.ExternalInt), _extIntIsr, FALLING);
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
uint8_t MBPeripherals::initExternalPeripherals(void)
|
||||
{
|
||||
uint8_t toReturn(0);
|
||||
|
||||
toReturn |= _NRF.begin();
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
float MBPeripherals::batteryVoltage(void)
|
||||
{
|
||||
//We close the voltage divider bridge and we do the measurement
|
||||
digitalWrite(_boardConfig.BattVSensEnable, HIGH);
|
||||
int rawBatteryValue = analogRead(_boardConfig.BattAnalogVSens);
|
||||
digitalWrite(_boardConfig.BattVSensEnable, LOW);
|
||||
|
||||
return float(rawBatteryValue) * ADC_QUANTUM * VOLTAGE_DIV_COEFF;
|
||||
}
|
||||
|
||||
void MBPeripherals::_3V3PowerRail(State state)
|
||||
{
|
||||
digitalWrite(_boardConfig.LDOEnable, state);
|
||||
if(state) //We let some time for the voltage to stabilize on the rail.
|
||||
delay(10);
|
||||
}
|
||||
|
||||
const RF24 &MBPeripherals::getRadio(void){return _NRF;}
|
||||
|
||||
void MBPeripherals::applyRadioConfig(uint8_t channel, uint8_t paLevel, bool enableLNA, rf24_datarate_e datarate)
|
||||
{
|
||||
_NRF.setChannel(channel);
|
||||
_NRF.setPALevel(paLevel, enableLNA);
|
||||
_NRF.setDataRate(datarate);
|
||||
}
|
||||
|
||||
MAILBOX_EVENT_e MBPeripherals::readMailboxEvent(void)
|
||||
{
|
||||
pinMode(_boardConfig.SwitchVSensEnable, OUTPUT);
|
||||
digitalWrite(_boardConfig.SwitchVSensEnable, HIGH);
|
||||
int analogValue = analogRead(_boardConfig.SwitchAnalogVSens);
|
||||
digitalWrite(_boardConfig.SwitchVSensEnable, LOW);
|
||||
pinMode(_boardConfig.SwitchVSensEnable, INPUT_PULLUP);
|
||||
|
||||
if(analogValue < 526)
|
||||
return MAILBOX_EVENT_e::MAILBOX_LETTER;
|
||||
else if(analogValue >= 526 && analogValue < 711)
|
||||
return MAILBOX_EVENT_e::MAILBOX_PACKAGE;
|
||||
else if(analogValue >= 711 && analogValue < 1000)
|
||||
return MAILBOX_EVENT_e::MAILBOX_COLLECTED;
|
||||
else return MAILBOX_EVENT_e::MAILBOX_UNKNOWN;
|
||||
}
|
||||
|
||||
void MBPeripherals::maskExtInt(void)
|
||||
{
|
||||
detachInterrupt(digitalPinToInterrupt(_boardConfig.ExternalInt));
|
||||
}
|
||||
|
||||
void MBPeripherals::unmaskExtInt(void)
|
||||
{
|
||||
attachInterrupt(digitalPinToInterrupt(_boardConfig.ExternalInt), _extIntIsr, FALLING);
|
||||
}
|
79
src/app/MBPeripherals.h
Normal file
79
src/app/MBPeripherals.h
Normal file
@ -0,0 +1,79 @@
|
||||
/**
|
||||
* Author : Anatole SCHRAMM-HENRY
|
||||
* Created the : 08/09/2022
|
||||
* This classe exposes all the methods necessary to init the MBPeripherals (Mail Box Peripherals) and
|
||||
* to retrieve various data and measurements like battery voltage, Mailbox events etc...
|
||||
*/
|
||||
#ifndef MBPERIPHERALS_H
|
||||
#define MBPERIPHERALS_H
|
||||
|
||||
#include <RF24.h>
|
||||
#include <LowPower.h>
|
||||
|
||||
#include "BoardConfig.h"
|
||||
|
||||
void defaultExtIntIsr(void);
|
||||
|
||||
class MBPeripherals
|
||||
{
|
||||
public:
|
||||
enum State {OFF, ON};
|
||||
|
||||
MBPeripherals(const BoardConfig &boardConfig, void (*extIntIsr)(void) = nullptr);
|
||||
/*
|
||||
* Returns 1 if all the external devices are working properly, or an other value if it is not the case.
|
||||
*/
|
||||
uint8_t init(void);
|
||||
|
||||
/*
|
||||
* After calling this methode , you need to execute initExternalPeripherals() to init the peripherals.
|
||||
*/
|
||||
void externalPeripherals(State state){_3V3PowerRail(state);}
|
||||
|
||||
/*
|
||||
* Used to init devices after each LDO powerup, external devices need to be turned one externalPeripherals(ON) before calling this function.
|
||||
*/
|
||||
uint8_t initExternalPeripherals(void);
|
||||
|
||||
/*
|
||||
* Starts a battery voltage measurement and returns a float value in Volts.
|
||||
*/
|
||||
float batteryVoltage(void);
|
||||
|
||||
/*
|
||||
* Before calling this method, externalPeripherals(ON) and initExternalPeripherals() must be called respectively.
|
||||
* This methods applies the NRF radio configuration.
|
||||
*/
|
||||
void applyRadioConfig(uint8_t channel = RADIO_CHANNEL, uint8_t paLevel = RADIO_PA_LEVEL, bool enableLNA = ENABLE_LNA, rf24_datarate_e datarate = RADIO_DATARATE);
|
||||
|
||||
/*
|
||||
* Use this function just after the interrupt wake up retrieve the wake up event.
|
||||
* Wake up event can be : MAILBOX_LETTER, MAILBOX_PACKAGE, MAILBOX_COLLECTED or MAILBOX_UNKNOWN.
|
||||
*/
|
||||
MAILBOX_EVENT_e readMailboxEvent(void);
|
||||
|
||||
/*
|
||||
* Disables wake up interrupts
|
||||
*/
|
||||
void maskExtInt(void);
|
||||
|
||||
/*
|
||||
* Enables wake up interrupts
|
||||
*/
|
||||
void unmaskExtInt(void);
|
||||
|
||||
/*
|
||||
* Gets the NRF radio object to access it's api.
|
||||
*/
|
||||
const RF24 &getRadio(void);
|
||||
|
||||
protected:
|
||||
private:
|
||||
void _3V3PowerRail(State state);
|
||||
const BoardConfig &_boardConfig;
|
||||
const RF24 _NRF;
|
||||
const void (*_extIntIsr)(void);
|
||||
|
||||
};
|
||||
|
||||
#endif //MBPERIPHERALS_H
|
142
src/app/app.ino
Normal file
142
src/app/app.ino
Normal file
@ -0,0 +1,142 @@
|
||||
#include <Arduino.h>
|
||||
#include <LowPower.h>
|
||||
#include <SPI.h>
|
||||
#include "definition.h"
|
||||
#include "BoardConfig.h"
|
||||
#include "MBPeripherals.h"
|
||||
|
||||
BoardConfig defaultBC;
|
||||
MBPeripherals MBP(defaultBC);
|
||||
|
||||
MailboxDataPacket payload;
|
||||
uint8_t rCode(0);
|
||||
|
||||
void setup()
|
||||
{
|
||||
#if SERIAL_DEBUG_ENABLED
|
||||
Serial.begin(SERIAL_BAUD_RATE);
|
||||
Serial.println("Setup begin");
|
||||
#endif
|
||||
|
||||
rCode = MBP.init();
|
||||
memset(&payload, 0, sizeof payload);
|
||||
|
||||
#if SERIAL_DEBUG_ENABLED
|
||||
Serial.print("Payload size : ");Serial.println(sizeof payload);
|
||||
debugStruct(&payload);
|
||||
#endif
|
||||
payload.header = HEADER_e::CONNECTED_MAILBOX;
|
||||
|
||||
#if SERIAL_DEBUG_ENABLED
|
||||
Serial.print("WSP init returned : ");Serial.println(rCode);
|
||||
Serial.println("Setup end");
|
||||
//Let time to the uart to spit out what's left
|
||||
delay(100);
|
||||
#endif
|
||||
|
||||
LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
MBP.maskExtInt();
|
||||
if((payload.mailbox_event = MBP.readMailboxEvent()) != MAILBOX_EVENT_e::MAILBOX_UNKNOWN)
|
||||
{
|
||||
payload.battery = MBP.batteryVoltage();
|
||||
|
||||
//We now send the event
|
||||
MBP.externalPeripherals(MBPeripherals::State::ON);
|
||||
rCode = MBP.initExternalPeripherals();
|
||||
|
||||
#if SERIAL_DEBUG_ENABLED
|
||||
Serial.print("MBP Ext Peripheral : "); Serial.println(rCode);
|
||||
debugStruct(&payload);
|
||||
#endif
|
||||
|
||||
if(MBP.getRadio().isChipConnected())
|
||||
{
|
||||
MBP.applyRadioConfig();
|
||||
MBP.getRadio().setRetries(15, 15);
|
||||
MBP.getRadio().openWritingPipe((const uint8_t *)RADIO_NODE_ADDRESS);
|
||||
MBP.getRadio().stopListening(); //Very important, if not called, no ack will be received !
|
||||
|
||||
for(uint8_t i(0); i < MAX_SEND_ROUND_RETRIES; i++)
|
||||
{
|
||||
if(MBP.getRadio().write(&payload, sizeof payload))
|
||||
{
|
||||
#if SERIAL_DEBUG_ENABLED
|
||||
Serial.println("Payload sent !");
|
||||
delay(100);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
#if SERIAL_DEBUG_ENABLED
|
||||
else
|
||||
{
|
||||
Serial.println("Failed to send payload !");
|
||||
delay(100);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#if SERIAL_DEBUG_ENABLED
|
||||
else
|
||||
{
|
||||
Serial.println("NRF missing !");
|
||||
delay(100);
|
||||
}
|
||||
#endif
|
||||
|
||||
MBP.externalPeripherals(MBPeripherals::State::OFF);
|
||||
|
||||
//We wait for some time before allowing next trigger
|
||||
//Done to prevent switch bounces
|
||||
LowPower.powerDown(SLEEP_2S, ADC_OFF, BOD_OFF);
|
||||
}
|
||||
#if SERIAL_DEBUG_ENABLED
|
||||
else
|
||||
{
|
||||
Serial.println("Unknown event :O !");
|
||||
delay(100);
|
||||
}
|
||||
#endif
|
||||
|
||||
MBP.unmaskExtInt();
|
||||
payload.id++;
|
||||
//Sleep until next trigger happens
|
||||
LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
|
||||
}
|
||||
|
||||
void debugStruct(MailboxDataPacket *p)
|
||||
{
|
||||
Serial.println("##############DATA##############");
|
||||
Serial.print("ID : ");
|
||||
Serial.println(p->id);
|
||||
|
||||
Serial.print("HEADER : ");
|
||||
Serial.println(p->header);
|
||||
|
||||
Serial.print("BATT : ");
|
||||
Serial.print(p->battery);
|
||||
Serial.println(" V");
|
||||
|
||||
Serial.print("EVENT : ");
|
||||
switch(p->mailbox_event)
|
||||
{
|
||||
case MAILBOX_LETTER:
|
||||
Serial.println("LETTER");
|
||||
break;
|
||||
case MAILBOX_PACKAGE:
|
||||
Serial.println("PACKAGE");
|
||||
break;
|
||||
case MAILBOX_COLLECTED:
|
||||
Serial.println("COLLECTED");
|
||||
break;
|
||||
default:
|
||||
Serial.println("UNKNOWN");
|
||||
break;
|
||||
}
|
||||
|
||||
delay(100); //Needed to prevent the micro to go to sleep to quickly and thus not sending the full serial output !
|
||||
}
|
63
src/app/definition.h
Normal file
63
src/app/definition.h
Normal file
@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Author : Anatole SCHRAMM-HENRY
|
||||
* Created the : 08/09/2022
|
||||
* This file contains all the config used by the other classes and sources files.
|
||||
*/
|
||||
#ifndef DEFINITION_H
|
||||
#define DEFINITION_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <RF24.h>
|
||||
#include "packet_format.h"
|
||||
|
||||
//Serial debug config part
|
||||
#define SERIAL_DEBUG_ENABLED 0
|
||||
#define SERIAL_BAUD_RATE 115200
|
||||
|
||||
//Battery config part
|
||||
#define ADC_QUANTUM 0.0033017578125 //ADC_VREF / ADC_RESOLUTION -> 3.314 and 10 bits (1024) in my case
|
||||
#define VOLTAGE_DIV_COEFF 1.321127673363577 //(R1 + R2)/R2
|
||||
|
||||
//NRF Radio config part
|
||||
#define RADIO_CHANNEL 108 //0-125
|
||||
#define RADIO_NODE_ADDRESS "WEST1" //Weather Station 1 network because the mail box is connected on it
|
||||
#define RADIO_PA_LEVEL RF24_PA_MAX //RF24_PA_MIN,RF24_PA_LOW,RF24_PA_HIGH,RF24_PA_MAX
|
||||
#define ENABLE_LNA false //true or false
|
||||
#define RADIO_DATARATE RF24_250KBPS //Slow datarate to maximize range
|
||||
#define MAX_SEND_ROUND_RETRIES 5 //If no ACK is received, tries to resend a MAX_SEND_ROUND_RETRIES-1 more times
|
||||
//Increase this parameter if the RF link is bad.
|
||||
|
||||
//Pin config part
|
||||
typedef enum
|
||||
{
|
||||
D2_EXTERNAL_INT = 2,
|
||||
D4_LDO_EN = 4,
|
||||
D5_BAT_V_SENS_EN = 5,
|
||||
D6_NRF_CE = 6,
|
||||
D7_SWITCH_V_SENS_EN = 7,
|
||||
D10_NRF_CS = 10,
|
||||
D11_MOSI = 11,
|
||||
D12_MISO = 12,
|
||||
D13_SCK = 13,
|
||||
A0_BAT_V_SENS = A0,
|
||||
A1_SWITCH_V_SENS = A1,
|
||||
} Pin;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MAILBOX_LETTER = 0,
|
||||
MAILBOX_PACKAGE,
|
||||
MAILBOX_COLLECTED,
|
||||
MAILBOX_UNKNOWN,
|
||||
} MAILBOX_EVENT_e;
|
||||
|
||||
//Payload structure
|
||||
typedef struct
|
||||
{
|
||||
uint16_t id;
|
||||
HEADER_e header : 6;
|
||||
float battery;
|
||||
MAILBOX_EVENT_e mailbox_event;
|
||||
} __attribute__((__packed__)) MailboxDataPacket;
|
||||
|
||||
#endif //DEFINITION_H
|
6
src/app/packet_format.h
Normal file
6
src/app/packet_format.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef PACKET_FORMAT_H
|
||||
#define PACKET_FORMAT_H
|
||||
|
||||
enum HEADER_e {WEATHER_STATION = 0, CONNECTED_MAILBOX};
|
||||
|
||||
#endif //PACKET_FORMAT_H
|
Loading…
Reference in New Issue
Block a user