microbit: added MicroBitLightSensor
Added a new class called MicroBitLightSensor which interleaves sensing with the display. This class takes advantage of the previous commits which add a dynamic system tick, and a new display mode for the display. A future optimisation would be for the display to handle the instantion of a light sensor when the display mode is changed!
This commit is contained in:
parent
6e316dc741
commit
2049e63039
4 changed files with 232 additions and 0 deletions
|
@ -24,6 +24,7 @@
|
|||
#include "MicroBitCompass.h"
|
||||
#include "MicroBitAccelerometer.h"
|
||||
#include "MicroBitThermometer.h"
|
||||
#include "MicroBitLightSensor.h"
|
||||
#include "MicroBitMultiButton.h"
|
||||
|
||||
#include "MicroBitSerial.h"
|
||||
|
|
99
inc/MicroBitLightSensor.h
Normal file
99
inc/MicroBitLightSensor.h
Normal file
|
@ -0,0 +1,99 @@
|
|||
#ifndef MICROBIT_LIGHT_SENSOR_H
|
||||
#define MICROBIT_LIGHT_SENSOR_H
|
||||
|
||||
#include "mbed.h"
|
||||
#include "MicroBitComponent.h"
|
||||
|
||||
#define MICROBIT_LIGHT_SENSOR_CHAN_NUM 3
|
||||
#define MICROBIT_LIGHT_SENSOR_AN_SET_TIME 4000
|
||||
#define MICROBIT_LIGHT_SENSOR_TICK_PERIOD 5
|
||||
|
||||
/**
|
||||
* Class definition for MicroBitLightSensor.
|
||||
*
|
||||
* This is an object that interleaves light sensing with uBit.display.
|
||||
*/
|
||||
class MicroBitLightSensor
|
||||
{
|
||||
|
||||
//contains the results from each section of the display
|
||||
int results[MICROBIT_LIGHT_SENSOR_CHAN_NUM] = { 0 };
|
||||
|
||||
//holds the current channel (also used to index the results array)
|
||||
uint8_t chan;
|
||||
|
||||
//a Timeout which triggers our analogReady() call
|
||||
Timeout analogTrigger;
|
||||
|
||||
//a pointer the currently sensed pin, represented as an AnalogIn
|
||||
AnalogIn* sensePin;
|
||||
|
||||
/**
|
||||
* After the startSensing method has been called, this method will be called
|
||||
* MICROBIT_LIGHT_SENSOR_AN_SET_TIME after.
|
||||
*
|
||||
* It will then read from the currently selected channel using the AnalogIn
|
||||
* that was configured in the startSensing method.
|
||||
*/
|
||||
void analogReady();
|
||||
|
||||
/**
|
||||
* Forcibly disables the AnalogIn, otherwise it will remain in possession
|
||||
* of the GPIO channel it is using, meaning that the display will not be
|
||||
* able to use a channel (COL).
|
||||
*
|
||||
* This is required as per PAN 3, details of which can be found here:
|
||||
*
|
||||
* https://www.nordicsemi.com/eng/nordic/download_resource/24634/5/88440387
|
||||
*/
|
||||
void analogDisable();
|
||||
|
||||
/**
|
||||
* The method that is invoked by sending MICROBIT_DISPLAY_EVT_LIGHT_SENSE
|
||||
* using the id MICROBIT_ID_DISPLAY.
|
||||
*
|
||||
* If you want to manually trigger this method, you should use the event bus.
|
||||
*/
|
||||
void startSensing(MicroBitEvent);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* Create a representation of the light sensor
|
||||
*/
|
||||
MicroBitLightSensor();
|
||||
|
||||
/**
|
||||
* This method returns a summed average of the three sections of the display.
|
||||
*
|
||||
* A section is defined as:
|
||||
* ___________________
|
||||
* | 1 | | 2 | | 3 |
|
||||
* |___|___|___|___|___|
|
||||
* | | | | | |
|
||||
* |___|___|___|___|___|
|
||||
* | 2 | | 3 | | 1 |
|
||||
* |___|___|___|___|___|
|
||||
* | | | | | |
|
||||
* |___|___|___|___|___|
|
||||
* | 3 | | 1 | | 2 |
|
||||
* |___|___|___|___|___|
|
||||
*
|
||||
* Where each number represents a different section on the 5 x 5 matrix display.
|
||||
*
|
||||
* @note currently values are inverted to how one would think:
|
||||
* - Lower is brighter
|
||||
* - Higher is darker
|
||||
* TODO: Normalise the returned values into an SI unit!
|
||||
*/
|
||||
int read();
|
||||
|
||||
/**
|
||||
* The destructor restores the default Display Mode and tick speed, and also
|
||||
* removes the listener from the MessageBus.
|
||||
*/
|
||||
~MicroBitLightSensor();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -29,6 +29,7 @@ set(YOTTA_AUTO_MICROBIT-DAL_CPP_FILES
|
|||
"MicroBitSerial.cpp"
|
||||
"MicroBitHeapAllocator.cpp"
|
||||
"MicroBitListener.cpp"
|
||||
"MicroBitLightSensor.cpp"
|
||||
"RefCounted.cpp"
|
||||
"MemberFunctionCallback.cpp"
|
||||
"ble-services/MicroBitBLEManager.cpp"
|
||||
|
|
131
source/MicroBitLightSensor.cpp
Normal file
131
source/MicroBitLightSensor.cpp
Normal file
|
@ -0,0 +1,131 @@
|
|||
/**
|
||||
* Class definition for MicroBitLightSensor.
|
||||
*
|
||||
* This is an object that interleaves light sensing with uBit.display.
|
||||
*/
|
||||
|
||||
#include "MicroBit.h"
|
||||
|
||||
/**
|
||||
* After the startSensing method has been called, this method will be called
|
||||
* MICROBIT_LIGHT_SENSOR_AN_SET_TIME after.
|
||||
*
|
||||
* It will then read from the currently selected channel using the AnalogIn
|
||||
* that was configured in the startSensing method.
|
||||
*/
|
||||
void MicroBitLightSensor::analogReady()
|
||||
{
|
||||
this->results[chan] = this->sensePin->read_u16();
|
||||
|
||||
analogDisable();
|
||||
|
||||
DigitalOut((PinName)(MICROBIT_DISPLAY_COLUMN_START + chan)).write(1);
|
||||
|
||||
chan++;
|
||||
|
||||
chan = chan % MICROBIT_LIGHT_SENSOR_CHAN_NUM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Forcibly disables the AnalogIn, otherwise it will remain in possession
|
||||
* of the GPIO channel it is using, meaning that the display will not be
|
||||
* able to use a channel (COL).
|
||||
*
|
||||
* This is required as per PAN 3, details of which can be found here:
|
||||
*
|
||||
* https://www.nordicsemi.com/eng/nordic/download_resource/24634/5/88440387
|
||||
*/
|
||||
void MicroBitLightSensor::analogDisable()
|
||||
{
|
||||
NRF_ADC->ENABLE = ADC_ENABLE_ENABLE_Disabled;
|
||||
|
||||
NRF_ADC->CONFIG = (ADC_CONFIG_RES_8bit << ADC_CONFIG_RES_Pos) |
|
||||
(ADC_CONFIG_INPSEL_SupplyTwoThirdsPrescaling << ADC_CONFIG_INPSEL_Pos) |
|
||||
(ADC_CONFIG_REFSEL_VBG << ADC_CONFIG_REFSEL_Pos) |
|
||||
(ADC_CONFIG_PSEL_Disabled << ADC_CONFIG_PSEL_Pos) |
|
||||
(ADC_CONFIG_EXTREFSEL_None << ADC_CONFIG_EXTREFSEL_Pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* The method that is invoked by sending MICROBIT_DISPLAY_EVT_LIGHT_SENSE
|
||||
* using the id MICROBIT_ID_DISPLAY.
|
||||
*
|
||||
* If you want to manually trigger this method, you should use the event bus.
|
||||
*
|
||||
* @note This is currently too churny, and allocates a lot of stuff on the stack
|
||||
* however, this makes this chunk of code platform agnostic in mbed land.
|
||||
*/
|
||||
void MicroBitLightSensor::startSensing(MicroBitEvent)
|
||||
{
|
||||
for(int rowCount = 0; rowCount < MICROBIT_DISPLAY_ROW_COUNT; rowCount++)
|
||||
DigitalOut((PinName)(MICROBIT_DISPLAY_ROW_START + rowCount)).write(0);
|
||||
|
||||
PinName currentPin = (PinName)(MICROBIT_DISPLAY_COLUMN_START + chan);
|
||||
|
||||
DigitalOut(currentPin).write(1);
|
||||
|
||||
DigitalIn(currentPin, PullNone).~DigitalIn();
|
||||
|
||||
if(this->sensePin != NULL)
|
||||
delete this->sensePin;
|
||||
|
||||
this->sensePin = new AnalogIn(currentPin);
|
||||
|
||||
analogTrigger.attach_us(this, &MicroBitLightSensor::analogReady, MICROBIT_LIGHT_SENSOR_AN_SET_TIME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* Create a representation of the light sensor
|
||||
*/
|
||||
MicroBitLightSensor::MicroBitLightSensor() : analogTrigger()
|
||||
{
|
||||
this->chan = 0;
|
||||
|
||||
uBit.MessageBus.listen(MICROBIT_ID_DISPLAY, MICROBIT_DISPLAY_EVT_LIGHT_SENSE, this, &MicroBitLightSensor::startSensing, MESSAGE_BUS_LISTENER_IMMEDIATE);
|
||||
|
||||
this->sensePin = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns a summed average of the three sections of the display.
|
||||
*
|
||||
* A section is defined as:
|
||||
* ___________________
|
||||
* | 1 | | 2 | | 3 |
|
||||
* |___|___|___|___|___|
|
||||
* | | | | | |
|
||||
* |___|___|___|___|___|
|
||||
* | 2 | | 3 | | 1 |
|
||||
* |___|___|___|___|___|
|
||||
* | | | | | |
|
||||
* |___|___|___|___|___|
|
||||
* | 3 | | 1 | | 2 |
|
||||
* |___|___|___|___|___|
|
||||
*
|
||||
* Where each number represents a different section on the 5 x 5 matrix display.
|
||||
*
|
||||
* @note currently values are inverted to how one would think:
|
||||
* - Lower is brighter
|
||||
* - Higher is darker
|
||||
* TODO: Normalise the returned values into an SI unit!
|
||||
*/
|
||||
int MicroBitLightSensor::read()
|
||||
{
|
||||
int sum = 0;
|
||||
|
||||
for(int i = 0; i < MICROBIT_LIGHT_SENSOR_CHAN_NUM; i++)
|
||||
sum += results[i];
|
||||
|
||||
return sum/MICROBIT_LIGHT_SENSOR_CHAN_NUM;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The destructor restores the default Display Mode and tick speed, and also
|
||||
* removes the listener from the MessageBus.
|
||||
*/
|
||||
MicroBitLightSensor::~MicroBitLightSensor()
|
||||
{
|
||||
uBit.MessageBus.ignore(MICROBIT_ID_DISPLAY, MICROBIT_DISPLAY_EVT_LIGHT_SENSE, this, &MicroBitLightSensor::startSensing);
|
||||
}
|
Loading…
Reference in a new issue