Forum: Mikrocontroller und Digitale Elektronik Tiny13 : Problem beim Entprellen mit internem Pullup


von Thiel (Gast)


Lesenswert?

Hallo!

Ich bin ziemlicher Neuling auf dem Mikrocontrollergebiet und habe für 
mein Problem die Sufu und Google verwendet, aber keine Antwort gefunden.

Ich bin auf ein seltsames Problem beim Tiny13 gestoßen:

Meine Interruptgesteuerte Entprellung funktioniert für PB0 und PB1 
tadellos. Wobei PB0 über einen externen 10 kOhm Pullup auf Vcc gezogen 
wird und PB1 per internem Pullup.

PB4 ist nun vom Aufbau gleich geschalten wie PB1, also per internem 
Pullup auf Vcc, jedoch macht der Taster was er möchte.
(Für alle Taster wird der selbe Programmcode verwendet, nur das DDR und 
PORT wird natürlich angepasst.) Die Taster togglen nur eine LED.

Außerdem habe ich auch schon andere Taster an PB4 angeschlossen, mit dem 
selben Ergebnis.

Möglicherweise nützlich: Die Schaltung wird gleich über den 
angeschlossen ISP- Programmer mit Spannung versorgt.

Bitte um Hilfe und Tipps!

MfG Thiel!

von Alexander V. (avogra)


Lesenswert?

Zeig uns mal deinen Quelltext, sonst kann man eigentlich nur raten, was 
nicht funktioniert :)

Gruß, Alex

von Thiel (Gast)


Angehängte Dateien:

Lesenswert?

Ja, sry! Die h-flies hab ich zur Übersicht weggelassen.

Kurze Erläuterung:
In DDTimer wird ButtonAsk() aufgerufen, wo der Counter alle ms erhöht 
wird, wenn die Taste gedrückt ist (active low).
In DDButton ändere ich bloß die Parameter in den Defines um das ganze 
mit einem der 3 Taster zu probieren!
Im main erfolgt die eigentliche Entprellung (ja ich weiß, sollte gleich 
im Buttonfile sein!)

Das ganze sollte nur ein schneller Buttontest werden, und wie man sieht 
verwende ich ja tatsächlich denselben Programmcode (abgesehen von den 
defines) für jeden Taster, deswegen verstehe ich nicht wieso so 
unterschiedliches Verhalten auftritt.

MfG Thiel

von Hannes L. (hannes)


Lesenswert?

Mit der Dannegger-Bulletproof-Entprellung (im Timer-Interrupt) wärst Du 
alle Deine Tastenprobleme mit einem Schlage los. Sie entprellt bis zu 8 
Taster/Schalter (an einem Port) gleichzeitig, Dein Tiny13 hat aber nur 5 
nutzbare I/Os.

...

von Thiel (Gast)


Lesenswert?

Danke für deine Antwort!

Ich kenne die Dannegger Entprellung und habe sie auch schon 
durchgedacht, aber ich möchte eigentlich wissen wieso meine Entprellung 
an den Pins 0 und 1 des Port B geht, nicht aber auf pin 4. Denn es wäre 
für mich sehr hilfreich die Ursache meines Problems zu kennen, da ich 
mich dann auch weiterentwicklen kann.

PS.: Zusätzlich zu den defines setzte ich natürlich auch das Portbit auf 
1 bzw 0, je nachdem ob intern oder externer pullup!

MfG Thiel

von Karl H. (kbuchegg)


Lesenswert?

Habe gerade etwas ins Datenblatt zum Tiny13 geschaut
Und da ist mir etwas seltsames aufgefallen, das zum Stolperstein werden 
könnte.
Das Pinout ist so
1
                      +----------+
2
                 PB5 -|          |- Vcc
3
                 PB3 -|          |- PB2
4
                 PB4 -|          |- PB1
5
                 GND -|          |- PB0
6
                      +----------+

Man beachte die Position von PB3, zwischen PB5 und PB4!

Hast du das berücksichtigt?

von Thiel (Gast)


Lesenswert?

Danke für die Mühe wegen dem Pinout, aber dabei sollte der Fehler nicht 
liegen,das habe ich berücksichtigt!

Aber nun scheinen wir der Lösung näher zu kommen...

Ich habe bemerkt, dass auch der Taster an PB1 (interner Pullup) spinnt, 
sobald ich den ISP Programmer vom USB nehme. Hängt der Adapter am USB 
funktioniert er gut.

Der Taster an PB4  (interner Pullup) spinnt egal ob USB angeschlossen 
oder nicht, jedoch spinnt er unterschiedlich stark.

Lediglich der Taster an PB0 (externer 10kOhm Pullup) funktioniert immer 
einwandfrei....

Was bedeutet das? Ist eine externe Pullupbeschaltung weniger 
Störanfällig? Und wie kommt das?

Zur Info: Ich hab das alles provisorisch am Steckbrett aufgebaut, der 
ISP Programmer ist mit lauter Verbindungskabeln in die Schaltung 
eingebaut. Ich stecke ihn also des Aufwands wegen nicht jedes mal 
komplett von der Schaltung weg, sondern trenne ihn vom USB Kabel. Sollte 
aber auch so funktionieren, da der Programmer dafür gedacht ist, die 
Schaltung gleich mitzuversorgen.

MfG Thiel!!

von Karl H. (kbuchegg)


Lesenswert?

Ähm
1
#include <avr/io.h>
2
3
#define KEY_DDR DDRB
4
#define KEY_DDRNO DDB1
5
#define KEY_PORT PORTB
6
#define KEY_PORTNO PORTB1
7
#define KEY_PIN PINB
8
#define KEY_PINNO PB4
9
10
volatile int KeyCounter;
11
12
void ButInit()
13
{
14
  KEY_DDR &= ~(1<<KEY_DDRNO);
15
  KEY_PORT |= (1<<KEY_PORTNO); //Internen Pull-Up-Widerstand an PortD , Bit 4 einschalten
16
17
}
18
19
20
void ButtonAsk()
21
{
22
  if ( !(KEY_PIN & (1<<KEY_PINNO)) )
23
  {
24
    KeyCounter++;
25
  }
26
  else 
27
  {
28
     KeyCounter = 0;
29
  }
30
}

Wenn ich das richtig sehe, dann schaltest du zwar den PB1 auf Eingang 
und auch dort den Pullup ein, benutzt dann aber PB4 zum einlesen.

Benutze nur 1 define für die Pinnummer!
DDB1, PB1 sind sowieso identisch
1
#define KEY_DDR   DDRB
2
#define KEY_PORT  PORTB
3
#define KEY_PIN   PINB
4
5
#define KEY_BIT   PB1
6
7
...

und überall im Code benutzt du nur diese Konstanten. Eigentlich sollte 
man auch die DDR, PORT und PIN Makros noch zusammenführen. Auf deinem 
Tiny müsste das gehen, aber im Allgemeinen geht das nicht.

von Thiel (Gast)


Lesenswert?

Oh, wie du siehst hab ich nicht geahnt, dass die beiden identisch sind. 
Hab ich auch schon ausgebessert, danke!
Der andere fehler, ja stimmt , aber war nur Flüchtigkeitsfehler bei der 
Eingabe für den test, bei den anderen Testläufen hab ich natürlich nur 
den selben Pin/Port verwendet.
Das sieht dann also so aus:

...
#define KEY_DDR DDRB
#define KEY_DDRNO DDB1 /*identisch mit: #define KEY_PINNO PB4*/
#define KEY_PORT PORTB
#define KEY_PORTNO PORTB1
#define KEY_PIN PINB
...
void ButtonAsk()
{
  if ( !(KEY_PIN & (1<<KEY_DDRNO)) )
  {
    KeyCounter++;
  }
  else
  {
     KeyCounter = 0;
  }
}


Das seltsame Tasterverhalten bleibt jedoch bestehen.

von Thiel (Gast)


Lesenswert?

Thiel schrieb:
> #define KEY_DDRNO DDB1 /*identisch mit: #define KEY_PINNO PB4*/

richtig:

#define KEY_DDRNO DDB1 /*identisch mit: #define KEY_PINNO PB1


Hab ich das mit den Konstanten nun auch verstanden so wie du sagst, denn 
bei dir sehe ich z.B. gar kein DDB1 .. ?

von Karl H. (kbuchegg)


Lesenswert?

Thiel schrieb:
> Thiel schrieb:
>> #define KEY_DDRNO DDB1 /*identisch mit: #define KEY_PINNO PB4*/
>
> richtig:
>
> #define KEY_DDRNO DDB1 /*identisch mit: #define KEY_PINNO PB1
>
>
> Hab ich das mit den Konstanten nun auch verstanden so wie du sagst, denn
> bei dir sehe ich z.B. gar kein DDB1 .. ?

Vergiss das DDB1

DDB1 ist nur ein anderer Name für 1
Genauso wie es auch DDA1 oder DDC1 oder PB1 oder PA1 oder ... ist.
Ist alles dasselbe, nämlich Synonyme für 1

Das einzige was diese unterschiedlichen Bezeichnungen für immer dasselbe 
hervorrufen sind Konfusion und Fehleranfälligkeit

Diese Makros hätte man IMHO nie einführen sollen

#define BIT_0    0
#define BIT_1    1
#define BIT_2    2
#define BIT_3    3
#define BIT_4    4
#define BIT_5    5
#define BIT_6    6
#define BIT_7    7

und dann

  DDRB  = ( 1 << BIT_4 );
  PORTB = ( 1 << BIT_4 );

und es wäre genauso lesbar gewesen ohne die Fehleranfälligkeit, dass man 
2 Konstanten die unterschiedlich aussehen auf gleich halten muss.

von Thiel (Gast)


Angehängte Dateien:

Lesenswert?

AHA! Du hast recht, das ist ja total unnötig und führt wie bei mir nur 
zu Verwirrung. Ich habe jetzt das main-file, geändert sowie ich es 
gerade gelernt habe (Anhang).
Ist so tatsächlich viel verständlicher, danke vielmals!

Mein Tasterproblem besteht jedoch weiterhin, bin also noch immer für 
jeden Ratschlag dankbar, egal ob Programmtechnisch oder vielleicht ein 
Lösungsvorschlag für das Tasterproblem!

