Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
ATmega168 7-Segmentni Display
#1
U prilogu postavljam shemu iz simulatora i kod u FastAVR-u koji mi neradi kako treba pa bih trebao malo pomoć:

Pošto čekam 3 digit 7 Segmentski Display Common Cathode počeo sam da pišem kod u FastAVR-u i simuliram shemu ispisa brojki od 000 do 480 (to ce biti kasnije soldering station controller)...i zapeo sam kod osnovnog programa evo koda:

'/////////////////////////////////////////////////////////

'///   FastAVR Basic Compiler for AVR by MICRODESIGN   ///
'///   Solder Station Controller
'/////////////////////////////////////////////////////////
$Device= m168 ' used device
$Stack = 32                         ' stack depth
$Clock = 12                          ' adjust for used crystal

Declare Sub segment_number(number As Byte) ' segments numbers

Dim i As Byte
Dim Numbers(9) As Byte         ' segments numbers
Numbers=(&h3F, &h06, &h5B, &h4F, &h66, &h6D, &h7D, &h07, &h7F, &h6F)

DDRB = &h07
DDRD = &hFF ' PORTD output for segments

Do                                        ' place your code in next line
   segment_number(123)
Loop

Sub segment_number(number As Byte)
      Reset PORTB.0 ' first segement
      Set PORTB.1
      Set PORTB.2
      PORTD = Numbers(Mid(number, 1, 1))

      Set PORTB.0 ' second segment
      Reset PORTB.1
      Set PORTB.2
      PORTD = Numbers(Mid(number, 2, 1))

      Set PORTB.0 ' third segment
      Set PORTB.1
      Reset PORTB.2
      PORTD = Numbers(Mid(number, 3, 1))
End Sub

Dakle u Do Loop pozivam proceduru segment_number(123) kojim zelim da prikazem na 3 znamekastom 7 segmentnu displayu brojku 123 (znam da ce tu trebati kasnije iz Byte u Integer jer Byte ide do 255 a mjerejne temperature ce ici do 480C pa Byte nece biti dovoljan), i imam problema sa funkcijom:

Mid dakle primjer:

number je 123

Funkcija:

Mid(number,  1, 1) treba da vrati 1
Mid(number,  2, 1) treba da vrati 2
Mid(number,  3, 1) treba da vrati 3

Ali posto Mid radi sa stringovima a ja imam integer variablu(tj trenutno byte) naravno da funkcija vraca prazan rezultat...ima li ko ideju kako to najbolje rjesiti?

Ili nekakvi primjer kako najlakse segmentirati 3 digit 7 segmentni display (ja na shemi imam 4 jer nema simulator 3 digit display koji cekam da mi stigne) pomocu tranzistora...ovo gore sam napisao i u simulatoru mi je uvijek aktivan samo jedan display dok su ostala 2 ugasena pa ako ima ko ideju ili primjer?

trebam da imam upis tri znameke (npr 3, 85, 158, 298, 369, 480) jer to ce mi vratiti MAX6675 tu brojku pa zato sam napisao tu proceduru.

Evo i sheme:

Reply
#2
Sema ti nije dobra ukoliko je led displej sa zajednickom katodom onda tranzistori treba da vode od mase na katodu svakog displeja kod tebe je samo prvi digit vezan na masi i zato je on uvek aktivan.

Tranzistore koristi NPN emiter na masi kolektor na katodi displeja.
Reply
#3
Da u pravu si...izbacio sam NPN tranzistore i spojio direkt na PORTB0 1 i 2 gdje odabirem koji segment display ce da se upise vrijednost.Stavio sam 5ms waitms nakon svakog odabira segmenta i u simulatoru to sad fino radi...dakle tocno se vidi kako sva tri displaya trepere... tako da mi netrebaju NPN tranzistori jer je dosta samo upaliti logicku "0" ili "1" sa Set ili Reset komandom i display je odabrani...ostaje mi samo rjesiti kod za znamenku dali ima ko ideju kako to rjesiti?

Npr: Basic funkcija koja 123 integer broj rastavlja i vraca 1 i 2 i 3...ovaj Mid radi samo sa stringovima pa nemogu da to korisitm..a pretvarati int u string nije bas za MCU...pa trazim neko bolje rjesenje ujedno trazim i za arduino sto ima po netu..

Reply
#4
Ovko u C-u mozes da napravis konverziju int tri cifre u string. Ne znam za Basic, ali mislim da ovo mozes lako da prekucas na Basic. Samo deljenje po modulu koristis.

KonvertovanBroj[0] = ((Broj % 1000) / 100);
KonvertovanBroj[1] = ((Broj % 100) / 10);
KonvertovanBroj[2] = (Broj % 10);

