Jump to content
Intermodellbau 2024: Unser Stand in Halle 3 ist fertig für Besucher - schaut mal 'rein. ×
Schiffsmodell.net

RC Signal lesen


JL

Recommended Posts

Hallo,

 

nachdem ich Evaluations- und Adapterboard zum Laufen gebracht habe, stellte sich natürlich die Frage, was stelle ich damit an. Da es auf jeden Fall etwas im Bereich der Fernsteuerung werden soll, ist die erste Aufgabe, das Signal eines RC-Kanals zu lesen. Bei der Recherche im Internet kristallisieren sich mehrere Ansätze heraus:

 

  1. Erhöhen einer Variablen, solange der Impuls anliegt
  2. Verwenden eines Timers (vorzugsweise 16 bit, um ohne weitere Klimmzüge die Längen im Bereich von Millisekunden messen zu können)
  3. Verwenden der externen Interrupts

Variante 1 hat den Nachteil, den Microprozessor mit dem Lesen des Impuls ständig zu beschäftigen; da hier die meiste Zeit mit Warten vergeht, ist das nicht besonders sinnvoll. Der Prozessor könnte in dieser Zeit sicher noch weitere Aufgaben übernehmen.

Variante 3 hat bei der von Thorsten gewählten Belegung des Adapterboards den Nachteil, dass die Pins dort nicht verfügbar sind.

Also habe ich es mit der Variante 2 versucht. Dabei ist das folgende Programm herausgekommen, das die minimale und maximale Impulslänge misst und daraus die aktuelle Impulsbreite berechnet. Danach geht es in eine Endlosschleife, die die jeweils gemessene Imulslänge des Kanals anzeigt.

Wenn länger als 65 ms kein Impuls anliegt, wird dieser Zustand über die LED1 auf dem Evaluationsboard angezeigt.

'----- Settings ----------------------------------------------------------------
$regfile = "m16DEF.Dat"
$crystal = 1000000

'----- Functions ---------------------------------------------------------------
Declare Sub Getpulse(PulseLength As Word )

'----- Variables ---------------------------------------------------------------
Dim PulseLength As Word                                     'stores current reading of RC signal
Dim PulseLengthTemp as Word
Dim PulseError As Byte                                      'stores errors, given by Timer0
Dim PulseLengthMin As Word                                  'stores mimimum pulse length
Dim PulseLengthMax As Word                                  'stores maximum pulse length
Dim PulseWidth As Word
Dim Count As Byte                                           'used as loop counter

'----- Settings for Pollin Evaluation Board -----
  Dim KeyPressed as Bit
  ddrd = &B11100000                                        'PinD5-7 output, PinD0-6 input
  portD = &B11111111                                       'PullUp PinD0-7 active
  Key1 Alias Pind.2
  Key2 Alias Pind.3
  Key3 Alias Pind.4
  LED1 Alias Portd.5
  LED2 Alias Portd.6
  Buzzer Alias Portd.7
'-----------------------------------

'----- Initialization ----------------------------------------------------------
Config LCD = 16 * 1
Config Lcdpin = Pin , Db4 = Portb.4 , Db5 = Portb.5 , Db6 = Portb.6 , Db7 = Portb.7 , E = Portb.2 , Rs = Portb.0
Cls

Config Pina.0 = Input                                       'used for RC signal
Config Timer0 = Timer , Prescale = 1024
Config Timer1 = Timer , Prescale = 1
Const Timer0PreSet = 158                                    'gives interrupt after 65 ms
Const CycleCount = 5                                        'defines number of cycles to read RC signal
LED1 = 0
LED2 = 0

On Timer0 Mispulse

PulseLength = 0
PulseLengthTemp = 0
PulseError = 0
PulseLengthMax = 0
PulseLengthMin = 65535
PulseWidth = 0

'===== Program =================================================================
'----- Part 1 ------------------------------------------------------------------
' Measures minimum pulse length
Cls
Lowerline : Lcd "Mes. Low"
Upperline

For Count = 9 To 0 Step -1
  Home
  Lcd Count
  Waitms 300
Next Count

For Count = 1 to CycleCount step 1
  Call GetPulse(PulseLength)
  PulseLengthMin = PulseLengthMin + Pulselength
Next Count
PulseLengthMin = PulseLengthMin / CycleCount

Cls
Upperline : Lcd "MinPulse"
Lowerline : Lcd " " ; PulseLengthMin
Wait 2

'----- Part 2 ------------------------------------------------------------------
' Measures maximum pulse length
Cls
Lowerline : Lcd "Mes.High"
Upperline

For Count = 9 To 0 Step -1
  Home
  Lcd Count
  Waitms 300
Next Count

For Count = 1 to CycleCount step 1
  Call GetPulse(PulseLength)
  PulseLengthMax = PulseLengthMax + Pulselength
Next Count
PulseLengthMax = PulseLengthMax / CycleCount

