Forum: Mikrocontroller und Digitale Elektronik Probleme Schieberegister 74LS164 an ATtiny


von Stefan R. (Gast)


Lesenswert?

Hallo,

ich habe an einen ATtiny45 ein o.g. Schieberegister gehängt, um eine 
7-Segment-Anzeige zu steuern.

Ich lese am ADC eine Spannung ein und lasse mir die einzelnen Ziffern 
für Spannung (Vorkomma, Nachkomma) abwechselnd auf der 7Seg-Anzeige 
darstellen.

Leider nur spinnt die Anzeige reichlich: einige LEDs werden nicht auf 
High gesetzt, so dass die Zeichen mitunter unleserlich sind. Ich habe 
schon: die Kabel gekürzt (auf 2cm), Pull-Down-Widerstände an die 
Eingänge am Schieber gelötet und jetzt sogar mit Kondensatoren (100pF) 
die Eingänge entstört. All diese Massnahmen haben aber nichts gebracht. 
Zeitweilig ging es recht gut, aber seit ich das Kabel gekürzt habe, 
treten wieder gehäuft Fehler auf.

Nun mache ich das mit dem Programmieren von µC erst seit etwa 2 Wochen 
und habe noch nicht den Überblick. Hier ist einfach mal mein Programm. 
An den Shifter gehen die Daten in w2led.

Ich weiss, dass hier nur einfach ein Datenbit gesetzt wird und dann 
einmal die Taktleitung an- und ausgeht. Prinzipiell funktioniert es ja 
schon mal und ich habe auch im Internet ein anderes Beispiel gefunden, 
in dem jemand das genau so gemacht hat.

Aber: kann hier die Ursache für die geschilderten Probleme liegen? Vor 
allem in Verbindung mit Störungen durch die fliegende Verdrahtung auf 
dem Breadboard?

Vielleicht hat ja jemand eine gute Idee,

Gruss, Stefan

void w2led(int number, int dot){                 //Bits zum Shifter
  for (int i=0;i<8;i++){

    if (number%2){                      //mittels MOD2 Bits auslesen
      PORTB|=(1<<PB1);                  //0 oder 1 auf Port setzen
    }else{
      if ((i==0)&&(dot==1)){
        PORTB|=(1<<PB1);
      }else{
        PORTB&=~(1<<PB1);
      }
    }
    number=number/2;                    //Division 2
    PORTB|=(1<<PB0);                    //1x Clock an, aus für Shifter
  asm("nop");
   PORTB&=~(1<<PB0);
  }
}

von derMetzger (Gast)


Lesenswert?

sind denn alle LED's an, wenn du
1
void alle(){
2
  while(1)
3
    {
4
    PORTB|=(1<<PB1); 
5
    asm("nop");
6
    asm("nop");
7
    asm("nop");
8
    PORTB|=(1<<PB1);
9
    asm("nop");
10
    asm("nop");
11
    asm("nop");
12
    }
13
}

schickst?

von Stefan R. (Gast)


Lesenswert?

Hallo Metzger,

hab das eben bei mir reingebastelt und aufgerufen. Nein, es sind nicht 
alle an: es leuchten a, d und der Dezimalpunkt.

Jetzt bin ich neugierig,was Du daraus schliessen kannst!!

Stefan

von Karl H. (kbuchegg)


Lesenswert?

Zeig doch mal den Rest.

Im Idealfall speckst du erst mal dein Programm komplett ab, so dass nur 
noch der 7-Seg Code übrig bleibt, auf dem du zb einfach nur konstante 
Werte ausgibst.
Auf die Art
* ist sicher gestellt, dass das Problem auch tatsächlich
  im 7_Seg Teil zu suchen ist und nicht zb dadurch entsteht, dass
  du rasend schnell unterschiedliche Zahlen ausgibst, die sich dann
  an der 7-Seg zu einem Lichtbrei verschmieren
* konzentriert sich dann auch die Fehlersuche auf einen bestimmten
  Bereich. Zb muss man sich dann nicht darauf konzentrieren ob
  du nicht schwankende Werte vom ADC einliest.

von Stefan R. (Gast)


Lesenswert?

OK, dann bau ich mir um Deine Schleife herum mal ein neues Testprogramm 
und gehe auf die Suche.

Danke! Stefan

von Karl H. (kbuchegg)


Lesenswert?

Stefan R. schrieb:
> Hallo Metzger,
>
> hab das eben bei mir reingebastelt und aufgerufen. Nein, es sind nicht
> alle an: es leuchten a, d und der Dezimalpunkt.
>
> Jetzt bin ich neugierig,was Du daraus schliessen kannst!!

Gar nix.
Es sei denn, du hättest den fehlenden Clock-Puls ergänzt.

: Bearbeitet durch Admin
von Stefan R. (Gast)


Lesenswert?

Das habe ich auch gerade eben gemerkt. Das muss natürlich noch rein...

von Stefan R. (Gast)


Lesenswert?

So, nun steht im Programm:


void alle(){
  while(1)
    {
    PORTB|=(1<<PB1);
    asm("nop");
    asm("nop");
    asm("nop");
    PORTB|=(1<<PB1);
    asm("nop");
    asm("nop");
    asm("nop");
    PORTB|=(1<<PB0);                    //1x Clock an, aus für Shifter
    asm("nop");
    PORTB&=~(1<<PB0);
    }
}


und es leuchten brav alle 8 LEDs. Hmm..

von http://www.mikrocontroller.net/topic/203153#new (Gast)


Lesenswert?

derMetzger schrieb:
> sind denn alle LED's an, wenn du
>
>
1
> void alle(){
2
>   while(1)
3
>     {
4
>     PORTB|=(1<<PB1);
5
>     asm("nop");
6
>     asm("nop");
7
>     asm("nop");
8
>     PORTB|=(1<<PB1);
9
>     asm("nop");
10
>     asm("nop");
11
>     asm("nop");
12
>     }
13
> }
14
>
>
> schickst?

Soll das beim zweiten Mal vielleicht PORTB&=~(1<<PB1) heissen?













.

von Stefan R. (Gast)


Lesenswert?

Diese Stelle im Programm hat schon  eine hohe Redundanz. Aber das Bit 
wieder zu löschen würde doch hier noch weniger bringen, oder irre ich 
da?

von Karl H. (kbuchegg)


Lesenswert?

Stefan R. schrieb:
> Diese Stelle im Programm hat schon  eine hohe Redundanz. Aber das Bit
> wieder zu löschen würde doch hier noch weniger bringen, oder irre ich
> da?

Vergiss es.


Systematisch vorgehen.

Anstatt alle LED in einer Schleife, mschst du jetzt mal alle 8 einzeln.
Ziel der Sache ist es, Volldampf auf den Leitungen zu haben um damit 
feststellen zu können, ob du zb Übersprechen oder sowas hast. Du willst 
ja wissen ob an deinem Hardwareaufbau was falsch ist.

Dann setzt du nacheinander einzelne LED gezielt auf 0
1
void Zero()
2
{
3
    PORTB &= ~(1<<PB1);
4
5
    PORTB |= (1<<PB0);                    //1x Clock an, aus für Shifter
6
    asm("nop");
7
    PORTB &= ~(1<<PB0);
8
}
9
10
void One()
11
{
12
    PORTB |= (1<<PB1);
13
14
    PORTB |= (1<<PB0);                    //1x Clock an, aus für Shifter
15
    asm("nop");
16
    PORTB &= ~(1<<PB0);
17
}
18
19
void alle(){
20
  while(1)
21
  {
22
    Zero();
23
    Zero();
24
    Zero();
25
    Zero();
26
    One();
27
    One();
28
    One();
29
    One();
30
31
    _delay_ms( 10 );
32
  }
33
}

dass lässt gezielt nur 4 LED aufleuchten. Sind die anderen Segmente 
(einigermassen) dunkel?
Was ist wenn du zb nur das 1-te Segment leuchten lässt und alle anderen 
dunkel sind? Dann nur das 2-te etc.

: Bearbeitet durch Admin
von Karl H. (kbuchegg)


Lesenswert?

Das 74164 war aber auch eine selten dämlich Wahl für ein 
Schieberegtister an dieser Stelle, weil es keine Output-Latches hat. 
D.h. du wirst auf deinen Anzeigen immer ein bischen sehen, wie im 
Hintergrund durchgeschoben wird.

von derMetzger (Gast)


Lesenswert?

ja, soll es. sollte die clock sein.

von Stefan R. (Gast)


Lesenswert?

Dafür, dass ich erst seit zwei Wochen an dem Thema µC dran bin, kann ich 
es mir verzeihen auch mal etwas dämliches zu tun. Dass ich das Geschiebe 
im Hintergrund sehe, stört mich weniger.

Was den Test mit 4 an / 4 aus angeht, habe ich jetzt auch verstanden, 
worum es geht. Und: nö, es leuchtet alles schön gleichmässig. Es kommt 
also Müll am Shifter an, oder?

von Karl H. (kbuchegg)


Lesenswert?

Stefan R. schrieb:

> Was den Test mit 4 an / 4 aus angeht, habe ich jetzt auch verstanden,
> worum es geht. Und: nö, es leuchtet alles schön gleichmässig. Es kommt
> also Müll am Shifter an, oder?


Probier zur Sicherheit auch noch ein paar andere Kombinationen. Aber bis 
jetzt sehen die Symptome eher so aus, dass deine Hardware in Ordnung 
ist. D.h dein Problem liegt nicht in der Funktion und auch nicht in der 
Hardware, sondern in den Programmteilen die du nicht gezeigt hast.

: Bearbeitet durch Admin
von Stefan R. (Gast)


Lesenswert?

OK, und weil ich keine Latches habe, kann ich jetzt auch nicht erkennen, 
ob das mit dem 4*an / 4*aus was gebracht hat, weil ich nur das Gewische 
sehe, oder?

von Karl H. (kbuchegg)


Lesenswert?

Stefan R. schrieb:
> OK, und weil ich keine Latches habe, kann ich jetzt auch nicht erkennen,
> ob das mit dem 4*an / 4*aus was gebracht hat, weil ich nur das Gewische
> sehe, oder?

Ich hab in der Vorlage noch mal ein wenig nachgebessert und einen 
kleinen _delay_ms eingebaut. Der sollte eigentlich dafür sorgen, dass 
sich aus dem Gewische wieder ein halbwegs stabile Anzeige ergibt, weil 
dann die Anzeigezeit der fertigen Anzeige länger ist, als die Zeit die 
das 'Gewische' benötigt um sich auf die nächsten 8 Bit einzustellen.

Das sollte so eigentlich ganz gut funktionieren. Wenn man genau hinsieht 
(vor allem im Dunkel) wird man bei den eigentlich dunklen Segmenten ein 
kleines Glimmen sehen können, das ist unvermeidlich bei einem 
Schieberegister ohne Latches. Dann muss man eben per Programm dafür 
sorgen, dass das nicht stört, weil zb das Schieben im Vergleich zur 
statischen Anzeige nur verschwindend wenig Zeit bekommt. Wenn das 
SChieben in 10µs verbei ist und die Anzeige danach 10ms ruhig vor sich 
hinleuchten darf, sollte man eigentlich fast nichts mehr sehen.

: Bearbeitet durch Admin
von Stefan R. (Gast)


Lesenswert?

OK, vielen Dank erst einmal an alle, die mir geholfen haben! Ich werde 
meinen restlichen Code noch einmal sichten und komplett neu 
überarbeiten. Wenn dabei etwas erwähnenswertes rauskommen sollte, werde 
ich das noch berichten..

Stefan

von Stefan R. (Gast)


Lesenswert?

Also in der Tat habe ich die Probleme mit der Anzeige bei meinem Code 
ausmachen können. In der Funktion w2led werden die Bits für die Zahl auf 
der 7(8)-Segment-Anzeige ausgelesen und entsprechend auf den Ausgang PB1 
gesetzt. Danach wir kurz die Clock auf PB0 gesetzt.

Nun habe ich alles wieder am Laufen und es tauchen auch keine Fehler 
mehr auf. Allerdings ist die Logik des Ablaufs noch nicht ganz so schön, 
wie ich es gern gehabt hätte und eben hier liegt auch das Problem. Wenn 
ich nämlich den Ablauf schöner schreibe, tauchen auch wieder die 
Aussetzer auf dem Display auf.

Hier im Quelltext die Funktion, so wie sie perfekt läuft. Über dem 
Codeblock zwischen den Strichen ist eine zweite Version desselben 
auskommentiert, die ich als schönere Version geschrieben hatte, die aber 
eben diese Aussetzer produziert. Obwohl ich der Meinung bin, dass beide 
logisch identisch sind.. oder übersehe ich da was?

Also: Byte mit Modulo2 leermachen und jeweils 1 oder Null an PB1. Wenn 
aber dot>0 an die Funktion übergeben wurde (=Zahl mit Dezimalpunkt 
ausgeben), dann das erste Bit als 1 ausgeben. Nach dem Schieben des 
gesamten Bytes ist das ja dann an der Stelle des Dezimalpunktes.

Vielleicht ist ja jemand dabei, der da den Fehler sehen kann—ich sehe 
gaaar nichts mehr.

Stefan R.




void w2led(int number, int dot){                 //Bits zum Shifter
  for (int i=0;i<8;i++){
/*
//===============================
    if ((i==0)&&(dot==1)){
      PORTB|=(1<<PB1);
    }else{
      if (number%2){
        PORTB|=(1<<PB1);
      }else{
        PORTB&=~(1<<PB1);
      }
    }
//==============================
*/

//==========================
    if (number%2){
      PORTB|=(1<<PB1);
    }else{
      PORTB&=~(1<<PB1);
    }
    if ((i==0)&&(dot==1)){                           //   <---- fand ich 
unschön
      PORTB|=(1<<PB1);
    }
//==============================


    number=number/2;                    //Division 2
    PORTB|=(1<<PB0);                    //1x Clock an, aus für Shifter
    asm("nop");
    PORTB&=~(1<<PB0);
  }
}

