Forum: Mikrocontroller und Digitale Elektronik 1 Servosignal - 4 Schaltzustände


von Andreas F. (mad_devil)


Lesenswert?

Hallo zusammen,

durch einiges Einarbeiten und ein paar Codesnippets ist es mir mit 
folgendem Code gelungen einen Servoausgang eines RC Empfängers dazu zu 
benutzen um 2 Ausgänge zu schalten. Mit den Positionen Stick oben und 
stick unten.

Erst mal der Code (teilw. aus RCline.de / Danke an dieser Stelle):
1
'======================================================
2
'System-Einstellungen
3
'======================================================
4
'Definition für Mega 8
5
$regfile "m32def.dat"
6
7
'Angabe der Taktfrequenz (8Mhz)
8
$crystal = 8000000
9
10
'Einbindung der LCD-Bibliothek für ein 2-Prozessor-Display
11
$lib "lcd4e2.lbx"
12
13
'======================================================
14
'Konfigurationen
15
'======================================================
16
17
'Konfiguration der I/O-Ports´s
18
Config Portc = Output
19
Config Portd = Input
20
Config Porta = Output
21
22
'Angabe der Display-Größe
23
Config Lcd = 20 * 4
24
25
'Konfiguration des Timer1
26
Config Timer1 = Timer , Prescale = 1
27
28
'Konfiguration des INT0
29
'Interrupt bei jedem Flankenwechsel (0->1 und 1->0)
30
Config Int0 = Change
31
32
'======================================================
33
'Deklarationen
34
'======================================================
35
36
'Variable für Umschaltung der Displayhälfte - Namen so lassen!
37
Dim ___lcde As Byte
38
39
Dim Reading As Bit
40
Dim Bargraph As Word
41
Dim Bargraph_old As Word
42
Dim Rc_value As Word
43
Dim Calc As Word
44
Dim Location As Word
45
Dim Error As Bit
46
'neue Variable als Speicher
47
Dim Leichtoben As Bit
48
'Dim Oben As Bit
49
Dim Leichtunten As Bit
50
'Dim Unten As Bit
51
Dim Zaehler1 As Byte
52
Dim Zaehler2 As Byte
53
54
'======================================================
55
'Initialisierungen
56
'======================================================
57
58
'Zuweisung der Interrupt-Service-Routinen
59
On Int0 Rc_read
60
On Timer1 Rc_error
61
62
'Timer-Freigabe
63
Enable Timer1
64
Stop Timer1
65
66
'Freigabe der Interrupt-Routinen
67
Enable Int0
68
Enable Interrupts
69
70
71
'Umschaltung auf die obere Hälfte
72
___lcde = 0
73
74
'Das Display löschen
75
Cls
76
'Text der ersten Zeile (max. 27 Zeichen!)
77
Locate 1 , 1
78
Lcd "**TEST**"
79
80
Waitms 1000
81
82
'Text der ersten Zeile löschen dann neu schreiben
83
Cls
84
Locate 1 , 1
85
Lcd "RC-KANAL"
86
87
Locate 2 , 1
88
Lcd "*LESEN* "
89
'Den Cursor ausschalten
90
Cursor Off
91
92
Waitms 2000
93
94
95
'Umschaltung auf die untere Hälfte
96
___lcde = 0
97
98
Cls
99
Locate 1 , 1
100
Lcd "Timer:  "
101
102
Waitms 1000
103
104
'Den Cursor ausschalten
105
Cursor Off
106
107
108
'======================================================
109
'Hauptprogramm-Schleife
110
'======================================================
111
112
Do
113
114
115
116
' Ausgang PA.2 schalten Knüppel leicht runter------------------------------------
117
If Rc_value >= 13000 And Leichtunten = 0 Then
118
119
Zaehler1 = 0
120
121
Do
122
Incr Zaehler1
123
Waitms 100
124
Loop Until Rc_value < 13000 Or Zaehler1 = 20
125
If Zaehler1 = 20 Then
126
127
Toggle Porta.2
128
Leichtunten = 1
129
Waitms 500
130
End If
131
End If
132
133
If Rc_value < 13000 Then
134
Leichtunten = 0
135
End If
136
137
138
139
' Ausgang PA.3 schalten Knüppel leicht oben--------------------------------------
140
If Rc_value <= 11800 And Leichtoben = 0 Then
141
142
Zaehler2 = 0
143
144
Do
145
Incr Zaehler2
146
Waitms 100
147
Loop Until Rc_value > 11800 Or Zaehler2 = 20
148
If Zaehler2 = 20 Then
149
150
Toggle Porta.3
151
Leichtoben = 1
152
Waitms 500
153
End If
154
End If
155
156
If Rc_value > 11800 Then
157
Leichtoben = 0
158
End If
159
160
161
162
'LCD-Ausgabe während der langen Lesepause...
163
If Reading = 0 Then
164
165
'Den Timerwert ausgeben
166
   Locate 2 , 1