Cls
Upperline : Lcd "MaxPulse"
Lowerline : Lcd " " ; PulseLengthMax
Wait 2

if PulseLengthMin > PulseLengthMax then
  PulseWidth = PulseLengthMin - PulseLengthMax
else
  PulseWidth = PulseLengthMax - PulseLengthMin
end if

Cls
Upperline : Lcd "Pulse Wi"
Lowerline : Lcd "dth " ; PulseWidth
Wait 3

'----- Part 4 ------------------------------------------------------------------
' Measures current pulse length and shows results at LCD
Enable Timer0
Enable Timer1
Enable Interrupts
Timer0 = Timer0PreSet

Cls
Upperline : Lcd "P-Length"

Do
  PulseLengthTemp = 0
'   Call GetPulse(PulseLength)

  For Count = 1 to CycleCount step 1
     Call GetPulse(PulseLength)
     PulseLengthTemp = PulseLengthTemp + PulseLength
  Next Count
  PulseLength = PulseLengthTemp / CycleCount

  Lowerline
  Locate 2 , 2
  Lcd PulseLength ; Spc(8)
  Waitms 20
Loop

End                                                         'end program
'===== End of program ==========================================================

'----- Subroutines -------------------------------------------------------------
Sub GetPulse(PulseLength As Word)
  PulseLength = 0

  Bitwait Pina.0 , Set
  Timer1 = 0
  Start Timer1
  Bitwait Pina.0 , Reset
  Stop Timer1
  PulseLength = Timer1
  Timer0 = Timer0PreSet

End Sub

'----- Interrupts --------------------------------------------------------------
Mispulse:
  Incr PulseError
  If PulseError > 10 Then
     Stop Timer0
     LED1 = 1
     Waitms 200
     LED1 = 0
     PulseError = 0
     Start Timer0
  End If
  Return

Ich hatte leider das falsche Display eingekauft, so dass ich die gesamte Ausgabe auf ein noch vorhandenes 16 stelliges Display (organisiert als 2*8 Zeichen) umgestellt habe.

 

Zur Berechnung der genauen Werte habe ich ein Tool (rnAvr) benutzt, das im Roboternetz (www.roboternetz.de) erhältlich ist.

Link to comment
...doch, die HW-Interrupts sind auf die Platine rausgeführt...

Jau, hast Recht. Ich hatte in meiner Dokumentation die falschen Bezeichnungen eingetragen.

Aber, wenn man einmal von der unterschiedlichen Kodierung im Programm absieht, sollte das Ergebnis doch gleich sein, nicht?

Link to comment

Also ich hab in den letzten Tagen viel rumexperimentiert mit RC-Signalen lesen und wieder ausgeben.

 

Also sinnvollste Variante bisher hat sich bei mir herausgestellt, vor allem wenn man lesen und sinnvoll wieder ausgeben will:

 

- RC Signal lesen über INT0 und dann mit Timer0 hochzählen (Auflösung ist mit 124 Schritten dann natürlich eher mau, aber reicht für die meisten Anwendungen), geht mit Sicherheit auch noch anders. Bascom-integrierte Befehle wie Pulsein funktionieren in zeitkritischen Anwendungen nicht richtig.

 

- Servosignale ausgeben über Timer1 (der BASCOM Servo Befehl funktioniert bei mir nur mit zitternden Digiservos)

Link to comment

Ich habe grade mal ein Beispiel gepostet, wie man über einen Hardware-Interrupt einen R/C-Kanal einlesen kann.

 

Zur Ansteuerung von Servos kommen wir dann als nächstes.

 

Ich hoffe, das hilft euch ein wenig weiter!

 

@Jürgen: Erlaubt ist, was funktioniert... Dein Ansatz hat auch was!

 

Viele Grüße

 

Torsten

Link to comment

Hallo,

 

die anfangs geschilderte Version mit einer definierten Funktion hat natürlich den Nachteil, den Microprozessor recht beschäftigt zu halten. Deshalb habe ich auch noch eine Interrupt-Version gemacht, die Int0 und den Timer1 benutzt.

Da das Ganze jetzt wesentlich schneller abläuft, macht sich schon die Warteschleife von 200 ms in der Interrupt-Routine "Mispulse:" teilweise negativ bemerkbar. Es wäre vermutlich besser, in der Routine nur den Fehlerzähler weiter zu zählen und die Anzeige im Hauptprogramm unterzubringen (das Fehlerbit "ErrorFlag" hat noch keine Funktion, das war nur so zum Probieren).

'----- Titel -------------------------------------------------------------------
' Module.......: RCSiMeas_Mega16_Int0
' Purpose......: Reads RC signal using external interrupt 0
'                Shows minimum and maximum pulse length, calculates pulse width
'                Measures RC signal in main loop
'                Measures reading errors and shows them on LED1 if number of
'                  errors > ErrorTolerance
' Author.......: JL
' Version......: 0.2
'                Loop for frequent RC signal readings deleted. Countdown and
'                delay in main program sufficient to get vaild readings
' MCU..........: ATmega16 on Pollin evaluation board
' Bascom.......: V2.0.7.5
'-------------------------------------------------------------------------------