Sto se tice zajednicke za displej, OK je to za simulaciju da koristis bez tranzistora, ali za realnost nije. Crci ce ti pin. Ako upalis sve segmente na jednoj cifri (broj 8), ukupna struja se zatvara kroz zajednicki pin na MCU. Prema tvojoj semi struja kroz jedan segment je 11,1mA. Za cifru 8 je to 88,8 mA sto je previse da jedan pin primi. Pogledaj PDF za MCU. Takodje proveri kolika je maksimalna struja po izlazu na AVR-u i kolika je ukupna dozvoljena struja za port.
Reply
#5
Odlicno...evo prekucao sam kod iz C-a u Basic:

Do
For i=0 To 100
segment_number(i)
Next i
Loop

Sub segment_number(number As Byte)
Reset PORTB.0 ' first segement
Set PORTB.1
Set PORTB.2
PORTD = Numbers((number mod 1000) / 100)
WaitMs 10

Set PORTB.0 ' second segment
Reset PORTB.1
Set PORTB.2
PORTD = Numbers((number mod 100) / 10)
WaitMs 10

Set PORTB.0 ' third segment
Set PORTB.1
Reset PORTB.2
PORTD = Numbers((number mod 10))
WaitMs 10
End Sub

Stavio sam namjerno For Loop petlju da broji od 0 do 100 i to radi savrseno.

Zanima me koja je preporučena frekvencija osvjezavanja 7 segmentnog displaya da bude neprimjetno trepterenje u stvarnosti? Ja sam stavio 10ms iza svakog odabranog displaya i u For loop petlji sto dodje (1000ms / 10ms = 100Hz sto ako sam dobro izracunao je vise nego dovoljno da "ljudsko" oko nevidi to trepterenje jer je jako brzo).

Ovo za npn tranzistore cu da sada ubacim u shemu da kada stignu djelovi da ih ne zaboravim staviti...da avr pin nemoze da to izdrzdi tako da idem da stavim tranzistore pa da vidim kako ce da se ponasa u simulatoru...
Reply
#6
Frekvencija osvezavanja treba da bude veca od 50Hz. To znaci da ako imas tri cifre i zelis da ti vreme osvezavanja bude 20ms (50Hz), onda je vreme dodeljeno za jednu cifru 20ms / 3 = 6,667ms. Ovo nije ceo broj i moj primer je za frekenceciju od 50Hz.
Takodje vodi racuna o sledecem. Kada prelazis u ispisu sa jedne cifre na drugu , redosled operacija mora da bude sledeci:
1. prvo se iskljucuje tekuca cifra
2. Postavlja se kod na segmente
3. Aktivira se cifra koja se prikazuje

Ovde je bitno da prvo iskljucis tekucu cifru, pa da onda ukljucis sledecu, inace ces imati obris na displeju.
Reply
#7
Dodani i NPN tranzistori samo su mi malo "čudno" spojeni ali teko jedino radi...dakle emiter na +5V a kolektor na odabir displaya 1 2 3.

Jeli tako ok?

Na slici se vidi samo brojka "3" jer se osvjezava svaki display posebno pa zato nema komplet 030 031 032...

Display sam naručio ovaj:

https://www.ebay.com/itm/5PCS-New-0-56-I...3089909036

Nemogu naci datasheet ali koliko sam vidio za slicne displaye RED displayi vuku po segmentu 20mA znaci (5V/20mA) stavljam otpornik od 250R-270R da bi dobio max kontrast.

Reply
#8
Nije ti dobra aktivacija zajednicke na displeju.
- Displej za zajednickom katodom: na segmente dovodis logicku jedinicu na mestima gde zelis da ti svetli segment, a zajednicku katodu povezujes na kolektor NPN tranzistora. Baza tranzistora ide na pin MCU-a, a emitor na masu. NPN se aktivira dovodjenjem struje u bazu.
- Displej sa zajednickom anodom: zajednicka anoda se pomocu PNP tranzistora povezuje sa MCU-om. Emitor PNP transitora ide na +5V (npr.), baza na MCU, a kolektor na zajednicku. Segmente displeja (katode) dovodis na MCU, pri cemu se na segment koji zelis da ukljucis dovodi logicka 0.
Reply
#9
Sada je spojeno kako treba ali simulacija ne radi kako treba....na slici sam postavio step by step simulaciju i kada je emiter spojeni na masu to neradi a kada je spojeni na Vcc onda simulacija radi...znam da je pravilno da je spojeni emiter na masu kao na shemi ali vidjet logicko stanje tranzistora Q1 i Q2 imaju logicku jedinicu sa MCU postavljenu i na otpornik tece struja od cca 3,8V sto daje na otporniku struju od 3,8mA da bi ga akitiviralo...ali iako su na R9 i R10 logicke jedinice tj struja baze je 3,8mA Q1 i Q2 su zatvoreni i uopce se ne aktiviraju...kod mene je u simulaciji zamjenjen NPN i PNP...dakle kod NPN spajanjem emitera na Vcc radi display a kod PNP spajanjem emitera na GND onda isto radi display.