167
   Lcd Rc_value ; "     "
168
169
170
171
End If
172
Loop
173
174
'Programmende (nur formal)
175
End
176
177
'======================================================
178
'ISR für INT0 - R/C-Kanal lesen
179
'======================================================
180
Rc_read:
181
'Den Timer starten mit steigender Flanke
182
If Reading = 0 Then
183
   Start Timer1
184
   Reading = 1
185
   Toggle Portc.0
186
'Den Timer stoppen mit fallender Flanke
187
Else
188
   Stop Timer1
189
   Rc_value = Timer1
190
   Timer1 = 0
191
   Reading = 0
192
   Toggle Portc.1
193
End If
194
'Error-Bit rücksetzen
195
Error = 0
196
Return
197
198
'======================================================
199
'ISR für Timer1 - Fehlerhandling
200
'======================================================
201
Rc_error:
202
'Error-Bit setzen
203
Error = 1
204
Reading = 0
205
Stop Timer1
206
Rc_value = 12000
207
208
Return

wie kann ich es allerdings realisieren das ich entweder zwei mal oben 
tippen kann um noch einen Kanal zu schalten oder bei einer anderen 
Position zu schalten.

hatte vorher im code die werte für 4 Schaltstellungen also oben 
leichtoben leichtunten und unten.

hier wurde aber zb bei oben immer der leichtoben ausgang mitgeschaltet.

Jemand ne idee dazu? PS noch frohe "Restweihnacht"

von Hannes L. (hannes)


Lesenswert?

Beitrag "Re: BASCOM AVR - Problem mit den Outputs (ATMega 8 und STK500)"

Schau Dir mal die "Gaak"-Versionen an, da kannst Du bestimmt was draus 
machen.

...

von Andreas F. (mad_devil)


Lesenswert?

Hi danke für den tip hab mir "gaak" 1-3 mal angeschaut. Ist aber leider 
ein komplett anderes funktionsprinzip und nicht direkt übertragbar.

Wäre gut wenn mir jemand  sagen könnte warum immer die halbe Stellung 
mitgeschaltet wird obwohl ich den Wertebereich eingegrenzt hatte.

Danke für Vorschläge.

von Hannes L. (hannes)


Lesenswert?

A. F. schrieb:
> Ist aber leider
> ein komplett anderes funktionsprinzip

Eben, und deshalb funktioniert es auch...

Mit Deiner Waitms-Orgie kann ich mich nicht anfreunden.

Wenn man mit einem "besseren" Controller als Tiny13 (also einem mit 
16-Bit-Timer und ICP-Interrupt) einen Servoimpuls auswerten will, dann 
bietet sich folgendes Vorgehen an:

- Servoimpuls auf ICP-Eingang legen
- 16-Bit-Timer mit 1 MHz Timertakt starten und durchlaufen lassen
- ICP-Interrupt auf steigende Flanke einschalten (freigeben)

Damit löst der ICP-Interrupt erstmal bei jedem Beginn eines 
Servoimpulses einen Interrupt aus, also alle 20 ms. Das reicht aber noch 
nicht, denn man will ja die Impulsbreite wissen. Also muss man auch die 
fallende Flanke erkennen. Die Interrupt-Service-Routine (ISR) muss daher 
Folgendes tun:

- prüfen, ob es die steigende oder fallende Flanke war
- wenn steigende Flanke, dann:
  - Zeitstempel (ICR1-Register) als Startzeit sichern
  - Interrupt auf fallende Flanke umstellen
- wenn fallende Flanke, dann:
  - Zeitstempel holen
  - Startzeit davon subtrahieren
  - Ergebnis als Impulsbreite sichern
  - Interrupt wieder auf steigende Flanke umstellen
  - Merker setzen, der dem Hauptprogramm sagt, dass ein neuer Impuls
    angekommen ist.

Dies bewirkt, dass etwa alle 20 ms ein neuer Wert in Impulsbreite steht 
und der Merker gesetzt wird.

