Forum: Mikrocontroller und Digitale Elektronik [C] ATmega32 tut nicht was er soll. Tasterabfrage


von Valentin S. (lochrasterer)


Lesenswert?

Hallo Leute

Ich hab hier nen ATmega32, der, wenn die Variable "Wuerfel" auf 1 
gesetzt ist, einen Motor einschalten soll und, wenn PINB,7 gedrückt (auf 
null gesetzt) ist, den Motor wieder ausschalten soll.
Code:
1
  case 4:    // Zucker ausgeben Teil 1
2
        if (wuerfel==0)
3
        {menu = 6;}
4
        if (wuerfel==1)
5
        {menu = 5;}
6
          break;
7
      case 5:    // Teil 2
8
        PORTA = 0x01;    
9
        loop_until_bit_is_clear(PINA,7);  
10
        PORTA = 0x00;    
11
        menu++; 
12
          break;
Wenn wuerfel also null ist wird der Teil (case 5) übersprungen. Das 
macht er auch. Wenn wuerfel aber 1 ist, springt er wie gewollt auch in 
case 5 und schaltet den motor an. Nach schätzungsweise 100ms schaltet er 
ihn aber wieder ab. Egal ob der Taster gedrückt ist oder nicht. Hab mit 
Multimeter und Oszi schon nachgemessen welche Spannung vom Taster kommt. 
Er ist aber nicht dauerhaft gedrückt.

Liegt das Problem am Code?

Mit freundlichen Grüßen
Valentin S.

von Valentin S. (lochrasterer)


Lesenswert?

Wenn ich folgendes Programm ausführe macht er alles 1x richtig und dann 
blinkt nur noch die 1 auf dem Display. den Rest lässt er aus.
1
#include <avr/io.h>
2
#define F_CPU 1000000
3
#include <util/delay.h>
4
#include "lcd-routines.c"
5
6
int main(void)
7
{
8
  lcd_init();
9
  DDRA = 0b00000001;  //Motor an PORTA 0
10
  PORTA = 0b01000000;  //Pullup für Taster
11
    while(1)
12
    {
13
  lcd_setcursor(0,1);
14
  PORTA = 0x01;    //Motor anschalten
15
  loop_until_bit_is_clear(PINA,7);  //Schleife bis PINA 7 gedrückt ist
16
  PORTA = 0x00;    //Motor ausschalten    
17
  _delay_ms(1000);
18
  lcd_string("1");
19
  _delay_ms(1000);
20
  lcd_clear();
21
  
22
  } //while(1)
23
}  //Main

: Bearbeitet durch User
von g457 (Gast)


Lesenswert?

> PORTA = 0b01000000;  //Pullup für Taster
[..]
> PORTA = 0x01;    //Motor anschalten
[..]
> PORTA = 0x00;    //Motor ausschalten

∗hüstel∗

von Valentin S. (lochrasterer)


Lesenswert?

Genau das hab ich doch gemacht.

von BattMan (Gast)


Lesenswert?

Valentin S. schrieb:
> #include "lcd-routines.c"

Wer macht denn so was?

Valentin S. schrieb:
> loop_until_bit_is_clear

Zeig mal diesen Teil der Source.

von Valentin S. (lochrasterer)


Lesenswert?

Das mit lcd-routines.c ist ein Fehler von mir. da hab ich im Dateinamen 
.c und .h verwechselt.
Meinst du das Problem liegt an der Tasterabfrage?

von Informer (Gast)


Lesenswert?

Hallo,

unabhängig vom schon genannten Problem: wenn der Taster an PinA.7 hängt 
(zweites Programm) und mit der Anweisung

>  PORTA = 0b01000000;  //Pullup für Taster

der Pullup für PinA.6 eingeschaltet wird, passt das auch nicht zusammen 
...

von Valentin S. (lochrasterer)


Lesenswert?

Pullup ist jetzt am richtigen pin. das ganze funktioniert aber immer 
noch nicht.

von g457 (Gast)


Lesenswert?

> Genau das hab ich doch gemacht.

Nein, hast Du nicht. Um genau zu sein fehlt bei den Kommentaren "Motor 
anschalten" und "Motor ausschalten" die Hälfte.

HTH

von BattMan (Gast)


Lesenswert?

Löte einen externen Pullup Widerstand an den PA7 (10k oder so),
dann funktioniert dein Programm.
Mit der Anweisung
1
PORTA = 0x01;    //Motor anschalten
schaltest Du den internen Pullup aus. Weil Du das Bit PA7 mit 0 
beschreibst.
Dass es einmal funktionieren soll wundert mich deshalb sehr.

von Valentin S. (lochrasterer)


Lesenswert?

Sieht inzwischen so aus:
1
while ( (PINB & (1<<PINB2)) )
2
        {PORTA = 0x01;}
3
        PORTA = 0x00;    //Motor ausschalten
4
        menu++;
funktioniert aber immer noch nicht.

von g457 (Gast)


Lesenswert?

> funktioniert aber immer noch nicht.

Wird immer schlimmer. Geh mal zurück auf Anfang, vergleich die 
Codezeilen, die ich Dir oben rauszitiert hab, nochmals ∗genau∗ mit den 
mitzitierten Kommentaren und stelle fest, dass die beiden letzteren 
Kommentare FALSCH sind (die kommentieren nicht das, was Du tatsächlich 
machst).

Dann überleg nochmal, was Du machen musst, damit die Kommentare RICHTIG 
werden.

von Nil (nilsnilss)


Lesenswert?

Stichwort Bitmanipulation

von Valentin S. (lochrasterer)


Lesenswert?

