Chinakracher als Basis für Studiouhr, Frage von "Nicht-Programmierer"

OP #4431291
Lesenswert?

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
Angehängte Dateien:
#4443989
Lesenswert?

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.
#4444040
Lesenswert?

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
 }
OP #4444160
Lesenswert?

...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);
  //}
}
#4444249
Lesenswert?

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
}
OP #4445481
Lesenswert?

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
#4445573
Lesenswert?

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.
#5237709
Lesenswert?

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.
#5237788
Lesenswert?

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
}
#5237824
Lesenswert?

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)
Gast #5238003
Lesenswert?

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?
Gast #5238025
Lesenswert?

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;
}

/*************************************************
Gast #5266811
Lesenswert?

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
#5266838
Lesenswert?

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.
Gast #6263135
Lesenswert?

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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren