Strona 1 z 20
Systemy wbudowane
Projekt:
Program sterujący układem zbiorników
Wykonał: Dawid Zięba
1. Układ sterowania.
2. Treść zadania.
Zbiornik 1: Poniżej poziomu X1 nalewanie w cyklu (5+t1).
Zbiornik 2: Poniżej poziomu X4 nalewanie z Z2, powyżej X4 nalewanie w cyklu (t2+1). Po osiągnięciu X3
zamkniecie Z2 i oczekiwanie na spadek poniżej X4.
Zbiornik 3: Poniżej poziomu X7 nalewanie z Z3 i Z4. Po przekroczeniu X7 nalewanie z Z3 i Z4 w cyklu
(t3+t4) aż do osiągnięcia X5. Następnie oczekiwanie, aż temperatura osiągnie T i wylewanie przez Z5 w
cyklu (t5a+t5b), aż do poziomu X7. Grzałka jest załączona cały czas powyżej poziomu X6, chyba, że
temperatura osiągnęła T . Mieszadełko pracuje podczas nalewania po przekroczeniu poziomu X6, oraz
podczas wylewania (niezależnie od poziomu).
Parametr (domyślnie)
Minimum
Maksimum
t1 (2s)
0s
5s
t2 (2s)
1s
5s
t3 (1s)
1s
5s
t4 (1s)
1s
5s
t5a (1s)
1s
5s
t5b (2s)
0s
3s
Strona 2 z 20
3. Krótki, słowny opis rozwiązania.
Zadanie zostało rozwiązane za pomocą układów sekwencyjno-czasowych. Najpierw
zostały opracowane maszyny stanów, a następnie został napisany dla sterownika
program w języku C.
4. Zaprojektowane programy: przebiegi czasowe, maszyny stanu, opis stanów, wejść i
wyjść, przeznaczenie timerów itp. W tym maszyna stanu dla menu.
Przeznaczenie timerów:
tim1- timer przeznaczony dla zbiornika 1
tim2- timer przeznaczony dla zbiornika 2
tim3- timer przeznaczony dla zbiornika 3
Strona 3 z 20
Strona 4 z 20
Strona 5 z 20
Strona 6 z 20
Strona 7 z 20
Strona 8 z 20
A. Instrukcja obsługi
Znaczenia napisów na wyświetlaczu LCD:
K1- klawisz 1
K2- klawisz 2
K3- klawisz 3
K4- klawisz 4
K5- klawisz 5
K6- klawisz 6
K7- klawisz 5
K8- klawisz 6
Z1- zawór 1
Z2- zawór 2
Z3- zawór 3
Z4- zawór 4
Z5- zawór 5
M- mieszadło
G- grzałka
P- powrót
D- dalej
‘+’ – zwiększ wartość
‘-‘ – zmniejsz wartość
Po uruchomieniu sterownika, na wyświetlaczu powinien ukazać się napis
„Sterowanie zbiornikiem” na 3s. Od momentu włączenia sterownika, będzie on
pracował domyślnie w trybie automatycznym.
Tryb ręczny:
W celu włączenia sterowania w trybie ręcznym należy wcisnąć klawisz 1, będąc w
menu głównym. Włączenie trybu ręcznego zostanie zakomunikowane
2 sekundowym komunikatem na ekranie LCD. Sterowanie zaworami, grzałką i
mieszadłem odbywa się po przez pojedyncze wciśnięcie danego klawisza
(włącza/wyłącza). Do sterowania zaworami należy używać klawiszy 1-5, do
mieszadła klawisz 6, natomiast do sterowania grzałką należy używać klawisza 7.
Powrót do trybu automatycznego odbywa się po przez wciśnięcie klawisza 8.
Ustawienia:
Aby wejść do ustawień należy wcisnąć klawisz 2, będąc w menu głównym. W
ustawieniach można dokonać zmian związanych z timerami. W menu ustawień
należy wybrać zawór za pomocą klawiszy od 1 do 5. Po wybraniu odpowiedniego
zaworu modyfikacja timera odbywa się po przez przytrzymanie lub pojedyncze
wciśnięcia klawisza 2 lub 3. Pojedyncze wciśnięcie klawisza modyfikuje czas o
0,1 sekundy. Czas na wyświetlaczu jest podawany w sekundach. Powrót do menu
wyboru zaworów odbywa się po przez wciśnięcie klawisza 1.
Strona 9 z 20
B. Kod źródłowy
#include <avr/io.h>
// Rejestry
mikrokontrolera ATmega32
#include <avr/interrupt.h>
// Przerwania
mikrokontrolera
#include <stdio.h>
// Standardowe I/O
#include "key.h"
// Obsługa
przycisków (SW0...SW7)
#include "led.h"
// Obsługa diod LED
(LD0...LD7)
#include "lcd.h"
// Obsługa
wyświetlacza LCD 2x16 znaków
#include "rslib.h"
// Obsługa
komunikacji z Symulatorem Obiektów
#include "SchematA.h"
// Oznaczenia
obiektu A
#define TCYKL 25
// Czas cyklu
obliczeń (25 x 4ms = 100ms)
volatile unsigned char cykl;
// Odmierzanie czasu
cyklu (pętli głównej)
char buf[64];
// Bufor komunikatów
LCD
//---------------------- Początek deklaracji użytkownika ---
-----------------------------
int t1=20, t2=20, t3=10, t4=10, t5a=10, t5b=20;
char tim1=50, stan1=1;
char tim2=0, stan2=1;
char tim3=0, stan3=1;
char stan4=1;
char timLCD=30, stanLCD=1;
//---------------------- Koniec deklaracji użytkownika -----
-----------------------------
int main(void)
{
DDRA = 0xff;
// Kierunek portu A
(diody LED): port wyjściowy
Strona 10 z 20
DDRB = 0x00;
// Kierunek portu B
(klawisze) : port wejściowy
PORTA = 0xff;
// Port A (diody
LED): ustaw "1" (wygaszone diody)
PORTB = 0xff;
// Port B (klawisze)
: aktywne rezystory podciągające
TCCR0 = _BV(WGM01)|_BV(CS02);
// Timer/Counter 0: tryb
CTC, dzielnik=256
OCR0 = 124;
// Limit zliczania
T0: 0.125us x 256 x (124+1) = 4ms
TIMSK = _BV(OCIE0);
// Odblokowanie
przewań T0 (Output Compare Match)
sei();
// Globalne
włączenie obsługi przerwań
LCD_init();
// Inicjowanie
wyświetlacza LCD
SYM_init(19200,0,0);
// Inicjowanie
komunikacji z symulatorem
while(1)
{
cykl = TCYKL;
// Deklarowany czas
cyklu (TCYKL x 4ms)
KEY_read();
// Odczyt stanu
klawiszy aK1..aK4
//-------------- Początek kodu użytkownika ---------
-----------------------------
//Wyswietlacz LCD
switch(stanLCD){
case 1:
LCD_xy(0,0);
LCD_puts("STEROWANIE ");
LCD_xy(0,1);
LCD_puts("ZBIORNIKAMI ");
if(!timLCD) {stanLCD=2; timLCD=20;}
break;
case 2:
LCD_xy(0,0);
LCD_puts("WLACZONY TRYB ");
LCD_xy(0,1);
Strona 11 z 20
LCD_puts("AUTOMATYCZNY ");
if(!timLCD) stanLCD=3;
break;
case 3:
LCD_xy(0,0);
LCD_puts("K1- TRYB RECZNY ");
LCD_xy(0,1);
LCD_puts("K2- USTAWIENIA ");
if(!pK1&&aK1) {
stanLCD=4;
timLCD=20;
stan1=4;
stan2=5;
stan3=9;
stan4=4;
}
if(!pK2&&aK2) {stanLCD=6; timLCD=50;}
break;
case 4:
LCD_xy(0,0);
LCD_puts("WLACZONY TRYB ");
LCD_xy(0,1);
LCD_puts("RECZNY ");
if(!timLCD) {stanLCD=5; timLCD=50;}
break;
case 5:
LCD_xy(0,0);
LCD_puts("Z1-Z5:K1-K5;M-K6");
LCD_xy(0,1);
LCD_puts("G-K7 POWROT:K8 ");
if(!pK8&&aK8){
timLCD=20;
stanLCD=2;
stan1=3;
stan2=4;
stan3=7;
stan4=1;
}
break;
case 6:
LCD_xy(0,0);
LCD_puts("WYBIERZ ZAWOR ");
LCD_xy(0,1);
Strona 12 z 20
LCD_puts("Z1-Z5:K1-K5;P:K6");
if(!pK6&&aK6) stanLCD=3;
if(!pK1&&aK1) {stanLCD=7; timLCD=50;}
if(!pK2&&aK2) {stanLCD=8; timLCD=50;}
if(!pK3&&aK3) {stanLCD=9; timLCD=50;}
if(!pK4&&aK4) {stanLCD=10; timLCD=50;}
if(!pK5&&aK5) {stanLCD=11; timLCD=50;}
if(!timLCD)
stanLCD=3;
break;
case 7:
LCD_xy(0,0);
sprintf(buf,"Z1:PRZERWA=%4.1f ",(float)t1/10);
LCD_puts(buf);
LCD_xy(0,1);
LCD_puts("+:K3 -:K2 P:K1");
if(aK3) { t1++; timLCD=50;}
if(t1>50) t1=50;
if(aK2) { t1--; timLCD=50;}
if(t1<1) t1=0;
if(!pK1&&aK1) {stanLCD=6; timLCD=50;}
if(!timLCD){
stanLCD=6;
timLCD=50;}
break;
case 8:
LCD_xy(0,0);
sprintf(buf,"Z2:NALEW. =%4.1f ",(float)t2/10);
LCD_puts(buf);
LCD_xy(0,1);
LCD_puts("+:K3 -:K2 P:K1");
if(aK3) {t2++; timLCD=50;}
if(t2>50) t2=50;
if(aK2) {t2--; timLCD=50;}
if(t2<10) t2=10;
if(!pK1&&aK1) {stanLCD=6; timLCD=50;}
if(!timLCD){
stanLCD=6;
timLCD=50;}
break;
case 9:
LCD_xy(0,0);
sprintf(buf,"Z3:NALEW. =%4.1f ",(float)t3/10);
Strona 13 z 20
LCD_puts(buf);
LCD_xy(0,1);
LCD_puts("+:K3 -:K2 P:K1");
if(aK3) {t3++; timLCD=50;}
if(t3>50) t3=50;
if(aK2) {t3--; timLCD=50;}
if(t3<10) t3=10;
if(!pK1&&aK1) {stanLCD=6; timLCD=50;}
if(!timLCD){
stanLCD=6;
timLCD=50;}
break;
case 10:
LCD_xy(0,0);
sprintf(buf,"Z4:NALEW. =%4.1f ",(float)t4/10);
LCD_puts(buf);
LCD_xy(0,1);
LCD_puts("+:K3 -:K2 P:K1");
if(aK3) {t4++; timLCD=50;}
if(t4>50) t4=50;
if(aK2) {t4--; timLCD=50;}
if(t4<10) t4=10;
if(!pK1&&aK1) {stanLCD=6; timLCD=50;}
if(!timLCD){
stanLCD=6;
timLCD=50;}
break;
case 11:
LCD_xy(0,0);
sprintf(buf,"Z5:WYLEW. =%4.1f ",(float)t5a/10);
LCD_puts(buf);
LCD_xy(0,1);
LCD_puts("+:K3 -:K2 D:K1");
if(aK3) {t5a++; timLCD=50;}
if(t5a>50) t5a=50;
if(aK2) {t5a--; timLCD=50;}
if(t5a<10) t5a=10;
if(!pK1&&aK1) {stanLCD=12; timLCD=50;}
if(!timLCD){
stanLCD=6;
timLCD=50;}
break;
case 12:
Strona 14 z 20
LCD_xy(0,0);
sprintf(buf,"Z5:PRZERWA=%4.1f ",(float)t5b/10);
LCD_puts(buf);
LCD_xy(0,1);
LCD_puts("+:K3 -:K2 P:K1");
if(aK3) {t5b++; timLCD=50;}
if(t5b>30) t5b=30;
if(aK2) t5b--;
if(t5b<=0) {t5b=0; timLCD=50;}
if(!pK1&&aK1) {stanLCD=6; timLCD=50;}
if(!timLCD){
stanLCD=6;
timLCD=50;}
break;
}
//Zbiornik 1
switch(stan1){
case 1:
Z1= 1;
if(X1) stan1=3;
else if(!tim1 && t1) {
tim1 = t1;
stan1 = 2;
}
break;
case 2:
Z1= 0;
if(!tim1) {
tim1=50;
stan1= 1;
}
break;
case 3:
Z1= 0;
if(!X1) {
tim1=50;
stan1= 1;
}
break;
case 4:
if(!pK1&&aK1) timLCD=50;
if((!pK1&&aK1)&&!Z1&&!X1) {Z1=1; timLCD=50;}
else if((!pK1&&aK1)&&Z1) {Z1=0; timLCD=50;}
Strona 15 z 20
if(X1) Z1=0;
break;
}
//Zbiornik 2
switch(stan2){
case 1:
Z2=1;
if(X4){
stan2= 2;
tim2=t2;
}
break;
case 2:
Z2=1;
if(!X4) stan2=1;
else if(X3) stan2=4;
else if(!tim2) {
tim2=10;
stan2=3;
}
break;
case 3:
Z2=0;
if(!X4) stan2=1;
else if(!tim2){
tim2=t2;
stan2=2;
}
break;
case 4:
Z2=0;
if(!X4) stan2=1;
break;
case 5:
if(!pK2&&aK2) timLCD=50;
if((!pK2&&aK2)&&!Z2&&!X3) {Z2=1; timLCD=50;}
else if((!pK2&&aK2)&&Z2) {Z2=0; timLCD=50;}
if(X3) Z2=0;
break;
}
//Zbiornik 3.1
switch(stan3) {
case 1:
Strona 16 z 20
Z3=1; Z4=1; Z5=0; M=0;
if(X7){
tim3=t3;
stan3=2;
}
break;
case 2:
Z3=1; Z4=0; Z5=0; M=0;
if(X6) stan3=4;
else if(!tim3){
tim3=t4;
stan3=3;
}
break;
case 3:
Z3=0; Z4=1; Z5=0; M=0;
if(X6) stan3=5;
else if(!tim3){
tim3=t3;
stan3=2;
}
break;
case 4:
Z3=1; Z4=0; Z5=0; M=1;
if(X5) stan3=6;
else if(!tim3){
tim3=t4;
stan3=5;
}
break;
case 5:
Z3=0; Z4=1; Z5=0; M=1;
if(X5) stan3=6;
else if(!tim3){
tim3=t3;
stan3=4;
}
break;
case 6:
Z3=0; Z4=0; Z5=0; M=0;
if(T){
stan3=7;
tim3=t5a;
Strona 17 z 20
}
break;
case 7:
Z3=0; Z4=0; Z5=1; M=1;
if(!X7) stan3=1;
else if(!tim3 && t5b) {
tim3=t5b;
stan3=8;
}
break;
case 8:
Z3=0; Z4=0; Z5=0; M=1;
if(!tim3){
tim3=t5a;
stan3=7;
}
break;
case 9:
if(!pK3&&aK3) timLCD=50;
if((!pK3&&aK3)&&!Z3&&!X5) {Z3=1; timLCD=50;}
else if((!pK3&&aK3)&&Z3) {Z3=0; timLCD=50;}
if(X5) Z3=0;
if(!pK4&&aK4) timLCD=50;
if((!pK4&&aK4)&&!Z4&&!X5) {Z4=1; timLCD=50;}
else if((!pK4&&aK4)&&Z4) {Z4=0; timLCD=50;}
if(X5) Z4=0;
if((!pK5&&aK5)&&!Z5) {Z5=1; timLCD=50;}
else if((!pK5&&aK5)&&Z5) {Z5=0;timLCD=50;}
if(!pK6&&aK6) timLCD=50;
if((!pK6&&aK6)&&!M&&X7) {Z4=1; timLCD=50;}
else if((!pK6&&aK6)&&M) {M=0; timLCD=50;}
if(!X7) M=0;
break;
}
//Zbiornik3.2
switch(stan4){
case 1:
G=0;
if(X6) stan4=2;
break;
Strona 18 z 20
case 2:
G=1;
if(T) stan4=3;
else if(!X6) stan4=1;
break;
case 3:
G=0;
if(!T) stan4=2;
else if(!X6) stan4=1;
break;
case 4:
if(!pK7&&aK7) timLCD=50;
if((!pK7&&aK7)&&!G) {G=1; timLCD=50;}
else if((!pK7&&aK7)&&G) {G=0; timLCD=50;}
if(!X7) G=0;
break;
}
if(tim1) --tim1;
if(tim2) --tim2;
if(tim3) --tim3;
if(timLCD) --timLCD;
//-------------- Wyświetlacz LCD --------------
/*sprintf(buf,"K1=%dK2=%dK3=%dK4=%d",(int)aK1,(int)aK2,(in
t)aK3,(int)aK4);
LCD_xy(0,0);
// Ustawienie
kursora w linii 1
LCD_puts(buf);
// Wyświetlenie
zawartości bufora
sprintf(buf,"L1=%dL2=%dL3=%dL4=%d",(int)L1,(int)L2,(int)L3
,(int)L4);
LCD_xy(0,0);
// Ustawienie
kursora w linii 2
LCD_puts(buf);
// Wyświetlenie
zawartości bufora*/
//-------------- Koniec kodu użytkownika -----------
-----------------------------
LED_set();
// Ustawienie diod
LED
Strona 19 z 20
//KEY_mem();
// Zapamiętanie
stanu klawiszy w pK1..pK4
SYM_send();
// Prześlij
stan wyjść do obiektu
SYM_read();
// Odczytaj
stan wejść z obiektu
//if(!cykl) L4=!L4;
// Sygnalizacja
przekroczenia czasu cyklu
while(cykl);
// Oczekiwanie na
koniec cyklu oblicz.
}
return 0;
}
//---------------------- Funkcje obsługi przerwań ----------
-----------------------------
ISR(TIMER0_COMP_vect)
// Przerwanie od
Timer/Counter 0 (co 4ms)
{
if(cykl) --cykl;
// Odmierzanie czasu
cyklu pętli głównej
}
Strona 20 z 20