Просмотр исходного кода

Merge branch 'jomjol:master' into master

Stefan 4 лет назад
Родитель
Сommit
b3afc9961d

+ 6 - 0
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

+ 13 - 0
README.md

@@ -47,7 +47,20 @@ In other cases you can contact the developer via email: <img src="https://raw.gi
 
 **General remark:** Beside the `firmware.bin`, typically also the content of `/html` needs to be updated!
 
+##### 9.2.0 - External Illumination (2021-12-02)
 
+- Direct JSON access: ``http://IP-ADRESS/json`` 
+- Error message in log file in case camera error during startup
+- Upgrade analog CNN to v9.1.0
+- Upgrade digital CNN to v13.3.0 (added new images)
+- html: support of different ports
+
+##### 9.1.1 - External Illumination (2021-11-16)
+
+- NEW 9.1.1 bug fix: LED implemenetation
+- External LEDs: change control mode (resolve bug with more than 2 LEDs)
+- Additional info into log file
+- Bug fix: decimal shift, html, log file
 
 ##### 9.0.0 - External Illumination (2021-10-23)
 

+ 31 - 13
code/components/jomjol_controlGPIO/server_GPIO.cpp

@@ -400,24 +400,19 @@ bool GpioHandler::readConfig()
 
     if (gpioExtLED > 0)
     {
-    //    LogFile.WriteToFile("Startsequence 06");      
+    //     LogFile.WriteToFile("Startsequence 06");      // Nremove
 //        vTaskDelay( xDelay );   
 //        xDelay = 5000 / portTICK_PERIOD_MS;
 //        printf("main: sleep for : %ldms\n", (long) xDelay);
 
-        SmartLed leds( LED_WS2812, 2, GPIO_NUM_12, 0, DoubleBuffer );
+//        SmartLed leds( LED_WS2812, 2, GPIO_NUM_12, 0, DoubleBuffer );
 
 
-        leds[ 0 ] = Rgb{ 255, 0, 0 };
-        leds[ 1 ] = Rgb{ 255, 255, 255 };
-        leds.show();    
-/*
-//        _SmartLED = new SmartLed(LEDType, LEDNumbers, gpioExtLED, 0, DoubleBuffer);
-        _SmartLED = new SmartLed( LED_WS2812, 2, GPIO_NUM_12, 0, DoubleBuffer );
-        (*_SmartLED)[ 0 ] = Rgb{ 255, 0, 0 };
-        (*_SmartLED)[ 1 ] = LEDColor;
-        _SmartLED->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 
                     }
                 }
         }

+ 6 - 1
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();

+ 27 - 1
code/components/jomjol_flowcontroll/ClassFlowControll.cpp

@@ -624,4 +624,30 @@ esp_err_t ClassFlowControll::GetJPGStream(std::string _fn, httpd_req_t *req)
     }
 
     return result;
-}
+}
+
+
+string ClassFlowControll::getJSON()
+{
+    std::vector<NumberPost*>* 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;
+}

+ 1 - 0
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);
 

+ 4 - 8
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;

+ 1 - 1
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);
 
 /*

+ 36 - 0
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);     
+
 }

+ 0 - 132
code/main/Color.cpp

@@ -1,132 +0,0 @@
-#include "Color.h"
-#include <algorithm>
-#include <cmath>
-#include <cassert>
-
-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;
-}

+ 0 - 69
code/main/Color.h

@@ -1,69 +0,0 @@
-#pragma once
-
-#include <cstdint>
-#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; }
-};

+ 0 - 63
code/main/SmartLeds.cpp

@@ -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;
-    }
-}

+ 0 - 530
code/main/SmartLeds.h

@@ -1,530 +0,0 @@
-#pragma once
-
-/*
- * A C++ driver for the WS2812 LEDs using the RMT peripheral on the ESP32.
- *
- * Jan "yaqwsx" Mrázek <email@honzamrazek.cz>
- *
- * 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 <memory>
-#include <cassert>
-#include <cstring>
-
-#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 <driver/spi_master.h>
-        #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 <esp_intr_alloc.h>
-        #include <esp_ipc.h>
-        #include <driver/gpio.h>
-        #include <freertos/FreeRTOS.h>
-        #include <freertos/semphr.h>
-        #include <soc/dport_reg.h>
-        #include <soc/gpio_sig_map.h>
-        #include <soc/rmt_struct.h>
-        #include <driver/spi_master.h>
-    }
-    #include <stdio.h>
-#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 ];
-};

+ 22 - 12
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();
+    }
 }
 

+ 2 - 2
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";
+const char* BUILD_TIME="2021-12-02 21:53";

+ 1 - 1
code/main/version.h

@@ -13,7 +13,7 @@ extern "C"
 #include "Helper.h"
 #include <fstream>
 
-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)

+ 2 - 2
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";
+const char* BUILD_TIME="2021-12-02 21:53";

BIN
firmware/bootloader.bin


BIN
firmware/firmware.bin


BIN
firmware/html.zip


BIN
images/config_s5_ROIs.jpg


BIN
images/config_s5_ROIs_details.jpg


BIN
sd-card/config/ana0910s3_longq.tflite


+ 3 - 3
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

BIN
sd-card/config/dig1210s2q.tflite


BIN
sd-card/config/dig1300s1q.tflite


BIN
sd-card/config/dig1330s1q.tflite


+ 1 - 1
sd-card/html/edit_config_param.html

@@ -1040,7 +1040,7 @@ textarea {
 				GPIO 12 is usable without restrictions
 			</td>
 		</tr>
-		<tr class=expert class="GPIO_IO12 GPIO_item">
+		<tr class="expert" class="GPIO_IO12 GPIO_item">
 			<td width="20px"  style="padding-left: 40px;"></td>
 			<td>
 				<span class="GPIO_IO12 GPIO_item">GPIO 12 use interrupt</span>

+ 8 - 1
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;
 }
 

+ 3 - 3
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);

+ 1 - 1
sd-card/html/version.txt

@@ -1 +1 @@
-11.0.0
+11.1.0