
Kamera rejestruje obrazy w odcieniach szarości (GRAYSCALE) o rozdzielczości 120x160 pikseli, z odświeżaniem co 0,3 s. Algorytm oblicza średnią jasność w skali od 0 do 255 na podstawie 960 pikseli. Regulator PID steruje diodą, aby zwiększać jasność otoczenia i osiągnąć zadaną wartość, np. do doświetlania biurka.
1. ESP8266 NodeMCU V3 z układem CH340
2. ESP32-CAM
Regulator PID
Regulator PID składa się z trzech składników:
- P (proporcjonalny)
- I (całkujący)
- D (różniczkujący)
Na podstawie uchybu regulacji e(t), czyli różnicy między zadaną jasnością r(t) (0-255), a rzeczywistą jasnością otoczenia y(t), algorytm dynamicznie dostosowuje moc diody.
Sygnał sterujący u(t) wyznaczany jest według wzoru:
Gdzie współczynniki kp, ki i kd regulują działanie członów proporcjonalnego, całkującego i różniczkującego.
Kroki wykonania:
Projekt został wykonany w MicroPythonie, jednak z racji na większą możliwość modyfikacji parametrów kamery zalecana jest również próba implementacji w C++ !!
Kod projektu zawarty jest w 4 plikach umieszczonych w zipie w załącznikach: jasnosc.py, latarka.py, kamera_P.py oraz kamera_PID.py
1. Wgranie obrazu na płytkę
Aby obsługiwać kamerę w MicroPythonie, należy wgrać odpowiednie oprogramowanie. Dostępne są dwie biblioteki:
- micropython-camera-driver (intuicyjna, użyta w projekcie):
- esp32-cam-micropython-2022 (umożliwiająca streamowanie obrazu, bardziej złożona w konfiguracji):
Wgranie obrazu odbywa się poprzez program Thonny. Po pobraniu pliku BIN należy podłączyć płytkę, wybrać odpowiedni port i załadować firmware.
2. Biblioteka "jasność"
Funkcja "jasność" analizuje obrazy i oblicza średnią wartość jasności. Biblioteka pozwala na uproszczenie kodu i może być wielokrotnie wykorzystywana bez konieczności ponownego definiowania funkcji.
Jej działanie opiera się odczycie wartości buforu dla co 20-stego piksela zdjęcia, zapisanego w formacie GRAYSCALE. Działa to optymalnie, ale potencjalną zmianę można dokonać w tej linicje kodu: "for i in range(0, len(buffer), 20):"
Aby wgrać bibliotekę na płytkę:
- W programie Thonny kliknij "Zapisz jako".
- Wybierz opcję zapisu na płytce ESP.
3. Program "latarka"
Sterowanie jasnością diody LED realizowane jest za pomocą sygnału PWM. Definicja latarka = PWM(Pin(4), 100) przypisuje wyjście, które jest odpowiedzialne za interesującą nas diodę oraz częstotliwość sygnału PWM.
Wyjście przypisywane jest za pośrednictwem oznaczeń GPIO:
Dla ESP32-CAM dioda znajduje się na GPIO4
W skali od "0 do 1024" deklarujemy jasność diody, za pomocą: latarka.duty(12)
Uwaga! Dioda świeci bardzo intensywnie! Zaleca się ograniczenie maksymalnej wartości do 150.
4. Regulator P i PID
W pierwszej kolejności zaleca się zaimplementować regulator P, a następnie regulator PID.
Zmienne:
- SETPOINT - zadana wartość jasności
- Kp - wzmocnienie składnika proporcjonalnego
- Ki - wzmocnienie składnika całkującego (dla PID)
- Kd - wzmocnienie składnika różniczkującego (dla PID)
Regulator PID dostosowuje jasność diody w czasie rzeczywistym, jednak ESP32-CAM w MicroPythonie automatycznie dostosowuje jasność obrazu, czego nie da się wyłączyć, używając tego języka programowania, co może wpływać na wyniki. Zaleca się:
- Testowanie w kontrolowanym, przyciemnionym otoczeniu
- Użycie filtra na obiektyw (np. kawałek kolorowej taśmy)
Domyślnie wyznaczone w programie współczynniki wzmocnień i SETPOINT są wynikiem moich testów. Ta konfiguracja była skuteczna u mnie zarówno po przysłonieniu obiektywu taśmą, jak i używaniem kamery pod kartonowym pudełkiem (w ten sposób stwarzając przyciemnione, kontrolowane środowisko)
5. Dobór nastaw regulatora
Wartości zmiennych można obserwować w ploterze Thonny.
Regulator P:
- Ustaw początkowe wzmocnienie Kp.
- Jeśli wykres nie stabilizuje się, zmniejsz wartość Kp.
Regulator PID:
- Dobierz wartość Kp (jak w regulatorze P).
- Stopniowo dostosuj Ki i Kd.
- Jeśli odpowiedź systemu jest zbyt powolna - zwiększ Ki.
- Jeśli system jest niestabilny - zmniejsz Kd.
Przykładowe wykresy:
- Niestabilna regulacja - oscylacje wokół zadanej wartości
- Stabilna regulacja - wartość jasności stabilizuje się po czasie
##############################
Plik: kamera_PID
####################
import camera
import network
import time
import gc
import jasnosc
from machine import Pin, PWM
latarka = PWM(Pin(4), 100)
latarka.duty(0)
SETPOINT = 40
#taśma
Kp = 1.2
Ki = 6
Kd = 0.001
#pudelko war. poczatkowe nr 1
#Kp = 0.2
#Ki = 1
#Kd = 0.002
#pudelko war. poczatkowe nr 2
#Kp = 0.05
#Ki = 0.5
#Kd = 0.001
previous_error = 0
integral = 0
dt = 0.32
# Funkcja regulatora PID
def pid_controller(setpoint, measured_value):
global previous_error, integral
# Obliczanie błędu
error = setpoint - measured_value
# Składowa proporcjonalna
P = Kp * error
# Składowa całkowa
integral += error * dt
I = Ki * integral
# Składowa różniczkowa
derivative = (error - previous_error) / dt
D = Kd * derivative
# Sygnał sterujący
control_signal = P + I + D
# Aktualizacja błędu poprzedniego
previous_error = error
return control_signal
try:
camera.init(0, format=camera.GRAYSCALE, framesize=camera.FRAME_QQVGA, xclk_freq=camera.XCLK_10MHz, fb_location=camera.PSRAM)
print('camera initialazed')
while True:
buffer = camera.capture()
average_brightness = jasnosc.calculate_average_brightness(buffer)
print(average_brightness)
buffer = None # Usuń dane bufora
gc.collect() # Wymuś zbieranie pamięci
control_signal = pid_controller(SETPOINT, average_brightness)
#print("control_signal:", control_signal)
control_signal = round(control_signal)
if control_signal < 0:
control_signal = 0
elif control_signal > 1023:
control_signal = 1023
#print("control_signal:", control_signal)
latarka.duty(control_signal)
time.sleep(0.2)
except Exception as e:
print('An issue occurred')
finally:
camera.deinit()
print('Camera deinitialized')
https://github.com/shariltumin/esp32-cam-micropython-2022