'---mikrokontroler
$regfile = "m328pdef.dat"
'---zewnetrzny kwarc
$crystal = 11059200
'---predkosc UART
$baud = 9600
'---konfiguracja stosu
$hwstack = 64
$swstack = 64
$framesize = 128
'---opoznienie wlaczenia/wylaczenia wyjscia UPS'a
Const Opoznienie_startu = 120 '120 x 0,5s = 60s = 1m
Const Opoznienie_wylaczenia = 120
'---czas przelaczania ekranow LCD
Const Zmiana_ekranu = 2 'czas w sekundach
'---korekta dla ADC
Const Korekta_prad = 0.001
Const Korekta_napiecie = 0.01
'---ilosc probek jakie wykonuje ADC
Const Ilosc_probek = 64
'---ustawienia dla akumulatora
Const Naladowany = 4.0
Const Ladowanie = 3.8
Const Rozladowany = 3.2
'---napiecie pustego akumulatora
Const Pusty_akumulator = 2.8
'---napiecie w pelni naladowanego akumulatora
Const Pelny_akumulator = 4.2
'---bufor UART
Config Serialin = Buffered , Size = 20
Config Submode = New
'---konfiguracja timera
Config Timer0 = Timer , Prescale = 1024 , Compare_a = Disconnect , Compare_b = Disconnect , Clear_timer = 1
Enable Compare0a : On Compare0a Timer0_isr Nosave : Compare0a = 107 '10ms @11MHz
'---konfiguracja przetwornika ADC
Config Adc = Single , Prescaler = Auto , Reference = Aref
'---wyjscia
Config Portd.2 = Output : Portd.2 = 0 : Ladowarka Alias Portd.2
Config Portd.6 = Output : Portd.6 = 0 : Wyjscie Alias Portd.6
'---wejscia
Config Pinb.2 = Input : Portb.2 = 1 : Usb Alias Pinb.2
'---ZMIENNE PROGRAMU
'---zmienne dla obliczen czasu
Dim 10ms As Byte , 500ms As Byte , 1s As Byte
Dim Sekundy As Byte , Ekran As Byte
Dim Odczekaj As Byte , Stan_urzadzenia As Byte
'---ADC
Dim Pomiar_wejscia As Word , Odczyt As Single , Krok As Byte
'---obliczenia danych odczytanych przez ADC
Dim V_wej As String * 6 , V_aku As String * 6 , V_wyj As String * 6
Dim Amper As String * 6 , Watt As String * 6
Dim Watt_volt As Single , Watt_amper As Single , Watt_oblicz As Single
Dim Napiecie_aku As Single , Napiecie_wej As Single
Dim Cs As Single , Akumulator As Single
'---pojemnosc akumulatora
Dim Pojemnosc_aku As Byte , Pojemnosc As Single , Aku_min_max As Single
Dim Ladowanie_aku As Byte
Dim Aku_poziom As Byte
'---status sieci 230V
Dim Siec As Byte
'---DS18B20
Dim Odczyt_ds(2) As Byte , T As Integer , T1 As Single , Temp As String * 5
'---UART
Dim Znak As Byte
'---miganie ikonami
Dim Mig As Bit , Migaj As Byte , Ikona_usb As Byte
'---konfiguracja linii 1-wire
Config 1wire = Portd.3
1wreset
1wwrite &HCC
1wwrite &H44
'---konfiguracja i2c
$lib "i2c_twi.lbx"
Config Scl = Portc.5
Config Sda = Portc.4
Config Twi = 400000
I2cinit
'---konfiguracja LCD
$lib "bl_Lcd_i2c.lib"
Config Lcd = 16x2
Const Pcf_d4 = 4
Const Pcf_d5 = 5
Const Pcf_d6 = 6
Const Pcf_d7 = 7
Const Pcf_rs = 0
Const Pcf_rw = 1
Const Pcf_e1 = 2
Dim _lcd_e As Byte
Dim Backlight As Byte
Backlight_on Alias &H08
Backlight_off Alias &H00
Backlight = Backlight_on
_lcd_e = 128
Const Pcf8574_lcd = &H4E
Waitms 100 : Cls
'---powitanie LCD
Locate 1 , 6 : Lcd "Pi UPS"
Locate 2 , 4 : Lcd "by @pimowo"
'---powitanie UART
Print ""
Print " Pi UPS"
Print "by @pimowo"
Print ""
'---odczekaj i wyczysc ekran
Wait 5 : Cls
'---deklaracja znakow
Deflcdchar 0 , 14 , 31 , 17 , 17 , 19 , 23 , 31 , 31 'akumulator
Deflcdchar 1 , 32 , 14 , 17 , 31 , 16 , 14 , 4 , 6 'ę
Deflcdchar 2 , 32 , 14 , 1 , 15 , 17 , 15 , 4 , 6 'ą
Deflcdchar 3 , 2 , 4 , 14 , 16 , 14 , 1 , 30 , 32 'ś
Deflcdchar 4 , 4 , 32 , 31 , 2 , 4 , 8 , 31 , 32 'ż
Deflcdchar 5 , 32 , 10 , 10 , 31 , 14 , 4 , 4 , 3 'wtyczka
Deflcdchar 6 , 27 , 31 , 4 , 14 , 21 , 27 , 21 , 14 'malina
Deflcdchar 7 , 6 , 9 , 9 , 6 , 32 , 32 , 32 , 32 'stopien
'---odczyt czujnika temperatury
Sub Temperatura
If Err = 0 Then
1wreset
1wwrite &HCC
1wwrite &HBE
Odczyt_ds(1) = 1wread(2)
T = Odczyt_ds(2)
Shift T , Left , 8
T = T + Odczyt_ds(1)
T1 = T * 0.0625
Temp = Fusing(t1 , "##.##")
Else
Temp = "0.0"
End If
'---tu DS szykuje nowy odczyt
1wreset
1wwrite &HCC
1wwrite &H44
End Sub
Sub Pomiary(byval Channel As Byte)
Local Pomiar As Word : Pomiar = 0
For Krok = 1 To Ilosc_probek
Pomiar = Pomiar + Getadc(channel)
Next
Pomiar_wejscia = Pomiar / Ilosc_probek
Select Case Channel
'---pomiar pradu na wyjsciu UPS
Case 0
Odczyt = Pomiar_wejscia * Korekta_prad
If Odczyt < 0.005 Then Odczyt = 0
Amper = Fusing(odczyt , "#.###")
Watt_amper = Odczyt
'---napiecie na wejsciu UPS
Case 1
Odczyt = Pomiar_wejscia * Korekta_napiecie
If Odczyt < 0.5 Then Odczyt = 0
V_wej = Fusing(odczyt , "#.###")
Napiecie_wej = Odczyt
If Napiecie_wej >= 1 Then
Siec = 0 'wszystko OK
Backlight = Backlight_on 'wlacz podswietlenie LCD
Else
Siec = 1 'brak zasialania sieciowego wiec alarm(1)
Backlight = Backlight_off 'wylacz podswietlenie LCD
End If
'---napiecie akumulatora
Case 2
Odczyt = Pomiar_wejscia * Korekta_napiecie
V_aku = Fusing(odczyt , "#.###")
Napiecie_aku = Odczyt
'---napiecie na wyjsciu UPS
Case 3
Odczyt = Pomiar_wejscia * Korekta_napiecie
If Odczyt < 0.005 Then Odczyt = 0
V_wyj = Fusing(odczyt , "#.###")
Watt_volt = Odczyt
End Select
End Sub
'---procentowa pojemnosc akumulatora
Sub Bateria
Pojemnosc = Napiecie_aku
Pojemnosc = Pojemnosc - Pusty_akumulator
Aku_min_max = Pelny_akumulator - Pusty_akumulator
Pojemnosc = Pojemnosc / Aku_min_max
Pojemnosc = 100 * Pojemnosc
Pojemnosc_aku = Pojemnosc
End Sub
'---moc pobierana z UPS
Sub Moc
Watt_oblicz = Watt_volt * Watt_amper
Watt = Fusing(watt_oblicz , "#.###")
End Sub
'---ustawienia poczatkowe
Poczatkowy Alias 0
Czekaj_i_wlacz Alias 2
Wlaczone Alias 4
Czekaj_i_wylacz Alias 10
Wylaczone Alias 15
Rozladowane Alias 20
'---wlaczenie globalnych przerwan
Enable Interrupts
'---------------
'---PETLA GLOWNA
Do
If 10ms = 1 Then
10ms = 0
'---jezeli jest podlaczony kabelek konwertera UART
If Usb = 0 Then
Locate 2 , 12 : Lcd "USB"
Else
Locate 2 , 12 : Lcd " "
End If
If 500ms < 50 Then 'x10ms = 500ms
Incr 500ms
Else
500ms = 0
If Odczekaj > 0 Then
Decr Odczekaj
If Odczekaj = 0 Then
'---1min odliczone
Select Case Stan_urzadzenia
Case Czekaj_i_wlacz
Wyjscie = 1
Stan_urzadzenia = Wlaczone
Case Czekaj_i_wylacz
Wyjscie = 0
Stan_urzadzenia = Wylaczone
End Select
'---end if 1min
End If
End If
'---wykonaj pomiary
Call Pomiary(0)
Call Pomiary(1)
Call Pomiary(2)
Call Pomiary(3)
Call Moc
Call Temperatura
Call Bateria
Gosub Miganie
Select Case Stan_urzadzenia
Case Poczatkowy
If Napiecie_wej >= 1 Then
Odczekaj = Opoznienie_startu
Stan_urzadzenia = Czekaj_i_wlacz
End If
Case Wlaczone
Select Case Napiecie_aku
Case Is <= Rozladowany
Wyjscie = 1
Ladowarka = 1
Stan_urzadzenia = Rozladowane
Aku_poziom = 1 'stan krytyczny akumulatora wiec alarm(1)
Case Is <= Ladowanie
Ladowarka = 1
Aku_poziom = 0
Case Is >= Naladowany
Ladowarka = 0
Aku_poziom = 0
End Select
'---jezeli nie ma zasilania sieciowego to wylacz ladowarke akumulatora
If Siec = 1 Then Ladowarka = 0
'---jezeli podlaczone urzadzenie zostanie odlaczone (zamkniecie systemu) to odczekaj 1m i wylacz wyjscie
' If Usb = 1 Then
' Odczekaj = Opoznienie_wylaczenia
' Stan_urzadzenia = Czekaj_i_wylacz
' End If
' Case Wylaczone
' If Siec = 0 Then Stan_urzadzenia = Poczatkowy
End Select
'---end if 500ms
End If
'---wyswietlanie wszystkich danych UPS na LCD/przewijanie ekranow LCD
If 1s < 100 Then
Incr 1s
Else
1s = 0
Incr Sekundy
If Sekundy >= Zmiana_ekranu Then
Sekundy = 0
Incr Ekran : If Ekran > 7 Then Ekran = 1
Locate 1 , 1 : Lcd Space(16) : Locate 1 , 1
Select Case Ekran
Case 1 : Lcd "Napi" ; Chr(1) ; "cie wej" ; Chr(3) ; "cie"
Case 2 : Lcd "Napi" ; Chr(1) ; "cie baterii"
Case 3 : Lcd "Napi" ; Chr(1) ; "cie wyj" ; Chr(3) ; "cie"
Case 4 : Lcd "Nat" ; Chr(1) ; Chr(4) ; "enie pr" ; Chr(2) ; "du"
Case 5 : Lcd "Moc pobierana"
Case 6 : Lcd "Temp. baterii"
Case 7 : Lcd "Bateria"
End Select
Locate 2 , 1 : Lcd Space(14) : Locate 2 , 1
Select Case Ekran
Case 1 : Lcd Chr(5) ; " " ; V_wej ; " V"
Case 2 : Lcd Chr(0) ; " " ; V_aku ; " V"
Case 3 : Lcd Chr(6) ; " " ; V_wyj ; " V"
Case 4 : Lcd Chr(6) ; " " ; Amper ; " A"
Case 5 : Lcd Chr(6) ; " " ; Watt ; " W"
Case 6 : Lcd Chr(0) ; " " ; Temp ; Chr(7) ; "C"
Case 7 : Lcd Chr(0) ; " " ; Pojemnosc_aku ; " %"
End Select
End If
'---end if 1s
End If
'---end if 10ms
End If
'---obsluga UART
If Ischarwaiting() > 0 Then 'jezeli w buforze czeka znak
Znak = Inkey()
Select Case Znak
'---jezeli odebrany znak to "R" (Reset) zresetuj UPS
Case "R"
Disable Interrupts 'wylaczenie przerwan
Start Watchdog 'uruchomienie Watchdoga
Do 'petla nieskonczona
Loop 'w niej czekamy na Reset
'---jezeli odebrany znak to "D" (Data) odeslij dane pomiarow
Case "D"
Print V_wej ; " " ; V_aku ; " " ; V_wyj ; " " ; Amper ; " " ; Watt ; " " ; Temp ; " " ; Pojemnosc_aku ; " " ; Siec ; " " ; Aku_poziom
End Select
End If
Loop
End
'---przerwanie od TIMERA
Timer0_isr:
$asm
!PUSH R16
!PUSH R24
!PUSH R26
!PUSH R27
!in R24, sreg
!PUSH R24
$end Asm
10ms = 1
'---Tuned with NoSave Tool
$asm
!POP R24
!out sreg, r24
!POP R27
!POP R26
!POP R24
!POP R16
$end Asm
Return
'---miganie ikonami
Miganie:
Mig = Not Mig
Locate 2 , 16
If Ladowarka = 1 Then
'---jezeli trwa ladowanie akumulatora mrugaj naprzemiennie ikonami kabelka i baterii
If Mig = 1 Then
Lcd Chr(5)
Else
Lcd Chr(0)
End If
Else
'---jezeli jest zasilanie sieciowe pokaz ikone kabelka
If Siec = 0 Then
Lcd Chr(5)
'---jezeli brak zasilania sieciowego pokaz ikone baterii
Else
Lcd Chr(0)
End If
End If
Return