Actions

Kamod ESP32-C3 (PL): Difference between revisions

From Kamamilabs.com - Wiki

 
(54 intermediate revisions by the same user not shown)
Line 2: Line 2:
==== Opis ====
==== Opis ====
'''Kamod ESP32-C3 - Płytka rozwojowa z układem ESP32-C3 Mini-1'''</br>
'''Kamod ESP32-C3 - Płytka rozwojowa z układem ESP32-C3 Mini-1'''</br>
Kamod ESP32-C3 jest układem opartym na zintegrowanym module mikrokontrolera ESP32-C3 Mini-1 firmy Espressif. ESP32-C3 Mini-1 zawiera 32-bitowy jednordzeniowy mikrokontroler SoC o architekturze RISC-V i maksymalnej częstotliwości taktowania 160 MHz. Dzięki 22 konfigurowalnym wejściom GPIO, 400 KB wewnętrznej pamięci RAM i obsłudze trybu niskiego zużycia energii, może być stosowany w różnych zastosowaniach związanych na przykład z układami IoT, systemami nadzoru lub sterowania. MCU jest dostępny w wielu wariantach ze zintegrowaną i zewnętrzną pamięcią flash. Wysoka maksymalna temperatura pracy sprawia, że idealnie nadaje się do zastosowań przemysłowych. Możliwości stosowania ESP32- C3 znacznie poszerzają wbudowane radiowe interfejsy Wi-Fi i Bluetooth 5 (LE) z obsługą dalekiego zasięgu (LR). Bezpieczeństwo aplikacji zapewniają funkcje bezpiecznego rozruchu oparty na RSA-3072 i szyfrowanie flash z AES-128/256-XTS. <br><br>
Na płytce KAmod ESP32-C3 znajduje się moduł ESP32-C3 Mini-1 firmy Espressif, który zawiera 32-bitowy, jednordzeniowy mikrokontroler SoC o architekturze RISC-V oraz interfejsy radiowe Wi-Fi i Bluetooth 5 (LE) z obsługą trybu dalekiego zasięgu (LR). <br><br>
Moduł Kamod ESP32 C3 jest przeznaczony do uruchomiania i testowania własnych aplikacji na przykład w środowisku Arduino, lub w języku Rust . Pomocne w tym mogą być umieszczone na płytce modułu układy peryferyjne: dokładny czujnik temperatury i wilgotności SHTC3, oraz czujnik MEMS typu ICM42670 zawierający 3-osiowy żyroskop i 3-osiowy akcelerometr. Dodatkowo do testów można wykorzystać diodę LED podłączoną do jednego z portów mikrokontrolera i programowaną 3-kolorową diodę WS28212. <br><br>
Częstotliwość taktowania MCU wynosi maksymalnie 160 MHz i jest wyposażony w aż 400 kB pamięci RAM i 4 MB pamięci Flash. Obsługuje tryby niskiego zużycia energii, działa w temperaturach od -40 do +85︒C, realizuje funkcje bezpiecznego rozruchu Secure Boot oraz szyfrowanie flash z AES-128/256-XTS, itd. Dzięki tak rozbudowanej specyfikacji doskonale nadaje się do zastosowań przemysłowych oraz z zakresu IoT. Ponadto, na płytce modułu znajdują się: dokładny czujnik temperatury i wilgotności SHTC3, czujnik MEMS typu ICM42670 zawierający 3-osiowy żyroskop i 3-osiowy akcelerometr, 3-kolorowa dioda typu WS28212, oraz dioda LED podłączona do jednego z portów mikrokontrolera. Komponenty te ułatwią budowę wielu różnych aplikacji. <br><br>
Moduł jest zasilany napięciem +5V dostarczanym przez złącze USB-C, lub napięciem z baterii Li-Jon. Napięcie +3,3V zasilające mikrokontroler i układy peryferyjne wytwarza przetwornica Buck DC/DC typu SY8088 o napięciu wejściowym z zakresu 2.5….5V. Po zaniku napięcia ze złącza USB-C zasilanie przełącza się automatycznie na baterię (jeżeli jest podłączona). Układ zasilania bateryjnego jest uzupełniony o ładowarkę baterii Li-Jon opartą o układ MCP7383 zasilany z napięcia VBUS +5V pochodzącego ze złącza USB-C.  
Moduł jest zasilany napięciem +5V dostarczanym przez złącze USB-C, lub napięciem z akumulatora Li-Ion. Napięcie +3,3 V zasilające mikrokontroler i układy peryferyjne wytwarza przetwornica Buck DC/DC typu SY8088 o napięciu wejściowym z zakresu 2.5….5 V. Po zaniku napięcia ze złącza USB-C zasilanie automatycznie dostarczane jest z akumulatora (jeżeli jest podłączony). Układ zasilania jest uzupełniony o ładowarkę akumulatora Li-Ion na bazie układu MCP7381, zasilanej ze złącza USB-C.<br><br>
 
Moduł Kamod ESP32-C3 jest przeznaczony do uruchamiania i testowania aplikacji w środowisku Arduino z użyciem języka C/C++ oraz Rust. <br><br>
 
<center>
<center>
[[File:KAmodESP32-C3_2.jpg|450px]]
[[File:KAmodESP32-C3_2.jpg|450px]]
Line 15: Line 14:
==== Podstawowe cechy i parametry ====
==== Podstawowe cechy i parametry ====


* Moduł ESP32C3 Mini-1
* Moduł ESP32C3 Mini-1 (Wi-Fi 802.11 b/g/n, Bluetooth 5 LE)
* IEEE 802.11 b/g/n-compliant
* Mikrokontroler 32-bit RISC-V jednordzeniowy 160 MHz, 400 kB SRAM, 4 MB Flash
* Bluetooth 5, Bluetooth
* 15 linii GPIO
* 32-bit RISC-V jednordzeniowy taktowanie do160MHz
* interfejsy komunikacyjne SPI, I2C, I2S, UART, USB
* 384 KB ROM
* przetwornik ADC 12-bit SAR do 6 kanałów
* 400 KB SRAM (16 KB pamięć cache)
* Akcelerometr ICM42670
* 8 KB SRAM dla modułu RTC
** Trójosiowy żyroskop MEMS - czujniki prędkości kątowej osi X, Y i Z
* 22 × programowanych linii GPIO
** Trójosiowy akcelerometr MEMS osi X, Y i Z
* 3 × SPI
** Interfejs komunikacyjny: I2C
* 2 × UART
* Termometr/higrometr SHTC3
* 1 × I2C
* 1 × I2S
* 2 × 54-bit uniwersalnych timerów
* 3 × watchdog timers
* 1 × 52-bit system timer
* Remote Control Peripheral (RMT)
* LED PWM controller (LEDC)
* Full-speed USB Serial/JTAG controller
* General DMA controller (GDMA)
* 1 × TWAI®
* 2 × przetwornik 12-bit SAR ADCs, do 6 kanałów
* 1 × sensor temperatury
* Akcelerometr ICM42670  
** Trójosiowy żyroskop MEMS Czujniki prędkości kątowej osi X, Y i Z z wyjściem cyfrowym (z programowalnym zakresem pełnej skali ±250, ±500, ±1000 i ±2000 stopni/sek.
** Trójosiowy akcelerometr MEMS osi X, Y i Z z wyjściem cyfrowym i programowalnym zakresem pełnej skali ±2 g, ±4 g, ±8 g i +16 g
** Zasilanie od+1.7V do +3,3V
**  Interfejs komunikacyjny I3C, I2C, SPI
* Termometr/higometr SHTC3
** Zakres pomiaru wilgotności 0…100%RH z dokładnością +/- 2%
** Zakres pomiaru wilgotności 0…100%RH z dokładnością +/- 2%
** Zakres pomiaru temperatury -40 do +125 °C. Dokładność pomiaru +/-0.2°C w zakresie od 0°C do +60°C
** Zakres pomiaru temperatury -40 do +125 °C. Dokładność pomiaru +/-0.2°C w zakresie od 0°C do +60°C
** Napięcie zasilania od+1.6V do +3,6V
** Interfejs komunikacyjny I2C
**  Interfejs komunikacyjny I2C  
* Przetwornica DC/DC typu SY8088
* Przetwornica DC/DC SY8088
* Układ ładowarki baterii Li-Ion typu MCP73831
* Układ ładowarki baterii Li-JON MCP73831
* Programowana dioda WS2812
* Programowana dioda WS2812
* Złącze USB-C  
* Złącze USB-C
** Zasilanie modułu napięciem +5V
** Zasilanie modułu napięciem +5V
** Interfejs programujący pamięć Flash mikrokontrolera
** Interfejs programujący pamięć Flash mikrokontrolera
** Interfejs JTAG  
** Interfejs JTAG
* Przyciski Reset i Boot
* Przyciski Reset i Boot
<hr>
<hr>
Line 67: Line 47:
| style="text-align: center;"|<b>KAmod ESP32-C3</b>
| style="text-align: center;"|<b>KAmod ESP32-C3</b>
| style="text-align: left;"|  
| style="text-align: left;"|  
Zmontowany i uruchomiony moduł<br>
*Zmontowany i uruchomiony moduł<br>
1 x prosta listwa goldpin 12-pin raster 2,54 mm
*1 x prosta listwa goldpin 12-pin raster 2,54 mm
1 x prosta listwa goldpin 16-pin raster 2,54 mm
*1 x prosta listwa goldpin 16-pin raster 2,54 mm
|}
|}
[[File:KAmodESP32-C3_4.jpg|none|700px|thumb|center]]
[[File:KAmodESP32-C3_4.jpg|none|700px|thumb|center]]
Line 83: Line 63:


==== Opis wyprowadzeń  ====
==== Opis wyprowadzeń  ====
<center>
[[File:KAmodESP32-C3_io.png|none|800px|thumb|center]]<br>
</center>
<hr>
<hr>
==== Zasilanie układu ====
==== Zasilanie układu ====


Standardowo moduł jest zasilany napięciem VBUS o wartości +5V ze złącza USB-C. To napięcie jest również wykorzystywane do ładowania pojedynczej celi baterii Li-Jon podłączonej do wyjścia Charger. Ładowaniem zajmuje się układ MCP7381 wykorzystujący algorytm ładowania o stałym natężeniu prądu/stałym napięciu z możliwością wyboru wstępnego kondycjonowania i zakończenia ładowania. Stała regulacja napięcia jest ustalona za pomocą czterech dostępnych opcji: 4,20 V, 4,35 V, 4,40 V lub 4,50. Stała wartość prądu jest ustawiana za pomocą jednego zewnętrznego rezystora. W naszym przypadku prąd ładowania to 100mA, a napięcie wyjściowe 4,20V.
Moduł jest zasilany napięciem VBUS o wartości +5 V ze złącza USB-C. To napięcie służy również do ładowania akumulatora Li-Ion 4,2 V, jeśli jest podłączony do wyjścia Charger. Za proces ładowania odpowiada układ MCP7381 realizujący algorytm ładowania o stałym natężeniu prądu/stałym napięciu, gdzie prąd ładowania jest ustawiony na 100 mA, a napięcie końcowe na 4,20 V.
<br><br>
<br><br>
<center>
[[File:KAmodESP32-C3 pwr.png|none|600px|thumb|left]]<br>
</center>
<hr>
<hr>


==== Konfiguracja środowiska Arduino i program testowy  ====
==== Konfiguracja środowiska Arduino i program testowy  ====
<hr>
<br>
=====Czynności wstępne=====
======<span style="color:#FFFFFF; background:#009999 ">Czynności wstępne</span>======
Podłączany moduł Kamod ESP-C3 do komputera z zainstalowanym środowiskiem Arduino IDE. W oknie wyboru modułu wybieramy moduł ESP32C3 Dev Module i wirtualny port szeregowy COMx z którym moduł jest połączony.
Podłączamy moduł Kamod ESP-C3 do komputera z zainstalowanym środowiskiem Arduino IDE. W oknie wyboru modułu wybieramy moduł ''ESP32C3 Dev Module'' i wirtualny port szeregowy COMx, poprzez który jest połączony moduł.
<center>
<center>
[[File:KAmodESP32-C3_Arduino_1.png|none|800px|thumb|center]]
[[File:KAmodESP32-C3_Arduino_1.png|none|800px|thumb|center]]
</center>
</center>
W naszej procedurze testowej będziemy używali okna terminala, w którym będą wyświetlanie wyniki działania programu. Żeby to było możliwe trzeba odblokować domyślnie zablokowaną opcję USB CDC On Boot
W naszej procedurze testowej będziemy używali okna terminala, w którym będą wyświetlane wyniki działania programu. Żeby to było możliwe trzeba odblokować domyślnie zablokowaną opcję ''USB CDC On Boot''
<center>
<center>
[[File:KAmodESP32-C3_Arduino_2.png|none|800px|thumb|center]]
[[File:KAmodESP32-C3_Arduino_2.png|none|800px|thumb|center]]
</center>
</center>
<br>
======<span style="color:#FFFFFF; background:#009999 ">Konfiguracja okna preferences</span>======
Otwieramy okno preferencji ''File->Preferences''. W polu ''Additional boards manager ULRs'' zakładki ''Settings'' wpisujemy adres https://dl.espressif.com/dl/package_esp32_index.json


=====Konfiguracja okna preferences=====
Otwieramy okno preferencji File->Preferences. W polu Additional boards manager ULRs zakładki Settings wpisujemy adres https://dl.espressif.com/dl/package_esp32_index.json
<center>
<center>
[[File:KAmodESP32-C3_Arduino_3.png|none|800px|thumb|center]]
[[File:KAmodESP32-C3_Arduino_3.png|none|800px|thumb|center]]
Line 109: Line 98:
<br><br>
<br><br>


=====Wybór typu procesora dla programowanego modułu=====
======<span style="color:#FFFFFF; background:#009999 ">Wybór typu procesora dla programowanego modułu</span>======
Wybieramy kolejno zakładkę Tools, następnie Board, rodzinę procesorów esp32 i moduł z procesorem ESP32C3. Każda zmiana modułu podłączonego do komputera przez USB będzie wymagała powtórzenia tego kroku. Jeżeli nie wykonamy go na początku, to można go wykonać przed kompilacją. W przeciwnym razie projekt nie zostanie prawidłowo skompilowany.  
Wybieramy kolejno zakładkę ''Tools'', następnie ''Board'', rodzinę procesorów ''esp32'' i moduł z procesorem ''ESP32C3''. Każda zmiana modułu podłączonego do komputera przez USB będzie wymagała powtórzenia tego kroku. Jeżeli nie wykonamy go na początku, to można go wykonać przed kompilacją. W przeciwnym razie projekt nie zostanie prawidłowo skompilowany.
<center>
<center>
[[File:KAmodESP32-C3_Arduino_4.png|none|800px|thumb|center]]
[[File:KAmodESP32-C3_Arduino_4.png|none|800px|thumb|center]]
</center>
</center>


=====Instalowanie bibliotek=====
======<span style="color:#FFFFFF; background:#009999 ">Instalowanie bibliotek</span>======
Program testowy wymaga zainstalowania bibliotek obsługujących układy peryferyjne: akcelerometr ICM42670P, termometr/higrometr SHTC3 i 3-kolorową diodę LED typu WS2812B. <br><br>
Program testowy wymaga zainstalowania bibliotek obsługujących układy peryferyjne: akcelerometr ICM42670P, termometr/higrometr SHTC3 i 3-kolorową diodę LED typu WS2812B. <br><br>
======Instalowanie biblioteki do obsługi układu ICM42670P======
 
Klikamy na pionowym pasku narzędzi ikonę bibliotek. W oknie wyszukiwanie wpisujemy ICM42670, wybieramy ICM42670P by TDK/Invensense i klikamy Install.  
======<span style="color:#FFFFFF; background:#009999 ">Instalowanie biblioteki do obsługi układu ICM42670P</span>======
Klikamy na pionowym pasku narzędzi ikonę bibliotek. W oknie wyszukiwanie wpisujemy ICM42670, wybieramy ''ICM42670P by TDK/Invensense'' i klikamy ''Install''.  
<center>
<center>
[[File:KAmodESP32-C3_Arduino_5.png|none|800px|thumb|center]]
[[File:KAmodESP32-C3_Arduino_5.png|none|800px|thumb|center]]
Line 124: Line 114:
<br>
<br>


======Instalowanie biblioteki do obsługi układu SHTC3======
======<span style="color:#FFFFFF; background:#009999 ">Instalowanie biblioteki do obsługi układu SHTC3</span>======
Wybieramy bibliotekę Adafruit SHTC3 Library dostarczaną przez Adafruit. Ta biblioteka wymaga doinstalowania koniecznych współpracujących z nią innych bibliotek. Aby to zrobić w wyskakującym dodatkowym oknie Install library dependencies klikamy Install All.  
Wybieramy bibliotekę ''Adafruit SHTC3 Library'' dostarczaną przez Adafruit. Wymaga ona doinstalowania powiązanych bibliotek - aby to zrobić w wyskakującym dodatkowym oknie ''Install library dependencies'' klikamy ''Install All''.
<center>
<center>
[[File:KAmodESP32-C3_Arduino_6.png|none|800px|thumb|center]]
[[File:KAmodESP32-C3_Arduino_6.png|none|800px|thumb|center]]
</center>
</center>
<br>


======Instalowanie biblioteki obsługującej 3-kolorową diodę RGB typu WS2812======
======<span style="color:#FFFFFF; background:#009999 ">Instalowanie biblioteki obsługującej 3-kolorową diodę RGB typu WS2812</span>======
======Obsługa akcelerometru ICM42670P======
Do sterowania 3-kolorowej diody RGB zastosujemy bibliotekę dostarczana przez Adafruit - ''Adafruit NeoPixel''
======Obsługa termometru/higrometru SHTC3======
<center>
======Obsługa diody RGB WS2812B ======
[[File:KAmodESP32-C3_Arduino_7.png|none|800px|thumb|center]]
</center>
<br>
 
======<span style="color:#FFFFFF; background:#009999 ">Obsługa akcelerometru ICM42670P</span>======
ICM42670P jest połączony z mikrokontrolerem za pomocą magistrali I2C. Do jej obsługi jest przeznaczona biblioteka Wire. Do inicjowania interfejsu I2S jest używana metoda begin z argumentami określającymi linie portów przypisane do sygnałów SDA i SCL
<br><br>
<span style="font-family: 'Courier New', monospace">
<nowiki>
#define I2C_SDA 10              //SDA IO10 </nowiki><br>
<nowiki>#define I2C_SCL 8               //SCL IO8 </nowiki><br>
<nowiki>Wire.begin(I2C_SDA, I2C_SCL); </nowiki><br>
</span>
<br>
 
======<span style="color:#FFFFFF; background:#009999 ">Obsługa termometru/higrometru SHTC3</span>======
Układ SHTC3 łączy się z mikrokontrolerem również za pomocą interfejsu I2C. Konfiguracja i inicjacja tego interfejsu została pokazana powyżej. Inicjalizacja biblioteki układu SHTC3 jest wykonywana standardowo przez metodę begin.
<br><br>
<span style="font-family: 'Courier New', monospace">
<nowiki>
shtc3.begin();</nowiki><br>
</span>
<br>
Odczytywanie i konwersję wartości temperatury wykonuje metoda htc3.getEvent
<br><br>
<span style="font-family: 'Courier New', monospace">
<nowiki>
htc3.getEvent(&humidity, &temp);        // read temp and humidity </nowiki><br>
</span>
<br>
Dane wyjściowe są umieszczane w zmiennych  temp.temperature i humidity.relative_humidity i można je bezpośrednio wyświetlić.
<br><br>
Przykładowy wydruk odczytanych danych z czujnika SHTC3 na konsoli znakowej Arduino IDE
<center>
[[File:KAmodESP32-C3_Arduino_8.png|none|800px|thumb|center]]
</center>
<br>
 
======<span style="color:#FFFFFF; background:#009999 ">Obsługa diody RGB WS2812B</span>======
Tworzymy instancję WS2812B, w której określamy: ilość diod WS2812 połączonych w łańcuchu (NUM_PIXELS), oraz numer portu linii danych (PIN_WS2812B). Pozostałe parametry można zostawić domyślnie. U nas jest jedna dioda (NUM_PIXELS = 1) podłączona do linii poru DO2 (PIN_WS2812B =2)
<br><br>
<span style="font-family: 'Courier New', monospace">
<nowiki>
#define PIN_WS2812B  2          // ESP32 pin that connects to WS2812B</nowiki><br>
<nowiki>
#define NUM_PIXELS     1        // The number of LEDs (pixels) on WS2812B</nowiki><br>
<nowiki>
Adafruit_NeoPixel WS2812B(NUM_PIXELS, PIN_WS2812B, NEO_GRB + NEO_KHZ800);</nowiki><br>
</span>
<br>
Inicjalizacja drivera jest standardowo wykonywana przez metodę begin:<br><br>
<span style="font-family: 'Courier New', monospace">
<nowiki>
WS2812B.begin();              //WS2812 driver config</nowiki><br>
</span><br>
Metoda setBrightness służy do ustawiania jasności świecenia wszystkich diod<br><br>
<span style="font-family: 'Courier New', monospace">
<nowiki>
WS2812B.setBrightness(50);    //WS8212 brightness</nowiki><br> <br>
</span>
Metoda clear wygasza wszystkie diody, a metoda setPixelColor określa składowe koloru dla każdej z diod. <br><br>
<span style="font-family: 'Courier New', monospace">
<nowiki>
WS2812B.setPixelColor(0, WS2812B.Color(255, 0, 0)); //kolor czerwony </nowiki><br> <br>
</span>
Skutki działania metod clear i setPixelColor są widoczne po wywołaniu metody show:  <br><br>
<span style="font-family: 'Courier New', monospace">
<nowiki>
WS2812B.show();</nowiki><br> <br>
</span>
 
======<span style="color:#FFFFFF; background:#009999 ">Sprawdzanie działania modułu WiFi </span>======
Procedura testowa sprawdzająca działanie modułu WiFi polega na skanowaniu radiowej sieci WiFi i wyświetlaniu znalezionych identyfikatorów SSID lokalnych sieci wraz z poziomem sygnału radiowego, kanałem radiowym oraz rodzajami szyfrowania danych. <br>
Najpierw jest ustawiany tryb WIFI_STA, czyli tryb stacji. W tym trybie moduł ESP32 może się łączyć z sieciami WIFI.  Po połączeniu z ruterem moduł może żądać informacji z Internetu (jeżeli ruter jest połączony z Internetem), lub z urządzeń z lokalnej sieci rutera. Po ustawieniu tego trybu wykonujemy ewentualne rozłączenie z siecią (jeżeli moduł był wcześniej połączony): <br><br>
<span style="font-family: 'Courier New', monospace">
<nowiki>
WiFi.mode(WIFI_STA);  //station mode</nowiki><br>
<nowiki>
WiFi.disconnect();        //disconnect WIFI network</nowiki><br>
</span><br>
Możemy teraz skanować identyfikatory sieci WIFI za pomocą metody scanNetworks<br>
Metoda zwraca ilość wykrytych sieci  wspomniane już parametry:  poziom sygnału radiowego, kanał radiowy oraz rodzaj szyfrowania danych. <br><br>
<span style="font-family: 'Courier New', monospace">
numNetworks = WiFi.scanNetworks();  //scan WIFI networks
</nowiki><br>
<span style="font-family: 'Courier New', monospace"> <nowiki>
   Serial.println("Scan done");
</nowiki><br>
<span style="font-family: 'Courier New', monospace"> <nowiki>
  if (numNetworks == 0)
</nowiki><br>
<span style="font-family: 'Courier New', monospace"> <nowiki>
  {
</nowiki><br>
<span style="font-family: 'Courier New', monospace"> <nowiki>
    Serial.println("no networks found");
</nowiki><br>
<span style="font-family: 'Courier New', monospace"> <nowiki>
  }
</nowiki><br>
</span><br>
 
Po wykonaniu skanowania można wyświetlić odczytane dane w konsoli i wykorzystać do w naszej aplikacji na przykład w celu połączenia z wybraną siecią. <br><br>
 
<span style="font-family: 'Courier New', monospace">
for (int i = 0; i < numNetworks; ++i) { <br>
      // Print SSID and RSSI for each network found<br>
      Serial.printf("%2d", i + 1);<br>
      Serial.print(" | ");<br>
      Serial.printf("%-32.32s", WiFi.SSID(i).c_str());<br>
      Serial.print(" | ");<br>
      Serial.printf("%4ld", WiFi.RSSI(i));<br>
      Serial.print(" | ");<br>
      Serial.printf("%2ld", WiFi.channel(i));<br>
      Serial.print(" | ");<br>
      switch (WiFi.encryptionType(i)) {<br>
        case WIFI_AUTH_OPEN:            Serial.print("open"); break;<br>
        case WIFI_AUTH_WEP:             Serial.print("WEP"); break;<br>
        case WIFI_AUTH_WPA_PSK:         Serial.print("WPA"); break;<br>
        case WIFI_AUTH_WPA2_PSK:        Serial.print("WPA2"); break;<br>
        case WIFI_AUTH_WPA_WPA2_PSK:    Serial.print("WPA+WPA2"); break;<br>
        case WIFI_AUTH_WPA2_ENTERPRISE: Serial.print("WPA2-EAP"); break;<br>
        case WIFI_AUTH_WPA3_PSK:        Serial.print("WPA3"); break;<br>
        case WIFI_AUTH_WPA2_WPA3_PSK:   Serial.print("WPA2+WPA3"); break;<br>
        case WIFI_AUTH_WAPI_PSK:        Serial.print("WAPI"); break;<br>
        default:                        Serial.print("unknown");<br>
      }<br>
      Serial.println();<br>
      delay(10);<br>
    }<br>
  }<br><br>
 
Przykładowy wydruk działania programu skanującego sieć WIFI na konsoli znakowej Arduino IDE
<center>
[[File:KAmodESP32-C3_Arduino_9.png|none|800px|thumb|center]]
</center>
<br>
 
Po wykonaniu skanowania i wyświetleniu danych trzeba wyczyścić dane, żeby przygotować moduł WiFi do kolejnego skanowania – metoda scanDelete
<br><br>
<span style="font-family: 'Courier New', monospace">
WiFi.scanDelete();
</span><br><br>
 
======<span style="color:#FFFFFF; background:#009999 ">Program testowy</span>======


