added ulp-pwm logic for timedlight
This commit is contained in:
parent
80828eadd7
commit
a745896643
@ -22,7 +22,8 @@
|
|||||||
"array": "cpp",
|
"array": "cpp",
|
||||||
"tuple": "cpp",
|
"tuple": "cpp",
|
||||||
"utility": "cpp",
|
"utility": "cpp",
|
||||||
"fstream": "cpp"
|
"fstream": "cpp",
|
||||||
|
"system_error": "cpp"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,9 +82,13 @@
|
|||||||
/** \addtogroup Configuration
|
/** \addtogroup Configuration
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
#define CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
|
||||||
|
#define CONFIG_COMPILER_CXX_EXCEPTIONS
|
||||||
|
|
||||||
|
|
||||||
#define FIRMWARE_VERSION "sw 2.0 hw 0.10b"
|
#define FIRMWARE_VERSION "sw 2.0 hw 0.10b"
|
||||||
|
|
||||||
#define TIMED_LIGHT_PIN CUSTOM1_PIN5
|
#define TIMED_LIGHT_PIN CUSTOM1_PIN7
|
||||||
//#define FLOWMETER_PIN CUSTOM1_PIN1
|
//#define FLOWMETER_PIN CUSTOM1_PIN1
|
||||||
#ifdef FLOWMETER_PIN
|
#ifdef FLOWMETER_PIN
|
||||||
#define FLOWMETER_FLOWFACTOR 23 /** F = 22 * Q;Q = L/min */
|
#define FLOWMETER_FLOWFACTOR 23 /** F = 22 * Q;Q = L/min */
|
||||||
|
@ -86,6 +86,7 @@ HomieSetting<const char *> ntpServer("ntpServer", "NTP server (pool.ntp.org as d
|
|||||||
HomieSetting<long> timedLightStart("LightStart", "hour to start light");
|
HomieSetting<long> timedLightStart("LightStart", "hour to start light");
|
||||||
HomieSetting<long> timedLightEnd("LightEnd", "hour to end light");
|
HomieSetting<long> timedLightEnd("LightEnd", "hour to end light");
|
||||||
HomieSetting<bool> timedLightOnlyWhenDark("LightOnlyDark", "only enable light, if solar is low");
|
HomieSetting<bool> timedLightOnlyWhenDark("LightOnlyDark", "only enable light, if solar is low");
|
||||||
|
HomieSetting<long> timedLightPowerLevel("LightPowerLevel", "0-255 power level");
|
||||||
#endif // TIMED_LIGHT_PIN
|
#endif // TIMED_LIGHT_PIN
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,3 +32,4 @@
|
|||||||
#define LOG_SLEEP_DAY 101
|
#define LOG_SLEEP_DAY 101
|
||||||
#define LOG_SLEEP_CYCLE 102
|
#define LOG_SLEEP_CYCLE 102
|
||||||
#define LOG_MISSING_PUMP -4
|
#define LOG_MISSING_PUMP -4
|
||||||
|
#define LOG_BOOT_ERROR_DETECTION 10000
|
188
esp32/include/ulp-pwm.h
Normal file
188
esp32/include/ulp-pwm.h
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
#ifndef ULP_PWM_h
|
||||||
|
#define ILP_PWM_h
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include "driver/rtc_io.h"
|
||||||
|
#include "soc/rtc_cntl_reg.h"
|
||||||
|
#include "soc/rtc.h"
|
||||||
|
#include "esp32/ulp.h"
|
||||||
|
#include "ControllerConfiguration.h"
|
||||||
|
|
||||||
|
#define LBL_START 1
|
||||||
|
#define LBL_DELAY_ON 2
|
||||||
|
#define LBL_DELAY_OFF 3
|
||||||
|
#define LBL_SKIP_ON 4
|
||||||
|
#define LBL_SKIP_OFF 5
|
||||||
|
#define REGISTER_DELAY_LOOP_COUNTER R0
|
||||||
|
#define REGISTER_TICKS_ON R1
|
||||||
|
#define REGISTER_TICKS_OFF R2
|
||||||
|
#define TOTAL_TICKS_DELAY 255
|
||||||
|
#define PIN TIMED_LIGHT_PIN
|
||||||
|
|
||||||
|
//support 20 vars
|
||||||
|
const size_t ulp_var_offset = CONFIG_ULP_COPROC_RESERVE_MEM - 20;
|
||||||
|
//use the first for dimming
|
||||||
|
const size_t ulp_dimm_offset = ulp_var_offset + 1;
|
||||||
|
const size_t ulp_alive_offset = ulp_var_offset + 2;
|
||||||
|
|
||||||
|
//see https://github.com/perseus086/ESP32-notes
|
||||||
|
const uint32_t rtc_bit[40] = {
|
||||||
|
25, //gpio0
|
||||||
|
0, //gpio1
|
||||||
|
26, //gpio2
|
||||||
|
0, //gpio3
|
||||||
|
24, //gpio4
|
||||||
|
0, //gpio5
|
||||||
|
0, //gpio6
|
||||||
|
0, //gpio7
|
||||||
|
0, //gpio8
|
||||||
|
0, //gpio9
|
||||||
|
0, //gpio10
|
||||||
|
0, //gpio11
|
||||||
|
29, //gpio12
|
||||||
|
28, //gpio13
|
||||||
|
30, //gpio14
|
||||||
|
27, //gpio15
|
||||||
|
0, //gpio16
|
||||||
|
31, //gpio17
|
||||||
|
0, //gpio18
|
||||||
|
0, //gpio19
|
||||||
|
0, //gpio20
|
||||||
|
0, //gpio21
|
||||||
|
0, //gpio22
|
||||||
|
0, //gpio23
|
||||||
|
0, //gpio24
|
||||||
|
20, //gpio25
|
||||||
|
21, //gpio26
|
||||||
|
0, //gpio27
|
||||||
|
0, //gpio28
|
||||||
|
0, //gpio29
|
||||||
|
0, //gpio30
|
||||||
|
0, //gpio31
|
||||||
|
23, //gpio32
|
||||||
|
22, //gpio33
|
||||||
|
18, //gpio34
|
||||||
|
19, //gpio35
|
||||||
|
14, //gpio36
|
||||||
|
15, //gpio37
|
||||||
|
16, //gpio38
|
||||||
|
17 //gpio39
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void ulp_internal_data_write(size_t offset, uint16_t value)
|
||||||
|
{
|
||||||
|
if (offset >= CONFIG_ULP_COPROC_RESERVE_MEM || offset <= ulp_var_offset)
|
||||||
|
{
|
||||||
|
Serial.print("Invalid ULP offset detected, refusing write!");
|
||||||
|
Serial.print(offset);
|
||||||
|
Serial.print("-");
|
||||||
|
Serial.print(ulp_var_offset);
|
||||||
|
Serial.print("-");
|
||||||
|
Serial.println(CONFIG_ULP_COPROC_RESERVE_MEM);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RTC_SLOW_MEM[offset] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint16_t ulp_internal_data_read(size_t offset)
|
||||||
|
{
|
||||||
|
if (offset >= CONFIG_ULP_COPROC_RESERVE_MEM || offset <= ulp_var_offset)
|
||||||
|
{
|
||||||
|
Serial.print("Invalid ULP offset detected");
|
||||||
|
Serial.print(offset);
|
||||||
|
Serial.print("-");
|
||||||
|
Serial.print(ulp_var_offset);
|
||||||
|
Serial.print("-");
|
||||||
|
Serial.println(CONFIG_ULP_COPROC_RESERVE_MEM);
|
||||||
|
}
|
||||||
|
return RTC_SLOW_MEM[offset] & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t rtc_io_number_get(gpio_num_t gpio_num)
|
||||||
|
{
|
||||||
|
assert(rtc_gpio_is_valid_gpio(gpio_num) && "Invalid GPIO for RTC");
|
||||||
|
uint32_t bit = rtc_bit[gpio_num];
|
||||||
|
Serial.print("Resolved GPIO ");
|
||||||
|
Serial.print(gpio_num);
|
||||||
|
Serial.print(" to rtc bit ");
|
||||||
|
Serial.println(bit);
|
||||||
|
return bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ulp_internal_start(void)
|
||||||
|
{
|
||||||
|
rtc_gpio_init(PIN);
|
||||||
|
rtc_gpio_set_direction(PIN, RTC_GPIO_MODE_OUTPUT_ONLY);
|
||||||
|
rtc_gpio_set_level(PIN, 0);
|
||||||
|
const uint32_t rtc_gpio = rtc_io_number_get(PIN);
|
||||||
|
|
||||||
|
// Define ULP program
|
||||||
|
const ulp_insn_t ulp_prog[] = {
|
||||||
|
M_LABEL(LBL_START),
|
||||||
|
|
||||||
|
I_MOVI(REGISTER_DELAY_LOOP_COUNTER, 1),
|
||||||
|
I_MOVI(REGISTER_TICKS_ON, 0),
|
||||||
|
I_ST(REGISTER_DELAY_LOOP_COUNTER, REGISTER_TICKS_ON, ulp_alive_offset), //store 1 with 0 offset into alive
|
||||||
|
|
||||||
|
I_LD(REGISTER_TICKS_ON, REGISTER_TICKS_ON, ulp_dimm_offset), //REGISTER_TICKS_ON = RTC_DATA[0+ulp_dimm_offset]
|
||||||
|
//in total there is always 255 delay loop iterations, but in different duty cycle
|
||||||
|
I_MOVI(REGISTER_TICKS_OFF, TOTAL_TICKS_DELAY),
|
||||||
|
I_SUBR(REGISTER_TICKS_OFF, REGISTER_TICKS_OFF, REGISTER_TICKS_ON),
|
||||||
|
|
||||||
|
//on phase
|
||||||
|
I_MOVR(REGISTER_DELAY_LOOP_COUNTER, REGISTER_TICKS_ON),
|
||||||
|
M_BL(LBL_SKIP_ON, 1), //if never on, skip on phase
|
||||||
|
I_WR_REG(RTC_GPIO_OUT_REG, rtc_gpio, rtc_gpio, HIGH), // on
|
||||||
|
M_LABEL(LBL_DELAY_ON),
|
||||||
|
I_DELAY(1), //wait 1 clock
|
||||||
|
I_SUBI(REGISTER_DELAY_LOOP_COUNTER, REGISTER_DELAY_LOOP_COUNTER, 1), // REGISTER_DELAY_LOOP_COUNTER--
|
||||||
|
M_BGE(LBL_DELAY_ON, 1), //if time left, goto start of on loop
|
||||||
|
M_LABEL(LBL_SKIP_ON),
|
||||||
|
|
||||||
|
//off phase
|
||||||
|
I_MOVR(REGISTER_DELAY_LOOP_COUNTER, REGISTER_TICKS_OFF),
|
||||||
|
|
||||||
|
M_BL(LBL_SKIP_OFF, 1), //if never off, skip on phase
|
||||||
|
I_WR_REG(RTC_GPIO_OUT_REG, rtc_gpio, rtc_gpio, LOW), // on
|
||||||
|
M_LABEL(3),
|
||||||
|
I_DELAY(1), //wait 1 clock
|
||||||
|
I_SUBI(REGISTER_DELAY_LOOP_COUNTER, REGISTER_DELAY_LOOP_COUNTER, 1), // REGISTER_DELAY_LOOP_COUNTER--
|
||||||
|
M_BGE(3, 1), //if time left, goto start of on loop
|
||||||
|
M_LABEL(LBL_SKIP_OFF),
|
||||||
|
|
||||||
|
M_BX(LBL_START),
|
||||||
|
};
|
||||||
|
// Run ULP program
|
||||||
|
size_t size = sizeof(ulp_prog) / sizeof(ulp_insn_t);
|
||||||
|
assert(size < ulp_var_offset && "ULP_DATA_OFFSET needs to be greater or equal to the program size");
|
||||||
|
esp_err_t error = ulp_process_macros_and_load(0, ulp_prog, &size);
|
||||||
|
Serial.print("ULP bootstrap status ");
|
||||||
|
Serial.println(error);
|
||||||
|
|
||||||
|
//allow glitchless start
|
||||||
|
ulp_internal_data_write(ulp_alive_offset, 0);
|
||||||
|
|
||||||
|
error = ulp_run(0);
|
||||||
|
Serial.print("ULP start status ");
|
||||||
|
Serial.println(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ulp_pwm_set_level(uint8_t level)
|
||||||
|
{
|
||||||
|
ulp_internal_data_write(ulp_dimm_offset, level);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ulp_pwm_init()
|
||||||
|
{
|
||||||
|
ulp_internal_data_write(ulp_alive_offset, 0);
|
||||||
|
delay(10);
|
||||||
|
if (ulp_internal_data_read(ulp_alive_offset) == 0)
|
||||||
|
{
|
||||||
|
ulp_internal_start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -35,12 +35,18 @@
|
|||||||
#include <VL53L0X.h>
|
#include <VL53L0X.h>
|
||||||
#include "driver/pcnt.h"
|
#include "driver/pcnt.h"
|
||||||
#include "MQTTUtils.h"
|
#include "MQTTUtils.h"
|
||||||
|
#include "esp_ota_ops.h"
|
||||||
|
#if defined(TIMED_LIGHT_PIN)
|
||||||
|
#include "ulp-pwm.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* DEFINES
|
* DEFINES
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
#define AMOUNT_SENOR_QUERYS 8
|
#define AMOUNT_SENOR_QUERYS 8
|
||||||
#define MAX_TANK_DEPTH 2000
|
#define MAX_TANK_DEPTH 2000
|
||||||
|
#define REBOOT_LOOP_DETECTION_ERROR 5
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* FUNCTION PROTOTYPES
|
* FUNCTION PROTOTYPES
|
||||||
@ -54,9 +60,7 @@ bool determineTimedLightState(bool lowLight);
|
|||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* NON VOLATILE VARIABLES in DEEP SLEEP
|
* NON VOLATILE VARIABLES in DEEP SLEEP
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#if defined(TIMED_LIGHT_PIN)
|
#if defined(TIMED_LIGHT_PIN)
|
||||||
RTC_DATA_ATTR bool timedLightOn = false; /**< allow fast recovery after poweron */
|
|
||||||
RTC_DATA_ATTR bool timedLightLowVoltageTriggered = false; /**remember if it was shut down due to voltage level */
|
RTC_DATA_ATTR bool timedLightLowVoltageTriggered = false; /**remember if it was shut down due to voltage level */
|
||||||
#endif // TIMED_LIGHT_PIN
|
#endif // TIMED_LIGHT_PIN
|
||||||
|
|
||||||
@ -104,11 +108,29 @@ Plant mPlants[MAX_PLANTS] = {
|
|||||||
* LOCAL FUNCTIONS
|
* LOCAL FUNCTIONS
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
|
void finsihedCycleSucessfully()
|
||||||
|
{
|
||||||
|
const esp_partition_t *running = esp_ota_get_running_partition();
|
||||||
|
esp_ota_img_states_t ota_state;
|
||||||
|
if (esp_ota_get_state_partition(running, &ota_state) == ESP_OK)
|
||||||
|
{
|
||||||
|
log(LOG_LEVEL_INFO, "Get State Partition was Successfull", LOG_BOOT_ERROR_DETECTION);
|
||||||
|
if (ota_state == ESP_OTA_IMG_PENDING_VERIFY)
|
||||||
|
{
|
||||||
|
log(LOG_LEVEL_INFO, "Diagnostics completed successfully! Marking as valid", LOG_BOOT_ERROR_DETECTION);
|
||||||
|
esp_ota_mark_app_valid_cancel_rollback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void espDeepSleep(bool afterPump = false)
|
void espDeepSleep(bool afterPump = false)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (mDownloadMode)
|
if (mDownloadMode)
|
||||||
{
|
{
|
||||||
log(LOG_LEVEL_DEBUG, "abort deepsleep, DownloadMode active", LOG_DEBUG_CODE);
|
log(LOG_LEVEL_DEBUG, "abort deepsleep, DownloadMode active", LOG_DEBUG_CODE);
|
||||||
|
//if we manage to get to the download mode, the device can be restored
|
||||||
|
finsihedCycleSucessfully();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (aliveWasRead())
|
if (aliveWasRead())
|
||||||
@ -139,10 +161,6 @@ void espDeepSleep(bool afterPump = false)
|
|||||||
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_FAST_MEM, ESP_PD_OPTION_ON);
|
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_FAST_MEM, ESP_PD_OPTION_ON);
|
||||||
esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON);
|
esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON);
|
||||||
|
|
||||||
#if defined(TIMED_LIGHT_PIN)
|
|
||||||
gpio_hold_en(TIMED_LIGHT_PIN);
|
|
||||||
#endif // TIMED_LIGHT_PIN
|
|
||||||
|
|
||||||
long secondsToSleep = -1;
|
long secondsToSleep = -1;
|
||||||
|
|
||||||
if (afterPump)
|
if (afterPump)
|
||||||
@ -165,6 +183,7 @@ void espDeepSleep(bool afterPump = false)
|
|||||||
}
|
}
|
||||||
|
|
||||||
esp_sleep_enable_timer_wakeup((secondsToSleep * 1000U * 1000U));
|
esp_sleep_enable_timer_wakeup((secondsToSleep * 1000U * 1000U));
|
||||||
|
finsihedCycleSucessfully();
|
||||||
if (aliveWasRead())
|
if (aliveWasRead())
|
||||||
{
|
{
|
||||||
delay(1000);
|
delay(1000);
|
||||||
@ -639,22 +658,19 @@ void pumpActiveLoop()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void safeSetup()
|
void setup()
|
||||||
{
|
{
|
||||||
/* reduce power consumption */
|
|
||||||
setCpuFrequencyMhz(80);
|
setCpuFrequencyMhz(80);
|
||||||
|
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
|
|
||||||
Serial << "Wifi mode set to " << WIFI_OFF << " to allow analog2 useage " << endl;
|
Serial << "Wifi mode set to " << WIFI_OFF << " to allow analog2 useage " << endl;
|
||||||
WiFi.mode(WIFI_OFF);
|
WiFi.mode(WIFI_OFF);
|
||||||
|
|
||||||
Serial.flush();
|
Serial.flush();
|
||||||
|
|
||||||
//restore state before releasing pin, to prevent flickering
|
//restore state before releasing pin, to prevent flickering
|
||||||
#if defined(TIMED_LIGHT_PIN)
|
#if defined(TIMED_LIGHT_PIN)
|
||||||
pinMode(TIMED_LIGHT_PIN, OUTPUT);
|
ulp_pwm_init();
|
||||||
digitalWrite(TIMED_LIGHT_PIN, timedLightOn);
|
|
||||||
gpio_hold_dis(TIMED_LIGHT_PIN);
|
|
||||||
#endif // TIMED_LIGHT_PIN
|
#endif // TIMED_LIGHT_PIN
|
||||||
|
|
||||||
/* Intialize Plant */
|
/* Intialize Plant */
|
||||||
@ -733,6 +749,8 @@ void safeSetup()
|
|||||||
{ return (candidate > 0) && (candidate < (20)); });
|
{ return (candidate > 0) && (candidate < (20)); });
|
||||||
|
|
||||||
#if defined(TIMED_LIGHT_PIN)
|
#if defined(TIMED_LIGHT_PIN)
|
||||||
|
timedLightPowerLevel.setDefaultValue(25).setValidator([](long candidate)
|
||||||
|
{ return (candidate > 0) && (candidate <= (255)); });
|
||||||
timedLightStart.setDefaultValue(18).setValidator([](long candidate)
|
timedLightStart.setDefaultValue(18).setValidator([](long candidate)
|
||||||
{ return (candidate > 0) && (candidate < (25)); });
|
{ return (candidate > 0) && (candidate < (25)); });
|
||||||
timedLightEnd.setDefaultValue(23).setValidator([](long candidate)
|
timedLightEnd.setDefaultValue(23).setValidator([](long candidate)
|
||||||
@ -825,26 +843,6 @@ void safeSetup()
|
|||||||
setupFinishedTimestamp = millis();
|
setupFinishedTimestamp = millis();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Startup function
|
|
||||||
* Is called once, the controller is started
|
|
||||||
*/
|
|
||||||
void setup()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
safeSetup();
|
|
||||||
}
|
|
||||||
catch (const std::exception &e)
|
|
||||||
{
|
|
||||||
Serial.printf("Exception thrown: \"%s\"", e.what());
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
Serial.println("Other exception thrown.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void selfTest()
|
void selfTest()
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -974,8 +972,18 @@ void plantcontrol()
|
|||||||
Serial.println("Skipping MQTT, offline mode");
|
Serial.println("Skipping MQTT, offline mode");
|
||||||
Serial.flush();
|
Serial.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isLowLight = (mSolarVoltage < SOLAR_CHARGE_MIN_VOLTAGE);
|
bool isLowLight = (mSolarVoltage < SOLAR_CHARGE_MIN_VOLTAGE);
|
||||||
|
|
||||||
|
#if defined(TIMED_LIGHT_PIN)
|
||||||
|
bool shouldLight = determineTimedLightState(isLowLight);
|
||||||
|
if(shouldLight){
|
||||||
|
ulp_pwm_set_level(timedLightPowerLevel.get());
|
||||||
|
}else {
|
||||||
|
ulp_pwm_set_level(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // TIMED_LIGHT_PIN
|
||||||
|
|
||||||
bool hasWater = true; //FIXME remaining > waterLevelMin.get();
|
bool hasWater = true; //FIXME remaining > waterLevelMin.get();
|
||||||
//FIXME no water warning message
|
//FIXME no water warning message
|
||||||
pumpToRun = determineNextPump(isLowLight);
|
pumpToRun = determineNextPump(isLowLight);
|
||||||
@ -1002,12 +1010,6 @@ void plantcontrol()
|
|||||||
{
|
{
|
||||||
espDeepSleep();
|
espDeepSleep();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(TIMED_LIGHT_PIN)
|
|
||||||
bool shouldLight = determineTimedLightState(isLowLight);
|
|
||||||
timedLightOn = shouldLight;
|
|
||||||
digitalWrite(TIMED_LIGHT_PIN, shouldLight);
|
|
||||||
#endif // TIMED_LIGHT_PIN
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @}*/
|
/** @}*/
|
||||||
@ -1032,11 +1034,14 @@ bool determineTimedLightState(bool lowLight)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((hoursStart > hoursEnd) &&
|
int curHour = getCurrentHour();
|
||||||
(getCurrentHour() >= hoursStart || getCurrentHour() <= hoursEnd)) ||
|
bool condition1 = ((hoursStart > hoursEnd) &&
|
||||||
/* Handle e.g. start = 8, end = 21 */
|
(curHour >= hoursStart || curHour <= hoursEnd));
|
||||||
|
bool condition2 = /* Handle e.g. start = 8, end = 21 */
|
||||||
((hoursStart < hoursEnd) &&
|
((hoursStart < hoursEnd) &&
|
||||||
(getCurrentHour() >= hoursStart && getCurrentHour() <= hoursEnd)))
|
(curHour >= hoursStart && curHour <= hoursEnd));
|
||||||
|
timedLightNode.setProperty("debug").send(String(curHour) + " " + String(hoursStart) + " " + String(hoursEnd) + " " + String(condition1) + " " + String(condition2));
|
||||||
|
if (condition1 || condition2)
|
||||||
{
|
{
|
||||||
bool voltageOk = !timedLightLowVoltageTriggered && battery.getVoltage(BATTSENSOR_INDEX_BATTERY) >= timedLightVoltageCutoff.get();
|
bool voltageOk = !timedLightLowVoltageTriggered && battery.getVoltage(BATTSENSOR_INDEX_BATTERY) >= timedLightVoltageCutoff.get();
|
||||||
if (voltageOk || equalish(timedLightVoltageCutoff.get(), -1))
|
if (voltageOk || equalish(timedLightVoltageCutoff.get(), -1))
|
||||||
|
@ -1,112 +0,0 @@
|
|||||||
/*
|
|
||||||
* DS2438.h
|
|
||||||
*
|
|
||||||
* by Joe Bechter
|
|
||||||
*
|
|
||||||
* (C) 2012, bechter.com
|
|
||||||
*
|
|
||||||
* All files, software, schematics and designs are provided as-is with no warranty.
|
|
||||||
* All files, software, schematics and designs are for experimental/hobby use.
|
|
||||||
* Under no circumstances should any part be used for critical systems where safety,
|
|
||||||
* life or property depends upon it. You are responsible for all use.
|
|
||||||
* You are free to use, modify, derive or otherwise extend for your own non-commercial purposes provided
|
|
||||||
* 1. No part of this software or design may be used to cause injury or death to humans or animals.
|
|
||||||
* 2. Use is non-commercial.
|
|
||||||
* 3. Credit is given to the author (i.e. portions © bechter.com), and provide a link to the original source.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef DS2438_h
|
|
||||||
#define DS2438_h
|
|
||||||
|
|
||||||
#include <Arduino.h>
|
|
||||||
#include <OneWire.h>
|
|
||||||
|
|
||||||
#define DS2438_TEMPERATURE_CONVERSION_COMMAND 0x44
|
|
||||||
#define DS2438_VOLTAGE_CONVERSION_COMMAND 0xb4
|
|
||||||
#define DS2438_WRITE_SCRATCHPAD_COMMAND 0x4e
|
|
||||||
#define DS2438_COPY_SCRATCHPAD_COMMAND 0x48
|
|
||||||
#define DS2438_READ_SCRATCHPAD_COMMAND 0xbe
|
|
||||||
#define DS2438_RECALL_MEMORY_COMMAND 0xb8
|
|
||||||
|
|
||||||
#define PAGE_MIN 0
|
|
||||||
#define PAGE_MAX 7
|
|
||||||
|
|
||||||
#define DS2438_CHA 0
|
|
||||||
#define DS2438_CHB 1
|
|
||||||
|
|
||||||
#define DS2438_MODE_CHA 0x01
|
|
||||||
#define DS2438_MODE_CHB 0x02
|
|
||||||
#define DS2438_MODE_TEMPERATURE 0x04
|
|
||||||
|
|
||||||
#define DS2438_TEMPERATURE_DELAY 10
|
|
||||||
#define DS2438_VOLTAGE_CONVERSION_DELAY 8
|
|
||||||
|
|
||||||
#define DEFAULT_PAGE0(var) uint8_t var[8] { \
|
|
||||||
0b00001011 /* X, ADB=0, NVB=0, TB=0, AD=1, EE=0, CA=1, IAD=1 */, \
|
|
||||||
0, /* Temperatur */ \
|
|
||||||
0, /* Temperatur */ \
|
|
||||||
0, /* Voltage */ \
|
|
||||||
0, /* Voltage */ \
|
|
||||||
0, /* Current */ \
|
|
||||||
0, /* Current */ \
|
|
||||||
0 /* Threashold */ \
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct PageOne {
|
|
||||||
uint8_t eleapsedTimerByte0; /**< LSB of timestamp */
|
|
||||||
uint8_t eleapsedTimerByte1;
|
|
||||||
uint8_t eleapsedTimerByte2;
|
|
||||||
uint8_t eleapsedTimerByte3; /**< MSB of timestamp */
|
|
||||||
uint8_t ICA; /**< Integrated Current Accumulator (current flowing into and out of the battery) */
|
|
||||||
uint8_t offsetRegisterByte0; /**< Offset for ADC calibdation */
|
|
||||||
uint8_t offsetRegisterByte1; /**< Offset for ADC calibdation */
|
|
||||||
uint8_t reserved;
|
|
||||||
} PageOne_t;
|
|
||||||
|
|
||||||
typedef struct PageSeven {
|
|
||||||
uint8_t userByte0;
|
|
||||||
uint8_t userByte1;
|
|
||||||
uint8_t userByte2;
|
|
||||||
uint8_t userByte3;
|
|
||||||
uint8_t CCA0; /**< Charging Current Accumulator (CCA) */
|
|
||||||
uint8_t CCA1; /**< Charging Current Accumulator (CCA) */
|
|
||||||
uint8_t DCA0; /**< Discharge Current Accumulator (DCA) */
|
|
||||||
uint8_t DCA1; /**< Discharge Current Accumulator (DCA) */
|
|
||||||
} PageSeven_t;
|
|
||||||
|
|
||||||
typedef uint8_t DeviceAddress[8];
|
|
||||||
|
|
||||||
class DS2438 {
|
|
||||||
public:
|
|
||||||
DS2438(OneWire *ow, float currentShunt);
|
|
||||||
DS2438(OneWire *ow, uint8_t *address);
|
|
||||||
|
|
||||||
void begin();
|
|
||||||
void update();
|
|
||||||
double getTemperature();
|
|
||||||
float getVoltage(int channel=DS2438_CHA);
|
|
||||||
float getCurrent();
|
|
||||||
boolean isError();
|
|
||||||
boolean isFound();
|
|
||||||
private:
|
|
||||||
bool validAddress(const uint8_t*);
|
|
||||||
bool validFamily(const uint8_t* deviceAddress);
|
|
||||||
|
|
||||||
bool deviceFound = false;
|
|
||||||
OneWire *_ow;
|
|
||||||
DeviceAddress _address;
|
|
||||||
uint8_t _mode;
|
|
||||||
double _temperature;
|
|
||||||
float _voltageA;
|
|
||||||
float _voltageB;
|
|
||||||
float _current;
|
|
||||||
float _currentShunt;
|
|
||||||
boolean _error;
|
|
||||||
boolean startConversion(int channel, boolean doTemperature);
|
|
||||||
boolean selectChannel(int channel);
|
|
||||||
void writePage(int page, uint8_t *data);
|
|
||||||
boolean readPage(int page, uint8_t *data);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
187
esp32test/Esp32DeepSleepTest/include/ulp-pwm.h
Normal file
187
esp32test/Esp32DeepSleepTest/include/ulp-pwm.h
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
#ifndef ULP_PWM_h
|
||||||
|
#define ILP_PWM_h
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include "driver/rtc_io.h"
|
||||||
|
#include "soc/rtc_cntl_reg.h"
|
||||||
|
#include "soc/rtc.h"
|
||||||
|
#include "esp32/ulp.h"
|
||||||
|
|
||||||
|
#define LBL_START 1
|
||||||
|
#define LBL_DELAY_ON 2
|
||||||
|
#define LBL_DELAY_OFF 3
|
||||||
|
#define LBL_SKIP_ON 4
|
||||||
|
#define LBL_SKIP_OFF 5
|
||||||
|
#define REGISTER_DELAY_LOOP_COUNTER R0
|
||||||
|
#define REGISTER_TICKS_ON R1
|
||||||
|
#define REGISTER_TICKS_OFF R2
|
||||||
|
#define TOTAL_TICKS_DELAY 255
|
||||||
|
#define PIN GPIO_NUM_12
|
||||||
|
|
||||||
|
//support 20 vars
|
||||||
|
const size_t ulp_var_offset = CONFIG_ULP_COPROC_RESERVE_MEM - 20;
|
||||||
|
//use the first for dimming
|
||||||
|
const size_t ulp_dimm_offset = ulp_var_offset + 1;
|
||||||
|
const size_t ulp_alive_offset = ulp_var_offset + 2;
|
||||||
|
|
||||||
|
//see https://github.com/perseus086/ESP32-notes
|
||||||
|
const uint32_t rtc_bit[40] = {
|
||||||
|
25, //gpio0
|
||||||
|
0, //gpio1
|
||||||
|
26, //gpio2
|
||||||
|
0, //gpio3
|
||||||
|
24, //gpio4
|
||||||
|
0, //gpio5
|
||||||
|
0, //gpio6
|
||||||
|
0, //gpio7
|
||||||
|
0, //gpio8
|
||||||
|
0, //gpio9
|
||||||
|
0, //gpio10
|
||||||
|
0, //gpio11
|
||||||
|
29, //gpio12
|
||||||
|
28, //gpio13
|
||||||
|
30, //gpio14
|
||||||
|
27, //gpio15
|
||||||
|
0, //gpio16
|
||||||
|
31, //gpio17
|
||||||
|
0, //gpio18
|
||||||
|
0, //gpio19
|
||||||
|
0, //gpio20
|
||||||
|
0, //gpio21
|
||||||
|
0, //gpio22
|
||||||
|
0, //gpio23
|
||||||
|
0, //gpio24
|
||||||
|
20, //gpio25
|
||||||
|
21, //gpio26
|
||||||
|
0, //gpio27
|
||||||
|
0, //gpio28
|
||||||
|
0, //gpio29
|
||||||
|
0, //gpio30
|
||||||
|
0, //gpio31
|
||||||
|
23, //gpio32
|
||||||
|
22, //gpio33
|
||||||
|
18, //gpio34
|
||||||
|
19, //gpio35
|
||||||
|
14, //gpio36
|
||||||
|
15, //gpio37
|
||||||
|
16, //gpio38
|
||||||
|
17 //gpio39
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void ulp_data_write(size_t offset, uint16_t value)
|
||||||
|
{
|
||||||
|
if (offset >= CONFIG_ULP_COPROC_RESERVE_MEM || offset <= ulp_var_offset)
|
||||||
|
{
|
||||||
|
Serial.print("Invalid ULP offset detected, refusing write!");
|
||||||
|
Serial.print(offset);
|
||||||
|
Serial.print("-");
|
||||||
|
Serial.print(ulp_var_offset);
|
||||||
|
Serial.print("-");
|
||||||
|
Serial.println(CONFIG_ULP_COPROC_RESERVE_MEM);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RTC_SLOW_MEM[offset] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint16_t ulp_data_read(size_t offset)
|
||||||
|
{
|
||||||
|
if (offset >= CONFIG_ULP_COPROC_RESERVE_MEM || offset <= ulp_var_offset)
|
||||||
|
{
|
||||||
|
Serial.print("Invalid ULP offset detected");
|
||||||
|
Serial.print(offset);
|
||||||
|
Serial.print("-");
|
||||||
|
Serial.print(ulp_var_offset);
|
||||||
|
Serial.print("-");
|
||||||
|
Serial.println(CONFIG_ULP_COPROC_RESERVE_MEM);
|
||||||
|
}
|
||||||
|
return RTC_SLOW_MEM[offset] & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t rtc_io_number_get(gpio_num_t gpio_num)
|
||||||
|
{
|
||||||
|
assert(rtc_gpio_is_valid_gpio(gpio_num) && "Invalid GPIO for RTC");
|
||||||
|
uint32_t bit = rtc_bit[gpio_num];
|
||||||
|
Serial.print("Resolved GPIO ");
|
||||||
|
Serial.print(gpio_num);
|
||||||
|
Serial.print(" to rtc bit ");
|
||||||
|
Serial.println(bit);
|
||||||
|
return bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ulp_pwm_start(void)
|
||||||
|
{
|
||||||
|
rtc_gpio_init(PIN);
|
||||||
|
rtc_gpio_set_direction(PIN, RTC_GPIO_MODE_OUTPUT_ONLY);
|
||||||
|
rtc_gpio_set_level(PIN, 0);
|
||||||
|
const uint32_t rtc_gpio = rtc_io_number_get(PIN);
|
||||||
|
|
||||||
|
// Define ULP program
|
||||||
|
const ulp_insn_t ulp_prog[] = {
|
||||||
|
M_LABEL(LBL_START),
|
||||||
|
|
||||||
|
I_MOVI(REGISTER_DELAY_LOOP_COUNTER, 1),
|
||||||
|
I_MOVI(REGISTER_TICKS_ON, 0),
|
||||||
|
I_ST(REGISTER_DELAY_LOOP_COUNTER, REGISTER_TICKS_ON, ulp_alive_offset), //store 1 with 0 offset into alive
|
||||||
|
|
||||||
|
I_LD(REGISTER_TICKS_ON, REGISTER_TICKS_ON, ulp_dimm_offset), //REGISTER_TICKS_ON = RTC_DATA[0+ulp_dimm_offset]
|
||||||
|
//in total there is always 255 delay loop iterations, but in different duty cycle
|
||||||
|
I_MOVI(REGISTER_TICKS_OFF, TOTAL_TICKS_DELAY),
|
||||||
|
I_SUBR(REGISTER_TICKS_OFF, REGISTER_TICKS_OFF, REGISTER_TICKS_ON),
|
||||||
|
|
||||||
|
//on phase
|
||||||
|
I_MOVR(REGISTER_DELAY_LOOP_COUNTER, REGISTER_TICKS_ON),
|
||||||
|
M_BL(LBL_SKIP_ON, 1), //if never on, skip on phase
|
||||||
|
I_WR_REG(RTC_GPIO_OUT_REG, rtc_gpio, rtc_gpio, HIGH), // on
|
||||||
|
M_LABEL(LBL_DELAY_ON),
|
||||||
|
I_DELAY(1), //wait 1 clock
|
||||||
|
I_SUBI(REGISTER_DELAY_LOOP_COUNTER, REGISTER_DELAY_LOOP_COUNTER, 1), // REGISTER_DELAY_LOOP_COUNTER--
|
||||||
|
M_BGE(LBL_DELAY_ON, 1), //if time left, goto start of on loop
|
||||||
|
M_LABEL(LBL_SKIP_ON),
|
||||||
|
|
||||||
|
//off phase
|
||||||
|
I_MOVR(REGISTER_DELAY_LOOP_COUNTER, REGISTER_TICKS_OFF),
|
||||||
|
|
||||||
|
M_BL(LBL_SKIP_OFF, 1), //if never off, skip on phase
|
||||||
|
I_WR_REG(RTC_GPIO_OUT_REG, rtc_gpio, rtc_gpio, LOW), // on
|
||||||
|
M_LABEL(3),
|
||||||
|
I_DELAY(1), //wait 1 clock
|
||||||
|
I_SUBI(REGISTER_DELAY_LOOP_COUNTER, REGISTER_DELAY_LOOP_COUNTER, 1), // REGISTER_DELAY_LOOP_COUNTER--
|
||||||
|
M_BGE(3, 1), //if time left, goto start of on loop
|
||||||
|
M_LABEL(LBL_SKIP_OFF),
|
||||||
|
|
||||||
|
M_BX(LBL_START),
|
||||||
|
};
|
||||||
|
// Run ULP program
|
||||||
|
size_t size = sizeof(ulp_prog) / sizeof(ulp_insn_t);
|
||||||
|
assert(size < ulp_var_offset && "ULP_DATA_OFFSET needs to be greater or equal to the program size");
|
||||||
|
esp_err_t error = ulp_process_macros_and_load(0, ulp_prog, &size);
|
||||||
|
Serial.print("ULP bootstrap status ");
|
||||||
|
Serial.println(error);
|
||||||
|
|
||||||
|
//allow glitchless start
|
||||||
|
ulp_data_write(ulp_alive_offset, 0);
|
||||||
|
|
||||||
|
error = ulp_run(0);
|
||||||
|
Serial.print("ULP start status ");
|
||||||
|
Serial.println(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ulp_pwm_set_level(uint8_t level)
|
||||||
|
{
|
||||||
|
ulp_data_write(ulp_dimm_offset, level);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ulp_pwm_init()
|
||||||
|
{
|
||||||
|
ulp_data_write(ulp_alive_offset, 0);
|
||||||
|
delay(10);
|
||||||
|
if (ulp_data_read(ulp_alive_offset) == 0)
|
||||||
|
{
|
||||||
|
ulp_pwm_start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -1,90 +1,30 @@
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "driver/pcnt.h"
|
#include "driver/pcnt.h"
|
||||||
#include "driver/rtc_io.h"
|
#include "ulp-pwm.h"
|
||||||
#include "esp32/ulp.h"
|
|
||||||
#include "soc/rtc_cntl_reg.h"
|
|
||||||
#include "soc/rtc.h"
|
|
||||||
|
|
||||||
#define ULP_DATA_OFFSET 200
|
RTC_SLOW_ATTR uint8_t tick = 0;
|
||||||
|
RTC_SLOW_ATTR bool dir = true;
|
||||||
#define ULP_START_OFFSET 0
|
void setup()
|
||||||
void ulp_start(void) {
|
|
||||||
// Slow memory initialization
|
|
||||||
//memset(RTC_SLOW_MEM, ULP_START_OFFSET, (8192-ULP_START_OFFSET));
|
|
||||||
// GPIO32 initialization (set to output and initial value is 0)
|
|
||||||
rtc_gpio_init(GPIO_NUM_12);
|
|
||||||
rtc_gpio_set_direction(GPIO_NUM_12, RTC_GPIO_MODE_OUTPUT_ONLY);
|
|
||||||
rtc_gpio_set_level(GPIO_NUM_12, 0);
|
|
||||||
// Define ULP program
|
|
||||||
const ulp_insn_t ulp_prog[] = {
|
|
||||||
M_LABEL(1),
|
|
||||||
|
|
||||||
I_MOVI(R2, 0),
|
|
||||||
I_MOVI(R3, 0),
|
|
||||||
I_LD(R2, R2, ULP_DATA_OFFSET),
|
|
||||||
I_LD(R3, R3, ULP_DATA_OFFSET+1),
|
|
||||||
|
|
||||||
|
|
||||||
I_WR_REG(RTC_GPIO_OUT_REG, 29, 29, 1), // on
|
|
||||||
|
|
||||||
//wait for 100*r2
|
|
||||||
I_MOVR(R0,R2),
|
|
||||||
M_LABEL(2),
|
|
||||||
I_DELAY(1),
|
|
||||||
I_SUBI(R0,R0,1),
|
|
||||||
M_BGE(2,1),
|
|
||||||
|
|
||||||
I_WR_REG(RTC_GPIO_OUT_REG, 29, 29, 0), // off
|
|
||||||
|
|
||||||
//wait for 100*R3
|
|
||||||
I_MOVR(R0,R3),
|
|
||||||
M_LABEL(3),
|
|
||||||
I_DELAY(1),
|
|
||||||
I_SUBI(R0,R0,1),
|
|
||||||
M_BGE(3,1),
|
|
||||||
|
|
||||||
M_BX(1),
|
|
||||||
};
|
|
||||||
// Run ULP program
|
|
||||||
size_t size = sizeof(ulp_prog) / sizeof(ulp_insn_t);
|
|
||||||
ulp_process_macros_and_load(ULP_START_OFFSET, ulp_prog, &size);
|
|
||||||
assert(size < ULP_DATA_OFFSET && "ULP_DATA_OFFSET needs to be greater or equal to the program size");
|
|
||||||
ulp_run(ULP_START_OFFSET);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void ulp_data_write(size_t offset, uint16_t value)
|
|
||||||
{
|
{
|
||||||
RTC_SLOW_MEM[ULP_DATA_OFFSET + offset] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint16_t ulp_data_read(size_t offset)
|
|
||||||
{
|
|
||||||
return RTC_SLOW_MEM[ULP_DATA_OFFSET + offset] & 0xffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setup() {
|
|
||||||
|
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
ulp_data_write(0,1000);
|
Serial.println(rtc_io_number_get(GPIO_NUM_12));
|
||||||
ulp_data_write(1,1000);
|
ulp_pwm_init();
|
||||||
ulp_start();
|
|
||||||
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
|
|
||||||
//esp_deep_sleep_start();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (dir) {
|
||||||
|
tick += 10;
|
||||||
|
} else {
|
||||||
|
tick -= 10;
|
||||||
|
}
|
||||||
|
ulp_pwm_set_level(tick);
|
||||||
|
if (tick == 250 || tick == 0) {
|
||||||
|
dir = !dir;
|
||||||
|
}
|
||||||
|
esp_sleep_enable_timer_wakeup(1000000);
|
||||||
|
Serial.println(ulp_data_read(ulp_dimm_offset));
|
||||||
|
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
|
||||||
|
esp_deep_sleep_start();
|
||||||
|
}
|
||||||
|
|
||||||
void loop(){
|
void loop(){
|
||||||
delay(1000);
|
|
||||||
Serial.println(ulp_data_read(0));
|
|
||||||
ulp_data_write(0, 50);
|
|
||||||
ulp_data_write(1, 150);
|
|
||||||
//test = 10;
|
|
||||||
//test2 = 255-test;
|
|
||||||
delay(1000);
|
|
||||||
//test = 50;
|
|
||||||
//test2 = 255 - test;
|
|
||||||
ulp_data_write(0, 150);
|
|
||||||
ulp_data_write(1, 50);
|
|
||||||
//Serial.print();
|
|
||||||
Serial.println("loop");
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user