Hallo liebes Forum,
Ich bin noch relativ neu im MC-Bereich und kenne mich auch
dementsprechend nicht gut aus.
Da ich schon diverse Projekte mit MC gemacht habe (Lauflicht, 7-Segment,
usw.) wollte ich mich mal an das Multiplexen von 7seg Anzeigen machen.
Ich weiß es gibt fertige Platinen und Steuerungen für Centbeträge aber
mir geht es um die Erfahrung die ich dadurch gewinne etwas selbst zu
erarbeiten...
Nun wollte ich eine Platine bauen die ein Eingangsbyte bekommt (2^0 -
2^7)
und dieses dann auf 2 7seg-Anz dezimal ausgibt (2^3 == 0 dann wird 8
ausgegeben usw.)
Dadurch dass mein Platinenlayout so kompakt ist musste ich die Ports
etwas "mischen".
Nun zu meinem Problem die Anzeige gibt nur eine 9 aus (egal welcher
eingang low ist und egal was ich mache...)
Ich habe nun den ganzen Tag rumprobiert und habe das Gefühl das mein
Code nur noch kaputter wird.
Hat jemand eine Idee? Ich denke sehr stark an einen Programmierfehler da
ich da eben noch kaum Kenntnisse habe....
LG Chainex
Chainex schrieb:> #define E_on PORTB = 0b11011111;
Das ist kaputt. Sieh Dir an, wie #defines funktionieren.
Chainex schrieb:> #define Eg PORTB = 0b11001+111;
Und das ist ganz sicher auch nicht das, was Du willst.
Mhm
Die Tranistoren sind richtig drin leider im schaltplan falsch. sorry...
Das Plus gehört da auch nicht hin ist klar...
Aber was ist an den #defines falsch? Kann ich nur einen Wert hinter den
Makronamen schreiben oder wie?
Chainex schrieb:> Die Tranistoren sind richtig drin leider im schaltplan falsch. sorry...
Wenn denn Deine Software irgendwann läuft, wirst Du sehen, dass Deine
Helligkeit stark schwankt. Es gehören 7 Widerstände dran, pro Segment
einer. In der C-Leitung vom Transistor entfällt er.
Warum hast du denn so eine beknackte Belegung gewählt? Da blickst du
doch selber übermorgen nicht mehr durch.
Die meisten von uns bevorzugen Multiplexen im Timerinterrupt, weil die
Zeiten und damit die Multiplex Helligkeit dann vorhersehbar sind.
Ausserdem sind die Basiswiderstände etwa um Faktor 10 zu hoch. Und
parallel schalten muss man da auch nichts, es reicht ein simpler 1k
Widerstand pro Transistor.
Die Widerstände hab ich nach Datenblatt ausgewählt...
und da ich keinen 8k Widerstand hatte eben die zwei paralell.
Die Belegung geht eben aus Platzgründen nicht anders.
Das anzeigen der 9 geht ja bisher und ich wollte eigentlich nur einen
Widerstand benutzen weshalb ja auch jedes Segment einzeln aufleuchtet...
> weshalb ja auch jedes Segment einzeln aufleuchtet...
WTF?
So hast du 1:14 Multiplexing, dabei kann kaum eine angemessene
Helligkeit heraus kommen. Es war außerdem extrem unvorteilhaft, die 7
Kathode auf mehr als einen Port zu verteilen.
Aber das erklärt, warum dein Code so wirr ist. Du hast dich wohl so
verzettelt, dass du selbst nicht mehr durchblickst. Bei DEM Code ist das
aber auch kein Wunder.
Dein Code ist unlesbar, viel zu kompliziert und verworren. Benutze
Zeichensatz-Tabellen und Funktionen!
Die Segmente brauchen einzelne Vorwiderstände, bei einem je Digit,
teilen sich die Ströme sonst ungleichmäßig auf. Außerdem ist so, die "1"
deutlich heller als die "8".
Chainex schrieb:> if (PIND0 == 0) { Ausgabe = (Ausgabe + 1 ); }
Das ist immer wahr.
Chainex schrieb:> if (PIND1 == 0) { Ausgabe = (Ausgabe + 2 ); }
Das ist immer falsch.
Chainex schrieb:> switch (Zehnerstelle)> [...ein Monster..]
Das so zu machen, ist Unfug.
Und längliche Quelltexte gehören als Dateianhang gemacht, nicht in den
Post.
Schritt eins: Wandle deine Pins in eine Binärzahl.
Da du mit deiner Pinbelegung großen Mist gebaut hast, ist das sehr
hässlicher Code.
int zahl = 0;
if (PIND & PIND5) { zahl |= 1; } zahl <<= 1;
if (PIND & PIND4) { zahl |= 1; } zahl <<= 1;
usw.
Schritt zwei: Wandle die Binärzahl in ihre dezimalen Stellen.
int zehner = zahl / 10;
int einer = zahl % 10;
Schritt drei: Wandle die Stellen in die Bitmuster für die Anzeige.
Bau dir eine Tabelle.
Schritt vier: Multiplexe die Anzeige.
Da du mit deiner Pinbelegung großen Mist gebaut hast, ist das auch sehr
hässlicher Code. Mache erstmal eine Funktion, die die einzelnen Segmente
ansteuert, damit das nicht ganz so furchtbar ist.
while(1) {
schreibe_segmente(zehner);
PORTB |= PORTB5;
_delay_ms(1);
PORTB &= ~PORTB5;
schreibe_segmente(einer);
PORTB |= PORTB2;
_delay_ms(1);
PORTB &= ~PORTB2;
}
Schritt fünf: Stopfe das Multiplexen in einen Timer-Interrupt.
Zeige ich nicht. Erstmal musst du das so hinkriegen.
@S. R.:
Ich würde deinen Beitrag gerne als Lesenwert kennzeichnen. Du hast
allerdings nicht beachtet, dass der TO absichtlich nur einen Widerstand
pro Anzeige eingebaut hat und jedes Segment einzeln ansteuern will.
Dein Lösungsansatz hingegen gilt für ein Multiplexing mit 2x7 (7
Segmente gleichzeitig).
Hey danke Leute,
also mit den geschweiften Klammern in den Makros kommt jetzt zumindest
eine fest einprogrammierte Zahl hinten raus.
Etwas dunkler aber das wusste ich schon vorher.
Ich muss aber sagen das ihr Recht hattet ich denke ich hab mich mit den
Pinbelegungen etwas übernommen.
Ich denke ich werde das ganze auf einer größeren Platine nochmal neu
angehen und die Anzeigen wie gewöhnlich MUXen (2x7).
Trotzdem Danke für die Hilfestellung.
Komm wohl nicht drumherum mich auch mal in Interrupts einzulesen...
LG Chainex
Stefanus F. schrieb:> Ich würde deinen Beitrag gerne als Lesenwert kennzeichnen. Du hast> allerdings nicht beachtet, dass der TO absichtlich nur einen Widerstand> pro Anzeige eingebaut hat und jedes Segment einzeln ansteuern will.
Na und? ;-) Hab ich aber tatsächlich übersehen.
Aber mit der Platine kann man trotzdem 2x7-Multiplexen (sieht halt doof
aus) und, wenn das funktioniert, auf ein segmentweises Multiplexing
erweitern. Der Code zeigt erstmal nur, dass da trotzdem noch viel zu
viele Baustellen offen sind (wie z.B. Eingangspins lesen).
Chainex schrieb:> Ich muss aber sagen das ihr Recht hattet ich denke ich hab mich mit den> Pinbelegungen etwas übernommen.
Die Pinbelegung ist zwar einfach nur große Scheiße, aber wenn du den
Code ordentlich baust, dann beschränkt sich das Hässlon nur auf zwei
Stellen: Den Eingangswert einlesen und die Segmente beschreiben. Die
Performance-Verluste sind auch eher egal.
> Ich denke ich werde das ganze auf einer größeren Platine nochmal neu> angehen und die Anzeigen wie gewöhnlich MUXen (2x7).
An deiner Stelle würde ich den Code erstmal geradeziehen, dass er
ordentlich funktioniert (mit 2x7-Multiplex). Also erstmal nur einen
Zähler hochzählen lassen, dann das ganze per Timer im Hintergrund
laufenlassen. Dann segmentweises Multiplexen machen (allein des
Spieltriebs wegen).
Neue Platine kannst du danach noch machen. Mit dem, was du bis dahin
gelernt hast, sollte die besser sein als das, was du jetzt entwerfen
würdest.
Du könntest die Vorwiderstände an den Anoden überbrücken und in die
sieben Kathoden-Leitungen jeweils einen 220Ω Widerstand einschleifen.
Ich weiß jetzt nicht wie klein deine Platine ist. Bei meinen wäre locker
genug Platz, um die 7 Leiterbahnen durchzuschneiden und einen kleinen
SMD Widerstand über die Schnittstelle zu Löten.
Chainex schrieb:> Die Belegung geht eben aus Platzgründen nicht anders.
Aber Platz für 2 parallele Basiswiderstände hast du schon? Ich kann dir
nur raten, gerade wenn du Anfänger bist, die Hardware so übersichtlich
wie möglich zu gestalten, damit du eben nicht in solche Schwierigkeiten
wie o.a. beim Programm kommst. Reiss den Mist nochmal auseinander und
folge den Ratschlägen für sinnvolle Hardware Anordnung und Struktur in
der Software.
Und sag mir jetzt nicht, das du dafür eine Platine hast fertigen lassen.
Wenn sowas mal unvermeidlich ist (z.B. PWM Ausgänge oder so), dann
benutze sinnvolle Bitmasken und Zuweisungen.
Er muß ja kein 14-fach Multiplexing machen. Die Schaltung ermöglicht
auch nen 7-fach Multiplexing der Segmente mit gleichmäßiger Helligkeit.
Die Widerstände sind allerdings etwas hoch.
Dass die Pin-Belegung sehr wild ist, mag dem Layout geschuldet sein
(evtl soll das ja auf ner Single-Layer-Platine direkt unter die Anzeige
passen). Muß man halt etwas mehr Software-Aufwand treiben. Da hier kein
ROM-Mangel herrscht und Geschwindigkeit keine Rolle spielt, kann man
sich das leisten.
Die Software ist aber greulich, selbst wenn man von Fehlern mal
abgesieht. Z.B.: wenn man schon ne Routine zum Einlesen des Wertes hat
(die prinzipiell ganz ok ist), darf man die auch aufrufen und nicht den
Code nochmal kopieren. Die Makros sind schon genannt worden - solche
Makros macht man nicht. Und die Schleife mit ihrem Mammut-Case ist sowas
von verquert.
Kurze Skizzierung ohne pipapo:
Ich schrieb:
> Die Schaltung ermöglicht auch nen 7-fach Multiplexing der Segmente mit> gleichmäßiger Helligkeit.
Ich merke gerade, dass das so nicht ganz stimmt. Ein I/O-Pin treibt nun
bis zu zwei LEDs und dadurch kann es zu Helligkeitsunterschieden kommen.
Die Transistoren selbst haben keinen Nutzen mehr. Wenn, müßten sie auf
die andere Seite.
>> Die Schaltung ermöglicht auch nen 7-fach Multiplexing der Segmente mit>> gleichmäßiger Helligkeit.> Ich merke gerade, dass das so nicht ganz stimmt. Ein I/O-Pin treibt nun> bis zu zwei LEDs und dadurch kann es zu Helligkeitsunterschieden kommen.
Bei 2x Multiplexing ist es noch schlimmer: Ein Widerstand treibt dann
bis zu 7 Segmente. Das sind 7 LEDs die quasi parallel geschaltet sind.
Aber ich denke, das war dem TO klar, weswegen er sich für 14x
Multiplexing entschieden hatte.
Chainex schrieb:> ... und ich wollte eigentlich nur einen> Widerstand benutzen weshalb ja auch jedes Segment einzeln aufleuchtet...
Dann kannst Du dir die Transitoren auch sparen.
Uwe K. schrieb:> Chainex schrieb:>>> ... und ich wollte eigentlich nur einen>> Widerstand benutzen weshalb ja auch jedes Segment einzeln aufleuchtet...>> Dann kannst Du dir die Transitoren auch sparen.
Stimmt alles in allem ziemlich undurchdacht...
Ich habs jetzt doch hinbekommen meine Software ist zwar immernoch ein
wirrwar, aber es funktioniert erstaunlich gut.
Die T´s sind in der Tat unnötig, naja war n hingekritzelter Entwurf bei
dem ich dachte ich hab nicht viel Aufwand.
Falsch gedacht allerdings hab ich denke ich einiges daraus gelernt.
Möchte mich trotzdem nochmal bedanken ;)
LG Chainex