12 Commits

12 changed files with 277 additions and 216 deletions
Binary file not shown.
+83 -69
View File
@@ -11,6 +11,8 @@
RadoMmm for suggesting an improvement on the ADC-to-Volts conversion RadoMmm for suggesting an improvement on the ADC-to-Volts conversion
*/ */
#define DEBUGLOG_DEFAULT_LOG_LEVEL_DEBUG
#include "Arduino.h" #include "Arduino.h"
#include "ADS1256.h" #include "ADS1256.h"
#include "SPI.h" #include "SPI.h"
@@ -62,16 +64,18 @@ ADS1256::ADS1256(const int8_t DRDY_pin, const int8_t RESET_pin, const int8_t SYN
updateConversionParameter(); updateConversionParameter();
// m_drdyHigh = xSemaphoreCreateBinary(); m_drdyHigh = xSemaphoreCreateBinary();
// m_drdyLow = xSemaphoreCreateBinary(); m_drdyLow = xSemaphoreCreateBinary();
// if (!m_drdyHigh || !m_drdyLow) { if (!m_drdyHigh || !m_drdyLow)
// LOG_ERROR("ADC Unable to create interrupt semaphores"); {
// return; LOG_ERROR("ADC Unable to create interrupt semaphores");
// } return;
}
// xSemaphoreGive(m_drdyHigh);
// xSemaphoreGive(m_drdyLow); xSemaphoreGive(m_drdyHigh);
//attachInterruptArg(DRDY_pin, drdyCallback, (void *)this, CHANGE); xSemaphoreGive(m_drdyLow);
attachInterruptArg(DRDY_pin, drdyCallback, (void *)this, CHANGE);
disableInterrupt(DRDY_pin);
} }
// Initialization // Initialization
@@ -84,7 +88,7 @@ void ADS1256::InitializeADC()
if (m_RESET_pin != PIN_UNUSED) if (m_RESET_pin != PIN_UNUSED)
{ {
digitalWrite(m_RESET_pin, LOW); digitalWrite(m_RESET_pin, LOW);
delay(200); delayMicroseconds(500);
digitalWrite(m_RESET_pin, HIGH); // RESET is set to high digitalWrite(m_RESET_pin, HIGH); // RESET is set to high
delay(1000); delay(1000);
} }
@@ -97,44 +101,48 @@ void ADS1256::InitializeADC()
// Applying arbitrary default values to speed up the starting procedure if the user just want to get quick readouts // Applying arbitrary default values to speed up the starting procedure if the user just want to get quick readouts
// We both pass values to the variables and then send those values to the corresponding registers // We both pass values to the variables and then send those values to the corresponding registers
delay(200); delayMicroseconds(500);
m_STATUS = 0b00110110; // BUFEN and ACAL enabled, Order is MSB, rest is read only m_STATUS = 0b00110110; // BUFEN and ACAL enabled, Order is MSB, rest is read only
writeRegister(STATUS_REG, m_STATUS); writeRegister(STATUS_REG, m_STATUS);
delay(200); delayMicroseconds(500);
m_MUX = DIFF_0_1; // MUX AIN0+AIN1 m_MUX = DIFF_0_1; // MUX AIN0+AIN1
writeRegister(MUX_REG, m_MUX); writeRegister(MUX_REG, m_MUX);
delay(200); delayMicroseconds(500);
m_ADCON = WAKEUP; // ADCON - CLK: OFF, SDCS: OFF, PGA = 0 (+/- 5 V) m_ADCON = WAKEUP; // ADCON - CLK: OFF, SDCS: OFF, PGA = 0 (+/- 5 V)
writeRegister(ADCON_REG, m_ADCON); writeRegister(ADCON_REG, m_ADCON);
delay(200); delayMicroseconds(500);
updateConversionParameter(); updateConversionParameter();
m_DRATE = DRATE_100SPS; // 100SPS m_DRATE = DRATE_100SPS; // 100SPS
writeRegister(DRATE_REG, m_DRATE); writeRegister(DRATE_REG, m_DRATE);
delay(200); delayMicroseconds(500);
sendDirectCommand(SELFCAL); // Offset and self-gain calibration sendDirectCommand(SELFCAL); // Offset and self-gain calibration
delay(200); delayMicroseconds(500);
m_isAcquisitionRunning = false; // MCU will be waiting to start a continuous acquisition m_isAcquisitionRunning = false; // MCU will be waiting to start a continuous acquisition
} }
void ADS1256::waitForLowDRDY() void ADS1256::waitForLowDRDY()
{ {
while(digitalRead(m_DRDY_pin) == HIGH) {vTaskDelay(1);}; if (!m_isAcquisitionRunning)
// xSemaphoreTake(m_drdyLow, pdMS_TO_TICKS(10)); while (digitalRead(m_DRDY_pin) == HIGH)
// xSemaphoreGive(m_drdyLow); ; // wait in loop only for single shot modes
xSemaphoreTake(m_drdyLow, pdMS_TO_TICKS(10));
xSemaphoreGive(m_drdyLow);
} }
void ADS1256::waitForHighDRDY() void ADS1256::waitForHighDRDY()
{ {
while(digitalRead(m_DRDY_pin) == LOW) {vTaskDelay(1);}; if (!m_isAcquisitionRunning)
// xSemaphoreTake(m_drdyHigh, pdMS_TO_TICKS(10)); while (digitalRead(m_DRDY_pin) == LOW)
// xSemaphoreGive(m_drdyHigh); ; // wait in loop only for single shot modes
xSemaphoreTake(m_drdyHigh, pdMS_TO_TICKS(10));
xSemaphoreGive(m_drdyHigh);
} }
void ADS1256::stopConversion() // Sending SDATAC to stop the continuous conversion void ADS1256::stopConversion() // Sending SDATAC to stop the continuous conversion
@@ -145,20 +153,21 @@ void ADS1256::stopConversion() // Sending SDATAC to stop the continuous conversi
_spi->endTransaction(); _spi->endTransaction();
m_isAcquisitionRunning = false; // Reset to false, so the MCU will be able to start a new conversion m_isAcquisitionRunning = false; // Reset to false, so the MCU will be able to start a new conversion
disableDRDYinterrupt();
} }
void ADS1256::setDRATE(uint8_t drate) // Setting DRATE (sampling frequency) void ADS1256::setDRATE(uint8_t drate) // Setting DRATE (sampling frequency)
{ {
writeRegister(DRATE_REG, drate); writeRegister(DRATE_REG, drate);
m_DRATE = drate; m_DRATE = drate;
delay(200); delayMicroseconds(500);
} }
void ADS1256::setMUX(uint8_t mux) // Setting MUX (input channel) void ADS1256::setMUX(uint8_t mux) // Setting MUX (input channel)
{ {
writeRegister(MUX_REG, mux); writeRegister(MUX_REG, mux);
m_MUX = mux; m_MUX = mux;
delay(200); delayMicroseconds(500);
} }
void ADS1256::setPGA(uint8_t pga) // Setting PGA (input voltage range) void ADS1256::setPGA(uint8_t pga) // Setting PGA (input voltage range)
@@ -169,7 +178,7 @@ void ADS1256::setPGA(uint8_t pga) // Setting PGA (input voltage range)
m_ADCON = (m_ADCON & 0b11111000) | (m_PGA & 0b00000111); // Clearing and then setting bits 2-0 based on pga m_ADCON = (m_ADCON & 0b11111000) | (m_PGA & 0b00000111); // Clearing and then setting bits 2-0 based on pga
writeRegister(ADCON_REG, m_ADCON); writeRegister(ADCON_REG, m_ADCON);
delay(200); delayMicroseconds(500);
updateConversionParameter(); // Update the multiplier according top the new PGA value updateConversionParameter(); // Update the multiplier according top the new PGA value
} }
@@ -217,7 +226,6 @@ void ADS1256::setCLKOUT(uint8_t clkout) // Setting CLKOUT
} }
writeRegister(ADCON_REG, m_ADCON); writeRegister(ADCON_REG, m_ADCON);
delay(100);
} }
void ADS1256::setSDCS(uint8_t sdcs) // Setting SDCS void ADS1256::setSDCS(uint8_t sdcs) // Setting SDCS
@@ -255,7 +263,6 @@ void ADS1256::setSDCS(uint8_t sdcs) // Setting SDCS
} }
writeRegister(ADCON_REG, m_ADCON); writeRegister(ADCON_REG, m_ADCON);
delay(100);
} }
void ADS1256::setByteOrder(uint8_t byteOrder) // Setting byte order (MSB/LSB) void ADS1256::setByteOrder(uint8_t byteOrder) // Setting byte order (MSB/LSB)
@@ -279,7 +286,6 @@ void ADS1256::setByteOrder(uint8_t byteOrder) // Setting byte order (MSB/LSB)
} }
writeRegister(STATUS_REG, m_STATUS); writeRegister(STATUS_REG, m_STATUS);
delay(100);
} }
uint8_t ADS1256::getByteOrder() // Getting byte order (MSB/LSB) uint8_t ADS1256::getByteOrder() // Getting byte order (MSB/LSB)
@@ -310,7 +316,6 @@ void ADS1256::setAutoCal(uint8_t acal) // Setting ACAL (Automatic SYSCAL)
} }
writeRegister(STATUS_REG, m_STATUS); writeRegister(STATUS_REG, m_STATUS);
delay(100);
} }
uint8_t ADS1256::getAutoCal() // Getting ACAL (Automatic SYSCAL) uint8_t ADS1256::getAutoCal() // Getting ACAL (Automatic SYSCAL)
@@ -341,7 +346,6 @@ void ADS1256::setBuffer(uint8_t bufen) // Setting input buffer (Input impedance)
} }
writeRegister(STATUS_REG, m_STATUS); writeRegister(STATUS_REG, m_STATUS);
delay(100);
} }
uint8_t ADS1256::getBuffer() // Getting input buffer (Input impedance) uint8_t ADS1256::getBuffer() // Getting input buffer (Input impedance)
@@ -405,7 +409,6 @@ void ADS1256::setGPIO(uint8_t dir0, uint8_t dir1, uint8_t dir2, uint8_t dir3) //
//----------------------------------------------------- //-----------------------------------------------------
writeRegister(IO_REG, m_GPIO); writeRegister(IO_REG, m_GPIO);
delay(100);
} }
void ADS1256::writeGPIO(uint8_t dir0value, uint8_t dir1value, uint8_t dir2value, uint8_t dir3value) // Writing GPIO void ADS1256::writeGPIO(uint8_t dir0value, uint8_t dir1value, uint8_t dir2value, uint8_t dir3value) // Writing GPIO
@@ -463,7 +466,6 @@ void ADS1256::writeGPIO(uint8_t dir0value, uint8_t dir1value, uint8_t dir2value,
//----------------------------------------------------- //-----------------------------------------------------
writeRegister(IO_REG, m_GPIO); writeRegister(IO_REG, m_GPIO);
delay(100);
} }
uint8_t ADS1256::readGPIO(uint8_t gpioPin) // Reading GPIO uint8_t ADS1256::readGPIO(uint8_t gpioPin) // Reading GPIO
@@ -478,8 +480,6 @@ uint8_t ADS1256::readGPIO(uint8_t gpioPin) // Reading GPIO
GPIO_bit1 = bitRead(m_GPIO, 1); GPIO_bit1 = bitRead(m_GPIO, 1);
GPIO_bit0 = bitRead(m_GPIO, 0); GPIO_bit0 = bitRead(m_GPIO, 0);
delay(100);
switch (gpioPin) // Selecting which value should be returned switch (gpioPin) // Selecting which value should be returned
{ {
case 0: case 0:
@@ -524,45 +524,32 @@ float ADS1256::convertToVoltage(int32_t rawData) // Converting the 24-bit data i
void ADS1256::writeRegister(uint8_t registerAddress, uint8_t registerValueToWrite) void ADS1256::writeRegister(uint8_t registerAddress, uint8_t registerValueToWrite)
{ {
waitForLowDRDY(); waitForLowDRDY();
_spi->beginTransaction(SPISettings(SPI_FREQ, MSBFIRST, SPI_MODE1)); // SPI_MODE1 = output edge: rising, data capture: falling; clock polarity: 0, clock phase: 1.
CS_LOW(); // CS must stay LOW during the entire sequence [Ref: P34, T24]
_spi->beginTransaction(SPISettings(SPI_FREQ, MSBFIRST, SPI_MODE1)); delayMicroseconds(5); // see t6 in the datasheet
// SPI_MODE1 = output edge: rising, data capture: falling; clock polarity: 0, clock phase: 1.
CS_LOW(); // CS must stay LOW during the entire sequence [Ref: P34, T24]
delayMicroseconds(5); // see t6 in the datasheet
_spi->transfer(WREG | registerAddress); // 0x50 = 01010000 = WREG _spi->transfer(WREG | registerAddress); // 0x50 = 01010000 = WREG
_spi->transfer(0x00); // 2nd (empty) command byte
_spi->transfer(0x00); // 2nd (empty) command byte _spi->transfer(registerValueToWrite); // pass the value to the register
_spi->transfer(registerValueToWrite); // pass the value to the register
CS_HIGH(); CS_HIGH();
_spi->endTransaction(); _spi->endTransaction();
delay(100);
} }
long ADS1256::readRegister(uint8_t registerAddress) // Reading a register long ADS1256::readRegister(uint8_t registerAddress) // Reading a register
{ {
waitForLowDRDY(); waitForLowDRDY();
_spi->beginTransaction(SPISettings(SPI_FREQ, MSBFIRST, SPI_MODE1)); // SPI_MODE1 = output edge: rising, data capture: falling; clock polarity: 0, clock phase: 1.
CS_LOW(); // CS must stay LOW during the entire sequence [Ref: P34, T24]
_spi->beginTransaction(SPISettings(SPI_FREQ, MSBFIRST, SPI_MODE1)); _spi->transfer(RREG | registerAddress); // 0x10 = 0001000 = RREG - OR together the two numbers (command + address)
// SPI_MODE1 = output edge: rising, data capture: falling; clock polarity: 0, clock phase: 1. _spi->transfer(0x00); // 2nd (empty) command byte
delayMicroseconds(5); // see t6 in the datasheet
CS_LOW(); // CS must stay LOW during the entire sequence [Ref: P34, T24]
_spi->transfer(RREG | registerAddress); // 0x10 = 0001000 = RREG - OR together the two numbers (command + address)
_spi->transfer(0x00); // 2nd (empty) command byte
delayMicroseconds(5); // see t6 in the datasheet
uint8_t regValue = _spi->transfer(0x00); // read out the register value uint8_t regValue = _spi->transfer(0x00); // read out the register value
CS_HIGH(); CS_HIGH();
_spi->endTransaction(); _spi->endTransaction();
delay(100);
return regValue; return regValue;
} }
@@ -592,6 +579,7 @@ long ADS1256::readSingleContinuous() // Reads the recently selected input channe
{ {
if (m_isAcquisitionRunning == false) if (m_isAcquisitionRunning == false)
{ {
enableDRDYinterrupt();
m_isAcquisitionRunning = true; m_isAcquisitionRunning = true;
_spi->beginTransaction(SPISettings(SPI_FREQ, MSBFIRST, SPI_MODE1)); _spi->beginTransaction(SPISettings(SPI_FREQ, MSBFIRST, SPI_MODE1));
CS_LOW(); // REF: P34: "CS must stay low during the entire command sequence" CS_LOW(); // REF: P34: "CS must stay low during the entire command sequence"
@@ -620,6 +608,7 @@ long ADS1256::cycleSingle()
{ {
if (m_isAcquisitionRunning == false) if (m_isAcquisitionRunning == false)
{ {
enableDRDYinterrupt();
m_isAcquisitionRunning = true; m_isAcquisitionRunning = true;
m_cycle = 0; m_cycle = 0;
_spi->beginTransaction(SPISettings(SPI_FREQ, MSBFIRST, SPI_MODE1)); _spi->beginTransaction(SPISettings(SPI_FREQ, MSBFIRST, SPI_MODE1));
@@ -629,9 +618,6 @@ long ADS1256::cycleSingle()
_spi->transfer(SING_0); // AIN0+AINCOM _spi->transfer(SING_0); // AIN0+AINCOM
delayMicroseconds(250); delayMicroseconds(250);
} }
else
{
}
if (m_cycle < 8) if (m_cycle < 8)
{ {
@@ -704,20 +690,16 @@ long ADS1256::cycleDifferential()
{ {
if (m_isAcquisitionRunning == false) if (m_isAcquisitionRunning == false)
{ {
enableDRDYinterrupt();
m_cycle = 0; m_cycle = 0;
m_isAcquisitionRunning = true; m_isAcquisitionRunning = true;
_spi->beginTransaction(SPISettings(SPI_FREQ, MSBFIRST, SPI_MODE1)); _spi->beginTransaction(SPISettings(SPI_FREQ, MSBFIRST, SPI_MODE1));
// Set the AIN0+AIN1 as inputs manually
CS_LOW(); // CS must stay LOW during the entire sequence [Ref: P34, T24] CS_LOW(); // CS must stay LOW during the entire sequence [Ref: P34, T24]
_spi->transfer(WREG | MUX_REG); // 0x50 = WREG //1 = MUX _spi->transfer(WREG | MUX_REG); // 0x50 = WREG //1 = MUX
_spi->transfer(0x00); _spi->transfer(0x00);
_spi->transfer(DIFF_0_1); // AIN0+AIN1 _spi->transfer(DIFF_0_1); // Set the AIN0+AIN1 as inputs manually
delayMicroseconds(250); delayMicroseconds(250);
} }
else
{
}
if (m_cycle < 4) if (m_cycle < 4)
{ {
@@ -798,4 +780,36 @@ inline void ADS1256::CS_HIGH()
{ {
digitalWrite(m_CS_pin, HIGH); digitalWrite(m_CS_pin, HIGH);
} }
} }
// functions for callback
inline uint8_t ADS1256::getDRDYpin()
{
return m_DRDY_pin;
}
inline SemaphoreHandle_t ADS1256::getDRDYsemaphoreHigh()
{
return m_drdyHigh;
}
inline SemaphoreHandle_t ADS1256::getDRDYsemaphoreLow()
{
return m_drdyLow;
}
inline void ADS1256::enableDRDYinterrupt()
{
// release semaphores to avoid deadlock
xSemaphoreGive(m_drdyHigh);
xSemaphoreGive(m_drdyLow);
enableInterrupt(m_DRDY_pin);
}
inline void ADS1256::disableDRDYinterrupt()
{
// release semaphores to avoid deadlock
disableInterrupt(m_DRDY_pin);
xSemaphoreGive(m_drdyHigh);
xSemaphoreGive(m_drdyLow);
}
+7 -18
View File
@@ -10,8 +10,7 @@
Benjamin Pelletier for pointing out and fixing an issue around the handling of the DRDY signal Benjamin Pelletier for pointing out and fixing an issue around the handling of the DRDY signal
*/ */
#ifndef _ADS1256_h #pragma once
#define _ADS1256_h
#include <SPI.h> #include <SPI.h>
#include <Arduino.h> #include <Arduino.h>
@@ -159,21 +158,10 @@ public:
// Stop AD // Stop AD
void stopConversion(); void stopConversion();
// functions for callback // functions for callback, public to be accessed by static callback
inline uint8_t getDRDYpin() inline uint8_t getDRDYpin();
{ inline SemaphoreHandle_t getDRDYsemaphoreHigh();
return m_DRDY_pin; inline SemaphoreHandle_t getDRDYsemaphoreLow();
}
SemaphoreHandle_t getDRDYsemaphoreHigh()
{
return m_drdyHigh;
}
SemaphoreHandle_t getDRDYsemaphoreLow()
{
return m_drdyLow;
}
private: private:
SPIClass *_spi; // Pointer to an SPIClass object SPIClass *_spi; // Pointer to an SPIClass object
@@ -183,6 +171,8 @@ private:
void updateMUX(uint8_t muxValue); void updateMUX(uint8_t muxValue);
inline void CS_LOW(); inline void CS_LOW();
inline void CS_HIGH(); inline void CS_HIGH();
inline void enableDRDYinterrupt();
inline void disableDRDYinterrupt();
void updateConversionParameter(); // Refresh the conversion parameter based on the PGA void updateConversionParameter(); // Refresh the conversion parameter based on the PGA
@@ -212,4 +202,3 @@ private:
SemaphoreHandle_t m_drdyHigh; SemaphoreHandle_t m_drdyHigh;
SemaphoreHandle_t m_drdyLow; SemaphoreHandle_t m_drdyLow;
}; };
#endif
+10 -9
View File
@@ -21,20 +21,21 @@ lib_deps =
me-no-dev/AsyncTCP@^3.3.2 me-no-dev/AsyncTCP@^3.3.2
me-no-dev/ESPAsyncWebServer@^3.6.0 me-no-dev/ESPAsyncWebServer@^3.6.0
upload_protocol = esptool upload_protocol = esptool
upload_port = /dev/ttyACM1 upload_port = /dev/ttyACM0
upload_speed = 921600 upload_speed = 921600
monitor_port = /dev/ttyACM0 monitor_port = /dev/ttyACM1
monitor_speed = 921600 monitor_speed = 921600
build_type = release build_type = release
build_flags = build_flags =
-DCORE_DEBUG_LEVEL=3 -DCORE_DEBUG_LEVEL=1
-DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_CDC_ON_BOOT=0
-DARDUINO_USB_MODE=0 -DARDUINO_USB_MODE=0
-DCONFIG_ASYNC_TCP_MAX_ACK_TIME=5000 -DCONFIG_ASYNC_TCP_MAX_ACK_TIME=5000
-DCONFIG_ASYNC_TCP_PRIORITY=21 -DCONFIG_ASYNC_TCP_PRIORITY=21
-DCONFIG_ASYNC_TCP_QUEUE_SIZE=128 -DCONFIG_ASYNC_TCP_QUEUE_SIZE=64
-DCONFIG_ASYNC_TCP_RUNNING_CORE=1 -DCONFIG_ASYNC_TCP_RUNNING_CORE=1
-DCONFIG_ASYNC_TCP_STACK_SIZE=8192 -DCONFIG_ASYNC_TCP_STACK_SIZE=4096
-fstack-protector-strong
[env:esp32-s3-devkitc1-n16r8-debug] [env:esp32-s3-devkitc1-n16r8-debug]
board = ${env:esp32-s3-devkitc1-n16r8.board} board = ${env:esp32-s3-devkitc1-n16r8.board}
@@ -45,9 +46,9 @@ framework = ${env:esp32-s3-devkitc1-n16r8.framework}
lib_deps = lib_deps =
${env:esp32-s3-devkitc1-n16r8.lib_deps} ${env:esp32-s3-devkitc1-n16r8.lib_deps}
upload_protocol = esptool upload_protocol = esptool
upload_port = /dev/ttyACM1 upload_port = /dev/ttyACM0
upload_speed = 921600 upload_speed = 921600
monitor_port = /dev/ttyACM0 monitor_port = /dev/ttyACM1
monitor_speed = 921600 monitor_speed = 921600
debug_tool = esp-builtin debug_tool = esp-builtin
debug_speed = 15000 debug_speed = 15000
@@ -61,6 +62,6 @@ build_flags =
-DARDUINO_USB_MODE=0 -DARDUINO_USB_MODE=0
-DCONFIG_ASYNC_TCP_MAX_ACK_TIME=5000 -DCONFIG_ASYNC_TCP_MAX_ACK_TIME=5000
-DCONFIG_ASYNC_TCP_PRIORITY=21 -DCONFIG_ASYNC_TCP_PRIORITY=21
-DCONFIG_ASYNC_TCP_QUEUE_SIZE=128 -DCONFIG_ASYNC_TCP_QUEUE_SIZE=64
-DCONFIG_ASYNC_TCP_RUNNING_CORE=1 -DCONFIG_ASYNC_TCP_RUNNING_CORE=1
-DCONFIG_ASYNC_TCP_STACK_SIZE=8192 -DCONFIG_ASYNC_TCP_STACK_SIZE=4096
-2
View File
@@ -14,8 +14,6 @@
#include "isr.h" #include "isr.h"
#include "psvector.h" #include "psvector.h"
const uint32_t max_history = 256;
class LITTLEFSGuard class LITTLEFSGuard
{ {
public: public:
+59 -27
View File
@@ -16,24 +16,24 @@
#include <ui.h> #include <ui.h>
#include <led.h> #include <led.h>
#define CH_A_ENABLE // #define CH_A_ENABLE
#define CH_B_ENABLE // #define CH_B_ENABLE
#define CH_A_RT_ENABLE #define CH_A_RT_ENABLE
#define CH_B_RT_ENABLE #define CH_B_RT_ENABLE
// #define I2C_ENABLE // #define I2C_ENABLE
// #define WEB_ENABLE #define WEB_ENABLE
// Debug Defines // Debug Defines
#define WIFI_SSID "AstroRotaxMonitor" #define WIFI_SSID "AstroRotaxMonitor"
#define WIFI_PASSWORD "maledettirotax" #define WIFI_PASSWORD "maledettirotax"
#define PSRAM_MAX 1024 #define PSRAM_MAX 4096
#define QUEUE_MAX 32 #define QUEUE_MAX 128
#define HTOP_DELAY 2000
void setup() void setup()
{ {
Serial.begin(115200); Serial.begin(921600);
delay(250); delay(250);
Serial.setTimeout(5000);
// Setup Logger // Setup Logger
LOG_ATTACH_SERIAL(Serial); LOG_ATTACH_SERIAL(Serial);
@@ -106,7 +106,7 @@ void loop()
spiA_ok = SPI_A.begin(SPI_A_SCK, SPI_A_MISO, SPI_A_MOSI); spiA_ok = SPI_A.begin(SPI_A_SCK, SPI_A_MISO, SPI_A_MOSI);
SPI_A.setDataMode(SPI_MODE1); // ADS1256 requires SPI mode 1 SPI_A.setDataMode(SPI_MODE1); // ADS1256 requires SPI mode 1
LOG_DEBUG("Init SPI_A -> OK"); LOG_DEBUG("Init SPI_A -> OK");
delay(500); delay(100);
LOG_DEBUG("Begin Init ADC_A"); LOG_DEBUG("Begin Init ADC_A");
ADS1256 ADC_A(ADC_A_DRDY, ADS1256::PIN_UNUSED, ADS1256::PIN_UNUSED, ADC_A_CS, 2.5, &SPI_A); ADS1256 ADC_A(ADC_A_DRDY, ADS1256::PIN_UNUSED, ADS1256::PIN_UNUSED, ADC_A_CS, 2.5, &SPI_A);
ADC_A.InitializeADC(); ADC_A.InitializeADC();
@@ -115,7 +115,7 @@ void loop()
dev.m_adc_a = &ADC_A; dev.m_adc_a = &ADC_A;
dev.m_spi_a = &SPI_A; dev.m_spi_a = &SPI_A;
LOG_DEBUG("Init ADC_A -> OK"); LOG_DEBUG("Init ADC_A -> OK");
delay(1000); delay(100);
#endif #endif
#ifdef CH_B_ENABLE #ifdef CH_B_ENABLE
@@ -124,7 +124,7 @@ void loop()
spiB_ok = SPI_B.begin(SPI_B_SCK, SPI_B_MISO, SPI_B_MOSI); spiB_ok = SPI_B.begin(SPI_B_SCK, SPI_B_MISO, SPI_B_MOSI);
SPI_B.setDataMode(SPI_MODE1); // ADS1256 requires SPI mode 1 SPI_B.setDataMode(SPI_MODE1); // ADS1256 requires SPI mode 1
LOG_DEBUG("Init SPI_B -> OK"); LOG_DEBUG("Init SPI_B -> OK");
delay(500); delay(100);
LOG_DEBUG("Begin Init ADC_B"); LOG_DEBUG("Begin Init ADC_B");
ADS1256 ADC_B(ADC_B_DRDY, ADS1256::PIN_UNUSED, ADS1256::PIN_UNUSED, ADC_B_CS, 2.5, &SPI_B); ADS1256 ADC_B(ADC_B_DRDY, ADS1256::PIN_UNUSED, ADS1256::PIN_UNUSED, ADC_B_CS, 2.5, &SPI_B);
ADC_B.InitializeADC(); ADC_B.InitializeADC();
@@ -133,7 +133,7 @@ void loop()
dev.m_adc_b = &ADC_B; dev.m_adc_b = &ADC_B;
dev.m_spi_b = &SPI_B; dev.m_spi_b = &SPI_B;
LOG_DEBUG("Init ADC_B -> OK"); LOG_DEBUG("Init ADC_B -> OK");
delay(1000); delay(100);
#endif #endif
if (!spiA_ok || !spiB_ok) if (!spiA_ok || !spiB_ok)
@@ -159,10 +159,10 @@ void loop()
esp_restart(); esp_restart();
} }
LOG_DEBUG("Init I2c ok"); LOG_DEBUG("Init I2c ok");
Serial.readStringUntil('\n');
// Init IO Expanders // Init IO Expanders
dev->m_ext_io = std::make_unique<ExternalIO>(Wire, dev->m_i2c_mutex, EXPANDER_ALL_INTERRUPT); ExternalIO extIo(Wire, dev.m_i2c_mutex, EXPANDER_ALL_INTERRUPT);
dev.m_ext_io = &extIo;
#endif #endif
//////// INIT REALTIME TASKS PARAMETERS //////// //////// INIT REALTIME TASKS PARAMETERS ////////
@@ -238,17 +238,17 @@ void loop()
BaseType_t ignB_task_success = pdPASS; BaseType_t ignB_task_success = pdPASS;
#ifdef CH_A_RT_ENABLE #ifdef CH_A_RT_ENABLE
auto task_A = rtIgnitionTask(taskA_params, PSRAM_MAX, QUEUE_MAX, CORE_1, fs_mutex); auto task_A = rtIgnitionTask(taskA_params, PSRAM_MAX, QUEUE_MAX, CORE_0, fs_mutex);
ignA_task_success = task_A.getStatus() == rtIgnitionTask::OK ? pdPASS : pdFAIL; ignA_task_success = task_A.getStatus() == rtIgnitionTask::OK ? pdPASS : pdFAIL;
//tasK_A_rt = task_A.start(); tasK_A_rt = task_A.start();
delay(1000); delay(100);
#endif #endif
#ifdef CH_B_RT_ENABLE #ifdef CH_B_RT_ENABLE
auto task_B = rtIgnitionTask(taskB_params, PSRAM_MAX, QUEUE_MAX, CORE_1, fs_mutex); auto task_B = rtIgnitionTask(taskB_params, PSRAM_MAX, QUEUE_MAX, CORE_1, fs_mutex);
ignB_task_success = task_B.getStatus() == rtIgnitionTask::OK ? pdPASS : pdFAIL; ignB_task_success = task_B.getStatus() == rtIgnitionTask::OK ? pdPASS : pdFAIL;
//task_B_rt = task_B.start(); task_B_rt = task_B.start();
delay(1000); delay(100);
#endif #endif
// Ignition A on Core 0 // Ignition A on Core 0
@@ -275,22 +275,54 @@ void loop()
bool data_a = false, data_b = false; bool data_a = false, data_b = false;
#ifdef WEB_ENABLE #ifdef WEB_ENABLE
AstroWebServer webPage(80, LittleFS); AstroWebServer webPage(80, LittleFS);
delay(1000); delay(100);
#ifdef CH_A_RT_ENABLE
task_A.onMessage([&webPage, &json_data, &data_a](ignitionBoxStatusFiltered sts) task_A.onMessage([&webPage, &json_data, &data_a](ignitionBoxStatusFiltered sts)
{ {
json_data["box_a"] = sts.toJson(); json_data["box_a"] = sts.toJson();
data_a = true; }); data_a = true; });
#endif
#ifdef CH_B_RT_ENABLE #ifdef CH_B_RT_ENABLE
task_B.onMessage([&webPage, &json_data, &data_b](ignitionBoxStatusFiltered sts) task_B.onMessage([&webPage, &json_data, &data_b](ignitionBoxStatusFiltered sts)
{ {
json_data["box_b"] = sts.toJson(); json_data["box_b"] = sts.toJson();
data_b = true; }); data_b = true; });
#endif
#endif #endif
// task_A.enableSave(true, "ignitionA_test.csv"); webPage.registerWsCommand("saveEnable", [&task_A, &task_B](const ArduinoJson::JsonDocument &doc) {
// task_B.enableSave(true, "ignitionB_test.csv"); if(!doc["params"].is<ArduinoJson::JsonObject>()) return;
if(!doc["filename_a"].is<std::string>() ||!doc["filename_b"].is<std::string>()){
LOG_ERROR("saveEnable invalid or missing filenames");
return;
}
task_A.enableSave(true, doc["filename_a"].as<std::string>());
task_B.enableSave(true, doc["filename_a"].as<std::string>());
return; });
webPage.registerWsCommand("saveDisable", [&task_A, &task_B](const ArduinoJson::JsonDocument &doc) {
task_A.enableSave(false, "");
task_B.enableSave(false, ""); });
webPage.registerWsCommand("downloadHistory", [](const ArduinoJson::JsonDocument &doc) {
LOG_WARN("Command downloadHistory not Implemented");
});
webPage.registerWsCommand("clearHistory", [](const ArduinoJson::JsonDocument &doc) {
LOG_WARN("Command clearHistory not Implemented");
});
webPage.registerWsCommand("startTest", [](const ArduinoJson::JsonDocument &doc) {
LOG_WARN("Command startTest not Implemented");
});
webPage.registerWsCommand("stopTest", [](const ArduinoJson::JsonDocument &doc) {
LOG_WARN("Command stopTest not Implemented");
});
#endif
uint32_t monitor_loop = millis(); uint32_t monitor_loop = millis();
uint32_t data_loop = monitor_loop; uint32_t data_loop = monitor_loop;
@@ -298,21 +330,21 @@ void loop()
while (running) while (running)
{ {
uint32_t this_loop = millis(); uint32_t this_loop = millis();
if (this_loop - monitor_loop > 5000) if (this_loop - monitor_loop > HTOP_DELAY)
{ {
clearScreen(); clearScreen();
printRunningTasksMod(Serial); printRunningTasksMod(Serial);
monitor_loop = millis(); monitor_loop = millis();
} }
vTaskDelay(pdMS_TO_TICKS(10)); #ifdef WEB_ENABLE
#ifdef WEB_ENABLE if ((data_a && data_b) || ((this_loop - data_loop > 500) && (data_b || data_b)))
if ((data_a && data_b) || (this_loop - data_loop > 500))
{ {
webPage.sendWsData(json_data.as<String>()); webPage.sendWsData(json_data.as<String>());
json_data.clear(); json_data.clear();
data_a = data_b = false; data_a = data_b = false;
data_loop = millis(); data_loop = millis();
} }
vTaskDelay(pdMS_TO_TICKS(10));
#endif #endif
} //////////////// INNER LOOP ///////////////////// } //////////////// INNER LOOP /////////////////////
+12 -13
View File
@@ -33,16 +33,15 @@
// ===================== // =====================
// SPI BUS ADC2 (HSPI) // SPI BUS ADC2 (HSPI)
// ===================== // =====================
#define SPI_B_MOSI 36 #define SPI_B_MOSI 17
#define SPI_B_SCK 37 #define SPI_B_SCK 18
#define SPI_B_MISO 38 #define SPI_B_MISO 8
// ===================== // =====================
// I2C BUS (PCA9555) // I2C BUS (PCA9555)
// ===================== // =====================
#define SDA 8 #define SDA 21
#define SCL 9 #define SCL 47
#define I2C_INT 17
// ===================== // =====================
// ADC CONTROL // ADC CONTROL
@@ -50,8 +49,8 @@
#define ADC_A_CS 14 #define ADC_A_CS 14
#define ADC_A_DRDY 13 #define ADC_A_DRDY 13
#define ADC_B_CS 21 #define ADC_B_CS 3
#define ADC_B_DRDY 47 #define ADC_B_DRDY 46
// ===================== // =====================
// TRIGGER INPUT INTERRUPTS // TRIGGER INPUT INTERRUPTS
@@ -81,12 +80,12 @@
// ===================== // =====================
// PCA9555 I/O EXPANDER INTERRUPT (Common) // PCA9555 I/O EXPANDER INTERRUPT (Common)
// ===================== // =====================
#define EXPANDER_ALL_INTERRUPT 17 #define EXPANDER_ALL_INTERRUPT 45
// ===================== // =====================
// PCA9555 I/O EXPANDER BOX_A (OUT) // PCA9555 I/O EXPANDER BOX_A (OUT)
// ===================== // =====================
#define EXPANDER_A_OUT_ADDR 0xFF #define EXPANDER_A_OUT_ADDR 0x7F
// --- DIGITAL POT CHIP SELECT LINES --- // --- DIGITAL POT CHIP SELECT LINES ---
#define POT_CS_A12 PIN2ADDR(0, EXPANDER_A_OUT_ADDR) #define POT_CS_A12 PIN2ADDR(0, EXPANDER_A_OUT_ADDR)
@@ -112,7 +111,7 @@
// ===================== // =====================
// PCA9555 I/O EXPANDER BOX_A (IN) // PCA9555 I/O EXPANDER BOX_A (IN)
// ===================== // =====================
#define EXPANDER_A_IN_ADDR 0xFF #define EXPANDER_A_IN_ADDR 0x7F
#define SS_A12_ON PIN2ADDR(0, EXPANDER_A_IN_ADDR) #define SS_A12_ON PIN2ADDR(0, EXPANDER_A_IN_ADDR)
#define SS_A12_OFF PIN2ADDR(1, EXPANDER_A_IN_ADDR) #define SS_A12_OFF PIN2ADDR(1, EXPANDER_A_IN_ADDR)
@@ -122,7 +121,7 @@
// ===================== // =====================
// PCA9555 I/O EXPANDER BOX_B (OUT) // PCA9555 I/O EXPANDER BOX_B (OUT)
// ===================== // =====================
#define EXPANDER_B_OUT_ADDR 0xFF #define EXPANDER_B_OUT_ADDR 0x7F
// --- DIGITAL POT CHIP SELECT LINES --- // --- DIGITAL POT CHIP SELECT LINES ---
#define POT_CS_B12 PIN2ADDR(0, EXPANDER_B_OUT_ADDR) #define POT_CS_B12 PIN2ADDR(0, EXPANDER_B_OUT_ADDR)
@@ -148,7 +147,7 @@
// ===================== // =====================
// PCA9555 I/O EXPANDER BOX_B (IN) // PCA9555 I/O EXPANDER BOX_B (IN)
// ===================== // =====================
#define EXPANDER_B_IN_ADDR 0xFF #define EXPANDER_B_IN_ADDR 0x7F
#define SS_B12_ON PIN2ADDR(0, EXPANDER_B_IN_ADDR) #define SS_B12_ON PIN2ADDR(0, EXPANDER_B_IN_ADDR)
#define SS_B12_OFF PIN2ADDR(1, EXPANDER_B_IN_ADDR) #define SS_B12_OFF PIN2ADDR(1, EXPANDER_B_IN_ADDR)
+39 -20
View File
@@ -6,7 +6,7 @@
//// GLOBAL STATIC FUNCTIONS //// GLOBAL STATIC FUNCTIONS
// Timeout callback for microsecond precision // Timeout callback for microsecond precision
void spark_timeout_callback(void *arg) void IRAM_ATTR spark_timeout_callback(void *arg)
{ {
TaskHandle_t handle = (TaskHandle_t)arg; TaskHandle_t handle = (TaskHandle_t)arg;
xTaskNotify(handle, SPARK_FLAG_TIMEOUT, eSetValueWithOverwrite); xTaskNotify(handle, SPARK_FLAG_TIMEOUT, eSetValueWithOverwrite);
@@ -21,10 +21,6 @@ void rtIgnitionTask::rtIgnitionTask_manager(void *pvParameters)
while (cls->m_running) while (cls->m_running)
{ {
cls->run(); cls->run();
// if (millis() - last_loop > 2000) {
// LOG_DEBUG("TASK [", cls->m_name.c_str(), "] Alive -", count++);
// last_loop = millis();
// }
vTaskDelay(pdMS_TO_TICKS(1)); vTaskDelay(pdMS_TO_TICKS(1));
} }
} }
@@ -47,10 +43,8 @@ void rtIgnitionTask::rtIgnitionTask_realtime(void *pvParameters)
QueueHandle_t rt_queue = params->rt_queue; QueueHandle_t rt_queue = params->rt_queue;
Devices *dev = params->dev; Devices *dev = params->dev;
ExternalIO *io = dev->m_ext_io; ExternalIO *io = dev->m_ext_io;
// ADS1256 *adc = params->name == "rtIgnTask_A" ? dev->m_adc_a : dev->m_adc_b; ADS1256 *adc = params->name == "rtIgnTask_A" ? dev->m_adc_a : dev->m_adc_b;
ADS1256 *adc = NULL; std::mutex &spi_mutex = params->name == "rtIgnTask_A" ? dev->m_spi_a_mutex : dev->m_spi_b_mutex;
// std::mutex &spi_mutex = params->name == "rtIgnTask_A" ? dev->m_spi_a_mutex : dev->m_spi_b_mutex;
std::mutex spi_mutex;
TaskStatus_t rt_task_info; TaskStatus_t rt_task_info;
vTaskGetInfo(NULL, &rt_task_info, pdFALSE, eInvalid); vTaskGetInfo(NULL, &rt_task_info, pdFALSE, eInvalid);
@@ -233,6 +227,15 @@ void rtIgnitionTask::rtIgnitionTask_realtime(void *pvParameters)
if (cycle12 && cycle34) // wait for both 12 and 34 cycles to complete before sending data to main loop and resetting peak detectors if (cycle12 && cycle34) // wait for both 12 and 34 cycles to complete before sending data to main loop and resetting peak detectors
{ {
// disable interrupts during adc samples
disableInterrupt(digitalPinToInterrupt(rt_int.trig_pin_12p));
disableInterrupt(digitalPinToInterrupt(rt_int.trig_pin_12n));
disableInterrupt(digitalPinToInterrupt(rt_int.trig_pin_34p));
disableInterrupt(digitalPinToInterrupt(rt_int.trig_pin_34n));
disableInterrupt(digitalPinToInterrupt(rt_int.spark_pin_12));
disableInterrupt(digitalPinToInterrupt(rt_int.spark_pin_34));
// reset coils 12 and 34 cycles
cycle12 = false; cycle12 = false;
cycle34 = false; cycle34 = false;
@@ -290,9 +293,18 @@ void rtIgnitionTask::rtIgnitionTask_realtime(void *pvParameters)
if (xQueueSendToBack(rt_queue, (void *)&ign_box_sts, 0) != pdPASS) if (xQueueSendToBack(rt_queue, (void *)&ign_box_sts, 0) != pdPASS)
ign_box_sts.n_queue_errors = ++n_errors; ign_box_sts.n_queue_errors = ++n_errors;
} }
// enable interrupts ready for a new cycle
enableInterrupt(digitalPinToInterrupt(rt_int.trig_pin_12p));
enableInterrupt(digitalPinToInterrupt(rt_int.trig_pin_12n));
enableInterrupt(digitalPinToInterrupt(rt_int.trig_pin_34p));
enableInterrupt(digitalPinToInterrupt(rt_int.trig_pin_34n));
enableInterrupt(digitalPinToInterrupt(rt_int.spark_pin_12));
enableInterrupt(digitalPinToInterrupt(rt_int.spark_pin_34));
} }
} }
// Delete the timeout timer // Delete the timeout timer
esp_timer_stop(timeout_timer);
esp_timer_delete(timeout_timer); esp_timer_delete(timeout_timer);
LOG_WARN("rtTask Ending [", params->name.c_str(), "]"); LOG_WARN("rtTask Ending [", params->name.c_str(), "]");
// Ignition A Interrupts DETACH // Ignition A Interrupts DETACH
@@ -321,15 +333,22 @@ rtIgnitionTask::rtIgnitionTask(const rtTaskParams params, const uint32_t history
else else
m_params.rt_queue = m_queue; m_params.rt_queue = m_queue;
// create PSram history vectors try
m_history_0 = PSHistory(history_size); {
m_history_1 = PSHistory(history_size); // create PSram history vectors
// assing active and writable history m_history_0 = PSHistory(history_size);
m_active_history = std::unique_ptr<PSHistory>(&m_history_0); m_history_1 = PSHistory(history_size);
m_save_history = std::unique_ptr<PSHistory>(&m_history_1); // assing active and writable history
m_active_history = std::unique_ptr<PSHistory>(&m_history_0);
m_save_history = std::unique_ptr<PSHistory>(&m_history_1);
}
catch (std::bad_alloc &e)
{
LOG_ERROR("Task [", params.name.c_str(), "] Unable to allocate history PSRAM: ", e.what());
return;
}
m_name = (std::string("man_") + m_params.name).c_str(); m_name = (std::string("man_") + m_params.name).c_str();
// auto task_success = pdPASS;
auto task_success = xTaskCreatePinnedToCore( auto task_success = xTaskCreatePinnedToCore(
rtIgnitionTask_manager, rtIgnitionTask_manager,
m_name.c_str(), m_name.c_str(),
@@ -379,7 +398,7 @@ void rtIgnitionTask::run()
m_partial_save = false; // reset partial save flag on new data cycle m_partial_save = false; // reset partial save flag on new data cycle
std::swap(m_active_history, m_save_history); std::swap(m_active_history, m_save_history);
if (m_enable_save) if (m_enable_save)
// saveHistory(m_save_history, m_history_path); // directly call the save task function to save without delay saveHistory(*m_save_history, m_history_path); // directly call the save task function to save without delay
LOG_INFO("Save History"); LOG_INFO("Save History");
} }
@@ -402,9 +421,9 @@ void rtIgnitionTask::run()
if (m_counter_status > 0 && !m_partial_save) if (m_counter_status > 0 && !m_partial_save)
{ {
LOG_DEBUG("Save Partial: ", m_counter_status); LOG_DEBUG("Save Partial: ", m_counter_status);
// m_active_history->resize(m_counter_status); m_active_history->resize(m_counter_status);
// saveHistory(m_active_history, m_history_path); saveHistory(*m_active_history, m_history_path);
// m_active_history->resize(m_max_history); m_active_history->resize(m_max_history);
m_counter_status = 0; m_counter_status = 0;
m_partial_save = true; m_partial_save = true;
} }
-1
View File
@@ -41,7 +41,6 @@ static const std::map<const uint32_t, const char *> names = {
class rtIgnitionTask class rtIgnitionTask
{ {
using PSHistory = PSRAMVector<ignitionBoxStatus>; using PSHistory = PSRAMVector<ignitionBoxStatus>;
// using PSHistory = std::vector<ignitionBoxStatus>;
public: public:
// RT task Interrupt parameters // RT task Interrupt parameters
+8 -8
View File
@@ -62,7 +62,7 @@ void printBar(Print &printer, const char *label, size_t used, size_t total, cons
k += sprintf(&str[k], "-"); k += sprintf(&str[k], "-");
} }
sprintf(&str[k], "] %s%6.2f%%%s (%5.3f/%5.3f)MB\n", sprintf(&str[k], "] %s%6.2f%%%s (%5.3f/%5.3f)MB",
color, color,
perc * 100.0, perc * 100.0,
COLOR_RESET, COLOR_RESET,
@@ -104,14 +104,14 @@ void printRunningTasksMod(Print &printer, std::function<bool(const TaskStatus_t
// PRINT MEMORY INFO // PRINT MEMORY INFO
printer.printf("\033[H"); printer.printf("\033[H");
printer.printf(COLOR_LBLUE "=================== ESP32 SYSTEM MONITOR ===================\n" COLOR_RESET); printer.printf(COLOR_WHITE "====================== ESP32 SYSTEM MONITOR ======================\n" COLOR_RESET);
std::string buffer; std::string buffer;
time_t now = time(nullptr); time_t now = time(nullptr);
struct tm *t = localtime(&now); struct tm *t = localtime(&now);
buffer.resize(64); buffer.resize(64);
strftime(buffer.data(), sizeof(buffer), "%Y-%m-%d %H:%M:%S", t); strftime(buffer.data(), sizeof(buffer), "%Y-%m-%d %H:%M:%S", t);
printer.printf(COLOR_YELLOW "=============== Datetime: %s ===============\n\n" COLOR_RESET, buffer.c_str()); printer.printf(COLOR_WHITE "=================== Datetime: %s ==================\n\n" COLOR_RESET, buffer.c_str());
// ===== HEAP ===== // ===== HEAP =====
size_t freeHeap = esp_get_free_heap_size(); size_t freeHeap = esp_get_free_heap_size();
@@ -121,7 +121,7 @@ void printRunningTasksMod(Print &printer, std::function<bool(const TaskStatus_t
// ===== RAM INTERNA ===== // ===== RAM INTERNA =====
size_t freeInternal = heap_caps_get_free_size(MALLOC_CAP_INTERNAL); size_t freeInternal = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
size_t totalInternal = heap_caps_get_total_size(MALLOC_CAP_INTERNAL); size_t totalInternal = heap_caps_get_total_size(MALLOC_CAP_INTERNAL);
printBar(printer, "INTERNAL", totalInternal - freeInternal, totalInternal, COLOR_BLUE); printBar(printer, "INTERNAL", totalInternal - freeInternal, totalInternal, COLOR_CYAN);
// ===== PSRAM ===== // ===== PSRAM =====
size_t totalPsram = heap_caps_get_total_size(MALLOC_CAP_SPIRAM); size_t totalPsram = heap_caps_get_total_size(MALLOC_CAP_SPIRAM);
@@ -160,13 +160,13 @@ void printRunningTasksMod(Print &printer, std::function<bool(const TaskStatus_t
size_t minHeap = esp_get_minimum_free_heap_size(); size_t minHeap = esp_get_minimum_free_heap_size();
printer.printf("%s\nMin Heap Ever:%s %u KB\n", COLOR_RED, COLOR_RESET, minHeap / 1024); printer.printf("%s\nMin Heap Ever:%s %u KB\n", COLOR_RED, COLOR_RESET, minHeap / 1024);
size_t max_block = heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM); size_t max_block = heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM);
printer.printf("%s\nMax PSRAM Block:%s %u KB\n\n", COLOR_RED, COLOR_RESET, max_block / 1024); printer.printf("%sMax PSRAM Block:%s %u KB\n\n", COLOR_RED, COLOR_RESET, max_block / 1024);
// Print Runtime Information // Print Runtime Information
printer.printf("Tasks: %u, Runtime: %lus, Period: %luus\r\n", uxArraySize, ulTotalRunTime / 1000000, ulCurrentRunTime); printer.printf("Tasks: %u, Runtime: %lus, Period: %luus\n", uxArraySize, ulTotalRunTime / 1000000, ulCurrentRunTime);
// Print Task Headers // Print Task Headers
printer.printf("Num\t Name\tLoad\tPrio\t Free\tCore\tState\r\n"); printer.printf("Num\t Name\tLoad\tPrio\t Free\tCore\tState\n");
for (const auto &task : pxTaskStatusArray) for (const auto &task : pxTaskStatusArray)
{ {
@@ -179,7 +179,7 @@ void printRunningTasksMod(Print &printer, std::function<bool(const TaskStatus_t
"\t%3lu%%" "\t%3lu%%"
"\t%4u\t%5lu" "\t%4u\t%5lu"
"\t%4c" "\t%4c"
"\t%s\r\n", "\t%s\n",
task.xTaskNumber, task.pcTaskName, task.xTaskNumber, task.pcTaskName,
ulTaskRunTime, ulTaskRunTime,
task.uxCurrentPriority, task.usStackHighWaterMark, task.uxCurrentPriority, task.usStackHighWaterMark,
+49 -38
View File
@@ -1,9 +1,4 @@
#include <webserver.h> #include <webserver.h>
#include <ArduinoJson.h>
static std::map<const std::string, AstroWebServer::c_commandEnum> s_webserverCommands = {
{"setTime", AstroWebServer::SET_TIME},
};
void on_ping(TimerHandle_t xTimer) void on_ping(TimerHandle_t xTimer)
{ {
@@ -14,7 +9,7 @@ void on_ping(TimerHandle_t xTimer)
ws->cleanupClients(); ws->cleanupClients();
} }
AstroWebServer::AstroWebServer(const uint8_t port, fs::FS &filesystem) : m_port(port), m_webserver(AsyncWebServer(port)), m_websocket(AsyncWebSocket("/ws")), m_filesystem(filesystem) AstroWebServer::AstroWebServer(const uint8_t port, fs::FS &filesystem) : c_port(port), m_webserver(AsyncWebServer(port)), m_websocket(AsyncWebSocket("/ws")), m_filesystem(filesystem)
{ {
LOG_DEBUG("Initializing Web Server"); LOG_DEBUG("Initializing Web Server");
m_websocket.onEvent([this](AsyncWebSocket *server, AsyncWebSocketClient *client, m_websocket.onEvent([this](AsyncWebSocket *server, AsyncWebSocketClient *client,
@@ -31,12 +26,18 @@ AstroWebServer::AstroWebServer(const uint8_t port, fs::FS &filesystem) : m_port(
m_webserver.begin(); m_webserver.begin();
m_websocket.enable(true); m_websocket.enable(true);
m_pingTimer = xTimerCreate("wsPingTimer", pdMS_TO_TICKS(2000), pdTRUE, (void *)&m_websocket, on_ping); m_pingTimer = xTimerCreate("wsPingTimer", pdMS_TO_TICKS(c_pingTime), pdTRUE, (void *)&m_websocket, on_ping);
xTimerStart(m_pingTimer, pdMS_TO_TICKS(10));
registerWsCommand("setTime", [this](const ArduinoJson::JsonDocument &doc)
{ onSetTme(doc); });
LOG_DEBUG("Webserver Init OK"); LOG_DEBUG("Webserver Init OK");
} }
AstroWebServer::~AstroWebServer() AstroWebServer::~AstroWebServer()
{ {
xTimerStop(m_pingTimer, 0);
xTimerDelete(m_pingTimer, pdMS_TO_TICKS(10)); xTimerDelete(m_pingTimer, pdMS_TO_TICKS(10));
m_webserver.removeHandler(&m_websocket); m_webserver.removeHandler(&m_websocket);
m_webserver.end(); m_webserver.end();
@@ -50,18 +51,33 @@ void AstroWebServer::sendWsData(const String &data)
} }
} }
void AstroWebServer::registerWsCommand(const std::string &cmd, const WScommand func)
{
if (cmd.empty() || m_webserverCommands.contains(cmd))
return;
if (!func)
return;
m_webserverCommands[cmd] = func;
}
void AstroWebServer::unRegisterWsCommand(const std::string &cmd)
{
if (m_webserverCommands.contains(cmd))
m_webserverCommands.erase(cmd);
}
void AstroWebServer::onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) void AstroWebServer::onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len)
{ {
switch (type) switch (type)
{ {
case WS_EVT_CONNECT: case WS_EVT_CONNECT:
LOG_DEBUG("WS client IP[", client->remoteIP().toString().c_str(), "]-ID[", client->id(), "] CONNECTED"); LOG_DEBUG("WS client IP [", client->remoteIP().toString().c_str(), "]-ID [", client->id(), "] CONNECTED");
break; break;
case WS_EVT_DISCONNECT: case WS_EVT_DISCONNECT:
LOG_DEBUG("WS client IP[", client->remoteIP().toString().c_str(), "]-ID[", client->id(), "] DISCONNECTED"); LOG_DEBUG("WS client IP [", client->remoteIP().toString().c_str(), "]-ID [", client->id(), "] DISCONNECTED");
break; break;
case WS_EVT_PONG: case WS_EVT_PONG:
LOG_DEBUG("WS client IP[", client->remoteIP().toString().c_str(), "]-ID[", client->id(), "] PONG"); LOG_DEBUG("WS client IP [", client->remoteIP().toString().c_str(), "]-ID [", client->id(), "] PONG");
break; break;
case WS_EVT_DATA: case WS_EVT_DATA:
{ {
@@ -75,38 +91,13 @@ void AstroWebServer::onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *cli
LOG_ERROR("WS Client unable to deserialize Json"); LOG_ERROR("WS Client unable to deserialize Json");
return; return;
} }
if (!doc["cmd"].is<std::string>() || !s_webserverCommands.contains(doc["cmd"])) if (!doc["cmd"].is<std::string>() || !m_webserverCommands.contains(doc["cmd"]))
{ {
LOG_WARN("WS Client Invalid Json command [", doc["cmd"].as<std::string>().c_str(), "]"); LOG_WARN("WS Client Invalid Json command [", doc["cmd"].as<std::string>().c_str(), "]");
return; return;
} }
std::string buffer; // execute callback function
switch (s_webserverCommands.at(doc["cmd"])) m_webserverCommands[doc["cmd"]](doc);
{
case SET_TIME:
{
auto epoch = doc["time"].as<time_t>();
timeval te{
.tv_sec = epoch,
.tv_usec = 0,
};
timezone tz{
.tz_minuteswest = 0,
.tz_dsttime = DST_MET,
};
settimeofday(&te, &tz);
time_t now = time(nullptr);
struct tm *t = localtime(&now);
buffer.resize(64);
strftime(buffer.data(), sizeof(buffer), "%Y-%m-%d %H:%M:%S", t);
LOG_DEBUG("WS Client set Datetime to: ", buffer.c_str());
break;
}
default:
// call external command callback
break;
}
} }
} }
} }
@@ -164,3 +155,23 @@ void AstroWebServer::onUploadHandler(AsyncWebServerRequest *request, const Strin
LOG_INFO("Uploaded file to LittleFS:", filename.c_str()); LOG_INFO("Uploaded file to LittleFS:", filename.c_str());
} }
} }
void AstroWebServer::onSetTme(const ArduinoJson::JsonDocument &doc)
{
std::string buffer;
auto epoch = doc["time"].as<time_t>();
timeval te{
.tv_sec = epoch,
.tv_usec = 0,
};
timezone tz{
.tz_minuteswest = 0,
.tz_dsttime = DST_MET,
};
settimeofday(&te, &tz);
time_t now = time(nullptr);
struct tm *t = localtime(&now);
buffer.resize(64);
strftime(buffer.data(), sizeof(buffer), "%Y-%m-%d %H:%M:%S", t);
LOG_DEBUG("WS Client set Datetime to: ", buffer.c_str());
}
+10 -11
View File
@@ -8,11 +8,13 @@
#include <AsyncTCP.h> #include <AsyncTCP.h>
#include <filesystem> #include <filesystem>
#include <map> #include <map>
#include <FS.h> #include <FS.h>
#include <ArduinoJson.h>
class AstroWebServer class AstroWebServer
{ {
public:
using WScommand = std::function<void(const ArduinoJson::JsonDocument &)>;
public: public:
AstroWebServer(const uint8_t port, fs::FS &filesystem); AstroWebServer(const uint8_t port, fs::FS &filesystem);
@@ -20,6 +22,9 @@ public:
void sendWsData(const String &data); void sendWsData(const String &data);
void registerWsCommand(const std::string &cmd, const WScommand func);
void unRegisterWsCommand(const std::string &cmd);
private: private:
void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client,
AwsEventType type, void *arg, uint8_t *data, size_t len); AwsEventType type, void *arg, uint8_t *data, size_t len);
@@ -27,22 +32,16 @@ private:
void onUploadRequest(AsyncWebServerRequest *request); void onUploadRequest(AsyncWebServerRequest *request);
void onUploadHandler(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final); void onUploadHandler(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final);
void onStart(AsyncWebServerRequest *request); void onSetTme(const ArduinoJson::JsonDocument &doc);
void onStop(AsyncWebServerRequest *request);
void onDownload(AsyncWebServerRequest *request);
private: private:
const uint8_t m_port = 80; const uint8_t c_port = 80;
const uint32_t c_pingTime = 5000;
fs::FS &m_filesystem; fs::FS &m_filesystem;
AsyncWebServer m_webserver; AsyncWebServer m_webserver;
AsyncWebSocket m_websocket; AsyncWebSocket m_websocket;
bool m_uploadFailed = false; bool m_uploadFailed = false;
fs::File m_uploadFile; fs::File m_uploadFile;
TimerHandle_t m_pingTimer = NULL; TimerHandle_t m_pingTimer = NULL;
std::map<const std::string, AstroWebServer::WScommand> m_webserverCommands;
public:
enum c_commandEnum
{
SET_TIME
};
}; };