mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Chinakracher als Basis für Studiouhr, Frage von "Nicht-Programmierer"


Autor: Udo S. (nixie)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

: Bearbeitet durch User
Autor: Udo S. (nixie)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
...schade. Keiner mit einer Idee wo ich ansetzen könnte? Bitte melden, 
falls ihr mehr input braucht. Danke.

Grüße

Udo

Autor: Klaus R. (klaus2)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Chr. M. (snowfly)
Datum:

Bewertung
0 lesenswert
nicht 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.
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;
 }

Autor: Udo S. (nixie)
Datum:

Bewertung
0 lesenswert
nicht 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);
  //}
}

Autor: Chr. M. (snowfly)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und wenn du Variante 3 so abwandelst?
void Display_OneLedlightenRun(void) //eine LED läuft als Sekunde um
{
  unsigned char disp_buf_x,disp_buf_b;
  static unsigned char miao_temp;
  disp_buf_x = miao_temp>>3;
  disp_buf[disp_buf_x] = 0x00;
  
  miao_temp = miao;  //ÏÔÊŸµ±Ç°µã
  disp_buf_x = miao_temp>>3;
  disp_buf_b = miao_temp&0x07;
  if (disp_buf[disp_buf_x] == 60)  //Wert 60 evtl. anpassen
  {
   disp_buf[disp_buf_x] = 0x00;
  }
  disp_buf[disp_buf_x]|=0x01<<disp_buf_b;
}

Autor: Chr. M. (snowfly)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nachtrag:
das erste "disp_buf[disp_buf_x] = 0x00;" muss dann natürlich raus.

Autor: Udo S. (nixie)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Chr. M. (snowfly)
Datum:

Bewertung
0 lesenswert
nicht 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:
void Display_OneLedlightenRun(void) //eine LED läuft als Sekunde um
{
  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;
  if (miau == 1)
  {
   disp_buf[disp_buf_x] = 0x00;
  }
  disp_buf[disp_buf_x]|=0x01<<disp_buf_b;
}

Wie du merkst bin ich auch kein Profiprogrammierer sondern noch am 
Anfang des lernens.
Aber so schwierig kann dein Wunsch nicht sein.

Autor: Slobbo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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-...

Gruß Slobbo

Autor: Liesma (Gast)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
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?

Autor: Liesma (Gast)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
??....

Autor: Philipp K. (philipp_k59)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Versuchs mal so.. das ist jetzt Arduino Like "Ich kann keine 
Bitoperationen und mache nur Copy&Paste"

uint8_t last=0;
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;
  
  if((fen&0x01)==0) // wenn Minute "gerade" Sekundenkreis sekundenweise aufbauen
  {
    disp_buf[disp_buf_x]|=0x01<<disp_buf_b;
    last=0; 
 }
  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., 
  {
  if(last==0)
    {
      for(i=0;i<8;i++)
      {
        disp_buf[i]=0x00;
      }
    }
  disp_buf[disp_buf_x]|=0x01<<disp_buf_b;
  last=1;
  }
}

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
Autor: Philipp K. (philipp_k59)
Datum:

Bewertung
1 lesenswert
nicht 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:
void display_second1()
{
  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; 

  if(disp_buf_x==7 && disp_buf_b==3)//oder so ähnlich, oder if(fen==0)
        for(i=0;i<8;i++)
      {
        disp_buf[i]=0x00;
      }
      
     disp_buf[disp_buf_x]|=0x01<<disp_buf_b;
   
}

: Bearbeitet durch User
Autor: Hörma (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich denke Liesma sieht das richtig!

Autor: Philipp K. (philipp_k59)
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: Jacko (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Jacko (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;
}

/*************************************************

Autor: Slobbo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Michael B. (laberkopp)
Datum:

Bewertung
0 lesenswert
nicht 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.

: Bearbeitet durch User
Autor: Hochstapler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sind alle 12
eingeschaltet also 12 * 40mA = 480m


Aber das sind Sie doch gar nicht.?!

Autor: Michael B. (laberkopp)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.