MFG Thiel

von Karl H. (kbuchegg)


Lesenswert?

Thiel schrieb:

> Mein Tasterproblem besteht jedoch weiterhin, bin also noch immer für
> jeden Ratschlag dankbar, egal ob Programmtechnisch oder vielleicht ein
> Lösungsvorschlag für das Tasterproblem!

Das verblüffende ist, dass du schon der zweite bist, der über diese 
Problem beim Tiny13 klagt.

Wenn du am entsprechenden Pin mal nichts anschliesst und da ein 
Voltmeter drann hängst, welche Spannung misst du da?
Eigentlich müssten es 5V sein, weil ja der Pullup für die 5V sorgt.

von Karl H. (kbuchegg)


Lesenswert?

Hmm probier mal dieses
1
int main()
2
{
3
  MCUCR &= ~( 1<<PUD );
4
5
  ... ab hier dein normales Program
6
}

von Thiel (Gast)


Lesenswert?

So..

Am entsprechnden Pin messe ich 5 V.
Das Einfügen der Codezeile brachte keine Verbesserung.Wo lag deine 
Vermutung?

von Thiel (Gast)


Lesenswert?

Außerdem sehr seltsam, dass jemand schon dasselbe Problem hatte.
Konnte es aber nicht in der Sufu finden!
Kennst du noch die Lösung bzw. gab es eine?

von Karl H. (kbuchegg)


Lesenswert?

Thiel schrieb:
> So..
>
> Am entsprechnden Pin messe ich 5 V.

Das .... ist in Ordnung so.
Der Pullup ist eingeschaltet.

> Das Einfügen der Codezeile brachte keine Verbesserung.Wo lag deine
> Vermutung?

Der Tiny hat in MCUCR ein Bit PUD, mit dem man die Pullup generell 
abschalten kann.  PUD .. Pull Up Disable

von Karl H. (kbuchegg)


Lesenswert?

Kopier doch bitte mal alle Funktionen in ein einziges *.c File zusammen 
(dann macht es auch nichts, wenn die Header Files fehlen)

Aber mit dem ständigen Wechseln der Files, muss ich mir jede Menge Zeugs 
merken. Und ich bin auch nicht mehr der Jüngste :-)

von Thiel (Gast)


Angehängte Dateien:

Lesenswert?

Natürlich (-; ! Alle Cfiles in TasterFail.c kopiert im Anhang.

von Karl H. (kbuchegg)


Lesenswert?

Probier doch mal diese Variante aus.
Eventuell musst du die Funktionen noch ein wenig umsortiern, main ganz 
nach unten und die Funktionen ein wenig umsortieren.

Ich hab leider keinen Tiny13 da, sonst hätte ich das selber praktisch 
ausprobiert.

von Karl H. (kbuchegg)


Lesenswert?

Ah, da seh ich was
1
void DDLedToggleYellow()
2
{
3
  PORTB=PINB^0x08;
4
}
5
6
void DDLedToggleRed()
7
{
8
  PORTB=PINB^0x04;
9
}

damit kann es dir passieren, dass du dir den Pullup unter dem Hintern 
wegschaltest.

In diesem Fall willst du nicht das PIN Register benutzen, sondern das 
PORT Register.
1
void DDLedToggleYellow()
2
{
3
  PORTB = PORTB ^ 0x08;
4
}
5
6
void DDLedToggleRed()
7
{
8
  PORTB = PORTB ^ 0x04;
9
}

von Thiel (Gast)


Lesenswert?

Ah! Ich probier das sofort aus... bloß meine gelbe LED hängt an PB3 und 
meine rote an PB2.

Seltsam, hätte gedacht, ich hab den Befehl in nem Tutorial gelesen!
Oder ist der Befehl für etwas anderes sinnvoll?

von Karl H. (kbuchegg)


Lesenswert?

PIN nimmst du dann, wenn du einen EXTERNEN Pegel einlesen willst.
Aber das willst du in deinem Fall ja gar nicht. Du willst ja eigentlich 
nur wissen, welchen Wert du zuletzt an PORT ausgegeben hast.

Normalerweise macht das keinen Unterschied. Nur ist es bei dir ja so, 
dass ein paar von den PORT Bits ja eine spezielle Bedeutung haben: Sie 
sind für den Pullup zuständig. D.h. selbst wenn dieses Bit beim einlesen 
von PIN eine 0 bringen würde, willst du diese 0 auf keinen Fall ins PORT 
Register schreiben.

von Thiel (Gast)


Lesenswert?

So! Verstehe... Habs soeben ausprobiert und es funktioniert nach Karl 
Heinz' Hilfe so wie gewünscht!

Außerdem funktionieren nicht nur die Taster, sondern ich habe auch 
gleich einiges programmiertechnisches dazugelernt.

Ein großes Dankeschön für deine geduldige und professionelle Hilfe! XD

So jetzt muss ich mich aber auch in dem Forum anmelden, denn so kann man 
die Posts auch nachkorrigieren (-;

Mit besten Grüßen, Thiel!!

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.