PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Wertebereich in eine Byte- Variable legen



Muddel
09.07.2006, 14:29
Hallo,

ich habe ein Problem mit Variablen bei dem ich nicht weiterkomme. Ich lese mit einem ATmega48 Signale einer RC- Fernbedienung aus, dazu habe ich folgenden Code abgeändernt:

http://www.rclineforum.de/forum/thread.php?threadid=106253&sid=

Der Code gibt Werte im Bereich von ca. 16300 (Steuerknüppel linke Pos.) bis 8590 (Steuerknüppel rechte Pos.) aus. Um Servos anzusteuern wird von der Lib. Servo in Bascom eine Byte- Variable verlangt (Das ganze soll ein Empf. seitiger Mischer werden). Wie kann ich den Bereich von 7710 Schritten Linear in eine Byte- Variable von 50- 200 legen. Ich habe mir bereits folgenden Thread hier im Forum angeschaut werde aber nicht richtig schlau bez. des Index beim Lookup- Befehl.

https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=20832


hier noch mein Code:


'Konfiguration des Timer1
Config Timer2 = Timer , Prescale = 1
Config Timer1 = Timer , Prescale = 1
Config Timer0 = Timer , Prescale = 1
'Konfiguration des INT0
'Interrupt bei jedem Flankenwechsel (0->1 und 1->0)
Config Int0 = Change

Config Servos = 2 , Servo1 = Portb.0 , Servo2 = Portb.1 , Reload = 10
Config Portb = Output

Dim Temp As Byte
Dim Reading As Bit
Dim Rc_value As Word
Dim I As Byte
Dim Error As Bit
'================================================= =====
'Initialisierungen
'================================================= =====

'Zuweisung der Interrupt-Service-Routinen
On Int0 Rc_read
On Timer1 Rc_error


'Timer-Freigabe
Enable Timer1
Stop Timer1


'Freigabe der Interrupt-Routinen
Enable Int0
Enable Interrupts

'================================================= =====
'Hauptprogramm-Schleife
'================================================= =====
Do
Temp = 0
If Reading = 0 Then

Print "Kanal1: " ; Rc_value
End If
Loop
End

'================================================= =====
'ISR für INT0 - R/C-Kanal lesen
'================================================= =====
Rc_read:
'Den Timer starten mit steigender Flanke
If Reading = 0 Then

Start Timer1
Reading = 1

'Den Timer stoppen mit fallender Flanke
Else
Stop Timer1
Rc_value = Timer1

Timer1 = 0
Reading = 0

End If
'Error-Bit rücksetzen
Error = 0
Return



'================================================= =====
'ISR für Timer1 - Fehlerhandling
'================================================= =====
Rc_error:
'Error-Bit setzen
Error = 1
Reading = 0
Stop Timer1
Rc_value = 6300
Return


besten Dank

Torsten[/url]

Marco78
09.07.2006, 16:24
Im Code habe ich Index oder sonstetwas anderes entdeckt, das dein Problem versucht in den Griff zu bekommen.

Wäre es nicht auch einfacher, das ganze per Dreisatz zu lösen?
Ein paar Rechenschritte und du hast den Wert in einer Bytevariable. Allerdings kann es sein, das die Programmlaufzeit sich dafür erhöht.

Muddel
09.07.2006, 17:18
Hallo Marco,



Im Code habe ich Index oder sonstetwas anderes entdeckt, das dein Problem versucht in den Griff zu bekommen.


ich hatte meine erfolglosen Versuche mit Lookup zu dem Zeitpunkt schon aus dem Quelltext gelöscht.



Wäre es nicht auch einfacher, das ganze per Dreisatz zu lösen?
Ein paar Rechenschritte und du hast den Wert in einer Bytevariable. Allerdings kann es sein, das die Programmlaufzeit sich dafür erhöht.


Wenn ich mit den Zahlen rechne bekomme ich heillosen Datenmüll, keine echten Werte. Liegt ja Wahrscheinlich an den zwangsläufig auftretenden Nachkommastellen, welchen Befehl muss ich verwenden um nur mit ganzzahlen zu rechnen?

Gruss Torsten

Marco78
09.07.2006, 19:17
Wenn ich mit den Zahlen rechne bekomme ich heillosen Datenmüll, keine echten Werte. Liegt ja Wahrscheinlich an den zwangsläufig auftretenden Nachkommastellen
heillosen Datenmüll kann ich mir garnicht vorstellen?!?
Wie sieht denn deine Rechnung aus? Oder wie der Code dafür? Dann sieht man gleich welche Variable du welchem Typ zugewiesen hast.

Muddel
09.07.2006, 19:25
Hallo,

habe es mittlerweile wieder mit berechnen versucht, diesmal klappt das! Ich teile den wert durch 40 und schiebe das Low- Byte mit LOW() in ein Byte. Ich weiss nicht warum das vorher schief ging

Danke für den "Ruck" in die richtige Richtung

Torsten

Marco78
10.07.2006, 01:22
Durch 40 teilen?

7710/150 ergibt ungefähr 51.

7710 ist der differenzielle Wert den du bekommst, 150 ist die Differenz zwischen 50 und 200, die du haben möchtest.

Wenn Y der gemessene Wert ist, würde ich den - 8590 nehmen und das Ergebnis X nennen.
Dann hat man den Wert quasi von 0 an gezählt und erhält als meximalen Wert die 7710.
Dann X/51+50
Alle 51 Schritte bewirken eine Erhöhung um 1 deiner Bytevariable.
+50, weil der minimale Wert deines Bytes 50 sein soll.

Aber wenn es mit LOW() auch geht ist es ja gut.

Wen du es doch anders machen solltest, kann ich dir den Tipp geben, die Werte des Senders mit CONST festzulegen.

Wenn sich linker und rechter Anschlag mal ändern, ändert sich auch der Wert pro Schritt. (Z.Zt. die 51). Und schon würde die Rechnung nicht mehr passen.
Ein neuer Sender und schon passt das ganze nicht mehr. Oder das Poti wird etwas verstellt...

Wenn die Werte ganz zu Anfang im Listing stehen und als Konstante festgelegt sind, müssten sie dann nur einmal geändert werden und nicht mühsellig im ganzen Programm nach gesucht werden. Das ist dann auch eine beliebte Fehlerquelle. Ich spreche da aus eigener Erfahrung!

Noch komfortabler wäre es ja (und damit auch für andere Personen geeignet) wenn der linke und rechte Anschlag selbstlernend sind.

Immer wenn man meinte es wäre mal wieder so weit, die Kalibrierung per externen Taster starten und dann 5 mal nach links und rechts schalten, das Programm erkennt automatisch welcher Wert wahrscheinlicher für links oder rechts war. Oder die Reihenfolge wird festgelegt und dann wird ein Mittelwert errechnet. Die Werte werden dann im EEPROM abgelegt und sind auch nach Stromausfall noch verhanden. Beim Neustart müssen die Werte dann nur noch ausgelesen werden.
Im Prinzip muss auch nur der Umrechnungsfaktor Senderwert/Byte gespeichert werden.

Das ganze erspart dir ein neues flashen des AVR wenn du dir n neuen Sender kaufst und ermöglich eine hohe Kompatiblität wenn jemand deine Schaltung nachbauen will.

Muddel
11.07.2006, 22:50
Hallo Marco,

ich habe inzwischen den Prescaler des Timers von 1 auf jetzt 64 erhöht, das ergibt schon einmal kleinere Werte, anschließend habe ich mit AND die letzten zwei Bits des Wortes "ausgeblendet". Danach reicht ein x-110 aus und das ganze passt mit der Steuerung überein. Das Problem das ich jetzt habe ist das die Servos ständig zucken, das hat mit der Einstellung des Prescalers scheinbar nichts zu tun, da das Zucken der Servos auch mit der Einstellung auf eins vorhanden war. Das ist insofern ärgerlich da die Werte ( x ) zur Berechnung der eigentlichen Servostellung dienen sollen ( Servos sollen gemischt werden). Es könnten während einer Berechnung beide Werte falsch sein und das Ergebnis wäre völlig falsch. Auf dem Oszilloskop sieht das Signal des Empfängers sauber aus. Deine Idee mit dem Kalibrieren ist garnicht so schlecht, wenn ich die Servos sauber ansteuern kann werd ich mal darüber her machen :-k

werde morgen mal weitersehen

Gruss
Torsten