=====Sprawdzanie działania modułu WiFi =====
=====Program testowy =====
<hr>
Program testowy ma zadanie przetestować wszystkie komponenty umieszczone na płytce modułu. Test składa się z kolejnych kroków:
Program testowy ma zadanie przetestować wszystkie komponenty umieszczone na płytce modułu. Test składa się z kolejnych kroków:
* Zapaleniu diody czerwonej LED podłączonej do linii portu IO7  
* Zapaleniu diody czerwonej LED podłączonej do linii portu IO7  
Line 146: Line 279:
* Zapaleniu co 0,5 sekundy kolejnych diod WS2812B czerwonej, zielonej i niebieskiej
* Zapaleniu co 0,5 sekundy kolejnych diod WS2812B czerwonej, zielonej i niebieskiej
* Zgaszeniu wszystkich diod WS2812B i rozpoczęciu testu od nowa
* Zgaszeniu wszystkich diod WS2812B i rozpoczęciu testu od nowa
Poniżej pokazany jest fragment ekranu konsoli znakowej Arduino IDE wyświetlający jeden przebieg programu testowego
<br>
Poniżej pokazany jest fragment ekranu konsoli znakowej Arduino IDE wyświetlający jeden przebieg programu testowego.
<center>
[[File:KAmodESP32-C3_Arduino_10.png|none|800px|thumb|center]]
</center>
<br>
Kod programu testowego znajduje się poniżej, można go skompilować w środowisku Arduino. <br>
<syntaxhighlight lang="arduino">
#include "WiFi.h"
#include<Wire.h>              //I2s DRIVER
#include <Adafruit_NeoPixel.h>//RGB diode WS2812
#include "Adafruit_SHTC3.h"
#include "ICM42670P.h"          //ICM42670P driver
 
#define LED_BUILTIN 7          //LED IO7 to flash
 
#define I2C_SDA 10              //SDA IO10
#define I2C_SCL 8              //SCL IO8
#define PIN_WS2812B  2          // ESP32 pin that connects to WS2812B
#define NUM_PIXELS    1        // The number of LEDs (pixels) on WS2812B
 
Adafruit_NeoPixel WS2812B(NUM_PIXELS, PIN_WS2812B, NEO_GRB + NEO_KHZ800);
ICM42670 IMU(Wire,0);          //I2S addres 0x68
Adafruit_SHTC3 shtc3 = Adafruit_SHTC3();
 
 
void setup() {
 
    //WS28212 setup 
    WS2812B.begin();              //WS2812 driver config
    WS2812B.setBrightness(50);    //WS8212 brightness
    //LED flash setup
    pinMode(LED_BUILTIN, OUTPUT);  //IO7 output
    //serial setup
    Serial.begin(115200);
    delay(2000);
    while(!Serial);                //wait to serial ready 
    //I2S line setup
    Wire.begin(I2C_SDA, I2C_SCL);                    //setup I2S driver
    IMU.begin();                                      //setup ICM42670P driver
    // Start accelerometer and gyroscope
    IMU.startAccel(100, 16); // 100 Hz, ±16g
    IMU.startGyro(100, 2000); // 100 Hz, ±2000 dps
    shtc3.begin();
    WiFi.mode(WIFI_STA);
    WiFi.disconnect();
    delay(100);
   
}
void loop()
{
  int numNetworks;
  sensors_event_t humidity, temp;
  inv_imu_sensor_event_t imu_event;
  digitalWrite (LED_BUILTIN, HIGH);
  //ICM42670P register read, convert and
  Serial.print("\n");
  Serial.print("********************************");
  Serial.print("\n");
  int ret = IMU.getDataFromRegisters(imu_event);  //ICM42670P register read
  Serial.println(ret);
  if (ret == 0) {
// Convert acceleration to g
  float accelX = imu_event.accel[0] / 2048.0;
  float accelY = imu_event.accel[1] / 2048.0;
  float accelZ = imu_event.accel[2] / 2048.0;
 
// Convert gyroscope to dps
  float gyroX = imu_event.gyro[0] / 16.4;
  float gyroY = imu_event.gyro[1] / 16.4;
  float gyroZ = imu_event.gyro[2] / 16.4;
//print converted result
  Serial.print("ICM42670P AccelX:");
  Serial.println(accelX);
  Serial.print("ICM42670P AccelY:");
  Serial.println(accelY);
  Serial.print("ICM42670P AccelZ:");
  Serial.println(accelZ);
  Serial.print("********************************");
  Serial.print("\n");
  Serial.print("ICM42670P GyroX:");
  Serial.println(gyroX);
  Serial.print("ICM42670P GyroY:");
  Serial.println(gyroY);
  Serial.print("ICM42670P GyroZ:");
  Serial.println(gyroZ);
  Serial.print("********************************");
  Serial.print("\n");
  Serial.print("ICM42670PTemperature:");
  Serial.println((imu_event.temperature/128.0)+25.0);
  Serial.print("********************************");
  Serial.print("\n");
}
  Serial.print("SHTC3P register read.........:");
  Serial.print("\n");
  Serial.print("********************************");
  Serial.print("\n");
  shtc3.getEvent(&humidity, &temp);// read temp and humidity
 
  Serial.print("SHTC3 Temperature: "); Serial.print(temp.temperature); Serial.println(" deg C");
  Serial.print("SHTC3 Humidity: "); Serial.print(humidity.relative_humidity); Serial.println("% rH");
  Serial.print("********************************");
  Serial.print("\n");
      numNetworks = WiFi.scanNetworks();
 
    Serial.println("Scan done");
  if (numNetworks == 0) {
    Serial.println("no networks found");
  } else {
    Serial.print(numNetworks);
    Serial.println(" networks found");
    Serial.println("Nr | SSID                            | RSSI | CH | Encryption");
    for (int i = 0; i < numNetworks; ++i) {
      // Print SSID and RSSI for each network found
      Serial.printf("%2d", i + 1);
      Serial.print(" | ");
      Serial.printf("%-32.32s", WiFi.SSID(i).c_str());
      Serial.print(" | ");
      Serial.printf("%4ld", WiFi.RSSI(i));
      Serial.print(" | ");
      Serial.printf("%2ld", WiFi.channel(i));
      Serial.print(" | ");
      switch (WiFi.encryptionType(i)) {
        case WIFI_AUTH_OPEN:            Serial.print("open"); break;
        case WIFI_AUTH_WEP:            Serial.print("WEP"); break;
        case WIFI_AUTH_WPA_PSK:        Serial.print("WPA"); break;
        case WIFI_AUTH_WPA2_PSK:        Serial.print("WPA2"); break;
        case WIFI_AUTH_WPA_WPA2_PSK:    Serial.print("WPA+WPA2"); break;
        case WIFI_AUTH_WPA2_ENTERPRISE: Serial.print("WPA2-EAP"); break;
        case WIFI_AUTH_WPA3_PSK:        Serial.print("WPA3"); break;
        case WIFI_AUTH_WPA2_WPA3_PSK:  Serial.print("WPA2+WPA3"); break;
        case WIFI_AUTH_WAPI_PSK:        Serial.print("WAPI"); break;
        default:                        Serial.print("unknown");
      }
      Serial.println();
      delay(10);
    }
  }
    WiFi.scanDelete();
    digitalWrite (LED_BUILTIN, LOW);
    WS2812B.clear();  // set all pixel colors to 'off'. It only takes effect if pixels.show() is called
    WS2812B.setPixelColor(0, WS2812B.Color(255, 0, 0));  // it only takes effect if pixels.show() is called
    WS2812B.show();   
    delay(500);
    WS2812B.setPixelColor(0, WS2812B.Color(0, 255, 0));  // it only takes effect if pixels.show() is called
    WS2812B.show();
    delay(500);
    WS2812B.setPixelColor(0, WS2812B.Color(0, 0, 255));  // it only takes effect if pixels.show() is called
    WS2812B.show();
    delay(500);
    WS2812B.clear();  // set all pixel colors to 'off'. It only takes effect if pixels.show() is called
    WS2812B.show();
    delay(100);  // 500ms pause between each pixel
  //}
}
 
 
</syntaxhighlight>
 
<hr>