: Bearbeitet durch Admin
von Stefan R. (Gast)


Angehängte Dateien:

Lesenswert?

Hier nochmal das ganze Programm als Anhang.

von Karl H. (kbuchegg)


Lesenswert?

Als allererstes solltest du mal die Beschäftigungstherapie für den µC 
abstellen. int ist in der Desktopprogrammierung schön und gut. Aber hier 
haben wir es mit einem 8 Bit µC zu tun. 16 Bit Verarbeitung ist für den 
ziemilch aufwändig.

daher gibt es die Datentypen uint8_t, mit denen man auf 8 Bit 
zurückschalten kann.

Dann gefällt mir nicht, was du da mit dot in der Funktion veranstaltest. 
Wenn dot auf 1 ist, dann setz duch einfach in number das 1-te Bit auf 1 
und die nachfolgende Schleife verarbeitet das dann richtig. Dann ist das 
was die Funktion bekommt im eigentlichen Sinn keine Zahl mehr, sondern 
ein Muster, das auf die Anzeige ausgegeben werden soll. Nenn es auch so!
Hier an dieser Stelle, in dieser Funktion ist das alles reines 
Bitgefummel. Da ist der Einsatz von Bitoperationen durchaus erlaubt. 
arithmetische Operationen % bzw / machen zwar in dem Fall das gleiche, 
sind aber nicht so aussagekräftig wie dezidierte Bitoperationen.
Schreib deine Codezeilen nicht so auf Knirsch. Seit du 6 Jahre alt bist, 
hast du dein Gehirn darauf trainiert, dass zwischen Wörter ein Leerraum 
steht und es da ganz schnell erkennen kann wo ein Wort aufhört und wo 
das nächste anfängt. Nutze dieses Training um deinen Code so zu 
gestalten, dass man ihn leicht elsen kann.



1
void w2led( uint8_t pattern, uint8_t dot)
2
{                 //Bits zum Shifter
3
  if( dot )
4
    pattern |= ( 1 << 0 );   // Dezimalpunkt setzen falls angefordert
5
6
  for( uint8_t i = 0; i < 8; i++ )
7
  {
8
    // Datenbis ausgeben. Es wird immer Bit 0 von pattern betrachtet ...
9
    if( pattern & 0x01 )
10
      PORTB |= ( 1<<PB1 );
11
    else
12
      PORTB &= ~( 1 << PB1 ); 
13
14
    // ... weil jetzt die Bits in pattern nachgeschoben werden
15
    pattern = pattern >> 1;
16
17
    // einen Clock Puls nachschieben
18
    PORTB |= ( 1<<PB0 );
19
    asm( "nop" );
20
    PORTB &= ~( 1<<PB0 );
21
  }
22
}

So würde ich die Funktion schreiben.
(Fürs erste. In dieser Funktion kann man noch vieles machen um sie 
lesbarer/wartbarer zu bekommen)

von Karl H. (kbuchegg)


Lesenswert?

1
    adc_lo=ADCL;
2
    adc_hi=ADCH;
3
    result=(adc_hi*256)+adc_lo;

diese Operation kann dein Compiler ganz von alleine

