Hier sind die Berechnungen im Code:
Eigentlich findet alles nicht im Array statt, trotzdem gehts nicht als Byte. Vielleicht liegt das daran, dass bei Fehlerhaftem Signal die Variable Meanrx in Empf geschrieben wird. Sicher bin ich mir da aber nicht. Vielleicht hast du eine Erklärung?Code:'--Noise filter-- For I = 1 To 5 Meanrx(i) = Meanrx(i) * 3 Meanrx(i) = Meanrx(i) + Empf(i) '"lowpass filter" of the RC signal Shift Meanrx(i) , Right , 2 ' (=divide by 4) Aempfh(i) = Meanrx(i) + 17 'upper acceptable fluctuation Aempfl(i) = Meanrx(i) - 17 'lower acceptable fluctuation If Empf(i) > Aempfh(i) Or Empf(i) < Aempfl(i) Then 'compare allowed fluctuation with current rc reading Empf(i) = Meanrx(i) 'if fluctuation was too high -> replace with averaged value Print "Error reading channel: " ; I 'handy to check for RC problems End If Next 'Empf(X) are filled in "getreceiver". They usually contain values ranging from 63 - 137. 'Empf(throttlechannel) is the throttle stick. it will be rescaled differently. If Empf(throttlechannel) > 61 And Empf(throttlechannel) < 139 Then 'don't process values that can't be correct Sempf(throttlechannel) = Empf(throttlechannel) - 61 Sempf(throttlechannel) = Sempf(throttlechannel) * 3 '==> values ranging from 3 (stick at bottom) to 228 (full throttle) End If 'Now nick, roll, yaw and idle up switch If Empf(nickchannel) > 61 And Empf(nickchannel) < 139 Then 'don't process values that can't be correct Sempf(nickchannel) = Empf(nickchannel) - 100 'convert to values ranging from -37 to +37 End If If Empf(rollchannel) > 61 And Empf(rollchannel) < 139 Then 'don't process values that can't be correct Sempf(rollchannel) = Empf(rollchannel) - 100 'convert to values ranging from -37 to +37 End If If Empf(yawchannel) > 61 And Empf(yawchannel) < 139 Then 'don't process values that can't be correct Sempf(yawchannel) = Empf(yawchannel) - 100 'convert to values ranging from -37 to +37 End If If Empf(5) > 61 And Empf(5) < 139 Then 'don't process values that can't be correct Sempf(5) = Empf(5) - 100 'convert to values ranging from -37 to +37 End If
Gruß
Chris
Hatte mich ein wenig gespielt, mit Testumgebung:
Code:$Regfile = "m32def.dat" $Crystal = 4000000 $hwstack = 32 $swstack = 8 $framesize = 24 '( Isr_int0: If Channel > 0 And Channel < 6 Then Empf(channel) = Timer0 End If Timer0 = 6 Incr Channel Return ') Dim tmp as Byte Dim Empf(5) As Word Dim Channel As Byte Dim Empf_tmp As Word Do channel = 0 For tmp = 0 To 7 TCNT0 = 255 - tmp Gosub Isr_int0 Next tmp Loop Isr_int0: ' cycles in range: 53, out of range: 29 !PUSH R16 !IN R16, SREG !PUSH R16 !LDS R16, {channel} !DEC R16 !CPI R16, 5 !BRCC NotInRange !PUSH R17 !PUSH XL !PUSH XH LoadAdr Empf(1) , X !MOV R17, R16 !LSL R17 !ADD XL, R17 !CLR R17 !ADC XH, R17 !IN R17, TCNT0 !ST X+, R17 !CLR R17 !ST X, R17 !POP XH !POP XL !POP R17 !NotInRange: !INC R16 !INC R16 !STS {channel}, R16 !LDI R16, 6 !OUT TCNT0, R16 !POP R16 !OUT SREG, R16 !POP R16 Return '( Isr_int0: ' cycles in range: 51, out of range: 30 !PUSH R16 !IN R16, SREG !PUSH R16 !LDS R16, {channel} !DEC R16 !CPI R16, 5 !BRCC NotInRange !PUSH R17 !PUSH XL !PUSH XH LoadAdr Empf(1) , X !CLR R17 !LSL R16 !ADD XL, R16 !ADC XH, R17 !IN R16, TCNT0 !ST X+, R16 !ST X, R17 !POP XH !POP XL !POP R17 !NotInRange: !LDS R16, {channel} !INC R16 !STS {channel}, R16 !LDI R16, 6 !OUT TCNT0, R16 !POP R16 !OUT SREG, R16 !POP R16 Return ')Ich sehe nicht ohne Weiteres, wie groß die werden kann.die Variable Meanrx in Empf geschrieben wird
Diese Zugriffe dürften übrigens recht "teuer" sein in Bezug auf die Ausführungszyklen:
Wenn Bascom die Arrayadresse nicht zur Compilezeit kennt, wie bei einem durch Variable indizierten Array, so wird zu jedem Vergleich die gleiche Arrayzelle immer wieder neu geladen. Du könntest durch temporäre Variablen eine Beschleunigung der Rechnung erreichen.Code:If Empf(throttlechannel) > 61 And Empf(throttlechannel) < 139 Then 'don't process values that can't be correct Sempf(throttlechannel) = Empf(throttlechannel) - 61
Und da Du ein Word nicht atomar verarbeiten kannst, hättest Du auch ein Problem wenn im Wordarray tatsächlich Werte > 255 drinstehen würden.
Du kannst nicht verhindern (außer durch Sperren der Interrupts) dass der Interrupt gerade dann unterbricht, nachdem das erste Byte von Empf(x) zum Vergleich eingelesen wurde, die ISR Empf(x) dann beide Bytes verändert und nach Rückkehr das zweite Byte des nun veränderten Empf(x) zusammen mit dem ersten, nicht veränderten Byte weiterverarbeitet wird.
Also erstmal möchte ich dir frohe Weihnachten wünschen
Das finde ich sehr nett, dass du dir soviel Mühe gibst.
Meanrx liegt zwischen 63 und 137, das sind die beiden maximalen Knüppelstellungen. Allerdings stimmt das nicht ganz, da das ja ein Tiefpass ist und dieser normalerweise diese Extremwerte nicht erreichen kann. Eigentlich sehe ich keinen Grund, warum Empf kein Byte sein kann, aber ich habs mal probeweise eingespielt und da hats nicht funktioniert... Ich werds aber morgen nochmal probieren.
Hm, das habe ich mir schon gedacht. Aber wenns morgen mit einem Byte doch funktionieren sollte, dann ist das ja nicht mehr soooo schlimm, oder?
Also Werte > 255 werden nie im Empf-Array drinstehen.
Was genau meinst du mit temporären Variablen? So:
Oder so:Code:Dim Tmp1 As Word Dim Tmp2 As Word Dim Tmp3 As Word Dim Tmp4 As Word Dim Tmp5 As Word ... Tmp1 = Empf(1) Tmp2 = Empf(2) Tmp3 = Empf(3) Tmp4 = Empf(4) Tmp5 = Empf(5) If Tmp1 > 61 And Tmp1 < 139 Then Sempf(1) = Tmp1 - 61 Sempf(1) = Sempf(1) * 3 End If
Vielen Dank & GrußCode:Dim Tmp1 As Word Dim Tmp2 As Word Dim Tmp3 As Word Dim Tmp4 As Word Dim Tmp5 As Word Dim Stmp1 As Integer Dim Stmp2 As Integer Dim Stmp3 As Integer Dim Stmp4 As Integer Dim Stmp5 As Integer ... Tmp1 = Empf(1) Tmp2 = Empf(2) Tmp3 = Empf(3) Tmp4 = Empf(4) Tmp5 = Empf(5) If Tmp1 > 61 And Tmp1 < 139 Then Stmp1 = Tmp1 - 61 Stmp1 = Stmp1 * 3 End If Sempf(1) = Stmp1
Chris
Danke, das wünsch' ich Dir auch
Ist auch ein Thema, das mich interessiert.Das finde ich sehr nett, dass du dir soviel Mühe gibst.
Da ist's dann interessant wie Du das machst, poste doch mal den entsprechenden Code. Würde dann das Byte Empf(x) vor weiterer Verarbeitung einer temporären Word-Variable zuweisen....aber ich habs mal probeweise eingespielt und da hats nicht funktioniert... Ich werds aber morgen nochmal probieren.
Ist nicht schlimm, da scheinbar kein schädlicher Nebeneffekt auftritt, wenn Highbyte des Words immer 0 ist, gibt's auch kein Problem durch Interruptunterbrechung.Hm, das habe ich mir schon gedacht. Aber wenns morgen mit einem Byte doch funktionieren sollte, dann ist das ja nicht mehr soooo schlimm, oder?
Du verschwendest halt ein paar Bytes SRam und ein paar Zyklen.
Dann kann man die ISR ein wenig kürzer halten, siehe unten.Also Werte > 255 werden nie im Empf-Array drinstehen.
So:Was genau meinst du mit temporären Variablen? So:
Und genauso mit nick, roll und yaw.Code:Empf_Tmp = Empf(throttlechannel) Sempf_Tmp = Sempf(throttlechannel) If Empf_Tmp > 61 And Empf_Tmp < 139 Then 'don't process values that can't be correct Sempf_Tmp = Empf_Tmp - 61 Sempf_Tmp = Sempf_Tmp * 3 '==> values ranging from 3 (stick at bottom) to 228 (full throttle) Empf(throttlechannel) = Empf_Tmp Sempf(throttlechannel) = Sempf_Tmp End If
Du hast bemerkt, dass mein vorher geposteter Code dafür gedacht ist, im Simulator zu laufen ?
So kann ohne großartige Rumprobiererei am lebenden Objekt die ISR auf korrekte Funktion überprüft werden.
Wenn Probleme beim Vergleich Byte mit Word existieren, dann solltest Du Michaels Ratschlag zum Update nachkommen.
Hier der Bytearraycode:
Code:Dim Empf(5) As Byte ' ... Isr_int0: ' byte-array, cycles in range: 43, out of range: 28 !PUSH R16 !IN R16, SREG !PUSH R16 !LDS R16, {channel} !INC R16 !STS {channel}, R16 !SUBI R16, 2 !CPI R16, 5 !BRCC NotInRange !PUSH XL !PUSH XH LoadAdr Empf(1) , X !ADD XL, R16 !CLR R16 !ADC XH, R16 !IN R16, TCNT0 !ST X, R16 !POP XH !POP XL !NotInRange: !LDI R16, 6 !OUT TCNT0, R16 !POP R16 !OUT SREG, R16 !POP R16 Return
Geändert von MagicWSmoke (24.12.2011 um 20:36 Uhr)
Also, ich habs gerade nochmal probiert:
Es funktioniert doch, anscheinend hatte ich damals irgendwo einen Fehler...Code:Config Pind.2 = Input Portd.2 = 0 Config Int0 = Rising On Int0 Getreceiver Nosave Config Timer0 = Timer , Prescale = 256 On Timer0 Detectrxpause Nosave 'timer overflow = pause in receiver's signal Dim Empf(5) As Byte ... Getreceiver: 'byte-array, cycles in range: 43, out of range: 28 !PUSH R16 !IN R16, SREG !PUSH R16 !LDS R16, {channel} !INC R16 !STS {channel}, R16 !SUBI R16, 2 !CPI R16, 5 !BRCC NotInRange !PUSH XL !PUSH XH LoadAdr Empf(1) , X !ADD XL, R16 !CLR R16 !ADC XH, R16 !IN R16, TCNT0 !ST X, R16 !POP XH !POP XL !NotInRange: !LDI R16, 6 !OUT TCNT0, R16 !POP R16 !OUT SREG, R16 !POP R16 Return 'that means that there are problems with the receiver Detectrxpause: !PUSH R16 !IN R16, SREG !PUSH R16 !ldi R16, 0 !sts {channel}, R16 !POP R16 !OUT SREG, R16 !POP R16 Return
Habe jetzt auch den Timer0 Interrupt umgeschrieben, wäre nett, wenn du kurz drüberschauen könntest, obs so passt!? Fliegen tut das ganze
Meinst du, ich solle jetzt noch die Arrays mit den temporären Variablen verändern? Habs gerade mal probiert, mithilfe der Overlay Funktion würde kein zusätzlicher Speicher verbraucht.
Außerdem würde ich mir dann die Zuweisung tmpx <--> empf(x) sparen?!Code:Dim Tmp1 As Byte At Empf(1) Overlay Dim Tmp2 As Byte At Empf(2) Overlay Dim Tmp3 As Byte At Empf(3) Overlay Dim Tmp4 As Byte At Empf(4) Overlay Dim Tmp5 As Byte At Empf(5) Overlay
Hältst du das für sinnvoll?
Gruß
Chris
EDIT:
Hab gerade folgendes eingefügt:
Der Code funktioniert. Ich werde jetzt mal im Simulator testen, ob der Code dadurch schneller läuft. Melde mich dann wiederCode:Dim Tmp1 As Byte At Empf(1) Overlay Dim Tmp2 As Byte At Empf(2) Overlay Dim Tmp3 As Byte At Empf(3) Overlay Dim Tmp4 As Byte At Empf(4) Overlay Dim Tmp5 As Byte At Empf(5) Overlay Dim Stmp1 As Integer At Sempf(1) Overlay Dim Stmp2 As Integer At Sempf(2) Overlay Dim Stmp3 As Integer At Sempf(3) Overlay Dim Stmp4 As Integer At Sempf(4) Overlay Dim Stmp5 As Integer At Sempf(5) Overlay
EDIT2:
Hab gerade im Simulator folgendes probiert:
Beide IF-Abfragen brauchen incl. dem !Nop genau 34 Takte. Habe ich etwas anderes gemacht, als du gemeint hast oder bringts doch keine Besserung?Code:If Sempf(1) > -37 And Sempf(1) < 37 Then !nop End If If Stmp1 > -37 And Stmp1 < 37 Then !nop End If
Geändert von Che Guevara (24.12.2011 um 22:09 Uhr)
Schön
Speziell in diesem Fall kannst Du Dir das Sichern des SREGs sparen, denn weder LDI noch STS verändert das SREG. Würdest Du statt dessen !CLR R16 schreiben, wär's etwas anderes.Habe jetzt auch den Timer0 Interrupt umgeschrieben, wäre nett, wenn du kurz drüberschauen könntest, obs so passt!? Fliegen tut das ganze![]()
Code:Detectrxpause: !PUSH R16 !LDI R16, 0 !STS {channel}, R16 !POP R16 ReturnIch seh' jetzt nicht so recht, wie Du im gezeigten Noise-Filter Code mit Overlay arbeiten willst.Habs gerade mal probiert, mithilfe der Overlay Funktion würde kein zusätzlicher Speicher verbraucht.
Hältst du das für sinnvoll?
Wie sieht's den mit der Aufrufrate dieses Noise-Filter Codes aus ? Normalerweise sind solche Filter an ein Timing gebunden. Oder läuft der da so schnell er kann ?
Müsstest mal den Code extrahieren und alleine laufen lassen, um zu sehen wie viel Rechenleistung der frisst und ob es lohnt da viel Arbeit reinzustecken.
Edit:
Das hier kann der Compiler zur Compilezeit auflösen und es ist deshalb genauso schnell wie die Adressierung einer einzelnen Variable.
Das kann der Compiler nicht vorher auflösen, da er den Wert von "i" nicht kennt, das kostet mehr Code und Ausführungszeit:Code:If Sempf(1) > -37 And Sempf(1) < 37 Then
Code:If Sempf(i) > -37 And Sempf(i) < 37 Then
Lesezeichen