Das Hauptprogramm prüft nun (neben anderen Aufgaben) diesen Merker und 
verzweigt bei gesetzem Merker zu einem Unterprogramm. In diesem 
Unterprogramm ist Folgendes zu tun:

- Merker löschen, damit der Job bis zum nächsten Impulsende nur
  einmal ausgeführt wird
- Impulsbreite mit dem Bereichsraster vergleichen und daraus die
  Nummer des Bereichs ermitteln (z.B. 0=Neutral, 1=halbhoch,
  2=ganzhoch, 3=halbrunter, 4=ganzrunter)
- ermittelte Bereichsnummer mit (gemerkter) Nummer der letzten
  Runde vergleichen, dann neue Bereichsnummer für nächste Runde
  merken
- Bei Ungleichheit Prellzähler auf Startwert setzen
- Bei Gleichheit Prellzähler vermindern, falls er noch nicht 0 ist
- Erreicht dabei der Prellzähler 0, dann ist die Bereichsnummer
  gültig, dann wird die Funktion ausgelöst. Dies geschieht am
  besten auch über Merker und ggf. Nummer

Damit wird erreicht, dass eine Aktion erst ausgeführt wird, wenn eine 
bestimmte Anzahl von Impulsen im selben Bereich (der Impulsdauer) direkt 
hintereinander aufgetreten ist. Das schnelle Überfahren der 
Halb-Bereiche beim Betätigen des Knüppels auf den Voll-Bereich reicht 
somit nicht mehr zum Auslösen einer Aktion. Da die Impulse im Abstand 
von etwa 20 ms eintreffen, wird dieses Unterprogramm alle 20 ms 
ausgeführt, der Prell-Zähler hat daher eine Auflösung von 20 ms pro 
Zählschritt.

Man hat hiermit den Telegrammabstand (des Senders) zum Synchronisieren 
der Entprellung missbraucht und sich jegliches Waitms gespart. In der 
Zeit zwischen den Aufrufen dieses Unterprogramms kann sich der 
Controller um andere Aufgaben kümmern.

Dieser 20ms-Takt (Telegrammabstand) kann auch noch für andere Dinge 
genutzt werden, z.B. für das Abzählen von Verzögerungszeiten für Blinker 
oder auch für das Abzählen eines Timeouts, in dem ein Rückstellen auf 
Bereich 0 (Neutralstellung) und ein erneutes Einstellen des Bereiches 
eine weitere Aktion auslösen darf (z.B. Hochzählen einer Aktionsnummer, 
die bei Ablauf dieses Timeouts ausgeführt wird).

...

von Andreas F. (mad_devil)


Lesenswert?

Hi vielen dank für das feedback ich werde mal versuchen nach diesem 
Ansatz Vorzugehen.
Werde mich erstmal mehr in die ganze icp isr Sache reinlesen müssen. Ich 
werde mich bei Erfolg oder auch Misserfolg wieder melden. Soweit erst 
mal danke.

Nur noch eine Frage zum Verständnis. Ist in dem gaak Programm dieser icp 
isr Ansatz denn besser enthalten oder gibt es dazu beispielprogramme?

Gruß ps und guten rutsch zusammen

von Hannes L. (hannes)


Lesenswert?

A. F. schrieb:
> Ist in dem gaak Programm dieser icp
> isr Ansatz denn besser enthalten oder gibt es dazu beispielprogramme?

Nein, Gaak läuft auf dem Tiny13, der hat nur einen 8-Bit-Timer, der auch 
kein ICP kann.

Gaak diente dazu, eine mit einer Zweikanalanlage ausgestattete Ente mit 
zusätzlichen Features (Soundmodul, Wechselblinker, evtl. 
Waschanlagenpumpe mit Spritzdüse im Schnabel) auszustatten und diese mit 
schnellen Bewegungen des Ruders zu steuern.

Der ICP-Interrupt (Input-Capture) ist eine Spezialform eines externen 
Interrupt, bei dem der Zählerstand des Timers bereits beim Auftreten des 
Ereignisses (in das ICPx-Register) kopiert wird. Somit ändert die 
Aufrufzeit des Interrupts (kann länger dauern, wenn gerade die ISR eines 
anderen Interrupts abgearbeitet wird) nichts am Messwert, obwohl der 
Timer inzwischen weitergelaufen ist.

