kopia lustrzana https://github.com/pimoroni/pimoroni-pico
Tidied LED strip class
rodzic
dda775c85e
commit
8075f04434
|
@ -11,4 +11,166 @@ namespace pimoroni {
|
|||
return adc_level == ADC_LOW && slow1 == HIGH && slow2 == HIGH && slow3 == HIGH;
|
||||
}
|
||||
|
||||
LEDStripModule::LEDStripModule(StripType strip_type, uint num_pixels, float brightness, bool halt_on_not_pgood) :
|
||||
YukonModule(),
|
||||
strip_type(strip_type),
|
||||
num_pixels(num_pixels),
|
||||
brightness(brightness),
|
||||
halt_on_not_pgood(halt_on_not_pgood),
|
||||
last_pgood(false),
|
||||
ws_pixels(nullptr),
|
||||
apa_pixels(nullptr),
|
||||
power_good(nullptr),
|
||||
power_en(nullptr) {
|
||||
}
|
||||
|
||||
LEDStripModule::~LEDStripModule() {
|
||||
if(strip_type == NEOPIXEL) {
|
||||
if(ws_pixels != nullptr) {
|
||||
ws_pixels->stop();
|
||||
delete(ws_pixels);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(apa_pixels != nullptr) {
|
||||
apa_pixels->stop();
|
||||
delete(apa_pixels);
|
||||
}
|
||||
}
|
||||
delete(power_good);
|
||||
delete(power_en);
|
||||
}
|
||||
|
||||
std::string LEDStripModule::name() {
|
||||
if(strip_type == NEOPIXEL) {
|
||||
return LEDStripModule::NAME + " (NeoPixel)";
|
||||
}
|
||||
else {
|
||||
return LEDStripModule::NAME + " (DotStar)";
|
||||
}
|
||||
}
|
||||
|
||||
void LEDStripModule::initialise(const SLOT& slot, SlotAccessor& accessor) {
|
||||
// Create the strip driver object
|
||||
if(strip_type == NEOPIXEL) {
|
||||
ws_pixels = new WS2812(num_pixels, pio0, 0, slot.FAST4);
|
||||
ws_pixels->start(60);
|
||||
for(auto i = 0u; i < ws_pixels->num_leds; ++i) {
|
||||
float hue = float(i) / ws_pixels->num_leds;
|
||||
ws_pixels->set_hsv(i, hue, 1.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
else {
|
||||
apa_pixels = new APA102(num_pixels, pio0, 0, slot.FAST4, slot.FAST3);
|
||||
apa_pixels->start(60);
|
||||
for(auto i = 0u; i < apa_pixels->num_leds; ++i) {
|
||||
float hue = float(i) / apa_pixels->num_leds;
|
||||
apa_pixels->set_hsv(i, hue, 1.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
// Create the power control pin objects
|
||||
power_good = new IO(slot.FAST1);
|
||||
power_en = new IO(slot.FAST2);
|
||||
|
||||
// Configure strip and power pins
|
||||
configure();
|
||||
|
||||
// Pass the slot and adc functions up to the parent now that module specific initialisation has finished
|
||||
YukonModule::initialise(slot, accessor);
|
||||
}
|
||||
|
||||
void LEDStripModule::configure() {
|
||||
power_en->to_output(false);
|
||||
power_good->to_input(true, false);
|
||||
}
|
||||
|
||||
void LEDStripModule::enable() {
|
||||
if(!is_initialised()) {
|
||||
throw std::runtime_error("Module not initialised\n");
|
||||
}
|
||||
power_en->value(true);
|
||||
}
|
||||
|
||||
void LEDStripModule::disable() {
|
||||
if(!is_initialised()) {
|
||||
throw std::runtime_error("Module not initialised\n");
|
||||
}
|
||||
power_en->value(false);
|
||||
}
|
||||
|
||||
bool LEDStripModule::is_enabled() {
|
||||
if(!is_initialised()) {
|
||||
throw std::runtime_error("Module not initialised\n");
|
||||
}
|
||||
return power_en->value();
|
||||
}
|
||||
|
||||
bool LEDStripModule::read_power_good() {
|
||||
if(!is_initialised()) {
|
||||
throw std::runtime_error("Module not initialised\n");
|
||||
}
|
||||
return power_good->value();
|
||||
}
|
||||
|
||||
float LEDStripModule::read_temperature() {
|
||||
return __read_adc2_as_temp();
|
||||
}
|
||||
|
||||
void LEDStripModule::monitor() {
|
||||
bool pgood = read_power_good();
|
||||
if(!pgood) {
|
||||
if(halt_on_not_pgood) {
|
||||
throw FaultError(__message_header() + "Power is not good! Turning off output\n");
|
||||
}
|
||||
}
|
||||
|
||||
float temperature = read_temperature();
|
||||
if(temperature > TEMPERATURE_THRESHOLD) {
|
||||
throw OverTemperatureError(__message_header() + "Temperature of " + std::to_string(temperature) + "°C exceeded the user set level of " + std::to_string(TEMPERATURE_THRESHOLD) + "°C! Turning off output\n");
|
||||
}
|
||||
|
||||
if(last_pgood && !pgood) {
|
||||
logging.warn(__message_header() + "Power is not good\n");
|
||||
}
|
||||
else if(!last_pgood && pgood) {
|
||||
logging.warn(__message_header() + "Power is good\n");
|
||||
}
|
||||
|
||||
// Run some user action based on the latest readings
|
||||
//if self.__monitor_action_callback is not None:
|
||||
// self.__monitor_action_callback(pgood, temperature)
|
||||
|
||||
last_pgood = pgood;
|
||||
power_good_throughout = power_good_throughout && pgood;
|
||||
|
||||
max_temperature = MAX(temperature, max_temperature);
|
||||
min_temperature = MIN(temperature, min_temperature);
|
||||
avg_temperature += temperature;
|
||||
count_avg += 1;
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::string, float>> LEDStripModule::get_readings() {
|
||||
std::vector<std::pair<std::string, float>> values;
|
||||
values.push_back(std::pair("PGood", power_good_throughout));
|
||||
values.push_back(std::pair("T_max", max_temperature));
|
||||
values.push_back(std::pair("T_min", min_temperature));
|
||||
values.push_back(std::pair("T_avg", avg_temperature));
|
||||
return values;
|
||||
}
|
||||
|
||||
void LEDStripModule::process_readings() {
|
||||
if(count_avg > 0) {
|
||||
avg_temperature /= count_avg;
|
||||
}
|
||||
}
|
||||
|
||||
void LEDStripModule::clear_readings() {
|
||||
power_good_throughout = true;
|
||||
max_temperature = -std::numeric_limits<float>::infinity();
|
||||
min_temperature = std::numeric_limits<float>::infinity();
|
||||
avg_temperature = 0;
|
||||
count_avg = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,185 +13,87 @@ using namespace plasma;
|
|||
namespace pimoroni {
|
||||
|
||||
class LEDStripModule : public YukonModule {
|
||||
//--------------------------------------------------
|
||||
// Constants
|
||||
//--------------------------------------------------
|
||||
public:
|
||||
static const std::string NAME;
|
||||
static const std::string NAME; // Required by all modules. Set in .cpp
|
||||
static constexpr float TEMPERATURE_THRESHOLD = 50.0f;
|
||||
|
||||
enum strip_type {
|
||||
|
||||
//--------------------------------------------------
|
||||
// Enums
|
||||
//--------------------------------------------------
|
||||
public:
|
||||
enum StripType {
|
||||
NEOPIXEL = 0,
|
||||
DOTSTAR = 1
|
||||
};
|
||||
|
||||
static constexpr float TEMPERATURE_THRESHOLD = 50.0f;
|
||||
|
||||
//--------------------------------------------------
|
||||
// Statics
|
||||
//--------------------------------------------------
|
||||
static bool is_module(uint adc_level, bool slow1, bool slow2, bool slow3);
|
||||
|
||||
virtual std::string name() {
|
||||
return LEDStripModule::NAME + " (NeoPixel)";
|
||||
}
|
||||
|
||||
TYPE_FUNCTION(LEDStripModule)
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
// Variables
|
||||
//--------------------------------------------------
|
||||
private:
|
||||
const StripType strip_type;
|
||||
const uint num_pixels;
|
||||
const float brightness;
|
||||
public:
|
||||
bool halt_on_not_pgood;
|
||||
bool __last_pgood;
|
||||
|
||||
bool __power_good_throughout;
|
||||
float __max_temperature;
|
||||
float __min_temperature;
|
||||
float __avg_temperature;
|
||||
float __count_avg;
|
||||
//--------------------------------------------------
|
||||
private:
|
||||
bool last_pgood;
|
||||
bool power_good_throughout;
|
||||
float max_temperature;
|
||||
float min_temperature;
|
||||
float avg_temperature;
|
||||
float count_avg;
|
||||
|
||||
WS2812* led_strip;
|
||||
APA102* apa_strip;
|
||||
IO* __power_good_io;
|
||||
IO* __power_en_io;
|
||||
//--------------------------------------------------
|
||||
public:
|
||||
WS2812* ws_pixels;
|
||||
APA102* apa_pixels;
|
||||
private:
|
||||
IO* power_good;
|
||||
IO* power_en;
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
// Constructors/Destructor
|
||||
//--------------------------------------------------
|
||||
public:
|
||||
LEDStripModule(StripType strip_type, uint num_pixels, float brightness = 1.0f, bool halt_on_not_pgood = false);
|
||||
virtual ~LEDStripModule();
|
||||
|
||||
LEDStripModule(bool halt_on_not_pgood = false) :
|
||||
YukonModule(),
|
||||
halt_on_not_pgood(halt_on_not_pgood),
|
||||
__last_pgood(false),
|
||||
led_strip(nullptr),
|
||||
apa_strip(nullptr),
|
||||
__power_good_io(nullptr),
|
||||
__power_en_io(nullptr) { //TODO strip_type, num_pixels, brightness=1.0, halt_on_not_pgood=False):
|
||||
//self.__strip_type = strip_type
|
||||
//if self.__strip_type == self.NEOPIXEL:
|
||||
// self.NAME += " (NeoPixel)"
|
||||
//else:
|
||||
// self.NAME += " (DotStar)"
|
||||
|
||||
//self.__num_pixels = num_pixels
|
||||
//self.__brightness = brightness
|
||||
}
|
||||
//--------------------------------------------------
|
||||
// Methods
|
||||
//--------------------------------------------------
|
||||
public:
|
||||
virtual std::string name();
|
||||
virtual void initialise(const SLOT& slot, SlotAccessor& accessor);
|
||||
virtual void configure();
|
||||
|
||||
~LEDStripModule() {
|
||||
delete(led_strip);
|
||||
delete(apa_strip);
|
||||
delete(__power_good_io);
|
||||
delete(__power_en_io);
|
||||
}
|
||||
//--------------------------------------------------
|
||||
void enable();
|
||||
void disable();
|
||||
bool is_enabled();
|
||||
bool read_power_good() ;
|
||||
float read_temperature();
|
||||
|
||||
virtual void initialise(const SLOT& slot, SlotAccessor& accessor) {
|
||||
/*
|
||||
// Create the strip driver object
|
||||
if self.__strip_type == self.NEOPIXEL:
|
||||
from neopixel import NeoPixel
|
||||
self.pixels = NeoPixel(slot.FAST4, self.__num_pixels, brightness=self.__brightness, auto_write=False)
|
||||
else:
|
||||
from adafruit_dotstar import DotStar
|
||||
self.pixels = DotStar(slot.FAST3, slot.FAST4, self.__num_pixels, brightness=self.__brightness, auto_write=False)
|
||||
*/
|
||||
led_strip = new WS2812(60, pio0, 0, slot.FAST4);
|
||||
led_strip->start(60);
|
||||
for(auto i = 0u; i < led_strip->num_leds; ++i) {
|
||||
float hue = float(i) / led_strip->num_leds;
|
||||
led_strip->set_hsv(i, hue, 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
// Create the power control pin objects
|
||||
__power_good_io = new IO(slot.FAST1);
|
||||
__power_en_io = new IO(slot.FAST2);
|
||||
|
||||
// Configure strip and power pins
|
||||
configure();
|
||||
|
||||
// Pass the slot and adc functions up to the parent now that module specific initialisation has finished
|
||||
YukonModule::initialise(slot, accessor);
|
||||
}
|
||||
|
||||
virtual void configure() {
|
||||
__power_en_io->to_output(false);
|
||||
__power_good_io->to_input(true, false);
|
||||
}
|
||||
|
||||
void enable() {
|
||||
if(!is_initialised()) {
|
||||
throw std::runtime_error("Module not initialised\n");
|
||||
}
|
||||
__power_en_io->value(true);
|
||||
}
|
||||
|
||||
void disable() {
|
||||
if(!is_initialised()) {
|
||||
throw std::runtime_error("Module not initialised\n");
|
||||
}
|
||||
__power_en_io->value(false);
|
||||
}
|
||||
|
||||
bool is_enabled() {
|
||||
if(!is_initialised()) {
|
||||
throw std::runtime_error("Module not initialised\n");
|
||||
}
|
||||
return __power_en_io->value();
|
||||
}
|
||||
|
||||
bool read_power_good() {
|
||||
if(!is_initialised()) {
|
||||
throw std::runtime_error("Module not initialised\n");
|
||||
}
|
||||
return __power_good_io->value();
|
||||
}
|
||||
|
||||
float read_temperature() {
|
||||
return __read_adc2_as_temp();
|
||||
}
|
||||
|
||||
virtual void monitor() {
|
||||
bool pgood = read_power_good();
|
||||
if(!pgood) {
|
||||
if(halt_on_not_pgood) {
|
||||
throw FaultError(__message_header() + "Power is not good! Turning off output\n");
|
||||
}
|
||||
}
|
||||
|
||||
float temperature = read_temperature();
|
||||
if(temperature > TEMPERATURE_THRESHOLD) {
|
||||
throw OverTemperatureError(__message_header() + "Temperature of " + std::to_string(temperature) + "°C exceeded the user set level of " + std::to_string(TEMPERATURE_THRESHOLD) + "°C! Turning off output\n");
|
||||
}
|
||||
|
||||
if(__last_pgood && !pgood) {
|
||||
logging.warn(__message_header() + "Power is not good\n");
|
||||
}
|
||||
else if(!__last_pgood && pgood) {
|
||||
logging.warn(__message_header() + "Power is good\n");
|
||||
}
|
||||
|
||||
// Run some user action based on the latest readings
|
||||
//if self.__monitor_action_callback is not None:
|
||||
// self.__monitor_action_callback(pgood, temperature)
|
||||
|
||||
__last_pgood = pgood;
|
||||
__power_good_throughout = __power_good_throughout && pgood;
|
||||
|
||||
__max_temperature = MAX(temperature, __max_temperature);
|
||||
__min_temperature = MIN(temperature, __min_temperature);
|
||||
__avg_temperature += temperature;
|
||||
__count_avg += 1;
|
||||
}
|
||||
|
||||
virtual std::vector<std::pair<std::string, float>> get_readings() {
|
||||
std::vector<std::pair<std::string, float>> values;
|
||||
values.push_back(std::pair("PGood", __power_good_throughout));
|
||||
values.push_back(std::pair("T_max", __max_temperature));
|
||||
values.push_back(std::pair("T_min", __min_temperature));
|
||||
values.push_back(std::pair("T_avg", __avg_temperature));
|
||||
return values;
|
||||
}
|
||||
|
||||
virtual void process_readings() {
|
||||
if(__count_avg > 0) {
|
||||
__avg_temperature /= __count_avg;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void clear_readings() {
|
||||
__power_good_throughout = true;
|
||||
__max_temperature = -std::numeric_limits<float>::infinity();
|
||||
__min_temperature = std::numeric_limits<float>::infinity();
|
||||
__avg_temperature = 0;
|
||||
__count_avg = 0;
|
||||
}
|
||||
//--------------------------------------------------
|
||||
virtual void monitor();
|
||||
virtual std::vector<std::pair<std::string, float>> get_readings();
|
||||
virtual void process_readings();
|
||||
virtual void clear_readings();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue