boothifier/z_old/my_board.cpp

250 lines
6.6 KiB
C++

#include "my_board.h"
#include <ArduinoJson.h>
#include <FS.h>
#include <LittleFS.h>
#include "global.h"
#include "JsonConstrain.h"
static const char* tag = "board";
PWM_Output *pwmOut[4];
RAMP_Output *RearLightControl;
void Init_Board_Pins(void)
{
pinMode(BoardLED1, OUTPUT);
pinMode(BoardLED2, OUTPUT);
pinMode(Button1_Pin, INPUT_PULLUP);
pinMode(Button2_Pin, INPUT_PULLUP);
pinMode(Button3_Pin, INPUT_PULLUP);
ESP_LOGV(tag, "Board pins initialized...");
}
void Init_PWM_Outputs(void)
{
File file = LittleFS.open("/cfg/relays.json");
if(!file){
ESP_LOGE(tag, "Error opening relays.json...");
}else{
StaticJsonDocument<1024> doc;
DeserializationError error = deserializeJson(doc, file);
if(!error){
file.close();
if(error){ ESP_LOGE(tag, "relays.json deserialize error!.."); return;}
JsonArray jsArray = doc["relays"];
if(jsArray.isNull() || jsArray.size() < 1 || jsArray.size() > 4 ) { return; }
int x = 0;
for(JsonObject obj : jsArray){
//Default config if keys are not found
if (!obj.containsKey("pin") || !obj.containsKey("freq") || !obj.containsKey("max") || !obj.containsKey("default")) {
pwmOut[x] = new PWM_Output(0, x, 12, 500, 100.0, false);
ESP_LOGD(tag, "pwmOut[%d] default config", x);
x++;
continue;
}
int pin;
switch(x){
case 0:
pin = jsonConstrainInt(obj, "pin", 0, 48, RELAY1_Pin);
break;
case 1:
pin = jsonConstrainInt(obj, "pin", 0, 48, RELAY2_Pin);
break;
case 2:
pin = jsonConstrainInt(obj, "pin", 0, 48, RELAY3_Pin);
break;
default:
pin = jsonConstrainInt(obj, "pin", 0, 48, RELAY4_Pin);
}
int freq = jsonConstrainInt(obj, "freq", 100, 2000, 500);
float maxVal = jsonConstrainInt(obj, "max", 2.0, 100.0, 95);
float defaultVal = jsonConstrainInt(obj, "default", 0.0, 100.0, 40);
ESP_LOGD(tag, "pwmOut[%d]: freq:%d, max:%F, default:%F", x, freq, maxVal, defaultVal);
pwmOut[x] = new PWM_Output(pin, x, RELAY_RES, freq, maxVal, false);
pwmOut[x]->setOutput(defaultVal);
x++;
}
}else{
ESP_LOGE(tag, "Deserialization error on relays.json");
}
}
}
int linearizeLED(float inp){
if(inp > 100.0){ inp = 100.0;};
return (inp*inp*0.4095f);
}
/******************* PWM_Output Definition ********************/
// max: 0-100%
PWM_Output::PWM_Output(uint8_t pin, uint8_t ch, int res, uint32_t freq, float maxDuty, bool visionCorrected)
{
this->currDuty = 0;
this->ch = ch;
this->maxDuty = maxDuty;
this->visionCorrected = visionCorrected;
this->freq = freq;
this->res = res;
//this->msecRampRate = msecRampRate;
pinMode(pin, OUTPUT);
if(!ledcSetup(ch, freq, res)) {
ESP_LOGE(tag, "pwmOut-> ch:%d ledcSetup failed!", ch);
return;
}
ledcAttachPin(pin, ch);
setOutput(this->currDuty);
}
// Range is 0 to 100%
void PWM_Output::setOutput(float duty)
{
if(duty > maxDuty) { duty = maxDuty;}
// calculate correct duty value
int outDutyVal;
if(this->visionCorrected){ outDutyVal = linearizeLED(duty); }
else{ outDutyVal = duty * 40.95f; }
// FIXME pwm output ramp cause a freeze here
// Smooth Transition to final duty value
/*
if(msecRampRate){
int d = this->currOutVal;
float dutyInc = (outDutyVal - this->currOutVal)/msecRampRate;
for(;;){
d += dutyInc;
if(d < 0){d = 0;}
if(d > 4095){d = 4095;}
ledcWrite(this->ch, d);
if(d >= outDutyVal || d <= 0){ break; }
vTaskDelay(msecRampRate);
}
ledcWrite(this->ch, outDutyVal);
this->currOutVal = outDutyVal;
}
else{
*/
ledcWrite(this->ch, outDutyVal);
this->currOutVal = outDutyVal;
//}
this->currDuty = duty;
}
void PWM_Output::setFreq(uint32_t fq)
{
uint32_t newFreq;
if(this->freq != fq){
newFreq = ledcChangeFrequency(this->ch, fq, this->res);
if(newFreq){
this->freq = fq;
}
}
}
/******************* RAMP_Output Definition ********************/
void Initialize_Rear_Control(int relayIndex, int buttonIndex, int rampTime, int steps, float min, float max){
RearLightControl = new RAMP_Output(pwmOut[relayIndex], btn[buttonIndex], rampTime, steps, min, max);
}
RAMP_Output *RAMP_Output::instance = nullptr; // Initialize the static member variable
void longPressStartCallback(void){
xTimerStart(RearLightControl->timerHandle, 0);
}
void longPressStopCallback(void){
xTimerStop(RearLightControl->timerHandle, 0);
RAMP_Output::instance->SwitchDirection(); // Call the non-static member function using the stored instance
}
void SingleClickCallback(void){
RAMP_Output::instance->ClickOnOff();
}
void RAMP_Output::TimerCallback(TimerHandle_t xTimer) {
RearLightControl->IncrementTick();
}
RAMP_Output::RAMP_Output(PWM_Output *output, OneButton *button, int rampTime, int steps, float min, float max) {
this->Output = output;
this->Button = button;
this->rampTime = rampTime;
this->steps = steps;
this->min = min;
this->max = max;
this->stepSize = (max - min) / steps;
ESP_LOGD(tag, "Rear Lights: stepSize= %.2f", stepSize);
instance = this; // Store the instance in the static member variable
if (this->Button) {
this->Button->attachLongPressStart(longPressStartCallback);
this->Button->attachLongPressStop(longPressStopCallback);
this->Button->attachClick(SingleClickCallback);
} else {
Serial.println("Error: Button is nullptr");
}
Output->visionCorrected = true;
Output->currDuty = min;
Output->setOutput(min);
timerHandle = xTimerCreate("RampTimer", pdMS_TO_TICKS(rampTime/8), pdTRUE, this, TimerCallback);
}
void RAMP_Output::ClickOnOff(void) {
if(IsOn){
IsOn = false;
Output->setOutput(0);
}else{
IsOn = true;
Output->setOutput(lastDuty);
}
}
void RAMP_Output::IncrementTick(void) {
if (dirFwd) {
// Increment output value while ensuring it doesn't exceed max
float newValue = std::min(Output->currDuty + stepSize, max);
Output->setOutput( newValue);
lastDuty = newValue;
//ESP_LOGD(tag, "up: %.2f", newValue);
} else {
// Decrement output value while ensuring it doesn't go below min
float newValue = std::max(Output->currDuty - stepSize, min);
Output->setOutput( newValue );
lastDuty = newValue;
//ESP_LOGD(tag, "down: %.2f", newValue);
}
}
void RAMP_Output::SwitchDirection(void) {
dirFwd = !dirFwd;
}
// Add destructor to clean up resources
RAMP_Output::~RAMP_Output() {
xTimerDelete(timerHandle, 0);
// Add any other necessary cleanup here
}