==== Konfiguracja środowiska do programowania w języku Rust i programy testowe  ====
==== Konfiguracja środowiska do programowania w języku Rust i programy testowe  ====
Najpierw pokażemy, jak szybko pobrać i skonfigurować niezbędne komponenty i narzędzia programowe do wygenerowania prostego projektu w języku Rust. Po skonfigurowaniu narzędzi będzie można projekt skompilować i przesłać do pamięci flash. Wszystkie czynności są wykonywane w systemie operacyjnym Linux Ubuntu wersja 24.04.2 LTS. Komputer musi być podłączony do Internetu.
<br><br>
======<span style="color:#FFFFFF; background:#ff9900 ">Włączenie repozytorium Universe</span>======
"Universe" to standardowe repozytorium dla Ubuntu. Repozytorium jest utrzymywane przez społeczność i zapewnia bezpłatne oprogramowanie typu open source. Domyślnie jest włączone w najnowszych wersjach Ubuntu. Jednak, gdyby tak nie było to możemy go włączyć za pomocą wiersza poleceń:
[[File:KAmodESP32-C3_Rust_1.png|none|800px|thumb|left]]
<br>
======<span style="color:#FFFFFF; background:#ff9900 ">Instalacja pakietów libssl-dev, libudev, kompilatora C/C++ clang  i interpretera Python 3</span>======
Pakiet libssl-dev zawiera protokoły kryptograficzne SSL i TLS do bezpiecznej komunikacji przez Internet. Pakiet libudev udostępnia interfejs API do introspekcji i wyliczania urządzeń na poziomie lokalnym system. Clang jest kompilatorem języków programowania C, C++ i Objective-C i jest częścią projektu LLVM. Znany z szybkiego czasu kompilacji i doskonałej diagnostyki, Clang może również działać jako zamiennik GCC. W projekcie jest używany linker Clang. Python3-pip jest pakietem instalacyjnym języka Python ver3, a python3-venv instaluje środowisko wirtualne.
[[File:KAmodESP32-C3_Rust_2.png|none|800px|thumb|left]]
[[File:KAmodESP32-C3_Rust_3.png|none|800px|thumb|left]]
<br>
======<span style="color:#FFFFFF; background:#ff9900 ">Instalacja pakietów Rust i menadżera Cargo</span>======
Rust to język programowania ogólnego przeznaczenia, kładący nacisk na wydajność, bezpieczeństwo typów i współbieżność. Cargo to menedżer pakietów Rust. Cargo pobiera zależności pakietu Rust, kompiluje pakiety, tworzy pakiety dystrybucyjne i przesyła je do crates.io, rejestru pakietów społeczności Rust.<br>
[[File:KAmodESP32-C3_Rust_4.png|none|800px|thumb|left]]
[[File:KAmodESP32-C3_Rust_5.png|none|800px|thumb|left]]
<br>
Instalacja niezbędnych modułów Cargo:
* espflash potrzebny do programowania pamięci Flash mikrokontrolera
* ldproxy   przekazanie argumentów konsolidatora 
* cargo-generate do generowania projektów według szablonu
[[File:KAmodESP32-C3_Rust_6.png|none|800px|thumb|left]]
<br>
======<span style="color:#FFFFFF; background:#ff9900 ">Tworzenie projektu</span>======
[[File:KAmodESP32-C3_Rust_7.png|none|800px|thumb|left]]<br>
Wykonanie tego polecenia otwiera okno uproszczonego menadżera projektu. Menadżer poprosi nas o:
* wpisanie nazwy projektu na przykład test-modulu-esp32c3
* wybranie z listy typu MCU – w naszym przypadku będzie to ESP32C3
* wybranie wersji ESP-IDF wybieramy v5.3
<br>
Pozostałe opcje można wybrać tak jak na rysunku poniżej
[[File:KAmodESP32-C3_Rust_8.png|none|800px|thumb|left]]<br>
Po wybraniu wszystkich opcji menadżer projektu utworzy katalog o nazwie projektu, w którym umieści niezbędne pliki. W katalogu src projektu menadżer umieści plik źródłowy main.rs ze szkieletem wczytanym poleceniem cargo generate. <br>
[[File:KAmodESP32-C3_Rust_9.png|none|800px|thumb|left]]
W tym momencie mamy już wszystko, żeby wyedytowany plik main.rs kompilować, przesyłać swój program do pamięci flash i uruchamiać jego działanie. Wszystkie te czynności są wykonywane automatycznie po wykonaniu polecenie. <br>
[[File:KAmodESP32-C3_Rust_10.png|none|800px|thumb|left]]<br>
Jeżeli wykonujemy to pierwszy raz to polecenie będzie pobierało z sieci szereg niezbędnych komponentów i może to trochę potrwać.
======<span style="color:#FFFFFF; background:#ff9900 ">Testowanie modułu – miganie diody D2 podłączonej do portu IO7</span>======
Na poniższym listingu jest wersja źródłowa programu cyklicznie zapalającego i gaszącego diodę LED co 500msek. Należy go umieścić w pliku main.rd (katalog src) i wykonać polecenie cargo run. <br><br>
<syntaxhighlight lang="rust">
use esp_idf_svc::hal::{delay::FreeRtos, gpio::PinDriver, peripherals::Peripherals};
//use esp_idf_sys as _; // If using the `binstart` feature of `esp-idf-sys`, always keep this module imported
fn main() {
// It is necessary to call this function once. Otherwise some patches to the runtime
// implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71
esp_idf_svc::sys::link_patches();
let peripherals = Peripherals::take().expect("Failed to take peripherals");
let mut led = PinDriver::output(peripherals.pins.gpio7).expect("Failed to create led driver");
loop {
led.toggle().expect("Failed to toggle LED");
FreeRtos::delay_ms(500);
}
}
</syntaxhighlight>
<br>
======<span style="color:#FFFFFF; background:#ff9900 ">Testowanie modułu – odczyt danych z termometru SHTC3 i akceleratora ICM42670======
Podobnie jak w poprzednim przykładzie należy wpisać do pliku poniższa wersję źródłową i wykonać polecenia cargo run.<br><br>
<syntaxhighlight lang="rust">
use esp_idf_svc::hal::{
delay::FreeRtos,
i2c::{I2cConfig, I2cDriver},
prelude::*,
};
//use esp_idf_sys as _;
use icm42670::{accelerometer::vector::F32x3, prelude::_accelerometer_Accelerometer, Address};
use shtcx::{Measurement, PowerMode::*};
fn main() {
esp_idf_svc::sys::link_patches();
let peripherals = Peripherals::take().expect("Failed to take peripherals");
let i2c_config = I2cConfig::new()
.baudrate(100.kHz().into())
.sda_enable_pullup(true)
.scl_enable_pullup(true);
let shared_bus = shared_bus::BusManagerSimple::new(
I2cDriver::new(
peripherals.i2c0,
peripherals.pins.gpio10,
peripherals.pins.gpio8,
&i2c_config,
)
.expect("Failed to create i2c driver"),
);
let mut shtc3 = shtcx::shtc3(shared_bus.acquire_i2c());
let mut icm42670 = icm42670::Icm42670::new(shared_bus.acquire_i2c(), Address::Primary)
.expect("Failed to instantiate icm42670");
loop {
let Measurement {
temperature,
humidity,
} = shtc3
.measure(NormalMode, &mut FreeRtos)
.expect("Failed to read SHTC3 temp/hum");
println!(
"SHTC3:\n\t- temp: {}\n\t- hum: {}",
temperature.as_degrees_celsius(),
humidity.as_percent()
);
let temp = icm42670
.temperature()
.expect("Failed to read ICM42670 temp");
let F32x3 {
x: ax,
y: ay,
z: az,
} = icm42670
.accel_norm()
.expect("Failed to read ICM42670 accel data");
let F32x3 {
x: gx,
y: gy,
z: gz,
} = icm42670
.gyro_norm()
.expect("Failed to read ICM42670 gyro data");
println!(
"ICM42670:\n\t- temp: {}\n\t- accel: {}, {}, {}\n\t- gyro: {}, {}, {}",
temp, ax, ay, az, gx, gy, gz
);
FreeRtos::delay_ms(1000);
}
}
</syntaxhighlight>
<br>
Po wykonaniu komendy cargo run po skompilowaniu i zapisaniu pamięci flash na ekranie terminala będą co sekundę wyświetlane odczytane po magistrali I2C dane z termometru i akceleratora.<br>
[[File:KAmodESP32-C3_Rust_11.png|850px]]<br>
<hr>
<hr>
===== Włączenie repozytorium Universe =====
===== Instalacja pakietów libssl-dev, libudev, kompilatora C/C++ clang  i interpretera Python 3 =====
===== Instalacja pakietów Rust i menadżera Cargo =====
===== Tworzenie projektu =====
===== Testowanie modułu – miganie diody D2 podłączonej do portu IO7 =====
===== Testowanie modułu – odczyt danych z termometru SHTC3 i akceleratora ICM42670 =====


