- 3D-Druck Einstieg und Tipps         
Ergebnis 1 bis 10 von 15

Thema: RC-Empfängers an PCINT1/2 bei ATMEGA88

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Benutzer Stammmitglied
    Registriert seit
    15.08.2013
    Ort
    Güstrow
    Beiträge
    31

    Frage RC-Empfängers an PCINT1/2 bei ATMEGA88

    Hallo an das Forum,

    bin neu hier und komme bei der Programmierung eines ATMEGA88 nicht weiter.

    Ich möchte an Pin 15 u. 16 die Signale eines RC-Empfängers in einer ISR einlesen lassen und diese dann im Hauptprogramm weiterverarbeiten. Die INT0/1 pins habe ich schon mit anderen Dingen belegt, so dass ich auf die PCINT1/2 zurückgreifen muss.
    In meinen Büchern und im Internet habe ich noch nicht die passenden Passagen gefunden, die mir bei meinem Problem weiterhelfen würden.

    Code:
    'Autosteuerung
    $regfile = "m88def.dat"
    $crystal = 16000000
    $hwstack = 40
    $swstack = 40
    $framesize = 40
    
    Dim I As Integer
    On Timer1 Fehler
    
    Config Portc.3 = Output
    Config Pinb.1 = Input
    
    Sreg.7 = 1                                        'Globale Interrupts einschalten
    Pcicr.0 = 1                                       'PCInterrupt einschalten
    Pcifr.0 = 1
    Pcmsk0 = &B00000010                               'Einschalten  pcint1
    Pinb.1 = 0
    
    On Pcint1 Lesen
    
    Config Timer1 = Counter , Prescale = 1 , Compare A = Toggle , Clear Timer = 1
    Enable Timer1
    Enable Interrupts
    
    'Display Einrichten
    Config Lcdpin = Pin , Db4 = Portb.0 , Db5 = Portd.7 , Db6 = Portd.1 , Db7 = Portd.0 , E = Portb.4 , Rs = Portb.5
    Config Lcd = 16 * 2
    Cursor Off
    Cls
    
    Upperline : Lcd "  Los gehts:"
    
    Do
     Lowerline : Lcd "  Puls: " ; I ; " ms   "
     Toggle Portc.3
    Loop
    
    
    Lesen:
      If Pinb.1 = 1 Then
       Pulsein I , Pinb , 1 , 1
      End If
    Return
    
    Fehler:
     Timer1 = 0
    Return
    end
    Nun zu meinen Fragen:
    - Was mache ich falsch, denn die ISR scheint nicht zu starten?
    - Wie messe ich mit dem TIMER1 die genaue Länge der Signale um sie dann für Berechnungen weiter zu verwenden?
    - Ich möchte weg von den Assembler-ähnlichen Eingaben, weil ich sie nicht verstehe. Im Datenblatt stehen nur Beispiele für C und Assembler. Wie muss der Code für Bascom aussehen, dass das richtig funktioniert?

  2. #2
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    15.01.2007
    Ort
    Göttingen
    Beiträge
    706
    Moin-moin!

    Das sieht schon ziemlich gut aus, und zu Deinen Fragen gibt´s auch Antworten!
    Erstmal gibt´s aber noch ein paar Anmerkungen zu Deinem bisherigen Code (von oben nach unten):

    SREG.7=1 ist korrekt - genau das gleiche macht aber auch der Befehl "Enable Interrupts". Das ist also quasi doppelt gemoppelt.
    PCICR.0=1 aktiviert den PCINT0 - auf "Bascom" könnte man aber analog dazu "Enable PCINT0" schreiben (liest sich einfacher).

    Das Bit PCIFR.0 dient dem Controller dagegen als sogenanntes "Flag" (so ´ne Art Signal) - es wird gesetzt wenn die Interrupt-Bedingung eintritt, und gelöscht wenn die dazugehörige Interrupt-Routine ausgeführt wurde. Der Controller macht das ganz alleine; dieses Bit solltest Du also erstmal in Ruhe lassen

    PINB.1=0: Die PIN-Register enthalten die logischen Zustände die an einem Anschluss anliegen, der als Eingang konfiguriert ist. Man fragt sie also ab wenn man wissen möchte, ob ein Anschluss High oder Low ist. Vermutlich wolltest Du den PullUp-Widerstand des Eingangs B.1 aktivieren - das ginge dann mit PORTB.1=1.

    Compare A = Toggle, Clear Timer = 1: Diese Befehle braucht man nur für PWM-Anwendungen - in diesem Fall sind sie unnötig.


    Und diese Sequenz

    Do:
    Lowerline : LCD " Puls: " ; I ; " ms"
    Toggle PORT.3
    Loop

    ist auch etwas problematisch: Dein LCD hämmert alle paar Millisekunden seine Buchstaben in die untere Zeile - und zwar hintereinander. Das heißt, schneller als Du sehen kannst ist die untere Zeile vollgeschrieben, und alles was danach kommt geht in´s "Nirvana".
    Abhilfe würde hier der Befehl "Locate 2,1" vor dem LCD-Befehl schaffen: Damit startet jeder Ausdruck an der ersten Stelle der zweiten Zeile.


    Und zu den PCINTs muss man auch ein paar Dinge wissen, um die Wirrnis zu verstehen:

    Es gibt 24 Anschlüsse, die einen Pinchange-Interrupt auslösen können: PCINT0, PCINT1,...PCINT23. Es gibt aber keine 24 unterschiedlichen Pinchange-Interrupts, sondern nur drei: PCINT0, PCINT1 und PCINT2 (vergleichbar mit den beiden "normalen" Interrupts INT0 und INT1). Dass diese drei Interrupts genauso heißen wie die ersten drei Anschlüsse, ist sehr verwirrend. Die Interrupt Anschlüsse sind nun in 8er-Gruppen zusammengefasst, von denen jeder Anschluss den selben Interrupt auslöst:

    Anschlüsse PCINT0-PCINT7 -> PCINT0
    Anschlüsse PCINT8-PCINT15 -> PCINT1
    Anschlüsse PCINT16-PCINT23 -> PCINT2

    Wenn Du also über den Pin 15 den Interrupt auslösen möchtest, ist das der Anschluss PCINT1, und somit die Interrupt-Routine PCINT0 ! (verwirrend, aber wahr)
    Das PCMSK-Register hast Du also korrekt gesetzt mit &B00000010. Und PCICR.0=1 ist auch korrekt, schließlich möchtest Du ja die Gruppe "PCINT0" aktivieren (man könnte auch in Bascom direkt schreiben "Enable PCINT0).
    Aber Du musst dann "On PCINT0 Lesen" schreiben!

    Und die Messung von RC-Impulsen habe ich immer so gemacht:

    Lesen:
    If PINB.1=1 then
    Timer1=0
    Else
    I=Timer1
    End if
    Return

    Heißt also, dass der Timer zurückgesetzt wird wenn der Impuls beginnt (Flanke und PINB.1=1), und sein aktueller Wert auf die Variable I überschrieben wird, wenn der Impuls endet (Flanke und PINB.1=0). Wenn Du einen Prescaler von 64 nimmst, läuft der Timer erst nach 200 ms über - in dieser Zeit sollten mindestens 10 Impulse aufgelaufen sein. Und wenn nicht, springt der Controller berechtigterweise in die ISR "Fehler".

    Wenn Du dann noch ein "Flag" setzt wenn das Impulsende erkannt wurde, kannst Du in der Hauptschleife das Flag abfragen und den LCD-Befehl nur ausführen lassen, wenn auch tatsächlich ein neuer Impuls gemessen wurde. Aber das wäre vielleicht was für die nächste Runde

    Ich hoffe, das waren nicht zu viele & verwirrende Informationen - ansonsten einfach nachfragen!
    Geändert von Sauerbruch (16.08.2013 um 15:37 Uhr)

  3. #3
    Erfahrener Benutzer Roboter Genie Avatar von HeXPloreR
    Registriert seit
    08.07.2008
    Ort
    Bad Bramstedt
    Alter
    45
    Beiträge
    1.369
    Hallo,

    Du könntest auch einfach auf den Bascombefehl "pulsein" ausweichen. Der PCINT muss dann ein einfacher Eingang sein(+PullUp an), an dem das RC-Signal anliegt. Da ist dann zwar kein Timer mehr händisch programmiert, aber man sieht eh nicht wozu Du den unbedingt brauchst

    Ein RC-Empfänger gibt soweit ich es burteilen kann immer ein Signal aus solange der Empfänger Spannung hat und der Sender am Empfänger ankommt. Kommt eine "0" an, ist die Verbindung weg ( das habe ich allerdings ganz sicher nur mit Spannungsunterbrechung probiert - also Reichweitentest steht noch aus.)

    Wichtig ist auch das die 16mega Crystal-Frequenz vom Mikrocontroller bereitgestellt wird und nicht nur im Code geschrieben wurde.
    Pulsein funktioniert nach meiner Erfahrung ab 4Mhz erst zufriedenstellend.
    Damit habe ich mit meiner Funke einen Neutralwert von ca. 150 (mit Trimmer) eingestellt. Auch auf LCD Display...da ich das aber nur zum üben dran hatte habe ich später wieder auf Terminalausgaben gewechselt.

    Hier mal ein Beispiel wie man es nutzen könnte:
    https://www.roboternetz.de/community...hlight=pulsein
    Geändert von HeXPloreR (16.08.2013 um 15:59 Uhr)

  4. #4
    Benutzer Stammmitglied
    Registriert seit
    15.08.2013
    Ort
    Güstrow
    Beiträge
    31
    Jippy, ich habs endlich kapiert.

    [code]
    'Autosteuerung
    $regfile = "m88def.dat"
    $crystal = 256000
    $hwstack = 40
    $swstack = 40
    $framesize = 40

    Dim I As Integer
    Dim I2 As Integer

    Config Portc.3 = Output
    Config Portc.2 = Output

    Enable Interrupts
    Enable Pcint0

    Pcmsk0.pcint1 = 1


    On Pcint0 Lesen:

    Do
    Portc.3 = 1
    Waitms 100
    Portc.3 = 0
    Waitms 100
    Loop

    Lesen:
    Toggle Portc.2
    Return


    End
    [code]

    so funktioniert erstmal das was ich wollte.

    vielen, vielen Dank
    Weiteres folgt

Ähnliche Themen

  1. [ERLEDIGT] Pwm Motorsteuerung mit PCINT1
    Von Balu18 im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 12
    Letzter Beitrag: 09.03.2013, 17:48
  2. ATmega88 (Blinklicht)
    Von steep im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 3
    Letzter Beitrag: 11.07.2011, 12:08
  3. PortD als Eingang mit Pullup bei Atmega88 geht nicht!?
    Von Stomper im Forum C - Programmierung (GCC u.a.)
    Antworten: 5
    Letzter Beitrag: 30.10.2008, 08:16
  4. Abschalten einer RC-Empfängers?
    Von krischan100 im Forum Elektronik
    Antworten: 3
    Letzter Beitrag: 15.07.2006, 08:34
  5. PS2 Steckerbelegung eines GPS Empfängers
    Von Amiwerewolf im Forum Vorstellung+Bilder+Ideen zu geplanten eigenen Projekten/Bots
    Antworten: 5
    Letzter Beitrag: 03.07.2006, 17:13

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Labornetzteil AliExpress