Hab jetzt nen externen Pullup dran. funktioniert aber nicht.

von Valentin S. (lochrasterer)


Lesenswert?

Nils Friess schrieb:
> Stichwort Bitmanipulation

Ich weiß was du meinst aber nurch den exteren Pullup brauche ich das 
nicht zu tun

von Valentin S. (lochrasterer)


Lesenswert?

push

von Felix P. (fixxl)


Lesenswert?

Wo hängt der externe Pullup? An A7 oder an B2?

von Valentin S. (lochrasterer)


Lesenswert?

A7

von Felix P. (fixxl)


Lesenswert?

Valentin S. schrieb:
> A7
Wie soll dann die Abfrage mit B2 funktionieren?

Das Problem sind einfach die Zuweisungen an den Port mittels 
Holzhammermethode. Bitmanipulation wurde ja bereits angesprochen, 
das sollte man sich von Beginn an so angewöhnen, denn gerade wenn man 
unterschiedliche Dinge an den Pins eines Ports hängen hat, wird man mit 
Direktzuweisungen früher oder später wahnsinnig.

von Valentin S. (lochrasterer)


Lesenswert?

Hab wie gesagt desshalb ja den ext. Pullup

von Felix P. (fixxl)


Lesenswert?

Was wäre so schlimm, das so zu schreiben?
1
#include <avr/io.h>
2
#define F_CPU 1000000
3
#include <util/delay.h>
4
#include "lcd-routines.c"
5
6
int main(void)
7
{
8
  lcd_init();
9
  DDRA  |= 1<<PA0;  //Motor an PORTA 0
10
  PORTA |= 1<<PA7;  //Pullup für Taster
11
    while(1)
12
    {
13
  lcd_setcursor(0,1);
14
  PORTA |= (1<<PA0);    //Motor anschalten
15
  loop_until_bit_is_clear(PINA,7);  //Schleife bis PINA 7 gedrückt ist
16
  PORTA &= ~(1<<PA0);    //Motor ausschalten    
17
  _delay_ms(1000);
18
  lcd_string("1");
19
  _delay_ms(1000);
20
  lcd_clear();
21
  
22
  } //while(1)
23
}  //Main

Wie ist der Motor angeschlossen? Direkt am Mikrocontroller?

von Valentin S. (lochrasterer)


Lesenswert?

@Felix:
Der Motor ist über einen BC548 mit 1kohm Basisvorwiderstand an den 
ATmega angesclossen.

Wenn ich das von dir geschriebene Programm starte, dreht sich der Motor 
unendlich.

von Valentin S. (lochrasterer)


Lesenswert?

Der Taster wird übrigens 70ms lang gedrückt (mit Oszi gemessen).
Reicht das?

von Felix P. (fixxl)


Lesenswert?

Ich bin davon ausgegangen, dass du einen Taster an A7 hast, der beim 
Drücken den Pfad nach GND schließt. Richtig? Ich kenne den Inhalt der 
Funktion loop_until_bit_is_clear(...) nicht, was passiert, wenn du das 
durch
1
while(PINA & (1<<PA7))

ersetzt?

Freilaufdiode ist vorhanden?

Edit: 70ms sind für den Controller eine Ewigkeit. Das muss reichen.

: Bearbeitet durch User
von Valentin S. (lochrasterer)


Lesenswert?

Felix Pflaum schrieb:
> (...]was passiert, wenn du das[...]
> durch
> while(PINA & (1<<PA7))
> ersetzt[...]

Gar nichts. Der Motor fängt gar nicht an sich zu drehen.
loop_until_bit_is_clear(...) heißt dass er wartet bis ein Taster 
gedrückt (gelöscht) ist.
while(PINA & (1<<PA7)) Als ersatz dafür funktioniert nicht.

von Valentin S. (lochrasterer)


Lesenswert?

Push

von Magnus M. (magnetus) Benutzerseite


Lesenswert?

Valentin S. schrieb:
> push

Valentin S. schrieb:
> Push

Lass das bitte.

von Felix P. (fixxl)


Lesenswert?

while(PINA &  (1<<PA7)) heißt auch nur, dass gewartet werden soll, 
solange an A7 High-Pegel anliegt.

Blinkt die 1 noch? Wenn ja, liegt A7 wahrscheinlich aus irgendeinem 
Grund dauerhaft auf Low.

von BattMan (Gast)


Lesenswert?

g457 schrieb:
> letzteren
> Kommentare FALSCH sind

Ach ja? Dann teile dein Wissen mit uns und sprich nicht wie ein Orakel.

von g457 (Gast)


Lesenswert?

> Ach ja?

Ja! Ich zitiere zweckmäßigerweise nochmals eine der bemängelten Zeilen:

> PORTA = 0x00;    //Motor ausschalten

Links (Code) steht im wesentlichen sowas wie 'setzte den gesamten Port 
auf 0 und schalte damit alle Pullups aus (wo auf Eingang konfiguriert) 
bzw. den Ausgang auf low (wo auf Ausgang konfiguriert)'.
Rechts (Kommentar) steht im wesentlichen sowas wie 'mach was an einem 
einzelnen bestimmten Pin uns sonst gar nie nicht nirgens woanders'.

Jetzt klarer? Dann ganz konkret: Der Code schaltet die 
Pull-Up-Widerstände (und den Motor) aus, der Kommentar behauptet er 
würde nur den Motor ausschalten. Das mit den Widerständen wurde 
mittlerweile mehrfach diskutiert, ändert aber nix daran dass im Original 
Code und Kommentare nicht zusammenpassen.

HTH und ich konnte damit alle Unklarheiten beseitigen.

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.