• Email
  • Forum

Porady i sztuczki

Przydatne instrukcje i skróty. Znasz jakieś i chcesz się podzielić. Napisz na forum.

LCD i EMI czyli krzaki na wyświetlaczu

Dostałem kiedyś sterownik do wytrawiarki. Podobno kiedyś był drogi :D
Co tu dużo mówić soft w niej był tragiczny a jakość wykonania także daleko odbiega od dzisiejszych standardów :D
No ale darowanemu koniowi się w zęby nie zagląda. Zmieniłem więc soft w Atmedze i tylko jedna rzecz mnie
jeszcze drażniła w tym sterowniku.
Otóż steruje on również pomką napowietrzania. O ile grzałka raczej nie jest obciążeniem indukcyjnym to silnik
już tak i zabezpieczenie cewek przekaźników diodami niewiele tu zmienia.

Na stykach przekaźnika pojawiają się łuki które sieją spustoszenie na wyświetlaczu.

Można temu zaradzić stosując odpowiednie gasiki i tym podobne przewidziane do tego rozwiązania.
Poszedłem jednak na skróty i dolutowałem kondensator 1nF pomiędzy masę a wejście EN wyświetlacza.

Sprawa krzaków załatwiona ;) Taki lifehack :D

[Rozmiar: 37989 bajtów]

Obsługa wartości przechowywanych w Eeprom

Może kogoś zaciekawi jak najczęściej rozwiązuję sprawy zmiennych przechowywanych w Eeprom i ich początkowych wartości

Należy wiedzieć że zaraz po programowaniu cała pamięć Eeprom jest "skasowana" czyli wypełniona &HFF

To powoduje że kiedy w programie umieścimy coś takiego jak odczyt do zmiennej typu Word to uC odczyta &HFFFF czyli 65535
Jeszcze gorzej jest kiedy odczytana wartośc ma być przepisana do zmiennej typu Integer. &HFFFF oznacza wtedy wartość -32767
Częstym sposobem na rozwiązanie tego problemu były zapisy typu:
Dim Zmienna As Word
Readeeprom Zmienna , 1
If Zmienna > Oczekiwana_wartośc_max Then Zmienna = 100 'przykladowa wartość
Niestety używając tego sposobu dla każdej zmiennej trzeba w kodzie zapisać jej wartość graniczną.

Dlatego piszę to inaczej

Wykorzystuję to, że Eeprom początkowo ma wartości &HFF
Odczytuję do zmiennej tylko jeden bajt i sprawdzam czy był już kiedyś zapisywany moją umówioną wartością.
Jeśli nie, to zapisuję ją tą umówioną wartością i przy okazji wpisuję do eeprom domyślne ustawienia dla urządzenia.
Sposób ten ma jeszcze jedną zaletę. Bardzo łatwo jest wbudować funkcję przywracania "ustawień fabrycznych".
Kolejność wtedy wygląda tak:
'**************************************************
'*    WARTOŚCI POCZĄTKOWE I PAMIĘTANE W EEPROM    *
'**************************************************
Config PINB.0 = Input : Set PORTB.0 : Reset_ustawien Alias PINB.0 
'przyciśnięcie przycisku przy starcie przywróci ustawienia domyślne

'zmienna do sprawdzenia stanu programowania eeprom, jej odpowiednik w eeprom i wartość umówiona
Dim Ee_check As Byte , Ee_check_ee As Eram Byte : Const Mem_ee = &H10

Dim Tryb_pracy As Byte , Tryb_pracy_ee As Eram Byte      ' zmienna programu i jej odpowiednik w eeprom
Dim Ilosc_stopni As Byte , Ilosc_stopni_ee As Eram Byte  ' zmienna programu i jej odpowiednik w eeprom
Dim Example_str As String * 15, Example_str_ee As Eram String * 15

Ee_check = Ee_check_ee                                   ' sprawdź czy eeprom była programowana