1
int main()
2
{
3
  uint16_t adcValue;
4
5
  ....
6
7
8
  while( 1 ) {
9
    ....
10
11
    adcValue = ADCW;

einfach den Wert aus dem 16 Bit Pseudoregister ADCW auslesen. Der 
Compiler dröselt das dann schon richtig auf.

von Karl H. (kbuchegg)


Lesenswert?

1
 ADMUX = 0b00000010;
2
  ADCSRA = 0b10000111;

das hier ist genau die Schreibweise die du nicht benutzen sollst. Kein 
Mensch kann hier sehen, welche Bits du setzt, und was sie bedeuten. 
Benutze die symbolischen Namen mit der (1<<xyz) Schreibweise. Dann 
findet man im Dtaenblatt (sofern man die Werte nicht auswändig kennt) 
die Bedeutungen viel schneller.

Schau dir im AVR-GCC-Tutorial im Abschnitt üder den ADC die 
Funktionen an. Dort siehst du wie man das schreiben kann, so dass man 
das auch leicht lesen kann.

von Stefan R. (Gast)


Lesenswert?

Aber es liegt ja nicht an der Schreibweise, dass das Programm nicht 
läuft. Deine Änderungen zu der Funktion finde ich interessant und die 
werde ich auch übernehmen. Aber trotzdem läuft die Funktion so, wie Du 
sie geschrieben hast, nicht. Damit kommt beim Display der gleiche 
Wirrwarr an, wie mit der, die ich auskommentiert habe. Wie gesagt: 
wundersamerweise läuft die, die ich im oben in der Funktion verwende, 
tadellos.

von Karl H. (kbuchegg)


Lesenswert?

Stefan R. schrieb:
> Aber es liegt ja nicht an der Schreibweise, dass das Programm nicht
> läuft. Deine Änderungen zu der Funktion finde ich interessant und die
> werde ich auch übernehmen. Aber trotzdem läuft die Funktion so, wie Du
> sie geschrieben hast, nicht. Damit kommt beim Display der gleiche
> Wirrwarr an, wie mit der, die ich auskommentiert habe. Wie gesagt:
> wundersamerweise läuft die, die ich im oben in der Funktion verwende,
> tadellos.

Dann nimm erst mal den ADC raus und ersetzte das durch einen fixen Wert, 
damit du erst mal fehlerhafte ADC Werte als Ursache ausschliessen 
kannst.
1
uint8_t map[] = {
2
  0b11111100, 0b01100000, 0b11011010,   //0,1,2
3
  0b11110010, 0b01100110, 0b10110110,   //3,4,5
4
  0b10111110, 0b11100000, 0b11111110,   //6,7,8
5
  0b11110110                            //9
6
};
7
8
void init(void)
9
                        //binäre Ausgänge setzen
10
  DDRB = (1<<PB1) | (1<<PB0);
11
12
  ADMUX  = 0b00000010;
13
  ADCSRA = 0b10000111;
14
}
15
16
void w2led( uint8_t pattern, uint8_t dot)
17
{                 //Bits zum Shifter
18
  if( dot )
19
    pattern |= ( 1 << 0 );   // Dezimalpunkt setzen falls angefordert
20
21
  for( uint8_t i = 0; i < 8; i++ )
22
  {
23
    // Datenbis ausgeben. Es wird immer Bit 0 von pattern betrachtet ...
24
    if( pattern & 0x01 )
25
      PORTB |= ( 1<<PB1 );
26
    else
27
      PORTB &= ~( 1 << PB1 ); 
28
29
    // ... weil jetzt die Bits in pattern nachgeschoben werden
30
    pattern = pattern >> 1;
31
32
    // einen Clock Puls nachschieben
33
    PORTB |= ( 1<<PB0 );
34
    asm( "nop" );
35
    PORTB &= ~( 1<<PB0 );
36
  }
37
}
38
39
int main(void)
40
{
41
  uint16_t adc_value;
42
43
  init();
44
45
  for(;;)
46
  {
47
/*
48
    ADCSRA |= (1<<ADSC); //go!
49
    while (ADCSRA & (1<<ADSC)){
50
    }
51
    adc_value = ADCW;
52
*/
53
    adc_value = 876;
54
55
    adc_value = adc_value / 21;
56
57
    w2led( map[ adc_value / 10], 1 );
58
    _delay_ms( 700 );
59
    w2led( map[ adc_value % 10], 0 );
60
    _delay_ms( 270 );
61
  }
62
}

was macht es damit?
Das sollte abwechselnd 4 und 1 darstellen.

: Bearbeitet durch Admin
von Karl H. (kbuchegg)


Lesenswert?

Wie übernimmt eigentlich dieses Schieberegister die Daten? Mit der 
steigenden oder mit der fallenden Flanke?

Dein Programm setzt auf steigende Flanke. Hast du das mit dem Datenblatt 
kontrolliert?

Edit: OK, ich habs kontrolliert. Steigende Flanke ist richtig.

von Stefan R. (Gast)


Angehängte Dateien:

Lesenswert?

Ja, jetzt zeigt das Display abwechselnd 4. und 1 an. Ohne Fehler. Mit 
dem Code, der im Anhang ist.

von Karl H. (kbuchegg)


Lesenswert?

OK. Dann aktivier den ADC mal dazu.

Was hast du eigentlich am ADC Eingang hängen?

von Karl H. (kbuchegg)


Lesenswert?

Diese Map

uint8_t map[] = {
  0b11111100, 0b01100000, 0b11011010,   //0,1,2
  0b11110010, 0b01100110, 0b10110110,   //3,4,5
  0b10111110, 0b11100000, 0b11111110,   //6,7,8
  0b11110110                            //9
};

hast du schon mal bei einem Programmlauf kontrolliert? (alle Zahlen 
durchlaufen lassen). Nicht dass sich da noch ein Fehler drinn versteckt.

von Stefan R. (Gast)


Angehängte Dateien:

Lesenswert?

Ich habe ein Poti 50k zwischen +5V und GND. Der Schleifer geht in den 
ADC. Jetzt habe ich den Festwert rausgenommen und nehme die Werte wieder 
aus den ADC (siehe Anhang). Und wieder Müll auf der Anzeige. Einzelne 
Segmente fehlen, der Dezimalpunkt wird fast nie angezeigt. Ist mir ein 
Rätsel..

von Stefan R. (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Diese Map
>
> uint8_t map[] = {
>   0b11111100, 0b01100000, 0b11011010,   //0,1,2
>   0b11110010, 0b01100110, 0b10110110,   //3,4,5
>   0b10111110, 0b11100000, 0b11111110,   //6,7,8
>   0b11110110                            //9
> };
>
> hast du schon mal bei einem Programmlauf kontrolliert? (alle Zahlen
> durchlaufen lassen). Nicht dass sich da noch ein Fehler drinn versteckt.

Nein, das habe ich noch nicht. Aber das merkwürdige ist doch, dass es 
mit meiner Version von 19Uhr25 ohne Probleme läuft. Auch wenn die sicher 
einige Schwächen bzgl. Inhalt und Form hat.

von LuXXuS 9. (aichn)


Lesenswert?

Also den 164er hab ich auch manchmal dafür verwendet, wenn nichts 
anderes da war. Das mit dem Durchgeschiebe würde man zwar theoretisch 
sehen, ich konnte es aber eigentlich noch nie wirklich erkennen, weil 
die Verweilzeit wesentlich länger ist, als das Reintakten.

Hängt aber sicher auch von der Geschwindigkeit ab, mit der man arbeitet.

von Karl H. (kbuchegg)


Lesenswert?

Stefan R. schrieb:
> Ich habe ein Poti 50k zwischen +5V und GND. Der Schleifer geht in den
> ADC. Jetzt habe ich den Festwert rausgenommen und nehme die Werte wieder
> aus den ADC (siehe Anhang). Und wieder Müll auf der Anzeige. Einzelne
> Segmente fehlen, der Dezimalpunkt wird fast nie angezeigt. Ist mir ein
> Rätsel..

Hmm.
Sieht für mich danach aus, als ob die Werte vom ADC nicht stimmen und da 
Werte rauskommen, die über 1023 liegen.

Begrenze die mal, so dass du in weiterer Folge beim Array-Zugriff keine 
Overflows produzierst.
1
int main()
2
{
3
  ....
4
5
  for(;;)
6
  {
7
    ....
8
9
10
    adc_value = ADCW;
11
12
    if( adc_value > 1023 )
13
      adc_value = 1023;
14
15
    adc_value /= 21;
16
17
    ....

: Bearbeitet durch Admin
von Karl H. (kbuchegg)


Lesenswert?

Stefan R. schrieb:

> Nein, das habe ich noch nicht. Aber das merkwürdige ist doch, dass es
> mit meiner Version von 19Uhr25 ohne Probleme läuft. Auch wenn die sicher
> einige Schwächen bzgl. Inhalt und Form hat.

Ich denke das war Zufall.
Das geht sich irgendwie dann mit dem ADC Timing besser aus.

Willst du die Zahlen durchprobieren?
Kannst du zb so machen
1
int main()
2
{
3
  uint8_t i;
4
5
  init();
6
7
  for( ;; )
8
  {
9
    for( i = 0; i < 10; ++i )
10
    {
11
      w2led( map[ i ], 1 );
12
      _delay_ms( 500 );      
13
    }
14
  }
15
}

da sollten jetzt mal alle Ziffern sauber durchrauschen.
Ich denke zwar die map ist in Ordnung, aber ich kann natürlich Lötfehler 
bzw. Lötbrücken nicht sehen. Von daher würd ich das mal probieren.

Edit: Oder Steckfehler. Irgendwo weiter oben hast du ein Steckbrett 
erwähnt.

: Bearbeitet durch Admin
von Stefan R. (Gast)


Lesenswert?

Also die Begrenzung


 if( adc_value > 1023 )
      adc_value = 1023;


hat nichts gebracht. Ja, ich probiere das mit den reinen Zahlen mal 
aus......

von Karl H. (kbuchegg)


Lesenswert?

Stefan R. schrieb:
> Also die Begrenzung
>
>
>  if( adc_value > 1023 )
>       adc_value = 1023;
>
>
> hat nichts gebracht. Ja, ich probiere das mit den reinen Zahlen mal
> aus......

Und sei es nur um Gewissheit zu haben, dass die Anzeige richtig 
verkabelt ist. Solche Tests sind nie schlecht und sind ja schnell 
gemacht. Das gibt eine gewisse Sicherheit, dass zumindest ein Subsystem 
sauber dasteht.


Hast du eigentlich dem µC und dem Schiebregister ein paar 
Blockkondensatoren spendiert?

: Bearbeitet durch Admin
von Stefan R. (Gast)


Lesenswert?

So, hab' ich gemacht. Läuft immer von 0 bis 9 durch.

0 ohne dot
1 ohne dot
2 korrekt
3 verstümmelt, ohne dot
4 verstümmelt
5 korrekt
6 verstümmelt
7 ohne dot
8 korrekt
9 verstümmelt

Und das jedes Mal genau dieser Ablauf. Immer wieder von vorn.

von Karl H. (kbuchegg)


Lesenswert?

Stefan R. schrieb:
> So, hab' ich gemacht. Läuft immer von 0 bis 9 durch.
>
> 0 ohne dot
> 1 ohne dot
> 2 korrekt
> 3 verstümmelt, ohne dot
> 4 verstümmelt
> 5 korrekt
> 6 verstümmelt
> 7 ohne dot
> 8 korrekt
> 9 verstümmelt
>
> Und das jedes Mal genau dieser Ablauf. Immer wieder von vorn.

Oha!

Das sieht dann aber eher danach aus, als ob deine Verkabelung vom SR zur 
7-Seg nicht stimmt!


Kann es sein, dass deine Bits im Byte genau seitenverkehrt sind?
(beliebter Fehler). Das erste Bit (Bit 0) das du reintaktest wandert am 
weitesten durch das SR kommt dort also an QH raus. Laut deinem Programm 
müsste das der Dezimalpunkt sein.

: Bearbeitet durch Admin
von Stefan R. (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:

> Hast du eigentlich dem µC und dem Schiebregister ein paar
> Blockkondensatoren spendiert?

Ich an den Eingängen direkt am Schieber Kondensatoren jeweils auf GND 
(100pF) und Pull-Down-Widerstände (unter 100k). Hat aber gar nichts 
geändert. Zusätzlich hatte ich ja auch noch das Kabel von etwa 10 auf 2 
cm verkürzt.

von Stefan R. (Gast)


Lesenswert?

> Das sieht dann aber eher danach aus, als ob deine Verkabelung vom SR zur
> 7-Seg nicht stimmt!

Ja, das könnte man annehmen. Aber dann frage ich mich, warum es wie 
gesagt mit der Version, die ich erwähnt habe, ohne Probleme 
funktioniert.

von Karl H. (kbuchegg)


Lesenswert?

Stefan R. schrieb:
>> Das sieht dann aber eher danach aus, als ob deine Verkabelung vom SR zur
>> 7-Seg nicht stimmt!
>
> Ja, das könnte man annehmen. Aber dann frage ich mich, warum es wie
> gesagt mit der Version, die ich erwähnt habe, ohne Probleme
> funktioniert.

Kann Zufall sein.



Das hier hast du gelesen:

Kann es sein, dass deine Bits im Byte genau seitenverkehrt sind?
(beliebter Fehler). Das erste Bit (Bit 0) das du reintaktest wandert am
weitesten durch das SR kommt dort also an QH raus. Laut deinem Programm
müsste das der Dezimalpunkt sein.

: Bearbeitet durch Admin
von Stefan R. (Gast)


Lesenswert?

>
> Kann Zufall sein.
>
>
>

Zufall? Das müsste dann doch aber ein toller Zufall sein. Dass meine 
Funktion genau die Fehler behebt, die ich in der Verkabelung habe. Das 
halte ich doch für sehr unwahrscheinlich.

von Stefan R. (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:

> Kann es sein, dass deine Bits im Byte genau seitenverkehrt sind?
> (beliebter Fehler). Das erste Bit (Bit 0) das du reintaktest wandert am
> weitesten durch das SR kommt dort also an QH raus. Laut deinem Programm
> müsste das der Dezimalpunkt sein.

Genau, der geht als erstes rein und wandert dann 7 Positionen weiter. 
Aber das ist bei mir auch richtig so verdrahtet.

Vom Shifter geht es bei mir so zum Display:
Q0->a
Q1->b
...
...
Q6->g
Q7->DP (dot)

von Karl H. (kbuchegg)


Lesenswert?

Was ich mir noch vorstellen könnte

Der µC ist ein klein wenig zu schnell für das SR (auch wenn ich nicht 
daran glaube. Alelrdings könnten Kapazitäten beim Aufbau da eine Rolle 
spielen). In deiner funktionierenden Variante dauert es vom Anlegen des 
Datenbits bis zum Clock Puls ein bischen länger als in der 'schöneren' 
Variante.

Kann man ja mal probieren. Einfach eine kleine Verzögerung rein und 
sehen was passiert.
1
void w2led( uint8_t pattern, uint8_t dot)
2
{                 //Bits zum Shifter
3
  if( dot )
4
    pattern |= ( 1 << 0 );   // Dezimalpunkt setzen falls angefordert
5
6
  for( uint8_t i = 0; i < 8; i++ )
7
  {
8
    // Datenbis ausgeben. Es wird immer Bit 0 von pattern betrachtet ...
9
    if( pattern & 0x01 )
10
      PORTB |= ( 1<<PB1 );
11
    else
12
      PORTB &= ~( 1 << PB1 ); 
13
14
    // ... weil jetzt die Bits in pattern nachgeschoben werden
15
    pattern = pattern >> 1;
16
17
    _delay_ms( 1 );
18
    // einen Clock Puls nachschieben
19
    PORTB |= ( 1<<PB0 );
20
    _delay_ms( 1 );
21
    PORTB &= ~( 1<<PB0 );
22
  }
23
}

von Karl H. (kbuchegg)


Lesenswert?

Wenn die Verzögerungen nix bewirken und die durchlaufenden Zahlen dann 
immer noch nicht stimmen, dann bleibt nur noch die fehlerhafte Tabelle.

von Stefan R. (Gast)


Lesenswert?

Hab' ich so reingesetzt, wie Du es geschrieben hast, aber das ändert 
auch nichts. Aber ich hatte auch schon die Vermutung, dass meine 
lauffähige Variante einfach ein etwas anderes Timing verursacht. Rein 
logisch betrachtet sehe ich zwischen den beiden Versionen (eine ist ja 
auskommentiert) in der Version von 19Uhr25 keinen Unterschied. Also muss 
hier auch die Lösung liegen. Ich könnte die Version ja einfach so lassen 
und mich freuen, dass es geht. Aber da kommt dann doch mein sportlicher 
Ehrgeiz durch.

von Stefan R. (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Wenn die Verzögerungen nix bewirken und die durchlaufenden Zahlen dann
> immer noch nicht stimmen, dann bleibt nur noch die fehlerhafte Tabelle.

Aber dann würde meine Version de Funktion ja die fehlerhafte Tabelle 
"korrigieren". Wie soll das gehen?

von Karl H. (kbuchegg)


Lesenswert?

Was passiert hier
1
int main()
2
{
3
  uint8_t i;
4
5
  init();
6
7
  for( ;; )
8
  {
9
    for( i = 0; i < 10; ++i )
10
    {
11
      w2led( 0, 1 );
12
      _delay_ms( 500 );      
13
    }
14
  }
15
}

eigentlich sollte der Dezimalpunkt sauber dauerleuchten

Edit: Ich schätze mal das wird er nicht. Statt dessen wird ein anderes 
Segment leuchten.

von Stefan R. (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Was passiert hier
>


>
> eigentlich sollte der Dezimalpunkt sauber dauerleuchten
>
> Edit: Ich schätze mal das wird er nicht. Statt dessen wird ein anderes
> Segment leuchten.

Ja, der leuchtet die ganze Zeit. Und auf dem restlichen Display blitzt 
zweimal in der Sekunde eine blasse 8. Genau das, was  passieren sollte, 
oder?

von Karl H. (kbuchegg)


Lesenswert?

Stefan R. schrieb:
> Karl Heinz Buchegger schrieb:
>> Was passiert hier
>>
>
>
>>
>> eigentlich sollte der Dezimalpunkt sauber dauerleuchten
>>
>> Edit: Ich schätze mal das wird er nicht. Statt dessen wird ein anderes
>> Segment leuchten.
>
> Ja, der leuchtet die ganze Zeit. Und auf dem restlichen Display blitzt
> zweimal in der Sekunde eine blasse 8. Genau das, was  passieren sollte,
> oder?

Jup. Das ist genau das was passieren sollte, wenn alles richtig ist.

Jetzt bin ich auch mit meinem Latein am Ende.


Die restlichen Pins vom Schieberegister, zb Clear, was hast du mit denen 
gemacht?

(irgendwas bringt das SR anscheinend ausser tritt.)

: Bearbeitet durch Admin
von Stefan R. (Gast)


Angehängte Dateien:

Lesenswert?

Also ein Reset ist ja noch am Shifter. Aber den habe ich unverdrahtet 
gelassen. Ich werde das Thema jetzt auch mal etwas sacken lassen. Ich 
werde die Tage ohnehin bestellen und mir dann einfach ein anderes 
74LS164 holen (habe irgendein Billigding von Händler um die Ecke) und 
wenn es geht auch ein anderes Register. Mal sehen, was ich da am besten 
nehmen kann. Zum Glück habe ich den Shifter auf der Platine gesockelt, 
so dass ich ihn locker rausholen kann.

Vielen Dank erst einmal für Deine Hilfe! Ich werde Dich wissen lassen, 
wenn ich irgendwie weiter gekommen bin. Umwege erhöhen zum Glück immer 
die Ortskenntnisse.

Gruss, Stefan

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
Noch kein Account? Hier anmelden.