Skocz do zawartości

Stacja pogodowa z semaforem nie odczytuje danych z partycji NVS.


Pomocna odpowiedź

Napisano (edytowany)

- mam stacje pogodową w zegarku opartym na wyswietlaczu GC9A01 i Esp32 Pico D4.
- korzystam z Arduino IDE 2.3.5 oraz Esp32 board wersja 2.0.17.
- ilośc flasha 4MB, pamieć RAM 340 kB.
- mam dwie partycje NVS, 20 kB oraz 24kB.
- w tej pierwszej są dane pogodowe aktualne, w drugiej dane pogodowe z trzech kolejnych dni.
- program posiada dwa wątki, muteksa, 4 timery, wszystko działa. 
- czasami podczas odczytu z tych partycji dane są przekłamane.
- dlatego chciałem zastosować semafory, podczas odczytu danych z partycji NVS.
- jednak po zastosowaniu semafora, program staje w miejscu gdzie jest semafor.
- coś jest żle tylko gdzie, jak to szukać.
- wartość wolnego stosu oscyluje na poziomie 100 - 150 kB.
- tak jest na dwóch egzemplarzach tych urządzeń.

partycja.thumb.jpg.89cc9f257abe79e22608fa3b21f331cb.jpgxSemafor2.thumb.jpg.b03798ac570d4013705aea301be47af2.jpgNVS1.thumb.jpg.06f42c08ae4c38d2fcb7c451d170a78b.jpgNVS2.thumb.jpg.21c7db898ab1805e942bdc2d39f93558.jpg

	// ---------------------