If Reset_ustawien = 0 Then Ee_check = &HFF               ' nawet jeśli to przyciskiem można to zmienić

If Ee_check <> Mem_ee Then                               ' jeśli nie była programowana
 Ee_check_ee = Mem_ee                                    ' to zostaw znak że programowana

  Ilosc_stopni_ee = 21                                   ' wpisz wartości domyślne
  Tryb_pracy_ee = 0
  Example_str_ee = "Zostaw wiadomosc"
	
End If

' ** MEMORY READING **
Ilosc_stopni = Ilosc_stopni_ee                           ' tutaj już normalne odczytywanie z eeprom
Tryb_pracy = Tryb_pracy_ee                               ' tylko to będzie się działo jeśli eeprom już programowana
Example_str = Example_str_ee

Symulator - sprawdzanie ilości cykli

Nie piszę programów z zegarkiem w ręce, ale czasem z chęci sprawdzenia jak lepiej pisać sprawdzam które rozwiązanie będzie bardziej optymalne.

Niedawno powstał krótki filmik na którym można zobaczyć, to o czym napisałem niżej.


Na pewno niejednokrotnie widziałeś różnie napisane Menu.
Sama logika najczęściej nie zajmuje dużo miejsca. Najwięcej zajmują "napisy" czyli łańcuchy danych tekstowych
Kiedy mamy wyświetlacz alfanumeryczny i chcemy na jego środku umieścić krótszy napis to stajemy przed dylematem.
Jeśli poprzedni napis był dłuższy od nowego to, albo musimy skasować ekran co wiąże się z długim czasem i nawet nieprzyjemnym mrugnięciem całego LCD, albo użyć innego rozwiązania.
Często spotykanym sposobem jest takie zapisanie napisów we Flash by przykryły poprzedni napis spacjami

Menu_string(1) = "    Menu 1    "
Menu_string(2) = "    Menu 2    "
Menu_string(3) = "    Menu 3    "
Menu_string(4) = "    Menu 4    "

Wyświetlacz już nie miga, ale te spacje zajmują bardzo dużo miejsca i kiedy mamy bardziej rozbudowane menu to taki sposób byłby bardzo nieefektywny
Dlatego napisałem sobie Suby które umieszczają napis na środku wyświetlacza ładując tylko potrzebne dane. Reszta pól zamazywana jest automatycznie.
Żeby zamazać nieużywane pola można użyć funkcji Spc(16) i tak też zbudowany jest pierwszy sub.
Najpierw czyści wybraną linię. Następnie oblicza długość nowego napisu. Długość dzieli na pół i o tyle cofa się z rozpoczęciem zapisu tak by połowa napisu była na środku wyświetlacza ;)

Po jakimś czasie wpadłem na pomysł, że można to zrobić jeszcze szybciej przygotowując w pamięci SRAM zmienną tekstową tak długą jak linia wyświetlacza.
Najpierw zmienną String (Msg_str) wypełniam spacjami za pomocą Space(16)
Powinno to w SRAM trwać krócej niż nadpisywanie wyświetlacza spacjami.
Później do tak utworzonego stringa wklejam dokładnie w jego środek nowy napis. Tak więc mam przygotowany string który po brzegach ma spacje ;)

Teraz pora na symulator Bascom - który Sub lepszy?

W kodzie umieściłem instrukcje NOP. Pozwalają mi one "oprzeć się kursorem" i prawym klawiszem dokonac wybranej akcji. Myślę że może się komuś przydać ponieważ kiedy chcemy się zatrzymać pomiędzy instrukcjami to symulator napisze że w tymi miejscu nie ma żadnego wykonywalnego kodu. A tak się odczepi i stanie na tym NOP.


[Rozmiar: 37989 bajtów]

[Rozmiar: 37989 bajtów]

[Rozmiar: 37989 bajtów]

[Rozmiar: 37989 bajtów]

Jak widać nowszy, drugi sposób jest szybszy :D