Man kann statt des ICPs auch einen externen Int oder einen PCI 
(PinChange) verwenden und in der ISR den Timerwert abfragen. Das kann 
aber aufgrund unterschiedlicher Interrupt-Reaktionszeiten Jitter 
erzeugen. Bei einem Schaltmodul, das die Impulsbreite nur in groben 
Schritten rastern muss, stört das aber nicht weiter.

...

von Andreas F. (mad_devil)


Lesenswert?

Hi hab jetzt das ein oder andere versucht. Leider reichen meine 
rudimentären Programmierkenntnisse nicht so ganz aus um etwas 
verwertbares hinzubekommen. Gibt's dazu irgendwo ein paar code schnipsel 
an denen ich mich lang hangeln könnte. Vorzugsweise in bascom.
Danke dir / euch.

Ach und noch frohes neues.

von Hannes L. (hannes)


Lesenswert?

Mit unverstanden zusammenkopierten Codeschnipseln wird das sicher auch 
nichts.

Vielleicht solltest Du ja erstmal mit kleineren Dingen beginnen und Dich 
nach und nach in die Materie einarbeiten. Rom ist auch nicht an einem 
Tag erbaut worden.

...

von Andreas F. (mad_devil)


Lesenswert?

Hi,
also ganz so schlimm ist es nicht. Es ist ja nicht so als ob ich gar 
nicht verstehe um was es wie geht.
Mir fehlt nur gerade der Ansatz.
Das erste Programm ist ja abgewandelt aus dem rc line forum.
Dort gibt es ja auch das Programm "Auswertung eines Nautic Expert 
Bausteins".

Das kommt denke ich im Ansatz mit dem hin was du mir geschrieben hast.

Soweit kann ichs auch grob verstehen und umsetzen.

Was ich allerdings nicht verstehe sind solche Passagen:
1
'======================================================
2
'Festlegung der remanenten Schaltsignale
3
'======================================================
4
5
'1: Remanent  0: Nicht remanent (dem Schalter folgend)
6
7
'Beispiel:
8
'Schalter 1 nach oben und Schalter 8 nach unten
9
'sind remanent, der Rest folgt den Schaltern
10
11
'Nach oben:     87654321
12
Remanent_up = &B00000001
13
14
'Nach unten:    87654321
15
Remanent_dn = &B10000000

Ich denke bei diesem Modul wird über verschiedene Schalterstellungen 
mehrerer Schalter eine Aktion erzeugt.
Ich denke das ist mehr wie Auflösung eines Summensignals was hier 
gemacht wird.

Wenn ich das jedoch richtig verstehe ist der Ansatz der gleiche nur das 
ich nunmal nicht mehrere Kanäle auswerte sondern nur einen.

Zumal denke ich das hier mit Hardcodierten Werten gerechnet wird was ich 
als unvorteilhaft erachte.

Wie hier:
1
'======================================================
2
'Synchronisationsschleife
3
'======================================================
4
Syncronize:
5
Signals = 1
6
N = 1
7
Sync_detect = 0
8
X = 0
9
Cls
10
Lcd "Syncronisiere..."
11
12
'Rücksetzen aller Schaltersignale
13
For X = 0 To 7
14
   Switch_up.x = 0
15
   Switch_dn.x = 0
16
Next X
17
18
X = 0
19
20
'Warten auf ersten Synchronisationswert
21
While Sync_detect = 0
22
Wend
23
24
N = 2
25
Sync_detect = 0
26
27
'Warten auf zweiten Synchronisationswert
28
'Begrenzt durch Zählschleife
29
While X < 5000 And Sync_detect = 0
30
   Incr X
31
Wend
32
33
'Auswertung des Synchronisationsergebnisses
34
If X < 5000 And Rc_value(1) > 8000 And Rc_value(2) > 8000 Then
35
   N = 3
36
   Signals = 10
37
Else
38
   Goto Syncronize
39
End If

von STK500-Besitzer (Gast)


Lesenswert?

A. F. schrieb:
> Ich denke bei diesem Modul wird über verschiedene Schalterstellungen
> mehrerer Schalter eine Aktion erzeugt.
> Ich denke das ist mehr wie Auflösung eines Summensignals was hier
> gemacht wird.

Um meine Lateinlehrerin zu zitieren: "Denken ist bei manchen 
Glückssache!"
So ein Nautik-Modul überträgt seine Signale ähnlich wie ein PPM-Sender 
als Kette mit gewissen Synchronisationsinformationen - nur nicht auf dem 
primären Kanal, sondern so, als würde man bei jedem Umlauf ein neues 
Servosignal schicken.

Dein Problem ist aber eher, dass du mit einem Kreuzknüppel-Kanal (also 
nur eine Richtung) 5 Zustände übertragen willst.

Du musst enfach die Pulslänge deines Servokanals messen und dann auf 
Grenzwerte vergleichen.
Da kannst du auch feste Werte benutzen. Die Signale sind i.d.R. zwischen 
1 und 2 ms lang.
Allerdings solltest du noch eine "Entprellung" einbauen. Wenn du nämlich 
die äusseren beiden "Kontakte" anwählst, musst du auf jeden Fall die 
Grenze der inneren überschreiten. Auch bei einer kurzen Wahl, würde 
dieser Kontakt dann schalten.
5-10 Zyklen sollten reichen.

Ich lasse mir bei solche Geschichten gerne erst mal die Pulslängen über 
die serielle Schnittstelle ausgeben.
Das wäre zumindest eine gute Übung, sich Programmierkenntnisse 
anzueignen ;)

von Andreas F. (mad_devil)


Lesenswert?

Hi

also wie ein Servosignal aussieht weiß ich bereits (20ms lang mit 
Offsets und High als Stellimpulse. Finde gerade die passende Seite nicht 
aber ist bekannt. Wurde hier ja auch schon ausreichend behandelt :-) )
Gibt ja einige Informationsquellen dazu.

In meinem im ersten Beitrag genannten Programm mache ich das ja so 
ähnlich.
Ich Messe das Signal mit nem Timer und gebe den Wert je Position des 
Knüppels auf dem LCD aus.

Und das Problem das der "Halbausschlags-Kanal" bei Vollausschlag 
mitgeschaltet wird ist ja genau das was bei mir aufgetreten ist.
Und meine "Entprellung" funktionniert ja nicht.

So ist dieser Thread ja gewachsen. Ich versuche jetzt aus diesem Grund 
den Ansatz von Hannes Lux umzusetzen was mir leider etwas schwer fällt.

Danke aber trotzdem schonmal allen die sich bis hier beteiligt haben.

Ich weiß das sehr zu schätzen. Kann auch verstehen das es nicht immer 
einfach ist auf immer die selben Fragen zu antworten und das es auch 
keine Patentlösung gibt.

Das komplett ausgeklügelte Programme nicht vorgekaut werden kann ich 
natürlich auch verstehen (wäre auch nicht wirtschaftlich für die die 
Ahnung haben ;-) ).

Allerdings lässt sich für mich daraus ableiten das das Interesse an so 
einer Universalschaltung für Viele (Modellbauer) sehr groß ist.

von Andreas F. (mad_devil)


Lesenswert?

Die eigentliche Idee ist es ein Programm zu entwerfen was folgendes 
macht:

1. Universell an jedem Empfänger-Servokanal einsetzbar

2. Einen Proportionalkanal (Stick) zum Schalten zu verwenden
   denke 4 Funktionen sind realistisch, störungsfrei umsetzbar

3. Automatische Nullstellungserkennung

Evtl. erweiterbar auf folgende Funktionen:

- Zweiten Propkanal hinzufügen um dadurch 4 weitere Funktionen steuern 
zu
  können

- evtl. Haltefunktion / Tipfunktion also Stick nach oben Tastent Funkt.1
  Stick oben halten > 2sekunden Funkt.2 jeweils bei erneuter Betätigung
  wieder ausschalten.

Dies ergäbe 8 Funktionen pro Propkanal (erweiterbar ;-) )

von STK500-Besitzer (Gast)


Lesenswert?

A. F. schrieb:
> also wie ein Servosignal aussieht weiß ich bereits (20ms lang mit
> Offsets und High als Stellimpulse.

Das Interessante am Servosignal sind nicht die 20ms, sondern die 
Pulslänge von 1-2ms.

A. F. schrieb:
> Das komplett ausgeklügelte Programme nicht vorgekaut werden kann ich
> natürlich auch verstehen (wäre auch nicht wirtschaftlich für die die
> Ahnung haben ;-) ).

Dann würdest du ja auch nichts lernen.

A. F. schrieb:
> Die eigentliche Idee ist es ein Programm zu entwerfen was folgendes
> macht:
> 1. Universell an jedem Empfänger-Servokanal einsetzbar

