Arduino steruje mocą grzałki

Hej! Dziś na łamach bloga za pomocą Arduino zaprojektujemy i wykonamy na płytce stykowej tak zwany grupowy regulator mocy. Jest to urządzenie za pomocą którego będziemy mogli sterować mocą np. grzałki na prąd przemienny. Zapraszam do lektury!

Najczęściej kiedy chcemy wysterować moc jakiegoś urządzenia zasilanego prądem przemiennym projektujemy układ, który po każdym przejściu sinusoidy przez punkt 0 wycina jej część. Im większa część zostanie wycięta tym mniejsza będzie moc odbiornika.

Niestety niesie to ze sobą konsekwencje w postaci sporych zakłóceń, które mogą niekorzystnie wpływać na pracę mikrokontrolera jeżeli nie zostaną dobrze odfiltrowane. Jeżeli jednak potrzebujemy zbudować taki regulator do urządzenia o charakterze rezystancyjnym, o dużej bezwładności np. grzałka do wody to idealnym rozwiązaniem dla nas będzie zbudowanie grupowego regulatora mocy. Różni się od tego opisanego powyżej tym, że podczas działania generuje dużo mniejsze zakłócenia oraz jest bardzo prosty w implementacji.

Zasada działania jest prosta – zliczamy ile razy napięcie przeszło przez zero. Jeżeli chcemy wysterować grzałkę x/y częścią pełnej mocy to włączamy ją przy pierwszym przejściu na kolejne x przejść po czym wyłączamy, a następnie po y przejściach włączamy ponownie. Zilustrujmy to na przykładzie:

Napięcie w gniazdkach w Polsce ma kształt sinusoidy o częstotliwości 50 Hz. Oznacza to, że w każdej sekundzie mamy pięćdziesiąt pełnych okresów. Sinusoida przechodzi przez 0 dwa razy na każdy okres, więc jedna sekunda to sto takich przejść przez 0. Załóżmy, że chcielibyśmy wysterować naszą grzałkę na 25% mocy – oznacza to, że na każdą sekundę powinna być ona włączona przez ćwierć sekundy. Wiemy, że w sekundę sinusoida przejdzie przez zero sto razy. Zliczamy więc pierwsze 25 przejść, po czym wyłączamy grzałkę i czekamy przez 75 przejść. Po tym czasie zaczynamy proces od nowa. Wygląda banalnie prawda? I takie też jest w implementacji.

Schemat

Uwaga! Napięcie sieciowe 230V jest niebezpieczne dla życia i zdrowia. Z tego też powodu zalecam prototypowanie na niskim napięciu (np. przez zasilacz w szczelnej obudowie, który na wyjściu da nam 12V AC). Po zrobieniu gotowego układu na płytce drukowanej, który miałby pracować z napięciem sieciowym należy zachować szczególną ostrożność a w przypadku osób małoletnich wykonywać takie prace tylko pod nadzorem osoby dorosłej!

Potrzebne elementy:

  • Triak BTA24-600BW
  • Optotriak MOC3041
  • Transoptor PC817
  • Rezystor ograniczający prąd dla diody w PC817
  • Rezystor o dużej rezystancji np. 10K
  • Gotowy mostek prostowniczy lub 4 diody
  • Potencjometr
  • Arduino, breadboard, trochę kabelków

UWAGA! Na schemacie zaznaczony jest rezystor R1 o rezystancji 220 Ω. Jest to rezystancja odpowiednia dla niskiego naięcia (ok. 12V prądu przemiennego). Jeżeli chcielibyśmy podłączyć tam pełne napięcie sieciowe należy użyć rezystora o większej rezystancji (dla 230V dobry będzie 220 kΩ).

L oraz N na schemacie to kolejno faza i przewód zerowy, GND oraz VCC to zasilanie z Arduino. Pozostałe wejścia / wyjścia zostały opisane tak jak w programie.

Jak to ma działać? Optotriak będzie bezpiecznie z poziomu Arduino sterował dużym triakiem, rezystor posłuży jako obciążenie, coby przebieg był widoczny na oscyloskopie. Mostek prostowniczy wymusi na wejściu transoptora napięcie dodatnie (będziemy tam mieli moduł z sin(x) ), a transoptor da nam już logiczne 0 lub 1 na wejściu Arduino. Podłączymy go do wejścia obsługującego przerwania, żeby móc natychmiastowo reagować na zmianę stanu.

Kod programu

Oto cały listing:

const int ZERO_CROSSING = 2;
const int OUT = 5;
const int POT = A5;

volatile int zeroCrossCount = 0;
int power = 0;

void setup() {
  pinMode(OUT, OUTPUT);
  pinMode(ZERO_CROSSING, INPUT_PULLUP);
  pinMode(POT, INPUT);
  attachInterrupt(digitalPinToInterrupt(ZERO_CROSSING), zeroCross, FALLING);
}

void loop() {
  power = map(analogRead(POT), 0, 1023, 0, 100);
  digitalWrite(OUT, zeroCrossCount < power || power == 100);
}

void zeroCross() {
  zeroCrossCount = (zeroCrossCount + 1) % 101;
}

Na początku jak zwykle ustawiamy kilka przydatnych stałych i zmiennych. Zmienną zeroCrossCount deklarujemy jako volatile, gdyż będzie się ona bardzo często zmieniała i nie chcemy, żeby kompilator nam ją zoptymalizował

W funkcji setup() najważniejsze jest wywołania attachInterrupt(). Funkcja ta ustawia nam przerwanie na wybranym przez nas pinie. W momencie, kiedy stan na danym pinie zmieni się z wysokiego na niski (FALLING) to wywoła nam się funkcja o nazwie zeroCross().

Ważne jest, aby funkcja obsługująca przerwanie robiła jak najmniej. Tak, żeby zajmować jak najmniej czasu procesora – z tego też powodu u nas będzie ona tylko inkrementowała zmienną zeroCrossCount oraz pilnowała, aby ta nie była większa niż 100.

W funkcji loop() musimy zadbać o to, żeby przeskalować wartość odczytaną z potencjometru (0 – 1023) na wartość od 0 do 100. Pomoże nam w tym zadaniu funkcja map(). Teraz już tylko prosty warunek: jeżeli zeroCrossCount będzie mniejsze bądź równe ustalonej mocy (która przekłada się u nas na liczbę przejść przez 0) to wyrażenie zwróci nam TRUE, czyli stan wysoki. W przeciwnym wypadku FALSE, czyli stan niski. Należy też uwzględnić opcję, kiedy mamy power = 100 i zeroCrossCount = 100. W takim przypadku na wyjściu Arduino będzie logiczne zero, chociaż oczekiwalibyśmy stanu wysokiego – dlatego też dodajemy OR power == 100.

Oto i cała magia. Teraz wystarczy wgrać program na płytkę i sprawdzić przebieg na zaciskach rezystora obciążającego na oscyloskopie.