Gdyby kogoś interesował kod - proszę bardzo

$regfile = "m16def.dat"
$crystal = 8000000
$hwstack = 64
$swstack = 64
$framesize = 64

$sim

Config Submode = New

Dim Help_str As String * 16
Dim Helpb As Byte , Posx As Byte , Posy As Byte

Help_str = "Test str."


Sub Show_central(byval Posy As Byte)

 Locate Posy , 1 : Lcd Spc(16)

  Helpb = Len(help_str)
   Shift Helpb , Right , 1
    Posx = 9 - Helpb
     Locate Posy , Posx : Lcd Help_str

End Sub

Sub Show_central2(byval Posy As Byte)

 Local Msg_str As String * 16
  Msg_str = Space(16)
 Local Copy As Byte

 Helpb = Len(help_str)
  Copy = Helpb
   Shift Helpb , Right , 1
    Posx = 9 - Helpb
     Mid(msg_str , Posx , Copy) = Help_str
      Locate Posy , 1 : Lcd Msg_str

End Sub

Cls

Do

 nop

  Call Show_central(1)                                      '4120 0,515ms

 nop

  Call Show_central2(2)                                     '3042 0,38025ms

 nop

Loop

Nazwy rejestrów mikrokontrolera.

Jeśli chcesz się dowiedzieć jak nazywa się interesujacy Cię rejestr możesz pomóc sobie zerkając do pliku *def.dat (tego z nagłówka Twojego programu). Są w nim ujęte prawie wszystkie rejestry i jest to bardzo przydatne przy przerabianiu programu z innego procesora.

Najlepiej jest go otworzyć w środowisku Bascom. Trzeba jedynie w opcjach otwierania zmienić widok na "All files"(zaznaczyłem elipsą), a pliku szukać w folderze gdzie zainstalowany jest Bascom.

[Rozmiar: 73353 bajtów]

Kiedy już mamy taki otwarty to naciskamy Ctrl+F i w nowo otwartym oknie wpisujemy czego szukamy np."Compare". Jeśli potem będziemy naciskać "F3" to zobaczymy wszystkie wpisy dotyczące Compare.

Wyłączanie bloków kodu

Jeśli chcemy szybko do testów wyłączyć większy niż linijka blok kodu to najlepiej użyć do tego kombinacji Ctrl+M. Jest to całkowicie odwracalne i nawet bardziej skuteczne niż zamykanie w nawiasy.

[Rozmiar: 68356 bajtów]

Dwie diody na jednym pinie

Może się czasem przydać dwukolorowa sygnalizacja, albo przełączana wizualizacja przełączenia jakichś urządzeń. Można oszczędzić na wyprowadzeniach mikrokontrolera jeśli podłaczy się LED`y w ten sposób. Proszę jednak mieć na uwadze, że diody dwukolorowe są inaczej połączone w środku. Przyda się przy małych mikrokontrolerach albo dużej ilości LED`ów

[Rozmiar: 6674 bajtów]

Kropka w kodzie...

Co oznacza kropka pomiędzy dwoma zmiennymi? Pytano mnie o to już wiele razy więc postanowiłem to opisać.

Tak jak cały port ma osiem "nóżek" i żeby ustawić jedną piszesz PORTB.1 = 1, tak i Bajt ma osiem Bitów. Jeśli wartość przykładowego bajtu będzie wynosić 2 to w zapisie binarnym będzie to B 00000010 (każde zero lub jedynka ma swoje miejsce liczone jednak od prawej strony i to liczone od zera. Tak więc tutaj jest tylko jedna jedynka i znajduje się na pozycji jeden, nie dwa!) Licz od prawej : zero, jeden, dwa, trzy, cztery, pięć, sześć, i siedem bo z zerem jest to osiem bitów.

Co ciekawe, numer bitu może być zmienną :)

Ma to wiele świetnych zastosowań!

Przykład pierwszy. Jeszcze na porcie. Zaraz przejdę dalej:

Dim  N As Byte , Wartosc As Byte
Wartosc = 4                                                 'przykladowa wartosc

Linijka_led:
For N = 1 To 7                                              'nie ruszamy nigdy PORTD.0
 If Wartosc >= N Then Set Portd.n Else Reset Portd.n 
 'Jeśli N ma w tym obiegu mniej niż wynosi Wartosc to ustaw pin w stan wysoki, jeśli nie to w stan niski
 'Piny od 1 do 4 będą w stanie wysokim, a 5 do 7 w stanie niskim
Next
Return

W tym kodzie na pinie PORTD.0 może być dioda która świeci zawsze jeśli spełniony jest inny warunek. Nie interesuje nas i jej nie dotykamy bo pętla jest dla wartosci od 1 do 7, nie od 0 do 7. Natomiast diody na pinach od 1 do 7 są zapalane w zależności od wartości zmiennej Wartosc.

Przykład drugi.
Znak ujemnej temperatury w zmiennej typu Integer zapisany jest w ostatnim bicie. Integer jest dwubajtowa więc bitów mamy 16. Jako że trzeba uwzględnić pozycję Zero to najstarszy Bit ma numer 15.

Dim T As Integer
Dim Minus As Bit
 
Temp:
 
   1wreset
   1wwrite &HCC
   1wwrite &HBE
   T = 1wread(2)
   Minus = T.15  'sprawdzamy czy tu jest jeden czy zero
   T = Abs(t)
   T = T * 10
   T = T / 16
   1wreset 
   1wwrite &HCC
   1wwrite &H44
Return

Przykład trzeci. Sprawdzamy wszystkie bity w bajcie :)

'funkcja koduje Manchesterem wiec koduje Bajt do dwa razy wiekszej Word
'Author Evert Dekker ( http://evertdekker.com )
Function Send(byval Temp As Byte) As Word
Local Manchester As Word                                   ' zmienna przechowujaca wynik
Local Bit_number As Byte                                   ' numery bitów po kropce (od 7 do 0)
'zmienna będzie od razu dekrementowana wiec ma o jeden wieksza wartość poczatkową
Bit_number = 8                                             
Do
Shift Manchester , Left , 2
Decr Bit_number                                            'tu zmienna ma już wartość 7  i to numer bitu
If Temp.bit_number = 1 Then                'jeśli w Bajcie na pozycji Bit_number jest 1 to
Manchester = Manchester + 1                                '01
Else                                       'jeśli nie (jeśli na pozycji Bit_number jest 0)
Manchester = Manchester + 2                                '10
End If
Loop Until Bit_number = 0
Send = Manchester
End Function

Przydatna sonda

Jak ktoś nie ma oscyloskopu, to może na własne uszy przekonać się o jakości zasilania swojego układu. Wystarczą zwykłe słuchawki.
To proste gniazdko "mały jack" wylutowane z czegoś, kondensator 100nF - 1uF i krokodylek.
Krokodylkiem podłączasz się do masy a pinem kondensatorka dotykasz sobie badanych nóżek. Zapewniam, że niejeden się zdziwi z czym musi pracować mikrokontroler. Tam ma być cisza a jest szum i piski... W poprawnym układzie powinien być tylko "pyk" ładowania kondensatorka. Żadnych szumów, pisków czy buczenia od trafo.

[Rozmiar: 37989 bajtów]

TYLKO dla bezpiecznych napięć!!!

Taki prosty układ naprawdę mi kilka razy dał pojęcie dlaczego coś nie działa. Na przykład gdy jakiś nadajnik typu 433 nadaje to "szarpie" zasilaniem. Dlatego one u mnie mają swój dławik i osobny kondensator za nim... Zasilanie z chińskiej ładowarki to tragedia.. Przykładów można by mnożyć...a to zwykłe słuchawki.

Email

Jeśli mogę w czymś pomóc, napisz.