Hallo Forum Mikrocontroller und Digitale Elektronik, ...nachdem meine wirklich laienhaften Versuche (und die meiner Maschinenbaukollegen) gescheitert sind, mein Versuch bei Euch Hilfe zu bekommen. Vorweg: Ich mag Uhren, inbesondere hier elektronische die ich selbst aufbauen kann. Basis des aktuellen Projekts ist ein € 8,50 "Chinabausatz" mit Atmel AT89S52,der als Basis für eine Studiouhr dienen soll. Mein Problem ist die Art der Anzeige des LED-Sekundenkreises. Die Uhr kann 4 verschiedene Modi, wovon nur einer in etwa dem entspricht was ich gerne hätte. In diesem wird der Sekundenkreis wie gewollt bis zur Sekunde-60 aufgebaut, danach aber leider wieder "abgebaut" durch sekundenweises abschalten der LEDs. Hoffe ich erkläre es verständlich. Der Aufbau des Kreises ist also OK. Ab Sekunde-60 sollte allerdings der Aufbauvorgang wieder neu beginnen, und nicht der eingeschaltete Kreis abgebaut werden. Ohne die Sprache "C" zu kennen: Ich habe die Datei "display.c" in den Anhang gestellt. Hier vermute ich ist die Funktion hinterlegt wie der LED-Sekundenkreis gebildet wird. Die Kommentare in Deutsch sind von mir eingefügt (das Original Programm ist leider nicht kommentiert; (Zeile 9-29 und 400-420 z.B.). Im Bereich Zeile 400-420 habe ich meine laienhaften Versuche gemacht und bin immer gescheitert. Das File im Anhang ist bis auf die Kommentare original. Dazu auch noch der Schaltplan der Uhr. Wo und wie könnte ich ansetzen um das was bei "if" richtig passiert (Sekundenkreisaufbau), bei "else" genauso wieder abläuft? Bis dahin, beste Grüße Udo p.s. Den Chinabausatz findet man mit "EC1204B" LED-Clock im Netz p.p.s. Meine Versuche mache ich mit Keil-C51, meine Versuche kommen mit ProgISP über die ISP-Schnittstelle auf den Prozessor
:
Bearbeitet durch User
...schade. Keiner mit einer Idee wo ich ansetzen könnte? Bitte melden, falls ihr mehr input braucht. Danke. Grüße Udo
Du hast ja schon die richtige Stelle gefunden. Es muss letztendlich egal sein, ob Minute gerade oder ungerade ist, es muss bei sek=60 der displaybuff auf 0x00 gesetzt werden und dann einfach wieder die ungerade-if-schleife durchlaufen werden...soweit ich das auf die schnelle verstehe - oder soll das konkret für dich umgeschrieben werden? :) Klaus.
Eigentlich geht es ja nicht einfacher... entweder du schreibst in den ELSE Zweig das gleiche rein wie im IF Zweig oder du nimmst die Abfage komplett raus.
1 | void display_second1() //Sekundenkreis wird aufgebaut und ab Sek-60 wieder abgebaut, so soll es letztendlich nicht sein |
2 | {
|
3 | unsigned char disp_buf_x,disp_buf_b; |
4 | static unsigned char miao_temp; |
5 | miao_temp=miao; |
6 | disp_buf_x=miao_temp>>3; |
7 | disp_buf_b=miao_temp&0x07; |
8 | |
9 | disp_buf[disp_buf_x]|=0x01<<disp_buf_b; |
10 | }
|
...danke für die Antworten. Habe ich mal so versucht: else-funktion wie if = Sekundenkreis wird hochgezählt, bleibt aber nach erreichen der Sek-60 eingeschaltet. Das Gleiche, wenn ich die if - else funktionen wie im Original belasse, aber Auswertung der Minuten gerade/ungerade auf "if((fen&0x01)==0|1)" gesetzt. Auch hier das Ergebnis wie zuvor. Von der Logig ist das was Klaus sagt klar für mich - beim Sprung auf Sek-60 soll der (oder die) display-buffer(s) gelöscht werden und dann mit der in der if-Schleife beschriebenen Funktion wieder neu hochgezäht werden. Wie bzw. mit welchem Befehl oder welcher Funktion könnte ich den/die buffer auf 0x00 setzen? Das ist glaube ich der Knackpunkt. Einen weiteren Versuch habe ich mit kommplett auskommentierten if-else Zeilen gemacht. Die "Hochzählfunktion" oben direkt eingefügt gefolgt von zwei Zeilen um die disp_buf auf 0x00 zu setzen. Programmtechnisch wohl Quatsch - hat auch zu keinem Ergebnis geführt. Unten diese Versuche. Zur Info: "miao" heißt "Sekunde", "fen" heißt "Minute". Mit Blick auf den Schaltplan Port P0 undP2: Ist disp_buf_x Bit 0-7 der Spaltenausgang, und disp_buf_b der Zeilenausgang X0-7 für den Sekundenkreis? { unsigned char disp_buf_x,disp_buf_b; static unsigned char miao_temp; miao_temp=miao; disp_buf_x=miao_temp>>3; disp_buf_b=miao_temp&0x07; disp_buf[disp_buf_x]|=0x01<<disp_buf_b; disp_buf_x = 0x00; disp_buf_b = 0x00; //if((fen&0x01)==0|1) // wenn Minute "gerade" Sekundenkreis sekundenweise aufbauen //{ //disp_buf[disp_buf_x]|=0x01<<disp_buf_b; //} //else // wenn Minute "ungerade" Sekundenkreis sekundenweise abbauen, das soll nicht so sein // sondern: es soll wieder so anfangen wie bei "if" // also: bei wechsel auf "ungerade" Minute" den mit "if" aufgebauten Sekundenkreis // ausschalten und wieder ab Sek-1 aufbauen, usw. usf., //{ //disp_buf[disp_buf_x]|=0x01<<disp_buf_b; //disp_buf[disp_buf_x]&=~(0x01<<disp_buf_b); //} }
Und wenn du Variante 3 so abwandelst?
1 | void Display_OneLedlightenRun(void) //eine LED läuft als Sekunde um |
2 | {
|
3 | unsigned char disp_buf_x,disp_buf_b; |
4 | static unsigned char miao_temp; |
5 | disp_buf_x = miao_temp>>3; |
6 | disp_buf[disp_buf_x] = 0x00; |
7 | |
8 | miao_temp = miao; //ÏÔÊŸµ±Ç°µã |
9 | disp_buf_x = miao_temp>>3; |
10 | disp_buf_b = miao_temp&0x07; |
11 | if (disp_buf[disp_buf_x] == 60) //Wert 60 evtl. anpassen |
12 | {
|
13 | disp_buf[disp_buf_x] = 0x00; |
14 | }
|
15 | disp_buf[disp_buf_x]|=0x01<<disp_buf_b; |
16 | }
|
Nachtrag: das erste "disp_buf[disp_buf_x] = 0x00;" muss dann natürlich raus.
Hallo, ...hab ich so wie von dir angeregt ins Programm geschrieben. Mit den Änderungen in diesem Sekundenmodus wird der Kreis hochgezählt, aber leider auch nicht bei Sek-60 bzw, Sek-0 abgeschaltet um dann wieder von vorn zu beginnen. Ein anpassen des Wertes bei "if" ändert nichts. Vielleicht hilft folgendes weiter: Simulieren kann ich das Gewünschte durch drücken der Reset-Taste auf der Platine. Z.B. bei Sekunde-60 gedrückt, wird der hochgezählte Kreis ausgeschaltet und die Sekunden wie gewünscht wieder aufgebaut. Drücke ich "Reset" z.B. bei Sek-15, werden die LED's 0-14 abgeschaltet und er baut ab Reset drücken weiter richtig auf (fängt also nicht bei Sekunde-60 wieder komplett neu an. Hat sich also trotz Reset die Sekundenposition gemerkt. Könnte ich das, was bei Reset drücken mit dem Buffer für die Sekunden passiert, mit irgendeinem Befehl oder einer Funktion z.B. beim Wechsel von gerader auf ungerade Minute realisieren? So wie ich das Verhalten interpretiere, ist dieser Reset über Pin-9 der CPU wohl auch nur eine Art "Soft-Reset", denn die Uhrzeit auf den 4-stelligen 7-Segment Display bleibt auch erhalten (Pufferbatterie ist entfernt). Danke für eure Geduld Udo
Der Controller hat doch einen UART(Rx/Tx) kommst du da ran? wenn ja dann lass dir doch einfach die Werte von disp_buf[disp_buf_x], disp_buf_b und miao ausgeben und den Wert der bei Sekunde 1 ausgegeben wird schreibst du in die If abfrage. Versuche vielleicht mal if (disp_buf[disp_buf_x] == 60) //Wert 60 evtl. anpassen durch if (miao == 1) //Wert 1 evtl. anpassen zu ersetzen. >ist dieser Reset über Pin-9 der CPU wohl auch nur eine >Art "Soft-Reset" Das ist der Reset des µC. Die Uhrzeit ist noch eingestellt weil die RTC weitehin Stromversorgt ist und nicht resetet wird. Also am Ende:
1 | void Display_OneLedlightenRun(void) //eine LED läuft als Sekunde um |
2 | {
|
3 | unsigned char disp_buf_x,disp_buf_b; |
4 | static unsigned char miao_temp; |
5 | |
6 | miao_temp = miao; //ÏÔÊŸµ±Ç°µã |
7 | disp_buf_x = miao_temp>>3; |
8 | disp_buf_b = miao_temp&0x07; |
9 | if (miau == 1) |
10 | {
|
11 | disp_buf[disp_buf_x] = 0x00; |
12 | }
|
13 | disp_buf[disp_buf_x]|=0x01<<disp_buf_b; |
14 | }
|
Wie du merkst bin ich auch kein Profiprogrammierer sondern noch am Anfang des lernens. Aber so schwierig kann dein Wunsch nicht sein.
Hallo, ich habe die EC1204B Uhr mit einem ATmega8515 bestückt. Die AVR Typen ATmega8515 und ATmega162 sind quasi pin kompatible. Ich musste lediglich einen Konndensator am Reset-Pin entfernen und eine Widerstand umlöten. Bei Interesse biite hier nachschlagen: http://elektro-slobbo.blogspot.de/2017/12/ec1204b-clock-with-atmega8515-or.html Gruß Slobbo
Die Hardware kann doch nur von „alle LED an“ runterzählen bis „alle LED aus“ und wieder von vorn beginnen! Wie soll das bitte andersrum bei der Beschaltung funktionieren?
Versuchs mal so.. das ist jetzt Arduino Like "Ich kann keine Bitoperationen und mache nur Copy&Paste"
1 | uint8_t last=0; |
2 | void display_second1() //Sekundenkreis wird aufgebaut und ab Sek-60 wieder abgebaut, so soll es letztendlich nicht sein |
3 | {
|
4 | unsigned char disp_buf_x,disp_buf_b; |
5 | static unsigned char miao_temp; |
6 | miao_temp=miao; |
7 | disp_buf_x=miao_temp>>3; |
8 | disp_buf_b=miao_temp&0x07; |
9 | |
10 | if((fen&0x01)==0) // wenn Minute "gerade" Sekundenkreis sekundenweise aufbauen |
11 | {
|
12 | disp_buf[disp_buf_x]|=0x01<<disp_buf_b; |
13 | last=0; |
14 | }
|
15 | else // wenn Minute "ungerade" Sekundenkreis sekundenweise abbauen, das soll nicht so sein |
16 | // sondern: es soll wieder so anfangen wie bei "if"
|
17 | // also: bei wechsel auf "ungerade" Minute" den mit "if" aufgebauten Sekundenkreis
|
18 | // ausschalten und wieder ab Sek-1 aufbauen, usw. usf.,
|
19 | {
|
20 | if(last==0) |
21 | {
|
22 | for(i=0;i<8;i++) |
23 | {
|
24 | disp_buf[i]=0x00; |
25 | }
|
26 | }
|
27 | disp_buf[disp_buf_x]|=0x01<<disp_buf_b; |
28 | last=1; |
29 | }
|
30 | }
|
EDIT: Nochmal fürs Verständnis: Die 60 Leds sind in 8er Bitreihen in 8Bytes disp_buf[0-7], mit "disp_buf_x=miao_temp>>3;" wird errechnet in welchem aktuellen Byte die anzeigende Sekunde sitzt zum Beispiel Sekunde 9 in disp_buf[1] und mit "disp_buf_b=miao_temp&0x07;" in welchem Bit des Bytes die Sekunde versteckt ist.. dann wird mit "disp_buf[disp_buf_x]|=0x01<<disp_buf_b;" das nächste Bit hinter dem aktuellen Bit auch noch auf 1 gesetzt.. und so weiter. Also muss man alle 60 Sekunden LEDs Byte 0-7 im array auf Null setzen. In der Erklärung könnten Fehler sein, da ich selbst nur Arduino Kleinigkeiten mache und Bitoperationen mir nicht liegen.
:
Bearbeitet durch User
Chr. M. schrieb: > void display_second1() //Sekundenkreis wird aufgebaut und ab Sek-60 > wieder abgebaut, so soll es letztendlich nicht sein > { > unsigned char disp_buf_x,disp_buf_b; > static unsigned char miao_temp; > miao_temp=miao; > disp_buf_x=miao_temp>>3; > disp_buf_b=miao_temp&0x07; > > disp_buf[disp_buf_x]|=0x01<<disp_buf_b; > } war also richtig bzw zu Ergänzen:
1 | void display_second1() |
2 | {
|
3 | unsigned char disp_buf_x,disp_buf_b; |
4 | static unsigned char miao_temp; |
5 | miao_temp=miao; |
6 | disp_buf_x=miao_temp>>3; |
7 | disp_buf_b=miao_temp&0x07; |
8 | |
9 | if(disp_buf_x==7 && disp_buf_b==3)//oder so ähnlich, oder if(fen==0) |
10 | for(i=0;i<8;i++) |
11 | {
|
12 | disp_buf[i]=0x00; |
13 | }
|
14 | |
15 | disp_buf[disp_buf_x]|=0x01<<disp_buf_b; |
16 | |
17 | }
|
:
Bearbeitet durch User
Ich denke Liesma sieht das richtig!
Hörma schrieb: > Ich denke Liesma sieht das richtig! Soweit wie ich das mit bekommen habe, hat er Hardware des Schaltplanes und Programmer zum programmieren der Hardware. Dann hat er disp_buf[] welcher die 8 Zeilen einer LED-Matrix mit 8 Leds pro Zeile speichert und wann auch immer regelmäßig auf die Outputs synchronisiert wird. Bit0-Bit,X0-X7 im Schaltplan markiert, ist wirklich nen bisschen klein der Plan. (musste zweimal schauen) Im Prinzip eine 8x8 Led Matrix. (4 Fehlen)
Müsste so gehen:
/*************************************************
void display_second1() // Neu: Sekundenkreis wird bis 60 aufgebaut
// und ab Sek 1 neu aufgebaut
{
unsigned char disp_buf_x, disp_buf_b;
static unsigned char miao_temp;
if ( miao == 1 ) // Sekunde == 1: Nur 1. Sekunde ON
{ for ( miao_temp = 0; miao_temp < 8; miao_temp++ )
disp_buf[miao_temp] = 0;
}
miao_temp = miao;
disp_buf_x = miao_temp >> 3;
disp_buf_b = miao_temp & 0x07;
disp_buf[disp_buf_x] |= 0x01 << disp_buf_b;
}
/*************************************************
Was soll
> //ÏÔÊŸµ±Ç°µã
uns eigentlich sagen?
Wenn mein voriger Vorschlag funktioniert hat, würde ich (!) es aber logischer und schöner so darstellen: /************************************************* void display_second1() // Neu: Sekundenkreis wird bis 59 aufgebaut // und ab Sek 0 neu aufgebaut { unsigned char disp_buf_x, disp_buf_b; static unsigned char miao_temp; if ( miao == 0 ) // Sekunde == 0: erst mal alle OFF { for ( miao_temp = 0; miao_temp < 8; miao_temp++ ) disp_buf[miao_temp] = 0; } miao_temp = miao; // Aufbau von 0 bis 59 disp_buf_x = miao_temp >> 3; disp_buf_b = miao_temp & 0x07; disp_buf[disp_buf_x] |= 0x01 << disp_buf_b; } /*************************************************
Warum geht eigentlich nicht einfach 'if(1)...' Oder den ganzen Rotz da drunter gleich auskommentieren. @Jacko: '显示当前点' soll heissen: "Der aktuelle Punkt wird angezeigt" @Udo: Kannst du uns den ganzen Code posten, also auch die anderen Dateien, die den RTC auslesen, etc.?! Danke & Gruß Slobbo
Udo S. schrieb: > Den Chinabausatz findet man mit "EC1204B" LED-Clock im Netz Ja, Chinesen, offenbar genau so schlimm wie manche Deutsche. Die Schaltung ist Murks, die Matrixanzeige ist falschrum. Die Widerstände zur Strombegrenzung durch die LEDs liegt an den Transistoren. Damit geht die Multiplexrichtung über die einfachen uC-Ausgänge die maximal 20mA liefern können. Dort schalten nun 1 bis 12 Transistoren die LED dran. Über 47 Ohm sollten (5-1-2.1)/47 = 40mA fliessen, dazu werden (5-1)/10k = 0.4mA Basistrom zur Verfügung gestellt werden (besser wären 4mA bei den schlechten 8550 Industrietransistoren). Sind alle 12 eingeschaltet also 12 * 40mA = 480mA: Die liefert kein uC Ausgang, der bgernzt irgendwo zwischen 20mA und 40mA. Eine LED ist also genau so hell wie alle 12 zusammen, weil jede einzelne dann mit einem Bruchteil des Stroms auskommen muss. 1.6mA, und die auch nur 1/8 der Zeit, also 200uA im Schnitt statt 10mA wie für 7-Segment Anzeigen üblich, was 1/50 oder 3% der Nominalhelligkeit ergibt. Die billige Chinaplstine ist also ein profundes Beispiel, wie man es NICHT macht und zeigt daß auch Chinesen Multiplexanzeigen nicht verstanden haben. Baut die Schaltung wenigstes so um, daß der uC an den Ausgängen bit0 bis bit11 erst MOSFETs schaltet wie IRLML5203 (dazu muss das Ausgangssignal invertiert werden) bevor diese dann die LED-Leitungen gegen Masse schalten, und verkleinert die Basiswiderstände der 8550 von 10k auf 1k. Die 40mA für 1/8 der zeit reichen dann für 5mA, also halbe Nennhelligkeit bei den 7-Segments und viertel Nennhelligkeit bei den LEDs.
:
Bearbeitet durch User
Sind alle 12 eingeschaltet also 12 * 40mA = 480m Aber das sind Sie doch gar nicht.?!
Hochstapler schrieb: > Aber das sind Sie doch gar nicht.?! Kommt drauf an. In der Ortiginaluhr läuft wohl nur 1 Punkt rundrum, da sind maximal 5 LEDs (4 Ziffern, 1 Punkt) mit zusammen 200mA an einem uC Ausgang, auch schon viel zu viel. Im Code von Jacko leuchten ggf. alle LEDs, dann sind es 480mA.
Hi, ich habe diese Platine aufgebaut und mit einem AVR ATMEL betrieben. Für Anelitung und Sourcecode bitte hier gucken: http://elektro-slobbo.blogspot.de/2017/12/ec1204b-clock-with-atmega8515-or.html Viel Spaß damit Slobbo
Slobbo schrieb: > Viel Spaß damit Das 7-Segment Display ist auch LED. Schön wärs gewesen, du hättest den Fehler der Chinesen, die strombegrenzenden Widerstände in die Hochstromleitungen zu legen korrigiert und sie in die nicht mit Transistoren verstärkten Leitungen zum uC gesetzt. Dann wäre die LED-Helligkeit nicht so unterschiedlich. Und deine Piezo-Beschaltung ist abenteuerlich, die hat mit dem elektrischen Verhalten eines Piezo nichts zu tun. Erstaunlich, dass sie überhaupt irgendwie funktioniert.
Wie soll das denn gehen ohne eine neue Platine zu routen? Die Led's im Original leuchten im Übrigen immer gleich hell, egal wie viele an sind. Wie machen die das bloss ?
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.