Re: ESP32 domácí automatizace

Jaroslav Buchta jaroslav.buchta na hascomp.cz
Úterý Srpen 3 07:43:23 CEST 2021


No, vytvaret tasky pro podobne ucely mi prijde velmi overkill metoda, 
ono to ma velkou rezii, nejen na pamet...
Normalne toto resim stavovym automatem, kde se casovani odvozuje od 
systemoveho casu a je to neblokujici. Pokud se ma v nejakem stavu cekat, 
tak se proste testuje, jestli uz je cas dosazen, pokud ne, nedela se nic 
a funkce konci do dalsi iterace/obsluhy neceho jineho, pokud ano, zmeni 
se stav a provede se akce.
Ale mozne jsou i jine postupy, treba jsem nekdy pouzil i knihovnu 
protothread, ESP32 ji ma myslim v API a je to takovy kooperativni 
multitasking, s minimalnimi naroky na system (Protothreads - 
Lightweight, Stackless Threads in C (dunkels.com) 
<http://dunkels.com/adam/pt/>)

Dne 03.08.2021 v 7:35 Jan Půhoný napsal(a):
> Tak jsem to přepsal na vTaskDelayUntil , ale chová se to stejně. 
> Problém je totiž v tom, že když se stiskne tlačítko we webovém 
> rozhraní pro ovládání toho ventilu rychleji než se provede ten task, 
> pustí se task pro otevírání a zavírání přes sebe a pak dochází k tomu, 
> že to zůstane viset někde uprostřed. Pro tuto aplikaci asi nebude 
> zásadní rozdíl mezi vTaskDelayUntil a vTaskDelay.
>
> Ošetřil jsem to přidáním proměnné unBlock, která blokuje čtení 
> tlačítka po dobu spuštění tasku. Takto to funguje spolehlivě. Nicméně 
> předpokládám, že to jde vyřešit nějak elegantněji. *Jak se to správně 
> dělá?*
>
> Díky,
>
> HP
>
> Callback tlačítka:
> button1.attachCallback([&](bool value)
>                          {
>                            /* Print our new button value received from dashboard */
> Serial.println("Button Triggered: " + String((value) ? "true" : "false"));
>                            /* Make sure we update our button's value and send update to dashboard */
> digitalWrite(ledPinRed, value);
> if (unBlock)
>                            {
> if (value)
>                              {
> xTaskCreatePinnedToCore(
> vent1On,   // Function that should be called
> "vent1On", // Name of the task (for debugging)
> 2000,      // Stack size (bytes)
> NULL,      // Parameter to pass
> 1,         // Task priority
> NULL,      // Task handle
> 0          // Core 1/0
>                                );
>                              }
> else
>                              {
> xTaskCreatePinnedToCore(
> vent1Off,   // Function that should be called
> "vent1Off", // Name of the task (for debugging)
> 2000,       // Stack size (bytes)
> NULL,       // Parameter to pass
> 1,          // Task priority
> NULL,       // Task handle
> 0           // Core 1/0
>                                );
>                              }
>                            }
> dashboard.sendUpdates();
>                          });
>
> Ovládání ventilů:
> void vent1On(void *parameter)
> {
> TickType_t xLastWakeTime;
> const TickType_t xFrequency = (20000 / portTICK_PERIOD_MS);
>   // Initialise the xLastWakeTime variable with the current time.
> xLastWakeTime = xTaskGetTickCount();
> for (;;)
>   {
> unBlock = 0;
> digitalWrite(ventMain1, HIGH);
> digitalWrite(ventOn1, HIGH);
> digitalWrite(ledPinRed, HIGH);
> button1.update(1);
> systemCard.update((float)xFrequency);
>     // Pause the task fo 20s
> vTaskDelayUntil(&xLastWakeTime, xFrequency);
>     //vTaskDelay(20000 / portTICK_PERIOD_MS);
> digitalWrite(ventMain1, LOW);
> digitalWrite(ventOn1, LOW);
> digitalWrite(ledPinRed, LOW);
> unBlock = 1;
> vTaskDelete(NULL); //spustí se jen jednou
>   }
> }
> void vent1Off(void *parameter)
> {
> TickType_t xLastWakeTime;
> const TickType_t xFrequency = (20000 / portTICK_PERIOD_MS);
>   // Initialise the xLastWakeTime variable with the current time.
> xLastWakeTime = xTaskGetTickCount();
> for (;;)
>   { // infinite loop
> unBlock = 0;
> digitalWrite(ventMain1, HIGH);
> digitalWrite(ventOn1, LOW);
> digitalWrite(ledPinRed, HIGH);
> button1.update(0);
> systemCard.update((float)xFrequency);
>     // Pause the task fo 20s
> vTaskDelayUntil(&xLastWakeTime, xFrequency);
>     //vTaskDelay(20000 / portTICK_PERIOD_MS);
> digitalWrite(ventMain1, LOW);
> digitalWrite(ventOn1, LOW);
> digitalWrite(ledPinRed, LOW);
> unBlock = 1;
> vTaskDelete(NULL); //spustí se jen jednou
>   }
> }
>
>
>
> po 2. 8. 2021 v 16:11 odesílatel Jaroslav Buchta 
> <jaroslav.buchta na hascomp.cz <mailto:jaroslav.buchta na hascomp.cz>> napsal:
>
>     A zrovna nad tim badam a jedna vec mi nejde do hlavy:
>     v modulu port.c je obsluha
>
>     BaseType_t xPortSysTickHandler( void )
>     {
>         BaseType_t ret;
>
>         portbenchmarkIntLatency();
>         traceISR_ENTER(SYSTICK_INTR_ID);
>         ret = xTaskIncrementTick();
>         if( ret != pdFALSE )
>         {
>             portYIELD_FROM_ISR();
>         } else {
>             traceISR_EXIT();
>         }
>         return ret;
>     }
>
>     Je logicky umistena v IRAM sekci ale proc??? Funkce nema
>     specifikovany IRAM_ATTR, ani v hlavicce.
>     zrovna tak BaseType_t xTaskIncrementTick( void ) v tasks.c
>
>     Tady uz treba attribut je
>     void IRAM_ATTR esp_vApplicationTickHook(void)
>     {
>         int n;
>         int core = xPortGetCoreID();
>         for (n=0; n<MAX_HOOKS; n++) {
>             if (tick_cb[core][n]!=NULL) {
>                 tick_cb[core][n]();
>             }
>         }
>     }
>
>     Funkce se vnoruji v tomto poradi.
>
>     Zkousel jsem se povesit na hook od toho casovace a funguje to, jak
>     z Flash, tak z IRAM (to je asi rozumnejsi, kdyz je to v ISR)
>
>
>     Dne 02.08.2021 v 12:32 Jaroslav Buchta napsal(a):
>>     At to ctu stale dokola, nevidim prostor pro zkraceni FreeRTOS -
>>     ESP32 - — ESP-IDF Programming Guide latest documentation
>>     (espressif.com)
>>     <https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/freertos.html#task-api>
>>     Jen je tam upozorneni, ze je nejista prodleva, kdy bude zavolana
>>     funkce a az od te doby se to pocita. vTaskDelayUntil bude mit asi
>>     jediny rozdil v tom, ze je tam dany cas ukonceni cekani jako
>>     parametr, u vTaskDelay se tato hodnot asi ulozi v okamziku volani.
>>     A i tak by se jednalo spis o milisekundy nez sekundy...
>>
>>     Koukam na to, ze ty funkce pracuji v principu uplne stejne,
>>     pouziji pro uspani
>>         prvAddCurrentTaskToDelayedList(...);
>>      jenom jinak pocitaji dobu pro uspani...
>>
>>     Pokud opravdu muze dojit ke zkraceni intervalu, bylo by v systemu
>>     neco velmi spatne. Neprobehne nahodou spis restart?
>>
>>     //////////////////////////////
>>
>>         void vTaskDelay( const TickType_t xTicksToDelay )
>>         {
>>         BaseType_t xAlreadyYielded = pdFALSE;
>>
>>             /* A delay time of zero just forces a reschedule. */
>>             if( xTicksToDelay > ( TickType_t ) 0U )
>>             {
>>                 configASSERT( uxSchedulerSuspended[xPortGetCoreID()]
>>     == 0 );
>>                 taskENTER_CRITICAL( &xTaskQueueMutex );
>>                 {
>>                     traceTASK_DELAY();
>>
>>                     /* A task that is removed from the event list
>>     while the
>>                     scheduler is suspended will not get placed in the
>>     ready
>>                     list or removed from the blocked list until the
>>     scheduler
>>                     is resumed.
>>
>>                     This task cannot be in an event list as it is the
>>     currently
>>                     executing task. */
>>                     prvAddCurrentTaskToDelayedList( xPortGetCoreID(),
>>     xTicksToDelay );
>>                 }
>>                 taskEXIT_CRITICAL( &xTaskQueueMutex );
>>             }
>>             else
>>             {
>>                 mtCOVERAGE_TEST_MARKER();
>>             }
>>
>>             /* Force a reschedule if xTaskResumeAll has not already
>>     done so, we may
>>             have put ourselves to sleep. */
>>             if( xAlreadyYielded == pdFALSE )
>>             {
>>                 portYIELD_WITHIN_API();
>>             }
>>             else
>>             {
>>                 mtCOVERAGE_TEST_MARKER();
>>             }
>>         }
>>
>>
>>
>>         void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime,
>>     const TickType_t xTimeIncrement )
>>         {
>>         TickType_t xTimeToWake;
>>         BaseType_t xAlreadyYielded = pdFALSE, xShouldDelay = pdFALSE;
>>
>>             configASSERT( pxPreviousWakeTime );
>>             configASSERT( ( xTimeIncrement > 0U ) );
>>             configASSERT( uxSchedulerSuspended[xPortGetCoreID()] == 0 );
>>
>>             taskENTER_CRITICAL( &xTaskQueueMutex );
>>             {
>>                 /* Minor optimisation.  The tick count cannot change
>>     in this
>>                 block. */
>>                 const TickType_t xConstTickCount = xTickCount;
>>
>>                 /* Generate the tick time at which the task wants to
>>     wake. */
>>                 xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;
>>
>>                 if( xConstTickCount < *pxPreviousWakeTime )
>>                 {
>>                     /* The tick count has overflowed since this
>>     function was
>>                     lasted called.  In this case the only time we
>>     should ever
>>                     actually delay is if the wake time has also   
>>     overflowed,
>>                     and the wake time is greater than the tick time. 
>>     When this
>>                     is the case it is as if neither time had
>>     overflowed. */
>>                     if( ( xTimeToWake < *pxPreviousWakeTime ) && (
>>     xTimeToWake > xConstTickCount ) )
>>                     {
>>                         xShouldDelay = pdTRUE;
>>                     }
>>                     else
>>                     {
>>                         mtCOVERAGE_TEST_MARKER();
>>                     }
>>                 }
>>                 else
>>                 {
>>                     /* The tick time has not overflowed.  In this
>>     case we will
>>                     delay if either the wake time has overflowed,
>>     and/or the
>>                     tick time is less than the wake time. */
>>                     if( ( xTimeToWake < *pxPreviousWakeTime ) || (
>>     xTimeToWake > xConstTickCount ) )
>>                     {
>>                         xShouldDelay = pdTRUE;
>>                     }
>>                     else
>>                     {
>>                         mtCOVERAGE_TEST_MARKER();
>>                     }
>>                 }
>>
>>                 /* Update the wake time ready for the next call. */
>>                 *pxPreviousWakeTime = xTimeToWake;
>>
>>                 if( xShouldDelay != pdFALSE )
>>                 {
>>                     traceTASK_DELAY_UNTIL();
>>
>>                     /* prvAddCurrentTaskToDelayedList() needs the
>>     block time, not
>>                     the time to wake, so subtract the current tick
>>     count. */
>>                     prvAddCurrentTaskToDelayedList( xPortGetCoreID(),
>>     xTimeToWake - xConstTickCount );
>>                 }
>>                 else
>>                 {
>>                     mtCOVERAGE_TEST_MARKER();
>>                 }
>>             }
>>             taskEXIT_CRITICAL( &xTaskQueueMutex );
>>
>>             /* Force a reschedule if xTaskResumeAll has not already
>>     done so, we may
>>             have put ourselves to sleep. */
>>             if( xAlreadyYielded == pdFALSE )
>>             {
>>                 portYIELD_WITHIN_API();
>>             }
>>             else
>>             {
>>                 mtCOVERAGE_TEST_MARKER();
>>             }
>>         }
>>
>>
>>     Dne 02.08.2021 v 12:09 as5s napsal(a):
>>>
>>>     Netusim ako to presne funguje, ale v dokumentacii na to upozornuju.
>>>
>>>     ale je mi cudne ze sa to skrati. O kolko sa to skrati?
>>>
>>>     Myre
>>>
>>>
>>>     On 2. 8. 2021 10:35, Jaroslav Buchta wrote:
>>>>     To jako opravdu vTaskDelay muze fungovat nespolehlive, teda
>>>>     jeste k tomu se zkratit?
>>>>     To snad primo pocita systemova preruseni od casovace (default
>>>>     tusim 100Hz), ze by se nejaky nestihly bych jeste pochopil...
>>>>
>>>>     Dne 02.08.2021 v 9:49 as5s napsal(a):
>>>>>
>>>>>     Dobry den,
>>>>>
>>>>>     skuste pozriet na vTaskDelayUntil()
>>>>>
>>>>>     https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/freertos.html#_CPPv415vTaskDelayUntilPC10TickType_tK10TickType_t
>>>>>     <https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/freertos.html#_CPPv415vTaskDelayUntilPC10TickType_tK10TickType_t>
>>>>>
>>>>>     mozno vam to bude stacit.
>>>>>
>>>>>     Myre
>>>>>
>>>>>     On 2. 8. 2021 9:45, Jan Půhoný wrote:
>>>>>>     Dobrý den,
>>>>>>
>>>>>>     mám tady další zádrhel - mějme funkci, která ovládá výstupní
>>>>>>     piny, potřebuji po nastavení udžet cca 20 sekund v HIGH a pak
>>>>>>     vrátit vše do low. Jedná se o otevítání a zavírání ventilu.
>>>>>>     Přidal jsem tedy mezi to vTaskDelay(20000 /
>>>>>>     portTICK_PERIOD_MS); , problém je v tom, že někdy se to
>>>>>>     zpoždění značně zkrátí a ventil zůstane napolo otevřený. Jak
>>>>>>     se toto dá ošetřit aby se vTaskDelay(20000 /
>>>>>>     portTICK_PERIOD_MS); nikdy nemohlo zkrátit a bylo dodrženo.
>>>>>>
>>>>>>     Volám to pak standardně přes xTaskCreatePinnedToCore() ....
>>>>>>
>>>>>>     void vent1On(void * parameter){
>>>>>>     for(;;){ // infinite loop
>>>>>>     button1.update(1);
>>>>>>     digitalWrite(ventMain1, HIGH);
>>>>>>     digitalWrite(ventOn1, HIGH);
>>>>>>     digitalWrite(ledPinRed, HIGH);
>>>>>>         // Pause the task fo 20s
>>>>>>     vTaskDelay(20000 / portTICK_PERIOD_MS);
>>>>>>     digitalWrite(ventMain1, LOW);
>>>>>>     digitalWrite(ventOn1, LOW);
>>>>>>     digitalWrite(ledPinRed, LOW);
>>>>>>     vTaskDelete(NULL); //spustí se jen jednou
>>>>>>       }
>>>>>>     }
>>>>>>
>>>>>>
>>>>>>     xTaskCreatePinnedToCore(
>>>>>>         vent1On,    // Function that should be called
>>>>>>         "vent1On",   // Name of the task (for debugging)
>>>>>>         1000,            // Stack size (bytes)
>>>>>>         NULL,            // Parameter to pass
>>>>>>         1,               // Task priority
>>>>>>         NULL,            // Task handle
>>>>>>         0            // Core 1/0
>>>>>>       );
>>>>>>
>>>>>>     HP
>>>>>>
>>>>>>
>>>>>>     so 31. 7. 2021 v 8:27 odesílatel Jan Půhoný
>>>>>>     <konference na puhy.cz <mailto:konference na puhy.cz>> napsal:
>>>>>>
>>>>>>         Díky, zkusil jsem jak 2000 tak 4000 ale stále stejné.
>>>>>>         Resetuje se to pořád dokola s tímto:
>>>>>>
>>>>>>         rst:0x1 (POWERON_RESET),boot:0x12 (SPI_FAST_FLASH_BOOT)
>>>>>>         configsip: 0, SPIWP:0xee
>>>>>>         clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
>>>>>>         mode:DIO, clock div:2
>>>>>>         load:0x3fff0018,len:4
>>>>>>         load:0x3fff001c,len:1044
>>>>>>         load:0x40078000,len:10124
>>>>>>         load:0x40080400,len:5828
>>>>>>         entry 0x400806a8
>>>>>>
>>>>>>         *Ale zjistil jsem, že to dělá jen pokud to napájím z USB.
>>>>>>         Když to dám přímo do svého zapojení, kde je pořádná
>>>>>>         kapacita na Vin, tak to drží. Takže skutečně jen problém
>>>>>>         s napájením.*
>>>>>>
>>>>>>         Teď už to budu programovat jen přes OTA, takže vyřešeno.
>>>>>>
>>>>>>         HP
>>>>>>
>>>>>>
>>>>>>         so 31. 7. 2021 v 6:44 odesílatel Jaroslav Buchta
>>>>>>         <jaroslav.buchta na hascomp.cz
>>>>>>         <mailto:jaroslav.buchta na hascomp.cz>> napsal:
>>>>>>
>>>>>>             kod jsem nezkoumal ale na prvni pohled mi prijde maly
>>>>>>             zasobnik pro
>>>>>>             vlakno, tady je to tusim v btech. dal bych 2 nebo 4K
>>>>>>             na zkousku
>>>>>>             _______________________________________________
>>>>>>             HW-list mailing list  -  sponsored by www.HW.cz
>>>>>>             <http://www.HW.cz>
>>>>>>             Hw-list na list.hw.cz <mailto:Hw-list na list.hw.cz>
>>>>>>             http://list.hw.cz/mailman/listinfo/hw-list
>>>>>>             <http://list.hw.cz/mailman/listinfo/hw-list>
>>>>>>
>>>>>>
>>>>>>     _______________________________________________
>>>>>>     HW-list mailing list  -  sponsored bywww.HW.cz  <http://www.HW.cz>
>>>>>>     Hw-list na list.hw.cz  <mailto:Hw-list na list.hw.cz>
>>>>>>     http://list.hw.cz/mailman/listinfo/hw-list  <http://list.hw.cz/mailman/listinfo/hw-list>
>>>>>
>>>>>     _______________________________________________
>>>>>     HW-list mailing list  -  sponsored bywww.HW.cz  <http://www.HW.cz>
>>>>>     Hw-list na list.hw.cz  <mailto:Hw-list na list.hw.cz>
>>>>>     http://list.hw.cz/mailman/listinfo/hw-list  <http://list.hw.cz/mailman/listinfo/hw-list>
>>>>
>>>>
>>>>
>>>>     _______________________________________________
>>>>     HW-list mailing list  -  sponsored bywww.HW.cz  <http://www.HW.cz>
>>>>     Hw-list na list.hw.cz  <mailto:Hw-list na list.hw.cz>
>>>>     http://list.hw.cz/mailman/listinfo/hw-list  <http://list.hw.cz/mailman/listinfo/hw-list>
>>>
>>>     _______________________________________________
>>>     HW-list mailing list  -  sponsored bywww.HW.cz  <http://www.HW.cz>
>>>     Hw-list na list.hw.cz  <mailto:Hw-list na list.hw.cz>
>>>     http://list.hw.cz/mailman/listinfo/hw-list  <http://list.hw.cz/mailman/listinfo/hw-list>
>>
>>
>>
>>     _______________________________________________
>>     HW-list mailing list  -  sponsored bywww.HW.cz  <http://www.HW.cz>
>>     Hw-list na list.hw.cz  <mailto:Hw-list na list.hw.cz>
>>     http://list.hw.cz/mailman/listinfo/hw-list  <http://list.hw.cz/mailman/listinfo/hw-list>
>
>
>     _______________________________________________
>     HW-list mailing list  -  sponsored by www.HW.cz <http://www.HW.cz>
>     Hw-list na list.hw.cz <mailto:Hw-list na list.hw.cz>
>     http://list.hw.cz/mailman/listinfo/hw-list
>     <http://list.hw.cz/mailman/listinfo/hw-list>
>
>
> _______________________________________________
> HW-list mailing list  -  sponsored by www.HW.cz
> Hw-list na list.hw.cz
> http://list.hw.cz/mailman/listinfo/hw-list


------------- další část ---------------
HTML příloha byla odstraněna...
URL: <http://list.hw.cz/pipermail/hw-list/attachments/20210803/eb5f86d9/attachment.html>


Další informace o konferenci Hw-list