==== Wymiary  ====
==== Wymiary  ====
Wymiary płytki Kamod ESP32-C3 to 63 x 27 mm.
<center>
[[File:KAmodESP32-C3_wym.png|none|800px|thumb|center]]
</center>
<hr>
<hr>
==== Linki zewnętrzne  ====
==== Linki zewnętrzne  ====
*[https://www.espressif.com/en/products/socs/esp32-c3 Dokumentacja układu ESP32-C3]
*[https://www.espressif.com/en/products/socs/esp32-c3 Dokumentacja układu ESP32-C3]

Latest revision as of 17:08, 29 October 2025

Opis

Kamod ESP32-C3 - Płytka rozwojowa z układem ESP32-C3 Mini-1
Na płytce KAmod ESP32-C3 znajduje się moduł ESP32-C3 Mini-1 firmy Espressif, który zawiera 32-bitowy, jednordzeniowy mikrokontroler SoC o architekturze RISC-V oraz interfejsy radiowe Wi-Fi i Bluetooth 5 (LE) z obsługą trybu dalekiego zasięgu (LR).

Częstotliwość taktowania MCU wynosi maksymalnie 160 MHz i jest wyposażony w aż 400 kB pamięci RAM i 4 MB pamięci Flash. Obsługuje tryby niskiego zużycia energii, działa w temperaturach od -40 do +85︒C, realizuje funkcje bezpiecznego rozruchu Secure Boot oraz szyfrowanie flash z AES-128/256-XTS, itd. Dzięki tak rozbudowanej specyfikacji doskonale nadaje się do zastosowań przemysłowych oraz z zakresu IoT. Ponadto, na płytce modułu znajdują się: dokładny czujnik temperatury i wilgotności SHTC3, czujnik MEMS typu ICM42670 zawierający 3-osiowy żyroskop i 3-osiowy akcelerometr, 3-kolorowa dioda typu WS28212, oraz dioda LED podłączona do jednego z portów mikrokontrolera. Komponenty te ułatwią budowę wielu różnych aplikacji.

Moduł jest zasilany napięciem +5V dostarczanym przez złącze USB-C, lub napięciem z akumulatora Li-Ion. Napięcie +3,3 V zasilające mikrokontroler i układy peryferyjne wytwarza przetwornica Buck DC/DC typu SY8088 o napięciu wejściowym z zakresu 2.5….5 V. Po zaniku napięcia ze złącza USB-C zasilanie automatycznie dostarczane jest z akumulatora (jeżeli jest podłączony). Układ zasilania jest uzupełniony o ładowarkę akumulatora Li-Ion na bazie układu MCP7381, zasilanej ze złącza USB-C.

Moduł Kamod ESP32-C3 jest przeznaczony do uruchamiania i testowania aplikacji w środowisku Arduino z użyciem języka C/C++ oraz Rust.


Podstawowe cechy i parametry

  • Moduł ESP32C3 Mini-1 (Wi-Fi 802.11 b/g/n, Bluetooth 5 LE)
  • Mikrokontroler 32-bit RISC-V jednordzeniowy 160 MHz, 400 kB SRAM, 4 MB Flash
  • 15 linii GPIO
  • interfejsy komunikacyjne SPI, I2C, I2S, UART, USB
  • przetwornik ADC 12-bit SAR do 6 kanałów
  • Akcelerometr ICM42670
    • Trójosiowy żyroskop MEMS - czujniki prędkości kątowej osi X, Y i Z
    • Trójosiowy akcelerometr MEMS osi X, Y i Z
    • Interfejs komunikacyjny: I2C
  • Termometr/higrometr SHTC3
    • Zakres pomiaru wilgotności 0…100%RH z dokładnością +/- 2%
    • Zakres pomiaru temperatury -40 do +125 °C. Dokładność pomiaru +/-0.2°C w zakresie od 0°C do +60°C
    • Interfejs komunikacyjny I2C
  • Przetwornica DC/DC typu SY8088
  • Układ ładowarki baterii Li-Ion typu MCP73831
  • Programowana dioda WS2812
  • Złącze USB-C
    • Zasilanie modułu napięciem +5V
    • Interfejs programujący pamięć Flash mikrokontrolera
    • Interfejs JTAG
  • Przyciski Reset i Boot

Wyposażenie standardowe

Kod Opis
KAmod ESP32-C3
  • Zmontowany i uruchomiony moduł
  • 1 x prosta listwa goldpin 12-pin raster 2,54 mm
  • 1 x prosta listwa goldpin 16-pin raster 2,54 mm

Schemat elektryczny


Opis wyprowadzeń



Zasilanie układu

Moduł jest zasilany napięciem VBUS o wartości +5 V ze złącza USB-C. To napięcie służy również do ładowania akumulatora Li-Ion 4,2 V, jeśli jest podłączony do wyjścia Charger. Za proces ładowania odpowiada układ MCP7381 realizujący algorytm ładowania o stałym natężeniu prądu/stałym napięciu, gdzie prąd ładowania jest ustawiony na 100 mA, a napięcie końcowe na 4,20 V.



Konfiguracja środowiska Arduino i program testowy


Czynności wstępne

Podłączamy moduł Kamod ESP-C3 do komputera z zainstalowanym środowiskiem Arduino IDE. W oknie wyboru modułu wybieramy moduł ESP32C3 Dev Module i wirtualny port szeregowy COMx, poprzez który jest połączony moduł.

W naszej procedurze testowej będziemy używali okna terminala, w którym będą wyświetlane wyniki działania programu. Żeby to było możliwe trzeba odblokować domyślnie zablokowaną opcję USB CDC On Boot


Konfiguracja okna preferences

Otwieramy okno preferencji File->Preferences. W polu Additional boards manager ULRs zakładki Settings wpisujemy adres https://dl.espressif.com/dl/package_esp32_index.json



Wybór typu procesora dla programowanego modułu

Wybieramy kolejno zakładkę Tools, następnie Board, rodzinę procesorów esp32 i moduł z procesorem ESP32C3. Każda zmiana modułu podłączonego do komputera przez USB będzie wymagała powtórzenia tego kroku. Jeżeli nie wykonamy go na początku, to można go wykonać przed kompilacją. W przeciwnym razie projekt nie zostanie prawidłowo skompilowany.

Instalowanie bibliotek

Program testowy wymaga zainstalowania bibliotek obsługujących układy peryferyjne: akcelerometr ICM42670P, termometr/higrometr SHTC3 i 3-kolorową diodę LED typu WS2812B.

Instalowanie biblioteki do obsługi układu ICM42670P

Klikamy na pionowym pasku narzędzi ikonę bibliotek. W oknie wyszukiwanie wpisujemy ICM42670, wybieramy ICM42670P by TDK/Invensense i klikamy Install.


Instalowanie biblioteki do obsługi układu SHTC3

Wybieramy bibliotekę Adafruit SHTC3 Library dostarczaną przez Adafruit. Wymaga ona doinstalowania powiązanych bibliotek - aby to zrobić w wyskakującym dodatkowym oknie Install library dependencies klikamy Install All.


Instalowanie biblioteki obsługującej 3-kolorową diodę RGB typu WS2812

Do sterowania 3-kolorowej diody RGB zastosujemy bibliotekę dostarczana przez Adafruit - Adafruit NeoPixel


Obsługa akcelerometru ICM42670P

ICM42670P jest połączony z mikrokontrolerem za pomocą magistrali I2C. Do jej obsługi jest przeznaczona biblioteka Wire. Do inicjowania interfejsu I2S jest używana metoda begin z argumentami określającymi linie portów przypisane do sygnałów SDA i SCL

#define I2C_SDA 10              //SDA IO10
#define I2C_SCL 8               //SCL IO8
Wire.begin(I2C_SDA, I2C_SCL);


Obsługa termometru/higrometru SHTC3

Układ SHTC3 łączy się z mikrokontrolerem również za pomocą interfejsu I2C. Konfiguracja i inicjacja tego interfejsu została pokazana powyżej. Inicjalizacja biblioteki układu SHTC3 jest wykonywana standardowo przez metodę begin.

shtc3.begin();

Odczytywanie i konwersję wartości temperatury wykonuje metoda htc3.getEvent

htc3.getEvent(&humidity, &temp); // read temp and humidity

Dane wyjściowe są umieszczane w zmiennych temp.temperature i humidity.relative_humidity i można je bezpośrednio wyświetlić.

Przykładowy wydruk odczytanych danych z czujnika SHTC3 na konsoli znakowej Arduino IDE


Obsługa diody RGB WS2812B

Tworzymy instancję WS2812B, w której określamy: ilość diod WS2812 połączonych w łańcuchu (NUM_PIXELS), oraz numer portu linii danych (PIN_WS2812B). Pozostałe parametry można zostawić domyślnie. U nas jest jedna dioda (NUM_PIXELS = 1) podłączona do linii poru DO2 (PIN_WS2812B =2)

#define PIN_WS2812B  2          // ESP32 pin that connects to WS2812B
#define NUM_PIXELS     1        // The number of LEDs (pixels) on WS2812B
Adafruit_NeoPixel WS2812B(NUM_PIXELS, PIN_WS2812B, NEO_GRB + NEO_KHZ800);

Inicjalizacja drivera jest standardowo wykonywana przez metodę begin:

WS2812B.begin();              //WS2812 driver config

Metoda setBrightness służy do ustawiania jasności świecenia wszystkich diod

WS2812B.setBrightness(50);    //WS8212 brightness

Metoda clear wygasza wszystkie diody, a metoda setPixelColor określa składowe koloru dla każdej z diod.

WS2812B.setPixelColor(0, WS2812B.Color(255, 0, 0)); //kolor czerwony

Skutki działania metod clear i setPixelColor są widoczne po wywołaniu metody show:

WS2812B.show();

Sprawdzanie działania modułu WiFi

Procedura testowa sprawdzająca działanie modułu WiFi polega na skanowaniu radiowej sieci WiFi i wyświetlaniu znalezionych identyfikatorów SSID lokalnych sieci wraz z poziomem sygnału radiowego, kanałem radiowym oraz rodzajami szyfrowania danych.
Najpierw jest ustawiany tryb WIFI_STA, czyli tryb stacji. W tym trybie moduł ESP32 może się łączyć z sieciami WIFI. Po połączeniu z ruterem moduł może żądać informacji z Internetu (jeżeli ruter jest połączony z Internetem), lub z urządzeń z lokalnej sieci rutera. Po ustawieniu tego trybu wykonujemy ewentualne rozłączenie z siecią (jeżeli moduł był wcześniej połączony):

WiFi.mode(WIFI_STA); //station mode

WiFi.disconnect();         //disconnect WIFI network


Możemy teraz skanować identyfikatory sieci WIFI za pomocą metody scanNetworks
Metoda zwraca ilość wykrytych sieci wspomniane już parametry: poziom sygnału radiowego, kanał radiowy oraz rodzaj szyfrowania danych.

numNetworks = WiFi.scanNetworks(); //scan WIFI networks </nowiki>
  Serial.println("Scan done");
  if (numNetworks == 0)
  {
    Serial.println("no networks found");
  }

Po wykonaniu skanowania można wyświetlić odczytane dane w konsoli i wykorzystać do w naszej aplikacji na przykład w celu połączenia z wybraną siecią.

for (int i = 0; i < numNetworks; ++i) {
      // Print SSID and RSSI for each network found
      Serial.printf("%2d", i + 1);
      Serial.print(" | ");
      Serial.printf("%-32.32s", WiFi.SSID(i).c_str());
      Serial.print(" | ");
      Serial.printf("%4ld", WiFi.RSSI(i));
      Serial.print(" | ");
      Serial.printf("%2ld", WiFi.channel(i));
      Serial.print(" | ");
      switch (WiFi.encryptionType(i)) {
        case WIFI_AUTH_OPEN:            Serial.print("open"); break;
        case WIFI_AUTH_WEP:             Serial.print("WEP"); break;
        case WIFI_AUTH_WPA_PSK:         Serial.print("WPA"); break;
        case WIFI_AUTH_WPA2_PSK:        Serial.print("WPA2"); break;
        case WIFI_AUTH_WPA_WPA2_PSK:    Serial.print("WPA+WPA2"); break;
        case WIFI_AUTH_WPA2_ENTERPRISE: Serial.print("WPA2-EAP"); break;
        case WIFI_AUTH_WPA3_PSK:        Serial.print("WPA3"); break;
        case WIFI_AUTH_WPA2_WPA3_PSK:   Serial.print("WPA2+WPA3"); break;
        case WIFI_AUTH_WAPI_PSK:        Serial.print("WAPI"); break;
        default:                        Serial.print("unknown");
      }
      Serial.println();
      delay(10);
    }
  }

Przykładowy wydruk działania programu skanującego sieć WIFI na konsoli znakowej Arduino IDE


Po wykonaniu skanowania i wyświetleniu danych trzeba wyczyścić dane, żeby przygotować moduł WiFi do kolejnego skanowania – metoda scanDelete

WiFi.scanDelete();

Program testowy

Program testowy ma zadanie przetestować wszystkie komponenty umieszczone na płytce modułu. Test składa się z kolejnych kroków:

  • Zapaleniu diody czerwonej LED podłączonej do linii portu IO7
  • Odczytaniu i wyświetleniu w konsoli Arduino IDE odczytanych danych z ICM42670P
  • Odczytaniu i wyświetleniu w konsoli Arduino IDE odczytanych danych z SHTC3
  • Skanowaniu sieci WIFI i wyświetleniu w konsoli Arduino IDE identyfikatorów SSID siłę sygnału radiowego, numer kanału WIFI i rodzaj kodowania danych w sieci dla każdej ze znalezionych sieci
  • Zgaszeniu czerwonej diody LED
  • Zapaleniu co 0,5 sekundy kolejnych diod WS2812B czerwonej, zielonej i niebieskiej
  • Zgaszeniu wszystkich diod WS2812B i rozpoczęciu testu od nowa


Poniżej pokazany jest fragment ekranu konsoli znakowej Arduino IDE wyświetlający jeden przebieg programu testowego.


Kod programu testowego znajduje się poniżej, można go skompilować w środowisku Arduino.

#include "WiFi.h"
#include<Wire.h>               //I2s DRIVER
#include <Adafruit_NeoPixel.h>//RGB diode WS2812
#include "Adafruit_SHTC3.h"
#include "ICM42670P.h"          //ICM42670P driver

#define LED_BUILTIN 7           //LED IO7 to flash 

#define I2C_SDA 10              //SDA IO10 
#define I2C_SCL 8               //SCL IO8
#define PIN_WS2812B  2          // ESP32 pin that connects to WS2812B
#define NUM_PIXELS     1        // The number of LEDs (pixels) on WS2812B

Adafruit_NeoPixel WS2812B(NUM_PIXELS, PIN_WS2812B, NEO_GRB + NEO_KHZ800);
ICM42670 IMU(Wire,0);           //I2S addres 0x68
Adafruit_SHTC3 shtc3 = Adafruit_SHTC3();


void setup() {

    //WS28212 setup   
    WS2812B.begin();              //WS2812 driver config
    WS2812B.setBrightness(50);    //WS8212 brightness
    //LED flash setup 
    pinMode(LED_BUILTIN, OUTPUT);  //IO7 output 
    //serial setup
     Serial.begin(115200);
     delay(2000);
     while(!Serial);                 //wait to serial ready  
    //I2S line setup 
    Wire.begin(I2C_SDA, I2C_SCL);                    //setup I2S driver
    IMU.begin();                                      //setup ICM42670P driver
    // Start accelerometer and gyroscope
    IMU.startAccel(100, 16); // 100 Hz, ±16g
    IMU.startGyro(100, 2000); // 100 Hz, ±2000 dps
    shtc3.begin();
    WiFi.mode(WIFI_STA);
    WiFi.disconnect();
    delay(100);
    
}
void loop()
 {
  int numNetworks;
  sensors_event_t humidity, temp;
  inv_imu_sensor_event_t imu_event;
   digitalWrite (LED_BUILTIN, HIGH);
  //ICM42670P register read, convert and 
  Serial.print("\n");
   Serial.print("********************************");
   Serial.print("\n");
  int ret = IMU.getDataFromRegisters(imu_event);   //ICM42670P register read 
  Serial.println(ret);
  if (ret == 0) {
// Convert acceleration to g
  float accelX = imu_event.accel[0] / 2048.0;
  float accelY = imu_event.accel[1] / 2048.0;
  float accelZ = imu_event.accel[2] / 2048.0;

// Convert gyroscope to dps
  float gyroX = imu_event.gyro[0] / 16.4;
  float gyroY = imu_event.gyro[1] / 16.4;
  float gyroZ = imu_event.gyro[2] / 16.4;
//print converted result
  Serial.print("ICM42670P AccelX:");
  Serial.println(accelX);
  Serial.print("ICM42670P AccelY:");
  Serial.println(accelY);
  Serial.print("ICM42670P AccelZ:");
  Serial.println(accelZ);
  Serial.print("********************************");
  Serial.print("\n"); 
  Serial.print("ICM42670P GyroX:");
  Serial.println(gyroX);
  Serial.print("ICM42670P GyroY:");
  Serial.println(gyroY);
  Serial.print("ICM42670P GyroZ:");
  Serial.println(gyroZ);
  Serial.print("********************************");
   Serial.print("\n");
  Serial.print("ICM42670PTemperature:");
  Serial.println((imu_event.temperature/128.0)+25.0);
  Serial.print("********************************");
  Serial.print("\n");
}
  Serial.print("SHTC3P register read.........:");
  Serial.print("\n");
  Serial.print("********************************");
  Serial.print("\n");
  shtc3.getEvent(&humidity, &temp);// read temp and humidity 
  
  Serial.print("SHTC3 Temperature: "); Serial.print(temp.temperature); Serial.println(" deg C");
  Serial.print("SHTC3 Humidity: "); Serial.print(humidity.relative_humidity); Serial.println("% rH");
  Serial.print("********************************");
  Serial.print("\n");
      numNetworks = WiFi.scanNetworks();
  
    Serial.println("Scan done");
  if (numNetworks == 0) {
    Serial.println("no networks found");
  } else {
    Serial.print(numNetworks);
    Serial.println(" networks found");
    Serial.println("Nr | SSID                             | RSSI | CH | Encryption");
    for (int i = 0; i < numNetworks; ++i) {
      // Print SSID and RSSI for each network found
      Serial.printf("%2d", i + 1);
      Serial.print(" | ");
      Serial.printf("%-32.32s", WiFi.SSID(i).c_str());
      Serial.print(" | ");
      Serial.printf("%4ld", WiFi.RSSI(i));
      Serial.print(" | ");
      Serial.printf("%2ld", WiFi.channel(i));
      Serial.print(" | ");
      switch (WiFi.encryptionType(i)) {
        case WIFI_AUTH_OPEN:            Serial.print("open"); break;
        case WIFI_AUTH_WEP:             Serial.print("WEP"); break;
        case WIFI_AUTH_WPA_PSK:         Serial.print("WPA"); break;
        case WIFI_AUTH_WPA2_PSK:        Serial.print("WPA2"); break;
        case WIFI_AUTH_WPA_WPA2_PSK:    Serial.print("WPA+WPA2"); break;
        case WIFI_AUTH_WPA2_ENTERPRISE: Serial.print("WPA2-EAP"); break;
        case WIFI_AUTH_WPA3_PSK:        Serial.print("WPA3"); break;
        case WIFI_AUTH_WPA2_WPA3_PSK:   Serial.print("WPA2+WPA3"); break;
        case WIFI_AUTH_WAPI_PSK:        Serial.print("WAPI"); break;
        default:                        Serial.print("unknown");
      }
      Serial.println();
      delay(10);
    }
  }
    WiFi.scanDelete();
    digitalWrite (LED_BUILTIN, LOW);
    WS2812B.clear();  // set all pixel colors to 'off'. It only takes effect if pixels.show() is called
    WS2812B.setPixelColor(0, WS2812B.Color(255, 0, 0));  // it only takes effect if pixels.show() is called
    WS2812B.show();    
    delay(500); 
    WS2812B.setPixelColor(0, WS2812B.Color(0, 255, 0));  // it only takes effect if pixels.show() is called
    WS2812B.show(); 
    delay(500); 
    WS2812B.setPixelColor(0, WS2812B.Color(0, 0, 255));  // it only takes effect if pixels.show() is called
    WS2812B.show(); 
    delay(500); 
     WS2812B.clear();  // set all pixel colors to 'off'. It only takes effect if pixels.show() is called
     WS2812B.show(); 
    delay(100);  // 500ms pause between each pixel
  //}
}

Konfiguracja środowiska do programowania w języku Rust i programy testowe

Najpierw pokażemy, jak szybko pobrać i skonfigurować niezbędne komponenty i narzędzia programowe do wygenerowania prostego projektu w języku Rust. Po skonfigurowaniu narzędzi będzie można projekt skompilować i przesłać do pamięci flash. Wszystkie czynności są wykonywane w systemie operacyjnym Linux Ubuntu wersja 24.04.2 LTS. Komputer musi być podłączony do Internetu.

Włączenie repozytorium Universe

"Universe" to standardowe repozytorium dla Ubuntu. Repozytorium jest utrzymywane przez społeczność i zapewnia bezpłatne oprogramowanie typu open source. Domyślnie jest włączone w najnowszych wersjach Ubuntu. Jednak, gdyby tak nie było to możemy go włączyć za pomocą wiersza poleceń:


Instalacja pakietów libssl-dev, libudev, kompilatora C/C++ clang i interpretera Python 3

Pakiet libssl-dev zawiera protokoły kryptograficzne SSL i TLS do bezpiecznej komunikacji przez Internet. Pakiet libudev udostępnia interfejs API do introspekcji i wyliczania urządzeń na poziomie lokalnym system. Clang jest kompilatorem języków programowania C, C++ i Objective-C i jest częścią projektu LLVM. Znany z szybkiego czasu kompilacji i doskonałej diagnostyki, Clang może również działać jako zamiennik GCC. W projekcie jest używany linker Clang. Python3-pip jest pakietem instalacyjnym języka Python ver3, a python3-venv instaluje środowisko wirtualne.


Instalacja pakietów Rust i menadżera Cargo

Rust to język programowania ogólnego przeznaczenia, kładący nacisk na wydajność, bezpieczeństwo typów i współbieżność. Cargo to menedżer pakietów Rust. Cargo pobiera zależności pakietu Rust, kompiluje pakiety, tworzy pakiety dystrybucyjne i przesyła je do crates.io, rejestru pakietów społeczności Rust.


Instalacja niezbędnych modułów Cargo:

  • espflash potrzebny do programowania pamięci Flash mikrokontrolera
  • ldproxy  przekazanie argumentów konsolidatora
  • cargo-generate do generowania projektów według szablonu


Tworzenie projektu


Wykonanie tego polecenia otwiera okno uproszczonego menadżera projektu. Menadżer poprosi nas o:

  • wpisanie nazwy projektu na przykład test-modulu-esp32c3
  • wybranie z listy typu MCU – w naszym przypadku będzie to ESP32C3
  • wybranie wersji ESP-IDF wybieramy v5.3


Pozostałe opcje można wybrać tak jak na rysunku poniżej


Po wybraniu wszystkich opcji menadżer projektu utworzy katalog o nazwie projektu, w którym umieści niezbędne pliki. W katalogu src projektu menadżer umieści plik źródłowy main.rs ze szkieletem wczytanym poleceniem cargo generate.

W tym momencie mamy już wszystko, żeby wyedytowany plik main.rs kompilować, przesyłać swój program do pamięci flash i uruchamiać jego działanie. Wszystkie te czynności są wykonywane automatycznie po wykonaniu polecenie.


Jeżeli wykonujemy to pierwszy raz to polecenie będzie pobierało z sieci szereg niezbędnych komponentów i może to trochę potrwać.

Testowanie modułu – miganie diody D2 podłączonej do portu IO7

Na poniższym listingu jest wersja źródłowa programu cyklicznie zapalającego i gaszącego diodę LED co 500msek. Należy go umieścić w pliku main.rd (katalog src) i wykonać polecenie cargo run.

use esp_idf_svc::hal::{delay::FreeRtos, gpio::PinDriver, peripherals::Peripherals};
//use esp_idf_sys as _; // If using the `binstart` feature of `esp-idf-sys`, always keep this module imported
fn main() {
	// It is necessary to call this function once. Otherwise some patches to the runtime
	// implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71
	esp_idf_svc::sys::link_patches();
let peripherals = Peripherals::take().expect("Failed to take peripherals");
	let mut led = PinDriver::output(peripherals.pins.gpio7).expect("Failed to create led driver");
	loop {
		led.toggle().expect("Failed to toggle LED");
		FreeRtos::delay_ms(500);
	}
}


Testowanie modułu – odczyt danych z termometru SHTC3 i akceleratora ICM42670

Podobnie jak w poprzednim przykładzie należy wpisać do pliku poniższa wersję źródłową i wykonać polecenia cargo run.

use esp_idf_svc::hal::{
	delay::FreeRtos,
	i2c::{I2cConfig, I2cDriver},
	prelude::*,
};
//use esp_idf_sys as _;
use icm42670::{accelerometer::vector::F32x3, prelude::_accelerometer_Accelerometer, Address};
use shtcx::{Measurement, PowerMode::*};

fn main() {
	esp_idf_svc::sys::link_patches();

	let peripherals = Peripherals::take().expect("Failed to take peripherals");

	let i2c_config = I2cConfig::new()
		.baudrate(100.kHz().into())
		.sda_enable_pullup(true)
		.scl_enable_pullup(true);

	let shared_bus = shared_bus::BusManagerSimple::new(
		I2cDriver::new(
			peripherals.i2c0,
			peripherals.pins.gpio10,
			peripherals.pins.gpio8,
			&i2c_config,
		)
		.expect("Failed to create i2c driver"),
	);

	let mut shtc3 = shtcx::shtc3(shared_bus.acquire_i2c());
	let mut icm42670 = icm42670::Icm42670::new(shared_bus.acquire_i2c(), Address::Primary)
		.expect("Failed to instantiate icm42670");

	loop {
		let Measurement {
			temperature,
			humidity,
		} = shtc3
			.measure(NormalMode, &mut FreeRtos)
			.expect("Failed to read SHTC3 temp/hum");

		println!(
			"SHTC3:\n\t- temp: {}\n\t- hum: {}",
			temperature.as_degrees_celsius(),
			humidity.as_percent()
		);

		let temp = icm42670
			.temperature()
			.expect("Failed to read ICM42670 temp");

		let F32x3 {
			x: ax,
			y: ay,
			z: az,
		} = icm42670
			.accel_norm()
			.expect("Failed to read ICM42670 accel data");

		let F32x3 {
			x: gx,
			y: gy,
			z: gz,
		} = icm42670
			.gyro_norm()
			.expect("Failed to read ICM42670 gyro data");

		println!(
			"ICM42670:\n\t- temp: {}\n\t- accel: {}, {}, {}\n\t- gyro: {}, {}, {}",
			temp, ax, ay, az, gx, gy, gz
		);
		
		FreeRtos::delay_ms(1000);
	}
}


Po wykonaniu komendy cargo run po skompilowaniu i zapisaniu pamięci flash na ekranie terminala będą co sekundę wyświetlane odczytane po magistrali I2C dane z termometru i akceleratora.



Wymiary

Wymiary płytki Kamod ESP32-C3 to 63 x 27 mm.


Linki zewnętrzne