Dakle koju god logicku jedinicu doveden na bilo koji NPN sa sheme tranzistor je uvijek zatvoren nikad se ne aktivira...spajanjem emitera na VCC onda sve radi sto je naravno pogresno...jucer sam navecer i danas gledam i nemogu shvatiti zasto radi obratno simulator? Jel ima ko kad takvih problema?

Mozda neko zna gdje grijesim? Ili je to bug u Proteus 8.6 SP2?

Reply
#10
Sa otpornicima od je 1k je velika struja baze u odnosu na struju kolektoka. Probaj da na bazu postavis otpornik od 8k2. To je struja baze od oko 550uA. Pojacanje tranzistora je 110, tako da komotno moze da se izgura kolektorska struja.
Reply
#11
Probao sve vrijednosti od 1k do 10k i nijedna ne aktivira tranzistor...mislim da je do modela LED displaya u proteusu...jer ni sa common anode sto sam probao ne radi ako se ne okrene polaritet na pnp-u... imas li mozda proteus instaliran na PC-u? Pa da postavim ovdje projekt u proteusu da probas kod sebe...jer meni nece da radi drugacije...
Reply
#12
(03-29-2018, 09:27 PM)ronovar Wrote: Npr: Basic funkcija koja 123 integer broj rastavlja i vraca 1 i 2 i 3...ovaj Mid radi samo sa stringovima pa nemogu da to korisitm..a pretvarati int u string nije bas za MCU...pa trazim neko bolje rjesenje ujedno trazim i za arduino sto ima po netu..

Za ovo možeš koristiti funkciju itoa();
Pogledaj šta rade i ostale atof(); atol(); ....

Postavi projekat pa ću ja da probam.
Reply
#13
Evo proteus fila i hex fila...

hex file je iskompilirani BasDoc1.zip u kojemu se nalazi fastavr source code...


Attached Files
.zip   NewProjects.zip (Size: 24,08 KB / Downloads: 4)
.hex   BasDoc1.hex (Size: 1,11 KB / Downloads: 3)
.zip   BasDoc1.zip (Size: 663 bytes / Downloads: 5)
Reply
#14
Dodaj neko kašnjenje u glavnoj petlji i kompajliraj ponovo pa stavi ovde hex. Kod mene radi izgleda OK ali se brojke brzo smenjuju. Tvoj proteus fajl nisam mogao da otvorim jer imam verziju 8.3 pa sam pravio nov projekat.

U skladu sa šemom koju si postavio ovo nije dobro

    Reset PORTB.0                                ' turn on first segement

Segment se uključuje sa:

    Set PORTB.0

Izmeni i to.
Reply
#15
Dodan WaitMs 50 u glavnoj petlji da se uspore brojanje brojki od 000 - 999

I zamjejnen Reset sa Set za ukljucivanje segmenta.

Evo hexa...

Znaci kolektor na segment displaya, baza na 10k otpornik MCU-a a emiteri svih triju tranzistora na GND...jesi tako spojio?

Ja probavam ali isto neide...ako bude kod tebe radilo onda cu umjesto verzije 8.6 staviti 8.3 ako je do verzije programa...

Mozda najbolje da skines:

http://cxem.net/software/download/FastAVR.rar

Free verzija ima kompaliranje do 100 linija imas gore kod pa da probas kompilirat i isprobavat..misli da ce tako biti lakse da se otkrije gdje je greska...


Attached Files
.hex   BasDoc1.hex (Size: 1,11 KB / Downloads: 3)
Reply
#16
Povezivanje ti je OK. Princip osvežavanja displeja ti nije dobar. Ne koristim bascom pa ne mogu tu da ti pomognem ali osvežavanje se radi u prekidnoj rutini tajmera.


- Podesiš neki od tajmera tako da generiše prekid nekom frekvencijom. Frekvencija osvežavanja zavisi od broja cifara koje prikazuješ.
- U prekidnoj rutini pogasiš sve tranzistore postavljanjem porta na 0.
- Na segmente (kod tebe je to port D) dovedeš izlaz iz tvoje funkcije Numbers i to samo za jednu cifru. Ovde uvedeš pomoćni brojač koji broji od 0 pa do ukupnog broja cifara minus 1. Svaki ulaz u prekidnu rutinu povećava taj brojač za jedan. Za vrednost brojača 0 izlaz iz Numbers treba da ti bude kodirana cifra za stotine, za vrednost brojača 1 izlaz iz Numbers ti je kodirana vrednost za desetice itd..
- Uključiš tranzistor za odgovarajuću cifru i on ostaje uključen sve do narednog ulaska u prekidnu rutinu. Svo to vreme svetli jedna cifra.

