Hallo, ich habe folgendes Problem: Im Dateianhang findet ihr einen Teil des Schaltplans, ich habe nur den Teil beigefügt der mir Probleme bereitet. Folgendes, der Controller läuft mit dem Programm (Code unten)auf dem STK500 sehr gut und schaltet mir über je 2 Taster je einen Ausgang, mit dem ich je ein Relai ansteuern möchte um den rechts-links-lauf für einen Motor zu realisieren. Leider leuchten auf dem STK500 alle LEDs so wie sie sollen aber das Relai schaltet nicht so wie es soll und der Ausgang am Controller ist nie wirklich auf 0V. Es liegt immer eine Spannung an, 4,87V oder geschaltet 1,76V und ich wüsste gerne warum ??? Zweites Problem, wie kann ich das schalten des Ausgangs im Programm am besten umkehren/negieren ??? Für Tips und Hilhen wäre ich euch sehr dankbar - ich habe langsam keine Gedult mehr, ist schon die dritte Platine...... Gruss Boris ____________________________________________________________________ #include <avr/io.h> int main (void) { DDRB &= ~( 1 << PB0 ); //PB0 Eingang DDRB &= ~( 1 << PB1 ); //PB1 Eingang PORTB |= ( 1 << PB0 ); //Pull up an PORTB |= ( 1 << PB1 ); //Pull up an DDRC &= ~( 1 << PC2 ); //PC2 Eingang DDRC &= ~( 1 << PC3 ); //PC3 Eingang PORTC |= ( 1 << PC2 ); //Pull up an PORTC |= ( 1 << PC3 ); //Pull up an DDRC |= ( 1 << PC0 ); //PC0 Ausgang DDRC |= ( 1 << PC1 ); //PC1 Ausgang while(1) { if (PINB & (1 << PB0))//wenn PB0 High ist... { PORTC |= (1 << PC0); //PC0 High } if (PINB & (1 << PB1))//wenn PB1 High ist... { PORTC |= (1 << PC1); //PC1 High } if (PINC & (1 << PC2))//wenn PC2 High ist... { PORTC |= (1 << PC0); //PC0 High } if (PINC & (1 << PC3))//wenn PC3 High ist... { PORTC |= (1 << PC1); //PC1 High } // Eine Schleife if (!(PINB & (1 << PB0))) //wenn PB0 Low ist... { PORTC &= ~(1 << PC0); //PC0 Low } if (!(PINB & (1 << PB1))) //wenn PB1 Low ist... { PORTC &= ~(1 << PC1); //PC1 Low } if (!(PINC & (1 << PC2))) //wenn PC2 Low ist... { PORTC &= ~(1 << PC0); //PC0 Low } if (!(PINC & (1 << PC3))) //wenn PC3 Low ist... { PORTC &= ~(1 << PC1); //PC1 Low } } return 0; } ____________________________________________________________________ sorry für den vielen Platz durch den Code !!!! ;-)
Hast du auch AVCC beschalten? Sonst funktioniert der PortC nicht richtig.
Ja, ich habe so ziemlich alle Anschlüsse wie im Datenblatt verdrahtet, aber irgendwas läuft da nicht. 8-( Gruss Boris
Hast Du wirklich AVCC, AGND und AREF richtig beschaltet? Das "Andersherum" Schalten des Ausgangs kann man z.B.in BASCOM mit dem NOT - Befehl erreichen. Ob es den in C gibt, weiß ich nicht, davon verstehe ich nichts. MfG Paul
Hallo Boris, ich kann mich meinen Vorrednern nur anschließen: nach Deinem Schaltplan liegt AVcc (Pin 20) nicht an Vcc! Gruß Fred
Sorry, habe ich in der Skizze leider vergessen - Pin 20 liegt an 5V VCC. Ich habe jetzt mal LEDs an die Stelle der Relais gelötet und festgestellt, das sie ständig leuchten und nur dann heller werden, wenn ich einen Taster für links oder rechts drücke. Stimmt etwas mit der Transistoransteuerung nicht oder das Programm ? auf dem STK500 geht es doch ??? Gruss Boris
@ Boris Bau dir eine H-Bücke dafür. Du musst den Motor eh erst stoppen bevor du ihn in eine andere Richtung drehen lässt.
Hallo, nein - eine H-Brücke ist nicht nötig, das ist ein Getriebemotor der sofort steht sobald der Taster losgelassen wird. Ich habe am Ausgang des Mic immer 4,8V stehen und sobald ich den Taster drücke, fällt der Pegel nur auf 1,2V ab. Abgesehen davon, das der Ausgang 0V liefern sollte und erst dann ca. 5V wenn der Taster gedrückt wird..... scheint das Programm zu laufen. Das mit dem umgekehrten Pegel liegt eben am STK500, das dreht den Pegel an den Ausgängen um. Also es wäre nett, wenn mir jemand helfen könnte. Danke ! Boris
Hallo, hier nochmal der komplette aktuelle Schaltplan. Was läuft da falsch ??? Gruss Boris
Ich hab jetzt dein Programm nicht in allen Einzelheiten analysiert. Da sind mir einfach zuviele if then-else die jeweils den Port-Pin verstellen. Ich könnte mir aber vorstellen, dass in Wirklichkeit dein PC0 bzw. PC1 Ausgang ständig den Pegel wechselt. Warum machst du nicht einfach mal ein simples Testprogram
1 | int main() |
2 | {
|
3 | DDRC = ( 1 << PC0 ) | ( 1 << PC1 ); |
4 | |
5 | while( 1 ) { |
6 | PORTC = 0x03; |
7 | }
|
8 | }
|
Jetzt müssen die beiden Relais sauber anziehen. Tun sie das, dann kommt der Gegentest
1 | int main() |
2 | {
|
3 | DDRC = ( 1 << PC0 ) | ( 1 << PC1 ); |
4 | |
5 | while( 1 ) { |
6 | PORTC = 0x00; |
7 | }
|
8 | }
|
Und die Relais sollten ruhig sein. Wenn das hier klappt (ruhig auch mal die Spannungen am µC Pin nachmessen), dann sieh dir nochmal dein Programm an. Zieh es umgekehrt auf: Geh nicht von den Eingängen aus und leite davon ab, was am Ausgang passieren soll, sondern geh von den Ausgängen aus und überleg dir, welche Bedingung an den Eingängen vorliegen muss, damit der Ausgang 1 bzw. 0 sein soll. Formulier das als eine einzige Bedingung. Dadurch läufst du dann nicht Gefahr, dass ein Programmteil den Portausgang auf 1 setzt und gleich darauf ein anderer Programmteil den Ausgang wieder auf 0 runterzieht.
Hallo, vielen Dank - es ist genau wie Du geschrieben hast, die Ausgänge werden sauber geschaltet. Das ist mein erstes Projekt mit einem AVR - wie bekomme ich das hin, das ich die Ausgänge mit einem Taster sauber schalte - ohne ein flimmern ? Gibt es da einen Trick, wie man die Ausgänge am sichersten schaltet ? Vielen Dank ! Gruss Buris
Boris wrote:
> Gibt es da einen Trick, wie man die Ausgänge am sichersten schaltet ?
Der Trick ist, die Ausgänge nur an einer einzigen STelle im Code
schalten. Entweder ein oder aus. Aber nicht an 5 verschiedenen
Stellen verstreut über den ganzen Code.
Ich geh mal davon aus, dass dein Eingänge 2 von 2 Tastern
und 2 Endschaltern kommen.
Das heist, der Motor darf nur dann in eine Richtung fahren,
wenn der entsprechende Taster gedrückt und der entsprechende
Endschalter nicht erreicht ist.
Um das ganze übersichtlicher zu gestalten, schlage ich die
Einführung von ein paar Funktionen vor
1 | uint8_t TasterRauf() |
2 | {
|
3 | PINB & ( 1 << PB0 ); |
4 | }
|
5 | |
6 | uint8_t EndschalterOben() |
7 | {
|
8 | PINC & ( 1 << PC2 ); |
9 | }
|
10 | |
11 | void MotorAuf() |
12 | {
|
13 | PORTC &= ~( 1 << PC1 ); |
14 | PORTC |= ( 1 << PC0 ); |
15 | }
|
16 | |
17 | void MotorZu() |
18 | {
|
19 | PORTC &= ~( 1 << PC0 ); |
20 | PORTC |= ( 1 << PC1 ); |
21 | }
|
22 | |
23 | void MotorStop() |
24 | {
|
25 | PORTC &= ~( 1 << PC0 ); |
26 | PORTC &= ~( 1 << PC1 ); |
27 | }
|
Der Zweck dieser Hilfsfunktionen besteht darin, den eigentlichen Code einfacher bzw. lesbarer zu gestaltet. Die Ganzen << und & und | lenken sonst extrem vom eigentlichen Geschehen ab. Du willst dich nicht ständig mit & und | herumschlagen, du willst dich mit deiner Logik beschäftigen.
1 | int main() |
2 | {
|
3 | ...
|
4 | |
5 | while( 1 ) { |
6 | |
7 | // Wenn die Taste für 'Rauf' gedrückt ist, dann fährt der
|
8 | // Motor nach oben. Aber nur, wenn der Endschalter dafür
|
9 | // nicht schon erreicht ist
|
10 | |
11 | if( TasterRauf() ) { |
12 | if( !EndschalterOben() ) |
13 | MotorAuf(); |
14 | }
|
15 | |
16 | // Wenn die Taste für 'Runter' gedrückt ist, dann fährt der
|
17 | // Motor nach unten. Aber nur dann, wenn der entsprechende
|
18 | // Endschalter nicht betätigt ist UND wenn die Kinder nicht
|
19 | // wieder mal ihre Patschehändchen auf beiden Tasten gleich-
|
20 | // zeitig haben. In dem Fall 'gewinnt' dann die Taste für
|
21 | // auf
|
22 | |
23 | else if( TasterRunter() ) { |
24 | if( !EndschalterUnten() ) |
25 | MotorZu(); |
26 | }
|
27 | |
28 | // nichts ist gedrückt. Dann soll auch nichts passieren
|
29 | else
|
30 | MotorStop(); |
31 | }
|
32 | }
|
Man beachte, wie der Code hier schon fast selbsterklärend wird. Durch die Funktionen ist der Code schon fast sowas wie eine Zusammenfassung des jeweils darüberstehenden Kommentars. PS: Ich habe jetzt nicht darauf geachtet, ob die Schatlerfunktionen korrekt auf PIN 0 oder 1 geschrieben sind. Da musst du ev. nachbessern. Dazu würde ich mir gleich wieder mal ein Testprogramm schreiben
1 | int main() |
2 | {
|
3 | ...
|
4 | |
5 | while( 1 ) { |
6 | |
7 | if( !EndschalterOben() ) |
8 | MotorAuf(); |
9 | }
|
10 | }
|
Die Erwartung dieses Testprogramms: Der Motor fährt auf, bis der Endschalter anspricht. Jetzt vergleichst du die Realität mit der Erwartung. Tut die Schaltung das erwartete? Wenn nein, dann untersuchst du warum nicht. Es gibt nur eine Möglichkeit: Die Auswertung des Endschalters ist genau verkehrt rum. Also korrigierst du sie in der Endschalter Funktion. Wenn das dann klappt, dann gehts ans überprüfen in die andere Richtung. Erst nachdem die Einzelteile geprüft sind, baust du dann wie oben angedeutet, das komplette Programm zusammen. Du musst anfangen modular zu arbeiten. Kleine Änderungen, die jede für sich einzeln testbar sind.
Super - vielen Dank !!! ich werde mich gleich mal dran machen...so hört es sich schon viel besser an und ich glaube das könnte etwas werden. Mit den Endschaltern ist eine gute Idee, nur die zwei weiteren Schalter wollte ich mir für später reservieren um das Projekt noch ausbauen zu können. Der Motor hat intern schon Endschalter und die Abschaltung wollte ich per Zeit machen - sicher ist sicher. Aber das ist dann das nächste Problem, erst müssen die Ausgänge auf die Taster reagieren, danach möchte ich das jeder Ausgang nur ca.2 Minuten aktiv ist und dann automatisch wieder auf low geht. Aber wie gesagt.... dieses Wochenende hoffe ich den Anfang zu finden und die Arbeitsweise zu begreifen. Nochmals vielen Dank, Du solltest Lehrgänge anbieten - sehr gut erklärt ! Gruss Boris
Hallo Karl Heinz, also mit dem Programm habe ich doch einige Probleme, was bedeuten die "unit8_t..." kann ich jetzt direkt unit8_t TasterAuf aufrufen und es als Variable nutzen oder wofür steht es ? Und die Definition für void MotorAuf() kann ich die auch als Variable aufrufen ? Also irgendwie bringt mich das jetzt doch durcheinander.... Muss ich die Ein-/Ausgänge nicht auch noch definieren ? Danke ! mfg. Boris uint8_t TasterAuf() { PINB & ( 1 << PB0 ); } uint8_t ExtAuf() { PINC & ( 1 << PC2 ); } uint8_t TasterZu() { PINB & ( 1 << PB1 ); } uint8_t ExtZu() { PINC & ( 1 << PC3 ); } void MotorAuf() { PORTC &= ~( 1 << PC1 ); PORTC |= ( 1 << PC0 ); } void MotorZu() { PORTC &= ~( 1 << PC0 ); PORTC |= ( 1 << PC1 ); } void MotorStop() { PORTC &= ~( 1 << PC0 ); PORTC &= ~( 1 << PC1 ); int main(void) { ... while( 1 ) { // Wenn die Taster für 'Rauf' oder Taster "Extauf" gedrückt ist, dann fährt der // Motor ca. 2 Minuten nach oben. // Wird ein Taster für "auf" gedrückt, stehen alle Ausgänge wieder auf "0". if( TasterRauf(PB0==0) ) { if( Extauf(PC2==0) ) MotorAuf(PC0==1); } // Wenn die Taste für 'Runter' oder Taster "Extzu" gedrückt ist, dann fährt der // Motor ca. 2 Minuten nach unten. // Wird ein Taster für "auf" gedrückt, stehen alle Ausgänge wieder auf "0". else if( TasterRunter(PB1==0) ) { if( Extzu(PC3==0) ) MotorZu(PC1==1); } // nichts ist gedrückt. Dann soll auch nichts passieren //else //MotorStop(); //} //} //int main() //{ //while( 1 ) //{ //if( !EndschalterOben() ) //MotorAuf(); //} //}
Boris wrote: > Hallo Karl Heinz, > also mit dem Programm habe ich doch einige Probleme, > was bedeuten die "unit8_t..." uint8_t ist ein Datentyp. So wie int oder double oder long. Nur ist dieser Datentyp so spezifiziert, dass er exakt einem Byte entspricht. > kann ich jetzt direkt unit8_t TasterAuf > aufrufen TasterAuf ist eine Funktion. Die kann man einfach aufrufen und diese Funktion liefert einen Wert. So wie sin(0.2) einen Wert liefert (nämlich den Sinus des angegebwnwn Winkels), so liefert TasterAuf einen Wert. Dieser Wert repräsentiert den Zustand der Taste 'auf' > Und die Definition für void MotorAuf() kann ich die auch als Variable > aufrufen ? Das ist keine Variable. Das ist wieder eine Funktion. Wird die aufgerufen, so sorgt sie dafür, dass der Motor in die 'Auf-Stellung' läuft. > Also irgendwie bringt mich das jetzt doch durcheinander.... C-Literatur besorgen. Eine Programmiersprache lernt man nicht dadurch, dass man sich durchwurschtelt. Modulares Programmieren (Programmieren indem man sich Funktionen für bestimmte Aufgaben schreibt und diese dann verwendet) ist das A und O einer vernünftigen Softwareentwicklung. > Muss ich die Ein-/Ausgänge nicht auch noch definieren ? Sicher musst du das. Da ich aber nicht 100% weiss, wo deine Taster und Motoren am µC hängen, habe ich das in main() mit den 3 Punkten ... angedeutet. > if( TasterRauf(PB0==0) ) TasterRauf liefert schon einen Wert (oder soll es zumindest), der eine Aussage darüber trifft, ob der Taster gedrückt ist oder nicht. if( TasterRauf() )
Hallo Karl Heinz, nochmals Danke für Deine Hilfe - momentan bin ich auf der Arbeit sehr eingespannt - also sorry das ich mich erst jetzt wieder melde. In der Schule habe ich C und Pascal gehabt.... ist nur schon sehr lange her und ich komme da nur schwer wieder rein. Also fange ich mal von ganz vorne an, Schritt für Schritt. Ich benötige 4 Eingänge und 2 Ausgänge PB0 oder PC2 schalten Ausgang PC0 auf "1" PB1 oder PC3 schalten Ausgang PC1 auf "1" (Die Eingänge liegen immer auf "1" und werden bei Betätigung auf "0" gezogen, die Ausgänge sollen "1" liefern wenn sie aktiv sind) Was benötige ich dafür und was muss ich wie definieren damit das schon mal funktioniert ? Danke ! Gruss Boris
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.