'----- Change History ----------------------------------------------------------
' 21.12.2012 V0.1: Created
'-------------------------------------------------------------------------------

'----- Settings ----------------------------------------------------------------
$regfile = "m16DEF.Dat"
$crystal = 1000000
  '----- Settings for Pollin Evaluation Board -----
  Dim KeyPressed as Bit
  ddrd = &B11100000                                        'PinD5-7 output, PinD0-4 input
  portD = &B11111111                                       'PullUp PinD0-7 active
'   Key1 Alias Pind.2                                       'used to read RC signal
  Key2 Alias Pind.3
  Key3 Alias Pind.4
  LED1 Alias Portd.5
  LED2 Alias Portd.6
  Buzzer Alias Portd.7

'----- Variables ---------------------------------------------------------------
Dim PulseLength As Word                                     'stores current reading of RC signal
Dim PulseError As Byte                                      'stores errors, given by Timer0
Dim PulseLengthMin As Word
Dim PulseLengthMax As Word
Dim PulseWidth As Word
Dim Count As Byte                                           'used as loop counter
Dim ErrorFlag as Bit
Dim RC_Read as Bit
Const Timer0PreSet = 158                                    'gives interrupt after 65 ms with prescale of 1024
Const ErrorTolerance = 10                                   'number of errors before showing error condition
RC_In alias Pind.2

'----- Initialization ----------------------------------------------------------
Config LCD = 16 * 1
Config Lcdpin = Pin , Db4 = Portb.4 , Db5 = Portb.5 , Db6 = Portb.6 , Db7 = Portb.7 , E = Portb.2 , Rs = Portb.0
Cls

Config int0 = Change                                        'used for RC signal
Config Timer0 = Timer , Prescale = 1024
Config Timer1 = Timer , Prescale = 1
On Timer0 Mispulse
On INt0 GetPulse

PulseLength = 0 : PulseLengthTemp = 0 : PulseError = 0
PulseLengthMax = 0
PulseLengthMin = 65535
PulseWidth = 0
Reset ErrorFlag
Set RC_Read
LED1 = 0 : LED2 = 0                                         'LED's on board off
Timer0 = Timer0PreSet

'===== Program =================================================================
Enable Timer0 : Enable Timer1 : Enable INT0
Enable Interrupts

'----- Part 1 ------------------------------------------------------------------
' Measures minimum pulse length
Cls
Lowerline : Lcd "Mes. Low"
Upperline
For Count = 9 To 0 Step -1
  Home : Lcd Count
  Waitms 300
Next Count
PulseLengthMin = PulseLength
Cls
Upperline : Lcd "MinPulse"
Lowerline : Lcd " " ; PulseLengthMin
Wait 2

'----- Part 2 ------------------------------------------------------------------
' Measures maximum pulse length
Cls
Lowerline : Lcd "Mes.High"
Upperline
For Count = 9 To 0 Step -1
  Home : Lcd Count
  Waitms 300
Next Count
PulseLengthMax = PulseLength
Cls
Upperline : Lcd "MaxPulse"
Lowerline : Lcd " " ; PulseLengthMax
Wait 2

'----- Part 3 ------------------------------------------------------------------
' Calculates pulse width
if PulseLengthMin > PulseLengthMax then
  PulseWidth = PulseLengthMin - PulseLengthMax
else
  PulseWidth = PulseLengthMax - PulseLengthMin
end if
Cls
Upperline : Lcd "Pulse Wi"
Lowerline : Lcd "dth" ; PulseWidth
Wait 3

'----- Part 4 ------------------------------------------------------------------
' Measures current pulse length and shows results at LCD
Cls
Upperline : Lcd "P-Length"

Do
  Lowerline
  Locate 2 , 2
  Lcd PulseLength ; Spc(8)
  Waitms 50
Loop

End                                                         'end program
'===== End of program ==========================================================
'----- Interrupts --------------------------------------------------------------
GetPulse:
  If RC_Read = 1 AND RC_In = 1 Then                        'start Timer1 if positive signal on input
     Start Timer1
     Reset RC_Read
  Else                                                     'stop timer1 if no positive signal
     Stop Timer1
     PulseLength = Timer1
     Set RC_Read
     Timer1 = 0
  End If
  Timer0 = Timer0PreSet
  Return

Mispulse:
  Set ErrorFlag
  Incr PulseError
  If PulseError > ErrorTolerance Then
     Stop Timer0
     LED1 = 1
     Waitms 200
     LED1 = 0
     PulseError = 0
     Reset ErrorFlag
     Start Timer0
  End If
  timer0 = Timer0PreSet
  Timer1 = 0
  Return

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.