U glavnoj petlji možeš da nastaviš uvećavanje broja koji želiš da prikažeš kao i do sada.
Prekid tajmera ti je vrlo bitna stvar i prava je prilika da ga savladaš sad uz ovo.
Reply
#17
Moze li u bilo kojem jeziku primjer? Tako najlakse bih shvatio...ovako mi nije bas jasnije...moze i arduino kod...
Reply
#18
Evo jedan primer za Arduino (STM32F1) i 7seg displej iskorisceno za neki voltmetar.
Malo je code u kršu, napisano na brzinu i neoptimizovano ali radi, kasnije sam to prepisao na bare-metal.


Attached Files
.txt   _7segVM.ino.txt (Size: 10,42 KB / Downloads: 23)
Reply
#19
Miki me preduhitrio. U tvom FastAVR imaš direktorijum Samples i primer TempDiag.bas. U tom primeru imaš iskorišćen prekid tajmera 1. Pogledaj ga!
Imaš i ovde primer baš kao tvoj:
http://www.ablab.in/0-to-999-display-in-...ontroller/
Reply
#20
(03-30-2018, 12:01 PM)gorankg Wrote: Povezivanje ti je OK. Princip osvežavanja displeja ti nije dobar. Ne koristim bascom pa ne mogu tu da ti pomognem ali osvežavanje se radi u prekidnoj rutini tajmera.


- Podesiš neki od tajmera tako da generiše prekid nekom frekvencijom. Frekvencija osvežavanja zavisi od broja cifara koje prikazuješ.
- U prekidnoj rutini pogasiš sve tranzistore postavljanjem porta na 0.
- Na segmente (kod tebe je to port D) dovedeš izlaz iz tvoje funkcije Numbers i to samo za jednu cifru. Ovde uvedeš pomoćni brojač koji broji od 0 pa do ukupnog broja cifara minus 1. Svaki ulaz u prekidnu rutinu povećava taj brojač za jedan. Za vrednost brojača 0 izlaz iz Numbers treba da ti bude kodirana cifra za stotine, za vrednost brojača 1 izlaz iz Numbers ti je kodirana vrednost za desetice itd..
- Uključiš tranzistor za odgovarajuću cifru i on ostaje uključen sve do narednog ulaska u prekidnu rutinu. Svo to vreme svetli jedna cifra.

U glavnoj petlji možeš da nastaviš uvećavanje broja koji želiš da prikažeš kao i do sada.
Prekid tajmera ti je vrlo bitna stvar i prava je prilika da ga savladaš sad uz ovo.

Evo citam gore navedeni tekst i FastAVR oko timera i nisu mi jasne nekve stvari:

- timer0 sam podesio sa preskalerom od 256 da daje na 12MHz kristalu 1002.667 us ili ti 1sekuda interrupt prekida sakodom:

$Timer0 = Timer, Prescale = 256 ' 1sec interrupt

Omogucio sam interrupte i startao timer0 da pocne brojati:

Enable Interrupts ' enable global interrupts

Start Timer0 ' start timer0


Zatim sam definirao prekidnu routinu koja se pokrece svakih 1sekundu (kad je timer0 overflow):

Interrupt Ovf0(), Save 1

      Reset PORTB.0 ' turn off all segments
      Reset PORTB.1
      Reset PORTB.2


End Interrupt

E sad po gore napisanim uputstvima treba da ugasim sve segmente to sam i napravio u Ovf0() interruptu...dalje trebam da dovedem na portD broj koji zelim da upisem na segment:

PORTD = segment_number((number mod 1000) / 100)

to mi je jasno kako se dovodi za stotice, desetine itd...ali nije mi jasna ta routina u tome interruptu koja treba da se povecava...novi sam sa timerima...i ovo mi je novo.

Ako mozes da fastavru da napises taj interrupt kod kako bi trebao da ite ta petlja...jer ovako neznam kako treba da i gdje se taj pomocni brojac povecava i kako se salju brojevi na display preko interrupt routine...npr u Do Loop kod:

For i=0 To 480

Next i

Dali globalnu varijablu i preuzima interrupt i prikazuje je na displayu i treba li delay?

evo i basic koda ali nedovrsenog jer neznam kako definirati taj pomocni brojac da broji cifre 1 2 3...


Attached Files
.rar   BasDoc1.rar (Size: 564 bytes / Downloads: 2)
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)