void odczyt_NVS2()																	// []
{
	Serial.println(" _3765_ odczyt NVS2 --> tablicy F");
		// ----------------------------------- RO_MODE -------------------------------
	
	nvs_open_from_partition("nvs2", "stuff", NVS_READONLY, &handle);	// ### 2
				//nvs_close(handle);	for(;;); 	
		// ----------------------- fIcon[] -odczyt---------------------
	LockPrefs();																			// [880]	
	UnlockPrefs();																		// [990]		
	for (int r = 0; r < max_readings; r++)
	{																																						
		key = "fIkon" + String(r); 
		nvs_get_str(handle, key.c_str(),  NULL, &required_size);			// pobierz rozmiar
		nvs_get_str(handle, key.c_str(), FIcon[r], &required_size);		// char[] String		
					// error: incompatible types in assignment of 'float' to 'char [4]'
	}	
		
			// -------------------
void odczyt_NVS1()																	// [4125]  --> debug_Tablice
{		
	Serial.println(" _3710_ odczyt NVS --> tablicy a");
		// ----------------------------------- RO_MODE -------------------------------
	mySketchPrefs.begin("myprefs", RO_MODE);        		//  reopen it in RO mode.
				//	mySketchPrefs.end(); for(;;);
	mySketchPrefs.getBool("nvsInit", false);  						// read from nvs.	
		// Serial.printf(" err: %d", mySketchPrefs.getBool("nvsaktualne", false));  // zapisano NVS, NVS2								
	aktualneSVN = mySketchPrefs.getBool("nvsaktualne", false);  // zapisano NVS, NVS2
	Serial.printf(" aktualneSVN: %d\n", aktualneSVN);
			
	// --------------------------
	//LockPrefs();																				// [885]
	//UnlockPrefs();																				// [990]
	mySketchPrefs.getFloat("alat", alat);
	
	mySketchPrefs.getFloat("alon", alon);
	mySketchPrefs.getInt("aYy", aYy);
	
	mySketchPrefs.getString("aPeriod", aPeriod);
	mySketchPrefs.getString("aTrend", aTrend);									
	mySketchPrefs.getString("aIcon", aIcon);									  
	mySketchPrefs.getString("aMain0", aMain0);									
	mySketchPrefs.getString("aForecast0", aForecast0);					
	mySketchPrefs.getString("aCountry", aCountry);

 

Edytowano przez 99teki
(edytowany)

A czy semafor ma przypisaną wartość to znaczy czy nie jest null i czy sprawdzasz czy zajęty? Poza tym w dokumentacji freertos piszą że bardzo często lepiej zastosować notyfikacje zamiast semafora

https://www.freertos.org/Documentation/02-Kernel/04-API-references/10-Semaphore-and-Mutexes/00-Semaphores

 

SemaphoreHandle_t xSemaphore = NULL;

/* Repetitive task. */
void vATask( void * pvParameters )
{
    /* We are using the semaphore for synchronisation so we create a binary
       semaphore rather than a mutex. We must make sure that the interrupt
       does not attempt to use the semaphore before it is created! */
    xSemaphore = xSemaphoreCreateBinary();

    for( ;; )
    {
        /* We want this task to run every 10 ticks of a timer. The semaphore
           was created before this task was started.

           Block waiting for the semaphore to become available. */
        if( xSemaphoreTake( xSemaphore, LONG\_TIME ) == pdTRUE )
        {
            /* It is time to execute. */

             ...

            /* We have finished our task. Return to the top of the loop where
               we will block on the semaphore until it is time to execute
               again. Note when using the semaphore for synchronisation with an
               ISR in this manner there is no need to 'give' the semaphore
               back. */
        }
    }
}

 

Edytowano przez _LM_
  • Lubię! 2

Aha i do ochrony zasobów to chyba lepiej użyć mutexów, choć być może błądzę w tej chwili... Dawno z tym nie działałem 🤔 

  • Lubię! 1

- na razie na wątkach i millis() działają semafory binarne.

semaforBin = xSemaphoreCreateBinary(); 							// Create binary semaphore 
		
    xTaskCreatePinnedToCore
		(
        upNVS2,      																	// Function name of the task - zapisz NVS2
        "upNVS2",   																	// Name of the task (e.g. for debugging)
        2048,       															 		// Stack size (bytes)
        NULL,       															 		// Parameter to pass
        1,           																	// Task priority
        &BlinkTaskHandle1,														// Task handle 1
				0                      												// Core to run the task on
    );

- po testach wszystkich wątków, wstawiam do programu.

	// ---------------------------
void upNVS2(void *pvParameters)
{
    pinMode(LED1, OUTPUT);
    pinMode(INT_PIN_1, INPUT_PULLUP);
	while(1)
	{
      xSemaphoreTake(semaforBin, portMAX_DELAY); 
						//	{
          // markerForecast();												// [130]  wypelnij --> WxForecast
					// debugWxForecast();									// [480] WxForecast --> print	
			Update_NVS2();													// [285]	WxForecast to NVS2  
            
						//	}
			xSemaphoreGive(semaforBin); 									// Release semaphore
				
			vTaskDelay(1000 / portTICK_PERIOD_MS); 				// ### nie kasuj 1000ms portTICK_PERIOD_MS == 1ms
			vTaskSuspend(NULL);														// From within the task itself
	}
}

 

(edytowany)

sprawdź jeszcze na twoim oryginalnym programie funkcje ESPLOG zamiast println:

#include "esp_log.h" // Obowiązkowe w plikach .cpp / opcjonalne w .ino

// 1. Definicja TAGu (najlepiej jako stała tekstowa statyczna dla tego pliku)
static const char* TAG = "MOJ_SYSTEM";

void setup() {
    Serial.begin(115200);
   

    // 2. Użycie logów w kodzie
    ESP_LOGI(TAG, "System uruchomiony poprawnie.");
    ESP_LOGW(TAG, "Test");
}

void loop() {
    // Pętla główna
}


takie małe RTOSowe macro które przynajmniej mi oszczędza pisania, zamiast:
 

vTaskDelay(1000 / portTICK_PERIOD_MS); 	

daję:

vTaskDelay(pdMS_TO_TICKS(1000));

 

Edytowano przez _LM_
  • Lubię! 1
(edytowany)

- właśnie dzisiaj dołożyłem, działa super.

- trochę ten program odłożyłem, bo dostałem do programowania ESP32-S3 1.85C.

- a tam większy ekran, dwa mikrofony, bas reflex, I2S, LVGL

- ale gdybym wiedział ze tam jest także QSPI, to bym się nie skusił.

- a tak głowa mnie boli od dwóch dni.

ESP32-S3-Touch-LCD-1.85C-details-19-1.thumb.jpg.c9e0faf17504a01686d3d129b9149f56.jpg

 

Edytowano przez 99teki

- po bólu głowy, jak zacząłem robić BLOB w NVS, to nawet struktury sie udały.

				// 1. Read test data blob
    ESP_LOGI(TAG, " 8 Reading test data blob:");
    test_data_t test_data;
    size_t test_data_size = sizeof(test_data_t);
    err = nvs_get_blob(my_handle, "test_data", &test_data, &test_data_size);
    if (err == ESP_OK) 
		{
        ESP_LOGI(TAG, "ID: %d", test_data.id);
        ESP_LOGI(TAG, "Name: %s", test_data.name);
        ESP_LOGI(TAG, "Values: %.3f, %.3f, %.3f, %.3f",
                 test_data.values[0], test_data.values[1],
                 test_data.values[2], test_data.values[3]);
        ESP_LOGI(TAG, "Flags: 0x%08" PRIX32, test_data.flags);
        ESP_LOGI(TAG, "Counts: %d, %d", test_data.counts[0], test_data.counts[1]);
        ESP_LOGI(TAG, "Active: %s", test_data.active ? "true" : "false");
    } else if (err == ESP_ERR_NVS_NOT_FOUND) 
		{
        ESP_LOGW(TAG, "Test data not found!");
    }
		nvs_close(my_handle);

 

  • Lubię! 1
(edytowany)

Nie byłem pewny jak zachowuje się serial.println w środowisku arduino, natomiast na pewno logi działają jak należy stąd mój pomysł na zmianę. No ja bym wpierw wczytał strukturę, zamknął nvs a potem wypisał pola, no chyba że jest błąd to można sprawdzić esp_err_check

Edytowano przez _LM_
  • Lubię! 1

- podobnie robię, zapis i potem odczyt blob-a.

		ESP_LOGI(TAG, " 4. Reading test WxF");
					// esp_err_t nvs_get_blob(nvs_handle_t, const char*, void*, size_t*);
		size_t required_size = sizeof(WxForecast); 			
    err = nvs_get_blob(handle2, "WxF_data", &WxForecast[0], &required_size);	
    if (err == ESP_OK) 
		{
			for (int r = 0; r < 1; r++) 		// max_readings
			{		
					// #define log_i(format, ...) log_printf(ARDUHAL_LOG_FORMAT(I, format), ##__VA_ARGS__)
				ESP_LOGI(TAG, "WxForecast[%d]: | TempR: %2.2f°C (HighR: %2.2f°C / LowR: %2.2f°C) | RainR: %2.2fmm | PresR: %4.2f hPa | TimeR: %d | DtR: %d | IconR: %s", 
         r, 
         WxForecast[r].Temperature, 
         WxForecast[r].High, 
         WxForecast[r].Low, 
         WxForecast[r].Rainfall, 
         WxForecast[r].Pressure, 
         WxForecast[r].Timezone, 
         WxForecast[r].Dt, 
         WxForecast[r].Icon); 								// Użyj .c_str() jeśli to obiekt klasy String 
			}						
						
    } else if (err == ESP_ERR_NVS_NOT_FOUND) 
		{
        ESP_LOGW(TAG, "WxF_data not found!");
    }
		nvs_close(handle2);

 

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...