solange es ein Proportionalkanal ist, ist da auch kein Problem. Die 
meisten Schaltkanäle (auch nichts anderes als ein Proportionalkanal bloß 
mit festen Werten)

> 2. Einen Proportionalkanal (Stick) zum Schalten zu verwenden
>    denke 4 Funktionen sind realistisch, störungsfrei umsetzbar
Denke ich auch.

> 3. Automatische Nullstellungserkennung
Was meinst du damit?
Wenn dein Stick federbelastet ist, stellt der sich sowieso in die Mitte.

> Evtl. erweiterbar auf folgende Funktionen:
> - Zweiten Propkanal hinzufügen um dadurch 4 weitere Funktionen steuern
Gab es schon von Conrad...

> - evtl. Haltefunktion / Tipfunktion also Stick nach oben Tastent Funkt.1
>
>   Stick oben halten > 2sekunden Funkt.2 jeweils bei erneuter Betätigung
>
>   wieder ausschalten.
geht alles...


> Dies ergäbe 8 Funktionen pro Propkanal (erweiterbar ;-) )
alles schöne,erfüllbare Wünsche.

Noch mal zu den 20ms: Das ist ja die Periodendauer. Also wird alle 20ms 
ein aktuelles Signal gesendet. Wenn du jetzt über mehrere Perioden die 
Impulsdauern miteinander vergleichst, hast du eine Entprellung.

Quasi so:
setze zähler = 5
schleifenbeginn:
ist die Pulsdauer <1,2ms dekrementiere zähler
springe zu schleifenbeginn, solange zähler>0
schalte den Ausgang ein.

Das wäre jetzt ein Pseudocode für eine Grenze. Wie könnte der Rest 
aussehen?

von Karl H. (kbuchegg)


Lesenswert?

A. F. schrieb:

> also wie ein Servosignal aussieht weiß ich bereits (20ms lang mit
> Offsets und High als Stellimpulse. Finde gerade die passende Seite nicht
> aber ist bekannt. Wurde hier ja auch schon ausreichend behandelt :-) )

Natürlich.
Die 20ms interessieren keinen. Alles was interessiert ist: wie lange ist 
das Signal high.

> Ich Messe das Signal mit nem Timer und gebe den Wert je Position des
> Knüppels auf dem LCD aus.

Na das ist doch schon mal was.

> Und das Problem das der "Halbausschlags-Kanal" bei Vollausschlag
> mitgeschaltet wird ist ja genau das was bei mir aufgetreten ist.
> Und meine "Entprellung" funktionniert ja nicht.

Ich will jetzt nicht groß raufscrollen und mir die Stelle suchen.
Aber was ist denn das Problem?

Du hast 4 Zeitbereiche, in denen dein Signal fallen kann (wenn du ein 
Signal hast).
Also klassifizierst du die gemessene Zeit erst mal in den jeweiligen 
'Schaltbereich'. Das sind 3 if bedingungen mit zugehörigem else

Jetzt weißt du in welchem Schaltbereich sich der Knüppel jetzt gerade 
befindet. Den übernimmst du aber nicht gleich als den gültigen, sondern 
erst dann wenn er eine bestimmte Anzahl oft aufgetreten ist. D.h. du 
hast eine weitere Variable in der du dir den zuletzt gesehenen 
Schaltbereich merkst. Stimmt der jetzt festgestellte mit dem zuletzt 
gesehenen überein, dann erhöhst du einen Zähler (wegen der 
Übereinstimmung) und wenn der Zähler eine gewisse Grenze überschreitet, 
dann übernimmst du diesen Schalteberich als den aktiven. Stimmen die 
beiden nicht überein, dann setzt du den Zähler wieder auf 0 zurück. Das 
ganze läuft also darauf hinaus: Nur wenn ich x mal hintereinander den 
Schaltbereich y übertragen bekomme, dann gilt der auch, weil dann der 
Knüppel aufgehört hat sich zu bewegen. Denn wenn er sich weiter bewegen 
würde, dann würde sich ja der Wert (entweder die Zeit oder eben der 
davon abgeleitete Schaltbereich) ändern.


> Ich weiß das sehr zu schätzen. Kann auch verstehen das es nicht immer
> einfach ist auf immer die selben Fragen zu antworten und das es auch
> keine Patentlösung gibt.

