Re: ESP32 domácí automatizace
Jan Půhoný
konference na puhy.cz
Úterý Srpen 3 07:35:46 CEST 2021
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>
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
>
> 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> 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> 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
>>> Hw-list na list.hw.cz
>>> http://list.hw.cz/mailman/listinfo/hw-list
>>>
>>
> _______________________________________________
> HW-list mailing list - sponsored by www.HW.czHw-list na list.hw.czhttp://list.hw.cz/mailman/listinfo/hw-list
>
>
> _______________________________________________
> HW-list mailing list - sponsored by www.HW.czHw-list na list.hw.czhttp://list.hw.cz/mailman/listinfo/hw-list
>
>
>
> _______________________________________________
> HW-list mailing list - sponsored by www.HW.czHw-list na list.hw.czhttp://list.hw.cz/mailman/listinfo/hw-list
>
>
> _______________________________________________
> HW-list mailing list - sponsored by www.HW.czHw-list na list.hw.czhttp://list.hw.cz/mailman/listinfo/hw-list
>
>
>
> _______________________________________________
> HW-list mailing list - sponsored by www.HW.czHw-list na list.hw.czhttp://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/3564ad02/attachment-0001.html>
Další informace o konferenci Hw-list