diff --git a/FeatureRequest.md b/FeatureRequest.md index 5eddc5dc..66f14d29 100644 --- a/FeatureRequest.md +++ b/FeatureRequest.md @@ -11,6 +11,12 @@ ____ +#### #12 Less reboots due to memory leakage + +* Issue: #414 & #425 #430 + + + #### #11 MQTT - configurable payload * https://github.com/jomjol/AI-on-the-edge-device/issues/344 diff --git a/README.md b/README.md index 92bd3367..3b3066c5 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,20 @@ In other cases you can contact the developer via email: show(); -*/ +// leds[ 0 ] = Rgb{ 255, 0, 0 }; +// leds[ 1 ] = Rgb{ 255, 255, 255 }; +// leds.show(); +// SmartLed leds = new SmartLed(LEDType, LEDNumbers, gpioExtLED, 0, DoubleBuffer); +// _SmartLED = new SmartLed( LED_WS2812, 2, GPIO_NUM_12, 0, DoubleBuffer ); } return true; @@ -565,18 +560,41 @@ void GpioHandler::flashLightEnable(bool value) { if (it->second->getMode() == GPIO_PIN_MODE_EXTERNAL_FLASH_WS281X) { +#ifdef __LEDGLOBAL + if (leds_global == NULL) { + ESP_LOGI(TAG_SERVERGPIO, "init SmartLed: LEDNumber=%d, GPIO=%d", LEDNumbers, (int)it->second->getGPIO()); + leds_global = new SmartLed( LEDType, LEDNumbers, it->second->getGPIO(), 0, DoubleBuffer ); + } else { + // wait until we can update: https://github.com/RoboticsBrno/SmartLeds/issues/10#issuecomment-386921623 + leds_global->wait(); + } +#else SmartLed leds( LEDType, LEDNumbers, it->second->getGPIO(), 0, DoubleBuffer ); +#endif + if (value) { for (int i = 0; i < LEDNumbers; ++i) +#ifdef __LEDGLOBAL + (*leds_global)[i] = LEDColor; +#else leds[i] = LEDColor; +#endif } else { for (int i = 0; i < LEDNumbers; ++i) +#ifdef __LEDGLOBAL + (*leds_global)[i] = Rgb{0, 0, 0}; +#else leds[i] = Rgb{0, 0, 0}; +#endif } - leds.show(); +#ifdef __LEDGLOBAL + leds_global->show(); +#else + leds.show(); +#endif } } } diff --git a/code/components/jomjol_controlGPIO/server_GPIO.h b/code/components/jomjol_controlGPIO/server_GPIO.h index 7e708222..074b08af 100644 --- a/code/components/jomjol_controlGPIO/server_GPIO.h +++ b/code/components/jomjol_controlGPIO/server_GPIO.h @@ -11,6 +11,9 @@ //#include "ClassControllCamera.h" +// wenn __LEDGLOBAL definiert ist, wird eine globale Variable für die LED-Ansteuerung verwendet, ansonsten lokal und jedesmal neu +#define __LEDGLOBAL + typedef enum { GPIO_PIN_MODE_DISABLED = 0x0, GPIO_PIN_MODE_INPUT = 0x1, @@ -86,7 +89,9 @@ private: int LEDNumbers = 2; Rgb LEDColor = Rgb{ 255, 255, 255 }; LedType LEDType = LED_WS2812; - +#ifdef __LEDGLOBAL + SmartLed *leds_global = NULL; +#endif bool readConfig(); void clear(); diff --git a/code/components/jomjol_flowcontroll/ClassFlowControll.cpp b/code/components/jomjol_flowcontroll/ClassFlowControll.cpp index aac8c8e3..e0a59bfe 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowControll.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlowControll.cpp @@ -624,4 +624,30 @@ esp_err_t ClassFlowControll::GetJPGStream(std::string _fn, httpd_req_t *req) } return result; -} \ No newline at end of file +} + + +string ClassFlowControll::getJSON() +{ + std::vector* NUMBERS = flowpostprocessing->GetNumbers(); + + std::string json="{\n"; + + for (int i = 0; i < (*NUMBERS).size(); ++i) + { + json += "\"" + (*NUMBERS)[i]->name + "\":\n"; + json += " {\n"; + json += " \"value\": " + (*NUMBERS)[i]->ReturnValueNoError + ",\n"; + json += " \"raw\": \"" + (*NUMBERS)[i]->ReturnRawValue + "\",\n"; + json += " \"error\": \"" + (*NUMBERS)[i]->ErrorMessageText + "\",\n"; + json += " \"rate\": " + std::to_string((*NUMBERS)[i]->FlowRateAct) + ",\n"; + json += " \"timestamp\": \"" + (*NUMBERS)[i]->timeStamp + "\"\n"; + if ((i+1) < (*NUMBERS).size()) + json += " },\n"; + else + json += " }\n"; + } + json += "}"; + + return json; +} diff --git a/code/components/jomjol_flowcontroll/ClassFlowControll.h b/code/components/jomjol_flowcontroll/ClassFlowControll.h index 904259ef..3f568b26 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowControll.h +++ b/code/components/jomjol_flowcontroll/ClassFlowControll.h @@ -48,6 +48,7 @@ public: string UpdatePrevalue(std::string _newvalue, std::string _numbers, bool _extern); string GetPrevalue(std::string _number = ""); bool ReadParameter(FILE* pfile, string& aktparamgraph); + string getJSON(); string TranslateAktstatus(std::string _input); diff --git a/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.cpp b/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.cpp index 027f34a1..7aefd09f 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.cpp @@ -492,8 +492,6 @@ void ClassFlowPostProcessing::InitNUMBERS() _number->MaxRateValue = 0.1; _number->useMaxRateValue = false; _number->checkDigitIncreaseConsistency = false; - _number->PreValueOkay = false; - _number->useMaxRateValue = false; _number->DecimalShift = 0; _number->DecimalShiftInitial = 0; _number->isExtendedResolution = false; @@ -568,12 +566,8 @@ bool ClassFlowPostProcessing::doFlow(string zwtime) time_t imagetime = 0; string rohwert; -// ErrorMessageText = ""; - // Update Nachkomma, da sich beim Wechsel von CNNType Auto --> xyz auch die Nachkommastellen ändern können: - - imagetime = flowMakeImage->getTimeImageTaken(); if (imagetime == 0) time(&imagetime); @@ -662,7 +656,7 @@ bool ClassFlowPostProcessing::doFlow(string zwtime) zwvalue = RundeOutput(NUMBERS[j]->Value, NUMBERS[j]->Nachkomma); } - if (NUMBERS[j]->useMaxRateValue && (abs(NUMBERS[j]->Value - NUMBERS[j]->PreValue) > NUMBERS[j]->MaxRateValue)) + if (NUMBERS[j]->useMaxRateValue && ((abs(NUMBERS[j]->Value - NUMBERS[j]->PreValue) > NUMBERS[j]->MaxRateValue))) { NUMBERS[j]->ErrorMessageText = NUMBERS[j]->ErrorMessageText + "Rate too high - Read: " + RundeOutput(NUMBERS[j]->Value, NUMBERS[j]->Nachkomma) + " - Pre: " + RundeOutput(NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma); NUMBERS[j]->Value = NUMBERS[j]->PreValue; @@ -688,6 +682,8 @@ bool ClassFlowPostProcessing::doFlow(string zwtime) UpdatePreValueINI = true; } } + string _zw = "PostProcessing - Raw: " + NUMBERS[j]->ReturnRawValue + " Value: " + NUMBERS[j]->ReturnValue + " Error: " + NUMBERS[j]->ErrorMessageText; + LogFile.WriteToFile(_zw); } SavePreValue(); @@ -724,8 +720,8 @@ void ClassFlowPostProcessing::UpdateNachkommaDecimalShift() { // printf("Nur digital + analog\n"); - NUMBERS[j]->Nachkomma = NUMBERS[j]->analog_roi->ROI.size(); NUMBERS[j]->DecimalShift = NUMBERS[j]->DecimalShiftInitial; + NUMBERS[j]->Nachkomma = NUMBERS[j]->analog_roi->ROI.size() - NUMBERS[j]->DecimalShift; if (NUMBERS[j]->isExtendedResolution && flowAnalog->isExtendedResolution()) // extended resolution ist an und soll auch bei dieser Ziffer verwendet werden NUMBERS[j]->Nachkomma = NUMBERS[j]->Nachkomma+1; diff --git a/code/components/jomjol_helper/Helper.cpp b/code/components/jomjol_helper/Helper.cpp index d5479c31..d8537b86 100644 --- a/code/components/jomjol_helper/Helper.cpp +++ b/code/components/jomjol_helper/Helper.cpp @@ -80,7 +80,7 @@ void memCopyGen(uint8_t* _source, uint8_t* _target, int _size) FILE* OpenFileAndWait(const char* nm, const char* _mode, int _waitsec) { - printf("open config file %s in mode %s\n", nm, _mode); + printf("open file %s in mode %s\n", nm, _mode); FILE *pfile = fopen(nm, _mode); /* diff --git a/code/components/jomjol_tfliteclass/server_tflite.cpp b/code/components/jomjol_tfliteclass/server_tflite.cpp index 354f9250..0469522a 100644 --- a/code/components/jomjol_tfliteclass/server_tflite.cpp +++ b/code/components/jomjol_tfliteclass/server_tflite.cpp @@ -189,6 +189,36 @@ esp_err_t handler_doflow(httpd_req_t *req) }; +esp_err_t handler_json(httpd_req_t *req) +{ +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("handler_json - Start"); +#endif + + + printf("handler_JSON uri:\n"); printf(req->uri); printf("\n"); + + char _query[100]; + char _size[10]; + + httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); + httpd_resp_set_type(req, "application/json"); + + std::string zw = tfliteflow.getJSON(); + if (zw.length() > 0) + httpd_resp_sendstr_chunk(req, zw.c_str()); + + string query = std::string(_query); + + /* Respond with an empty chunk to signal HTTP response completion */ + httpd_resp_sendstr_chunk(req, NULL); + +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("handler_JSON - Done"); +#endif + return ESP_OK; +}; + esp_err_t handler_wasserzaehler(httpd_req_t *req) @@ -710,4 +740,10 @@ void register_server_tflite_uri(httpd_handle_t server) camuri.handler = handler_wasserzaehler; camuri.user_ctx = (void*) "Wasserzaehler"; httpd_register_uri_handler(server, &camuri); + + camuri.uri = "/json"; + camuri.handler = handler_json; + camuri.user_ctx = (void*) "JSON"; + httpd_register_uri_handler(server, &camuri); + } diff --git a/code/main/Color.cpp b/code/main/Color.cpp deleted file mode 100644 index b2beb9ac..00000000 --- a/code/main/Color.cpp +++ /dev/null @@ -1,132 +0,0 @@ -#include "Color.h" -#include -#include -#include - -namespace { - -// Int -> fixed point -int up( int x ) { return x * 255; } - -} // namespace - -int iRgbSqrt( int num ) { - // https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Binary_numeral_system_.28base_2.29 - assert( "sqrt input should be non-negative" && num >= 0 ); - assert( "sqrt input should no exceed 16 bits" && num <= 0xFFFF ); - int res = 0; - int bit = 1 << 16; - while ( bit > num ) - bit >>= 2; - while ( bit != 0 ) { - if ( num >= res + bit ) { - num -= res + bit; - res = ( res >> 1 ) + bit; - } else - res >>= 1; - bit >>= 2; - } - return res; -} - -Rgb::Rgb( Hsv y ) { - // https://stackoverflow.com/questions/24152553/hsv-to-rgb-and-back-without-floating-point-math-in-python - // greyscale - if( y.s == 0 ) { - r = g = b = y.v; - return; - } - - const int region = y.h / 43; - const int remainder = ( y.h - ( region * 43 ) ) * 6; - - const int p = ( y.v * ( 255 - y.s ) ) >> 8; - const int q = ( y.v * ( 255 - ( ( y.s * remainder ) >> 8 ) ) ) >> 8; - const int t = ( y.v * ( 255 - ( ( y.s * (255 -remainder ) ) >> 8 ) ) ) >> 8; - - switch( region ) { - case 0: r = y.v; g = t; b = p; break; - case 1: r = q; g = y.v; b = p; break; - case 2: r = p; g = y.v; b = t; break; - case 3: r = p; g = q; b = y.v; break; - case 4: r = t; g = p; b = y.v; break; - case 5: r = y.v; g = p; b = q; break; - default: __builtin_trap(); - } - - a = y.a; -} - -Rgb& Rgb::operator=( Hsv hsv ) { - Rgb r{ hsv }; - swap( r ); - return *this; -} - -Rgb Rgb::operator+( Rgb in ) const { - auto copy = *this; - copy += in; - return copy; -} - -Rgb& Rgb::operator+=( Rgb in ) { - unsigned int red = r + in.r; - r = ( red < 255 ) ? red : 255; - unsigned int green = g + in.g; - g = ( green < 255 ) ? green : 255; - unsigned int blue = b + in.b; - b = ( blue < 255 ) ? blue : 255; - return *this; -} - -Rgb& Rgb::blend( Rgb in ) { - unsigned int inAlpha = in.a * ( 255 - a ); - unsigned int alpha = a + inAlpha; - r = iRgbSqrt( ( ( r * r * a ) + ( in.r * in.r * inAlpha ) ) / alpha ); - g = iRgbSqrt( ( ( g * g * a ) + ( in.g * in.g * inAlpha ) ) / alpha ); - b = iRgbSqrt( ( ( b * b * a ) + ( in.b * in.b * inAlpha ) ) / alpha ); - a = alpha; - return *this; -} - -uint8_t IRAM_ATTR Rgb::getGrb( int idx ) { - switch ( idx ) { - case 0: return g; - case 1: return r; - case 2: return b; - } - __builtin_unreachable(); -} - -Hsv::Hsv( Rgb r ) { - int min = std::min( r.r, std::min( r.g, r.b ) ); - int max = std::max( r.r, std::max( r.g, r.b ) ); - int chroma = max - min; - - v = max; - if ( chroma == 0 ) { - h = s = 0; - return; - } - - s = up( chroma ) / max; - int hh; - if ( max == r.r ) - hh = ( up( int( r.g ) - int( r.b ) ) ) / chroma / 6; - else if ( max == r.g ) - hh = 255 / 3 + ( up( int( r.b ) - int( r.r ) ) ) / chroma / 6; - else - hh = 2 * 255 / 3 + ( up( int( r.r ) - int( r.g ) ) ) / chroma / 6; - - if ( hh < 0 ) - hh += 255; - h = hh; - - a = r.a; -} - -Hsv& Hsv::operator=( Rgb rgb ) { - Hsv h{ rgb }; - swap( h ); - return *this; -} diff --git a/code/main/Color.h b/code/main/Color.h deleted file mode 100644 index 1923cf0b..00000000 --- a/code/main/Color.h +++ /dev/null @@ -1,69 +0,0 @@ -#pragma once - -#include -#include "esp_attr.h" -union Hsv; - -union Rgb { - struct __attribute__ ((packed)) { - uint8_t r, g, b, a; - }; - uint32_t value; - - Rgb( uint8_t r = 0, uint8_t g = 0, uint8_t b = 0, uint8_t a = 255 ) : r( r ), g( g ), b( b ), a( a ) {} - Rgb( Hsv c ); - Rgb& operator=( Rgb rgb ) { swap( rgb ); return *this; } - Rgb& operator=( Hsv hsv ); - Rgb operator+( Rgb in ) const; - Rgb& operator+=( Rgb in ); - bool operator==( Rgb in ) const { return in.value == value; } - Rgb& blend( Rgb in ); - void swap( Rgb& o ) { value = o.value; } - void linearize() { - r = channelGamma(r); - g = channelGamma(g); - b = channelGamma(b); - } - - uint8_t IRAM_ATTR getGrb( int idx ); - - void stretchChannels( uint8_t maxR, uint8_t maxG, uint8_t maxB ) { - r = stretch( r, maxR ); - g = stretch( g, maxG ); - b = stretch( b, maxB ); - } - - void stretchChannelsEvenly( uint8_t max ) { - stretchChannels( max, max, max ); - } - -private: - uint8_t stretch( int value, uint8_t max ) { - return ( value * max ) >> 8; - } - - uint8_t channelGamma( int channel ) { - /* The optimal gamma correction is x^2.8. However, this is expensive to - * compute. Therefore, we use x^3 for gamma correction. Also, we add a - * bias as the WS2812 LEDs do not turn on for values less than 4. */ - if (channel == 0) - return channel; - channel = channel * channel * channel * 251; - channel >>= 24; - return static_cast< uint8_t >( 4 + channel ); - } -}; - -union Hsv { - struct __attribute__ ((packed)) { - uint8_t h, s, v, a; - }; - uint32_t value; - - Hsv( uint8_t h, uint8_t s = 0, uint8_t v = 0, uint8_t a = 255 ) : h( h ), s( s ), v( v ), a( a ) {} - Hsv( Rgb r ); - Hsv& operator=( Hsv h ) { swap( h ); return *this; } - Hsv& operator=( Rgb rgb ); - bool operator==( Hsv in ) const { return in.value == value; } - void swap( Hsv& o ) { value = o.value; } -}; diff --git a/code/main/SmartLeds.cpp b/code/main/SmartLeds.cpp deleted file mode 100644 index a2ba7b29..00000000 --- a/code/main/SmartLeds.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include "SmartLeds.h" - -IsrCore SmartLed::_interruptCore = CoreCurrent; -intr_handle_t SmartLed::_interruptHandle = NULL; - -SmartLed*& IRAM_ATTR SmartLed::ledForChannel( int channel ) { - static SmartLed* table[8] = { nullptr }; - assert( channel < 8 ); - return table[ channel ]; -} - -void IRAM_ATTR SmartLed::interruptHandler(void*) { - for (int channel = 0; channel != 8; channel++) { - auto self = ledForChannel( channel ); - - if ( RMT.int_st.val & (1 << (24 + channel ) ) ) { // tx_thr_event - if ( self ) - self->copyRmtHalfBlock(); - RMT.int_clr.val |= 1 << ( 24 + channel ); - } else if ( RMT.int_st.val & ( 1 << (3 * channel ) ) ) { // tx_end - if ( self ) - xSemaphoreGiveFromISR( self->_finishedFlag, nullptr ); - RMT.int_clr.val |= 1 << ( 3 * channel ); - } - } -} - -void IRAM_ATTR SmartLed::copyRmtHalfBlock() { - int offset = detail::MAX_PULSES * _halfIdx; - _halfIdx = !_halfIdx; - int len = 3 - _componentPosition + 3 * ( _count - 1 ); - len = std::min( len, detail::MAX_PULSES / 8 ); - - if ( !len ) { - for ( int i = 0; i < detail::MAX_PULSES; i++) { - RMTMEM.chan[ _channel].data32[i + offset ].val = 0; - } - } - - int i; - for ( i = 0; i != len && _pixelPosition != _count; i++ ) { - uint8_t val = _buffer[ _pixelPosition ].getGrb( _componentPosition ); - for ( int j = 0; j != 8; j++, val <<= 1 ) { - int bit = val >> 7; - int idx = i * 8 + offset + j; - RMTMEM.chan[ _channel ].data32[ idx ].val = _bitToRmt[ bit & 0x01 ].value; - } - if ( _pixelPosition == _count - 1 && _componentPosition == 2 ) { - RMTMEM.chan[ _channel ].data32[ i * 8 + offset + 7 ].duration1 = - _timing.TRS / ( detail::RMT_DURATION_NS * detail::DIVIDER ); - } - - _componentPosition++; - if ( _componentPosition == 3 ) { - _componentPosition = 0; - _pixelPosition++; - } - } - - for ( i *= 8; i != detail::MAX_PULSES; i++ ) { - RMTMEM.chan[ _channel ].data32[ i + offset ].val = 0; - } -} diff --git a/code/main/SmartLeds.h b/code/main/SmartLeds.h deleted file mode 100644 index 824eb337..00000000 --- a/code/main/SmartLeds.h +++ /dev/null @@ -1,530 +0,0 @@ -#pragma once - -/* - * A C++ driver for the WS2812 LEDs using the RMT peripheral on the ESP32. - * - * Jan "yaqwsx" Mrázek - * - * Based on the work by Martin F. Falatic - https://github.com/FozzTexx/ws2812-demo - */ - -/* - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include - -#if defined ( ARDUINO ) - extern "C" { // ...someone forgot to put in the includes... - #include "esp32-hal.h" - #include "esp_intr_alloc.h" - #include "esp_ipc.h" - #include "driver/gpio.h" - #include "driver/periph_ctrl.h" - #include "freertos/semphr.h" - #include "soc/rmt_struct.h" - #include - #include "esp_idf_version.h" -#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL( 4, 0, 0 ) - #include "soc/dport_reg.h" -#endif - } -#elif defined ( ESP_PLATFORM ) - extern "C" { // ...someone forgot to put in the includes... - #include - #include - #include - #include - #include - #include - #include - #include - #include - } - #include -#endif - -#include "Color.h" - -namespace detail { - -struct TimingParams { - uint32_t T0H; - uint32_t T1H; - uint32_t T0L; - uint32_t T1L; - uint32_t TRS; -}; - -union RmtPulsePair { - struct { - int duration0:15; - int level0:1; - int duration1:15; - int level1:1; - }; - uint32_t value; -}; - -static const int DIVIDER = 4; // 8 still seems to work, but timings become marginal -static const int MAX_PULSES = 32; // A channel has a 64 "pulse" buffer - we use half per pass -static const double RMT_DURATION_NS = 12.5; // minimum time of a single RMT duration based on clock ns - -} // namespace detail - -using LedType = detail::TimingParams; - -static const LedType LED_WS2812 = { 350, 700, 800, 600, 50000 }; -static const LedType LED_WS2812B = { 400, 850, 850, 400, 50100 }; -static const LedType LED_SK6812 = { 300, 600, 900, 600, 80000 }; -static const LedType LED_WS2813 = { 350, 800, 350, 350, 300000 }; - -enum BufferType { SingleBuffer = 0, DoubleBuffer }; - -enum IsrCore { CoreFirst = 0, CoreSecond = 1, CoreCurrent = 2}; - -class SmartLed { -public: - // The RMT interrupt must not run on the same core as WiFi interrupts, otherwise SmartLeds - // can't fill the RMT buffer fast enough, resulting in rendering artifacts. - // Usually, that means you have to set isrCore == CoreSecond. - // - // If you use anything other than CoreCurrent, the FreeRTOS scheduler MUST be already running, - // so you can't use it if you define SmartLed as global variable. - SmartLed( const LedType& type, int count, int pin, int channel = 0, BufferType doubleBuffer = SingleBuffer, IsrCore isrCore = CoreCurrent) - : _timing( type ), - _channel( channel ), - _count( count ), - _firstBuffer( new Rgb[ count ] ), - _secondBuffer( doubleBuffer ? new Rgb[ count ] : nullptr ), - _finishedFlag( xSemaphoreCreateBinary() ) - { - assert( channel >= 0 && channel < 8 ); - assert( ledForChannel( channel ) == nullptr ); - - xSemaphoreGive( _finishedFlag ); - - DPORT_SET_PERI_REG_MASK( DPORT_PERIP_CLK_EN_REG, DPORT_RMT_CLK_EN ); - DPORT_CLEAR_PERI_REG_MASK( DPORT_PERIP_RST_EN_REG, DPORT_RMT_RST ); - - PIN_FUNC_SELECT( GPIO_PIN_MUX_REG[ pin ], 2 ); - gpio_set_direction( static_cast< gpio_num_t >( pin ), GPIO_MODE_OUTPUT ); - gpio_matrix_out( static_cast< gpio_num_t >( pin ), RMT_SIG_OUT0_IDX + _channel, 0, 0 ); - initChannel( _channel ); - - RMT.tx_lim_ch[ _channel ].limit = detail::MAX_PULSES; - RMT.int_ena.val |= 1 << ( 24 + _channel ); - RMT.int_ena.val |= 1 << ( 3 * _channel ); - - _bitToRmt[ 0 ].level0 = 1; - _bitToRmt[ 0 ].level1 = 0; - _bitToRmt[ 0 ].duration0 = _timing.T0H / ( detail::RMT_DURATION_NS * detail::DIVIDER ); - _bitToRmt[ 0 ].duration1 = _timing.T0L / ( detail::RMT_DURATION_NS * detail::DIVIDER ); - - _bitToRmt[ 1 ].level0 = 1; - _bitToRmt[ 1 ].level1 = 0; - _bitToRmt[ 1 ].duration0 = _timing.T1H / ( detail::RMT_DURATION_NS * detail::DIVIDER ); - _bitToRmt[ 1 ].duration1 = _timing.T1L / ( detail::RMT_DURATION_NS * detail::DIVIDER ); - - if ( !anyAlive() ) { - _interruptCore = isrCore; - if(isrCore != CoreCurrent) { - ESP_ERROR_CHECK(esp_ipc_call_blocking(isrCore, registerInterrupt, NULL)); - } else { - registerInterrupt(NULL); - } - } - - ledForChannel( channel ) = this; - } - - ~SmartLed() { - ledForChannel( _channel ) = nullptr; - if ( !anyAlive() ) { - if(_interruptCore != CoreCurrent) { - ESP_ERROR_CHECK(esp_ipc_call_blocking(_interruptCore, unregisterInterrupt, NULL)); - } else { - unregisterInterrupt(NULL); - } - } - vSemaphoreDelete( _finishedFlag ); - } - - Rgb& operator[]( int idx ) { - return _firstBuffer[ idx ]; - } - - const Rgb& operator[]( int idx ) const { - return _firstBuffer[ idx ]; - } - - void show() { - _buffer = _firstBuffer.get(); - startTransmission(); - swapBuffers(); - } - - bool wait( TickType_t timeout = portMAX_DELAY ) { - if( xSemaphoreTake( _finishedFlag, timeout ) == pdTRUE ) { - xSemaphoreGive( _finishedFlag ); - return true; - } - return false; - } - - int size() const { - return _count; - } - - Rgb *begin() { return _firstBuffer.get(); } - const Rgb *begin() const { return _firstBuffer.get(); } - const Rgb *cbegin() const { return _firstBuffer.get(); } - - Rgb *end() { return _firstBuffer.get() + _count; } - const Rgb *end() const { return _firstBuffer.get() + _count; } - const Rgb *cend() const { return _firstBuffer.get() + _count; } - -private: - static intr_handle_t _interruptHandle; - static IsrCore _interruptCore; - - static void initChannel( int channel ) { - RMT.apb_conf.fifo_mask = 1; //enable memory access, instead of FIFO mode. - RMT.apb_conf.mem_tx_wrap_en = 1; //wrap around when hitting end of buffer - RMT.conf_ch[ channel ].conf0.div_cnt = detail::DIVIDER; - RMT.conf_ch[ channel ].conf0.mem_size = 1; - RMT.conf_ch[ channel ].conf0.carrier_en = 0; - RMT.conf_ch[ channel ].conf0.carrier_out_lv = 1; - RMT.conf_ch[ channel ].conf0.mem_pd = 0; - - RMT.conf_ch[ channel ].conf1.rx_en = 0; - RMT.conf_ch[ channel ].conf1.mem_owner = 0; - RMT.conf_ch[ channel ].conf1.tx_conti_mode = 0; //loop back mode. - RMT.conf_ch[ channel ].conf1.ref_always_on = 1; // use apb clock: 80M - RMT.conf_ch[ channel ].conf1.idle_out_en = 1; - RMT.conf_ch[ channel ].conf1.idle_out_lv = 0; - } - - static void registerInterrupt(void *) { - ESP_ERROR_CHECK(esp_intr_alloc( ETS_RMT_INTR_SOURCE, 0, interruptHandler, nullptr, &_interruptHandle)); - } - - static void unregisterInterrupt(void*) { - esp_intr_free( _interruptHandle ); - } - - static SmartLed*& IRAM_ATTR ledForChannel( int channel ); - static void IRAM_ATTR interruptHandler( void* ); - - void IRAM_ATTR copyRmtHalfBlock(); - - void swapBuffers() { - if ( _secondBuffer ) - _firstBuffer.swap( _secondBuffer ); - } - - void startTransmission() { - // Invalid use of the library - if( xSemaphoreTake( _finishedFlag, 0 ) != pdTRUE ) - abort(); - - _pixelPosition = _componentPosition = _halfIdx = 0; - copyRmtHalfBlock(); - if ( _pixelPosition < _count ) - copyRmtHalfBlock(); - - RMT.conf_ch[ _channel ].conf1.mem_rd_rst = 1; - RMT.conf_ch[ _channel ].conf1.tx_start = 1; - } - - static bool anyAlive() { - for ( int i = 0; i != 8; i++ ) - if ( ledForChannel( i ) != nullptr ) return true; - return false; - } - - const LedType& _timing; - int _channel; - detail::RmtPulsePair _bitToRmt[ 2 ]; - int _count; - std::unique_ptr< Rgb[] > _firstBuffer; - std::unique_ptr< Rgb[] > _secondBuffer; - Rgb *_buffer; - - xSemaphoreHandle _finishedFlag; - - int _pixelPosition; - int _componentPosition; - int _halfIdx; -}; - -class Apa102 { -public: - struct ApaRgb { - ApaRgb( uint8_t r = 0, uint8_t g = 0, uint32_t b = 0, uint32_t v = 0xFF ) - : v( 0xE0 | v ), b( b ), g( g ), r( r ) - {} - - ApaRgb& operator=( const Rgb& o ) { - r = o.r; - g = o.g; - b = o.b; - return *this; - } - - ApaRgb& operator=( const Hsv& o ) { - *this = Rgb{ o }; - return *this; - } - - uint8_t v, b, g, r; - }; - - static const int FINAL_FRAME_SIZE = 4; - static const int TRANS_COUNT = 2 + 8; - - Apa102( int count, int clkpin, int datapin, BufferType doubleBuffer = SingleBuffer ) - : _count( count ), - _firstBuffer( new ApaRgb[ count ] ), - _secondBuffer( doubleBuffer ? new ApaRgb[ count ] : nullptr ), - _initFrame( 0 ) - { - spi_bus_config_t buscfg; - memset( &buscfg, 0, sizeof( buscfg ) ); - buscfg.mosi_io_num = datapin; - buscfg.miso_io_num = -1; - buscfg.sclk_io_num = clkpin; - buscfg.quadwp_io_num = -1; - buscfg.quadhd_io_num = -1; - buscfg.max_transfer_sz = 65535; - - spi_device_interface_config_t devcfg; - memset( &devcfg, 0, sizeof( devcfg ) ); - devcfg.clock_speed_hz = 1000000; - devcfg.mode = 0; - devcfg.spics_io_num = -1; - devcfg.queue_size = TRANS_COUNT; - devcfg.pre_cb = nullptr; - - auto ret = spi_bus_initialize( HSPI_HOST, &buscfg, 1 ); - assert( ret == ESP_OK ); - - ret = spi_bus_add_device( HSPI_HOST, &devcfg, &_spi ); - assert( ret == ESP_OK ); - - std::fill_n( _finalFrame, FINAL_FRAME_SIZE, 0xFFFFFFFF ); - } - - ~Apa102() { - // ToDo - } - - ApaRgb& operator[]( int idx ) { - return _firstBuffer[ idx ]; - } - - const ApaRgb& operator[]( int idx ) const { - return _firstBuffer[ idx ]; - } - - void show() { - _buffer = _firstBuffer.get(); - startTransmission(); - swapBuffers(); - } - - void wait() { - for ( int i = 0; i != _transCount; i++ ) { - spi_transaction_t *t; - spi_device_get_trans_result( _spi, &t, portMAX_DELAY ); - } - } -private: - void swapBuffers() { - if ( _secondBuffer ) - _firstBuffer.swap( _secondBuffer ); - } - - void startTransmission() { - for ( int i = 0; i != TRANS_COUNT; i++ ) { - _transactions[ i ].cmd = 0; - _transactions[ i ].addr = 0; - _transactions[ i ].flags = 0; - _transactions[ i ].rxlength = 0; - _transactions[ i ].rx_buffer = nullptr; - } - // Init frame - _transactions[ 0 ].length = 32; - _transactions[ 0 ].tx_buffer = &_initFrame; - spi_device_queue_trans( _spi, _transactions + 0, portMAX_DELAY ); - // Data - _transactions[ 1 ].length = 32 * _count; - _transactions[ 1 ].tx_buffer = _buffer; - spi_device_queue_trans( _spi, _transactions + 1, portMAX_DELAY ); - _transCount = 2; - // End frame - for ( int i = 0; i != 1 + _count / 32 / FINAL_FRAME_SIZE; i++ ) { - _transactions[ 2 + i ].length = 32 * FINAL_FRAME_SIZE; - _transactions[ 2 + i ].tx_buffer = _finalFrame; - spi_device_queue_trans( _spi, _transactions + 2 + i, portMAX_DELAY ); - _transCount++; - } - } - - spi_device_handle_t _spi; - int _count; - std::unique_ptr< ApaRgb[] > _firstBuffer, _secondBuffer; - ApaRgb *_buffer; - - spi_transaction_t _transactions[ TRANS_COUNT ]; - int _transCount; - - uint32_t _initFrame; - uint32_t _finalFrame[ FINAL_FRAME_SIZE ]; -}; - -class LDP8806 { -public: - struct LDP8806_GRB { - - LDP8806_GRB( uint8_t g_7bit = 0, uint8_t r_7bit = 0, uint32_t b_7bit = 0 ) - : g( g_7bit ), r( r_7bit ), b( b_7bit ) - { - } - - LDP8806_GRB& operator=( const Rgb& o ) { - //Convert 8->7bit colour - r = ( o.r * 127 / 256 ) | 0x80; - g = ( o.g * 127 / 256 ) | 0x80; - b = ( o.b * 127 / 256 ) | 0x80; - return *this; - } - - LDP8806_GRB& operator=( const Hsv& o ) { - *this = Rgb{ o }; - return *this; - } - - uint8_t g, r, b; - }; - - static const int LED_FRAME_SIZE_BYTES = sizeof( LDP8806_GRB ); - static const int LATCH_FRAME_SIZE_BYTES = 3; - static const int TRANS_COUNT_MAX = 20;//Arbitrary, supports up to 600 LED - - LDP8806( int count, int clkpin, int datapin, BufferType doubleBuffer = SingleBuffer, uint32_t clock_speed_hz = 2000000 ) - : _count( count ), - _firstBuffer( new LDP8806_GRB[ count ] ), - _secondBuffer( doubleBuffer ? new LDP8806_GRB[ count ] : nullptr ), - // one 'latch'/start-of-data mark frame for every 32 leds - _latchFrames( ( count + 31 ) / 32 ) - { - spi_bus_config_t buscfg; - memset( &buscfg, 0, sizeof( buscfg ) ); - buscfg.mosi_io_num = datapin; - buscfg.miso_io_num = -1; - buscfg.sclk_io_num = clkpin; - buscfg.quadwp_io_num = -1; - buscfg.quadhd_io_num = -1; - buscfg.max_transfer_sz = 65535; - - spi_device_interface_config_t devcfg; - memset( &devcfg, 0, sizeof( devcfg ) ); - devcfg.clock_speed_hz = clock_speed_hz; - devcfg.mode = 0; - devcfg.spics_io_num = -1; - devcfg.queue_size = TRANS_COUNT_MAX; - devcfg.pre_cb = nullptr; - - auto ret = spi_bus_initialize( HSPI_HOST, &buscfg, 1 ); - assert( ret == ESP_OK ); - - ret = spi_bus_add_device( HSPI_HOST, &devcfg, &_spi ); - assert( ret == ESP_OK ); - - std::fill_n( _latchBuffer, LATCH_FRAME_SIZE_BYTES, 0x0 ); - } - - ~LDP8806() { - // noop - } - - LDP8806_GRB& operator[]( int idx ) { - return _firstBuffer[ idx ]; - } - - const LDP8806_GRB& operator[]( int idx ) const { - return _firstBuffer[ idx ]; - } - - void show() { - _buffer = _firstBuffer.get(); - startTransmission(); - swapBuffers(); - } - - void wait() { - while ( _transCount-- ) { - spi_transaction_t *t; - spi_device_get_trans_result( _spi, &t, portMAX_DELAY ); - } - } -private: - void swapBuffers() { - if ( _secondBuffer ) - _firstBuffer.swap( _secondBuffer ); - } - - void startTransmission() { - _transCount = 0; - for ( int i = 0; i != TRANS_COUNT_MAX; i++ ) { - _transactions[ i ].cmd = 0; - _transactions[ i ].addr = 0; - _transactions[ i ].flags = 0; - _transactions[ i ].rxlength = 0; - _transactions[ i ].rx_buffer = nullptr; - } - // LED Data - _transactions[ 0 ].length = ( LED_FRAME_SIZE_BYTES * 8 ) * _count; - _transactions[ 0 ].tx_buffer = _buffer; - spi_device_queue_trans( _spi, _transactions + _transCount, portMAX_DELAY ); - _transCount++; - - // 'latch'/start-of-data marker frames - for ( int i = 0; i < _latchFrames; i++ ) { - _transactions[ _transCount ].length = ( LATCH_FRAME_SIZE_BYTES * 8 ); - _transactions[ _transCount ].tx_buffer = _latchBuffer; - spi_device_queue_trans( _spi, _transactions + _transCount, portMAX_DELAY ); - _transCount++; - } - } - - spi_device_handle_t _spi; - int _count; - std::unique_ptr< LDP8806_GRB[] > _firstBuffer, _secondBuffer; - LDP8806_GRB *_buffer; - - spi_transaction_t _transactions[ TRANS_COUNT_MAX ]; - int _transCount; - - int _latchFrames; - uint8_t _latchBuffer[ LATCH_FRAME_SIZE_BYTES ]; -}; diff --git a/code/main/main.cpp b/code/main/main.cpp index 9b2947fa..6b4fabed 100644 --- a/code/main/main.cpp +++ b/code/main/main.cpp @@ -142,13 +142,7 @@ void task_NoSDBlink(void *pvParameter) extern "C" void app_main(void) { TickType_t xDelay; - - - printf("Do Reset Camera\n"); - PowerResetCamera(); - Camera.InitCam(); - Camera.LightOnOff(false); - + if (!Init_NVS_SDCard()) { xTaskCreate(&task_NoSDBlink, "task_NoSDBlink", configMINIMAL_STACK_SIZE * 64, NULL, tskIDLE_PRIORITY+1, NULL); @@ -176,8 +170,8 @@ extern "C" void app_main(void) printf("DNS IP: %s\n", dns); - wifi_init_sta(ssid, passwd, hostname, ip, gateway, netmask, dns); - + wifi_init_sta(ssid, passwd, hostname, ip, gateway, netmask, dns); + xDelay = 2000 / portTICK_PERIOD_MS; printf("main: sleep for : %ldms\n", (long) xDelay); @@ -198,8 +192,8 @@ extern "C" void app_main(void) printf("time %s\n", zw.c_str()); // Camera.InitCam(); -// Camera.LightOnOff(false); - xDelay = 2000 / portTICK_PERIOD_MS; +// Camera.LightOnOff(false); + xDelay = 2000 / portTICK_PERIOD_MS; printf("main: sleep for : %ldms\n", (long) xDelay); vTaskDelay( xDelay ); @@ -215,6 +209,22 @@ extern "C" void app_main(void) register_server_main_uri(server, "/sdcard"); printf("vor dotautostart\n"); - TFliteDoAutoStart(); + + // init camera module + printf("Do Reset Camera\n"); + PowerResetCamera(); + esp_err_t cam = Camera.InitCam(); + if (cam != ESP_OK) { + ESP_LOGE(TAGMAIN, "Failed to initialize camera module. " + "Check that your camera module is working and connected properly."); + + LogFile.SwitchOnOff(true); + LogFile.WriteToFile("Failed to initialize camera module. " + "Check that your camera module is working and connected properly."); + LogFile.SwitchOnOff(false); + } else { + Camera.LightOnOff(false); + TFliteDoAutoStart(); + } } diff --git a/code/main/version.cpp b/code/main/version.cpp index 85a37164..a5a09117 100644 --- a/code/main/version.cpp +++ b/code/main/version.cpp @@ -1,4 +1,4 @@ -const char* GIT_REV="be90240"; +const char* GIT_REV="e22b4b6"; const char* GIT_TAG=""; const char* GIT_BRANCH="master"; -const char* BUILD_TIME="2021-10-23 16:33"; \ No newline at end of file +const char* BUILD_TIME="2021-12-02 21:53"; \ No newline at end of file diff --git a/code/main/version.h b/code/main/version.h index 3f5c6e29..51e17839 100644 --- a/code/main/version.h +++ b/code/main/version.h @@ -13,7 +13,7 @@ extern "C" #include "Helper.h" #include -const char* GIT_BASE_BRANCH = "master - v9.0.0 - 2021-10-23"; +const char* GIT_BASE_BRANCH = "master - v9.2.0 - 2021-12-02"; const char* git_base_branch(void) diff --git a/code/version.cpp b/code/version.cpp index 85a37164..a5a09117 100644 --- a/code/version.cpp +++ b/code/version.cpp @@ -1,4 +1,4 @@ -const char* GIT_REV="be90240"; +const char* GIT_REV="e22b4b6"; const char* GIT_TAG=""; const char* GIT_BRANCH="master"; -const char* BUILD_TIME="2021-10-23 16:33"; \ No newline at end of file +const char* BUILD_TIME="2021-12-02 21:53"; \ No newline at end of file diff --git a/firmware/bootloader.bin b/firmware/bootloader.bin index 02cb4166..e098b648 100644 Binary files a/firmware/bootloader.bin and b/firmware/bootloader.bin differ diff --git a/firmware/firmware.bin b/firmware/firmware.bin index 1e30840b..13c742bf 100644 Binary files a/firmware/firmware.bin and b/firmware/firmware.bin differ diff --git a/firmware/html.zip b/firmware/html.zip index 36896475..10102500 100644 Binary files a/firmware/html.zip and b/firmware/html.zip differ diff --git a/images/config_s5_ROIs.jpg b/images/config_s5_ROIs.jpg index 53a5b045..406ea0d9 100644 Binary files a/images/config_s5_ROIs.jpg and b/images/config_s5_ROIs.jpg differ diff --git a/images/config_s5_ROIs_details.jpg b/images/config_s5_ROIs_details.jpg new file mode 100644 index 00000000..b7c30e81 Binary files /dev/null and b/images/config_s5_ROIs_details.jpg differ diff --git a/sd-card/config/ana0910s3_longq.tflite b/sd-card/config/ana0910s3_longq.tflite new file mode 100644 index 00000000..045b6a5b Binary files /dev/null and b/sd-card/config/ana0910s3_longq.tflite differ diff --git a/sd-card/config/config.ini b/sd-card/config/config.ini index b4873eb1..2a0f50bb 100644 --- a/sd-card/config/config.ini +++ b/sd-card/config/config.ini @@ -20,7 +20,7 @@ FlipImageSize = false /config/ref1.jpg 442 142 [Digits] -Model = /config/dig1310s3q.tflite +Model = /config/dig1330s1q.tflite ;LogImageLocation = /log/digit ;LogfileRetentionInDays = 3 ModelInputSize = 20 32 @@ -29,7 +29,7 @@ main.dig2 343 126 30 54 main.dig3 391 126 30 54 [Analog] -Model = /config/ana0700s1lq.tflite +Model = /config/ana0910s3_longq.tflite ;LogImageLocation = /log/analog ;LogfileRetentionInDays = 3 ModelInputSize = 32 32 @@ -46,7 +46,7 @@ PreValueAgeStartup = 720 AllowNegativeRates = false main.MaxRateValue = 0.1 ErrorMessage = true -CheckDigitIncreaseConsistency = true +CheckDigitIncreaseConsistency = false ;[MQTT] ;Uri = mqtt://IP-ADRESS:1883 diff --git a/sd-card/config/dig1210s2q.tflite b/sd-card/config/dig1210s2q.tflite deleted file mode 100644 index 0f531fff..00000000 Binary files a/sd-card/config/dig1210s2q.tflite and /dev/null differ diff --git a/sd-card/config/dig1300s1q.tflite b/sd-card/config/dig1300s1q.tflite deleted file mode 100644 index 305335b7..00000000 Binary files a/sd-card/config/dig1300s1q.tflite and /dev/null differ diff --git a/sd-card/config/dig1330s1q.tflite b/sd-card/config/dig1330s1q.tflite new file mode 100644 index 00000000..438327f8 Binary files /dev/null and b/sd-card/config/dig1330s1q.tflite differ diff --git a/sd-card/html/edit_config_param.html b/sd-card/html/edit_config_param.html index 4ab95d21..99622406 100644 --- a/sd-card/html/edit_config_param.html +++ b/sd-card/html/edit_config_param.html @@ -1040,7 +1040,7 @@ textarea { GPIO 12 is usable without restrictions - + GPIO 12 use interrupt diff --git a/sd-card/html/gethost.js b/sd-card/html/gethost.js index e9f056e8..b7cbc078 100644 --- a/sd-card/html/gethost.js +++ b/sd-card/html/gethost.js @@ -3,9 +3,12 @@ function gethost_Version(){ return "1.0.0 - 20200910"; } + function getbasepath(){ var host = window.location.hostname; - if ((host == "127.0.0.1") || (host == "localhost") || (host == "")) + if (((host == "127.0.0.1") || (host == "localhost") || (host == "")) + && ((window.location.port == "80") || (window.location.port == ""))) + { // host = "http://192.168.2.219"; // jomjol interner test // host = "http://192.168.178.46"; // jomjol interner test @@ -18,6 +21,10 @@ function getbasepath(){ { host = "http://" + host; } + + if (window.location.port != "") { + host = host + ":" + window.location.port; + } return host; } diff --git a/sd-card/html/readconfigparam.js b/sd-card/html/readconfigparam.js index 68f7c5c2..1c2f5c63 100644 --- a/sd-card/html/readconfigparam.js +++ b/sd-card/html/readconfigparam.js @@ -2,9 +2,9 @@ function readconfig_Version(){ return "1.0.0 - 20200910"; } -var config_gesamt; -var config_split; -var param; +var config_gesamt = ""; +var config_split = []; +var param = []; var category; var ref = new Array(2); var NUMBERS = new Array(0); diff --git a/sd-card/html/version.txt b/sd-card/html/version.txt index 4a68b557..d8ffaa07 100644 --- a/sd-card/html/version.txt +++ b/sd-card/html/version.txt @@ -1 +1 @@ -11.0.0 \ No newline at end of file +11.1.0 \ No newline at end of file