Schwer ist es vor allen Dingen immer wieder akzeptieren zu müssen, dass 
Leute immer denken, programmieren ist was, das man an einem Nachmittag 
lernt.
Vor das Wollen haben die Götter das Können gestellt. Es reicht nicht, 
wenn man ein Projekt machen WILL. Man muss es auch KÖNNEN. Und das muss 
man eben lernen. Ging uns nicht anders als Dir.

von Andreas F. (mad_devil)


Lesenswert?

STK500-Besitzer schrieb:
>> 3. Automatische Nullstellungserkennung
> Was meinst du damit?
> Wenn dein Stick federbelastet ist, stellt der sich sowieso in die Mitte.

Ich meine das er den aktuellen ?Timer?-Wert der beim Einschalten in 
Nullstellung des Sticks automatisch als Nullstellung erkennt bzw sich 
merkt.

>> Evtl. erweiterbar auf folgende Funktionen:
>> - Zweiten Propkanal hinzufügen um dadurch 4 weitere Funktionen steuern
> Gab es schon von Conrad...

Ok das versteh ich jetzt nicht? Der Link geht auf die Con*** Startseite

Karl Heinz Buchegger schrieb:

>> Und das Problem das der "Halbausschlags-Kanal" bei Vollausschlag
>> mitgeschaltet wird ist ja genau das was bei mir aufgetreten ist.
>> Und meine "Entprellung" funktionniert ja nicht.
>
> Ich will jetzt nicht groß raufscrollen und mir die Stelle suchen.
> Aber was ist denn das Problem?
>
> Du hast 4 Zeitbereiche, in denen dein Signal fallen kann (wenn du ein
> Signal hast).
> Also klassifizierst du die gemessene Zeit erst mal in den jeweiligen
> 'Schaltbereich'. Das sind 3 if bedingungen mit zugehörigem else

Hier nochmal ein Auszug aus dem Programm:
1
' Ausgang PA.2 schalten Knüppel leicht runter------------------------------------
2
If Rc_value >= 13000 And Leichtunten = 0 Then
3
4
Zaehler1 = 0
5
6
Do
7
Incr Zaehler1
8
Waitms 100
9
Loop Until Rc_value < 13000 Or Zaehler1 = 20
10
If Zaehler1 = 20 Then
11
12
Toggle Porta.2
13
Leichtunten = 1
14
Waitms 500
15
End If
16
End If
17
18
If Rc_value < 13000 Then
19
Leichtunten = 0
20
End If

Eigentlich dachte ich das wäre nach diesem Prinzip.

Wenn der passende Ausschlag erreicht und gehalten wird, wird der 
Zaehler1 hochgezählt. Geschaltet wird dann auch nur wenn der Wert so 
lange da war bis Zaehler1 den Wert 20 hat sonst wird nicht geschaltet.

Und oben wird nicht nur der Rc_value abgefragt mit > sondern auch ob der 
Ausgang nicht evtl. schon geschaltet wurde.

von Karl H. (kbuchegg)


Lesenswert?

A. F. schrieb:
> STK500-Besitzer schrieb:
>>> 3. Automatische Nullstellungserkennung
>> Was meinst du damit?
>> Wenn dein Stick federbelastet ist, stellt der sich sowieso in die Mitte.
>
> Ich meine das er den aktuellen ?Timer?-Wert der beim Einschalten in
> Nullstellung des Sticks automatisch als Nullstellung erkennt bzw sich
> merkt.

Machs nicht so kompliziert!
Du weißt doch ungefähr, welche Zeit da kommt! Es sind ca. 1.5ms

Du hast anscheinend noch nicht behirnt, dass du deinen Knüppelweg 
sowieso in 5(!) Bereiche aufteilen musst (so wie ich das verstanden 
habe)

Knüppel in Mittelstellung:   nix passiert
Knüppel zu 50% nach oben ausgeschlagen (+/- 25%)  Schalter 1 umsschalten
Knüppel geht wieder zurück auf Mitte: Der nächste Schaltvorgang wird 
scharf gestellt.
etc.
etc.

d.h. du bewegst den Knüppel aus der Mitte heraus in eine 'Endposition', 
hältst den Knüppel ein wenig, bis der Schaltvorgang kommt und dann lässt 
du den Knüppel wieder zurück zur Mitte.

Denn wie willst du denn sonst 2 mal hintereinander denselben 
Schaltvorgang auslösen?

Also hast du 5 Bereiche, in denen der Knüppel sein kann.
Und da du großzügige Bereiche wählst, hast du natürlich auch einen 
großen Bereich, in dem der Knüppel in Mittelstellung ist.
Ergo: Ob das jetzt 1.5ms, oder 1.51ms oder 1.48ms sind, ist doch völlig 
wurscht.

von Karl H. (kbuchegg)


Lesenswert?

> Eigentlich dachte ich das wäre nach diesem Prinzip.


Deine ewigen waitms treiben uns das Adrenalin ins Blut.



Nein.
Du misst EINEN Puls aus.
Wenn du das Ergebnis der Pulslänge hast, dann stellst du fest, was du 
damit machen sollst.
Nicht warten!

loop

  Pulslänge messen

  if Pulslänge ist im Bereich 1
    neue mögliche Schaltstellung = 1

  else if Pulslänge ist im Bereich 2
    neue mögliche Schaltstellung = 2

  else if Pulslänge ist im Bereich 3
    neue mögliche Schaltstellung = 3

  else if Pulslänge ist im Bereich 4
    neue mögliche Schaltstellung = 4

  else if Pulslänge ist im Bereich 5
    neue mögliche Schaltstellung = 5

  else
    Schaltstellung = 6 ; weil es kein gültiger Puls war


  if neue mögliche Schaltstellung gleich vorhergehender Schaltstellung
    Erkannt = Erkannt plus 1
  else
    Erkannt = 0

  vorhergehende Schaltstellung = neue mögliche Schaltstellung

  if Erkannt größer als 50
    if Schaltstellung ist gleich 1 UND Schalten Erlaubt gleich 1
      schalte Ausgang 1 um
      Schalten Erlaubt = 0

    if Schaltstellung ist gleich 2 UND Schalten Erlaubt gleich 1
      schalte Ausgang 2 um
      Schalten Erlaubt = 0

    if Schaltstellung ist gleich 3
      Schalten Erlaubt = 1

    if Schaltstellung ist gleich 4 UND Schalten Erlaubt gleich 1
      schalte Ausgang 4 um
      Schalten Erlaubt = 0

    if Schaltstellung ist gleich 5 UND Schalten Erlaubt gleich 1
      schalte Ausgang 5 um
      Schalten Erlaubt = 0

end loop


so circa.
Noch feiner kann ich es dir nicht mehr machen, denn dann würde ich dir 
schon dein Programm schreiben. Und das will ich nicht.

von Andreas F. (mad_devil)


Lesenswert?

Ja hab ich im Programm auch so gemacht. In dem von mir geposteten fehlen 
noch 2 Schalterstellungen. Mittelstellung ist bei Ca 12000.
Eigentlich steht drin:

Größer 13000 toggle kanal1

Größer 14000 toggle kanal2

Kleiner 11000 toggle Kanal 3

Kleiner 10000 toggle Kanal 4

Habe aber kein else für nullstellung drin.

von Andreas F. (mad_devil)


Lesenswert?

Es soll mir hier auch keiner mein Programm schreiben. Ich will es ja 
auch selbst hinbekommen. Nur habe ich den Ansatz ja so wie von dir 
beschrieben.

Das das mit dem waitms nicht ok ist habe ich mittlerweile verstanden ist 
halt im Post noch so drin sorry.

von Karl H. (kbuchegg)


Lesenswert?

NB:
Hannes würde den Puls mittels ICP ausmessen. Würde ich auch so machen.

Da du allerdings keine allzugroße Genauigkeit brauchst und der µC auch 
sonst nichts zu tun hat, würde ich an deiner Stelle das BASCOM Mittel 
PULSIN einsetzen um den Puls auszumessen.

Zumindest fürs erste.

von STK500-Besitzer (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> NB:
>
> Hannes würde den Puls mittels ICP ausmessen. Würde ich auch so machen.

dito, aber in C... ;)

A. F. schrieb:
>> Gab es schon von Conrad...
> Ok das versteh ich jetzt nicht? Der Link geht auf die Con*** Startseite

da hast du ein "Bug"/Feature der Forensoftware gefunden.
Ich habe nur den Namen zitiert und keinen Link mitgegeben.
Das sollte nur ein Hinweis darauf sein, dass es möglich ist, das System 
zu erstellen.

von Andreas F. (mad_devil)


Lesenswert?

ok wenn ich mich jetzt damit auseinandersetze und so viele tips von euch 
bekomme dann versuche ich es schon mit icp umzusetzen.

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
Noch kein Account? Hier anmelden.