Hallo *,
Ich habe ein externes Gerät was Signale in einfacher Codierung ausgibt.
(Zahlenblock mit Impulsverfahren). Betätigt man die 1 kommt ein Impuls,
betätigt man die 2 kommen zwei Impulse, u.s.w. Die Pause zwischen den
Impulsen einer Sequenz beträgt 100ms. Ich gehe (ungeprüft) davon aus,
das die Pause zwischen zwei Sequenzen entsprechend länger ist, betätigt
man 2 Zahlen direkt nacheinander,
Mein Mikrochip (ein ATmega328) soll die Codierung auslesen und die
betätigte Zahl in einer Variable vorhalten.
Am Ende benötige ich einen String mit der eingegebenen Zahlenfolge. z.B:
“367022143”
Meine grundsätzliche Idee ist es, bei einkommenden Signal an einem
DigitalPin in einen Interrupt zu springen. Wenn der State, den ich
definiere “off” ist, wird eine neue Sequenz gestartet. Der state wird
auf “on” gestellt. Eine Zählervariable wird auf 1 gesetzt.
wird der Nächste Interrupt unterhalb 101ms aufgerufen, wird die
Zählervariable um 1 erhöht.
Ein Timer wird gestartet, zählt dieser über 101ms wird die Sequenz als
beendet angesehen. Der state wird wieder auf “off” gesetzt und die
Zählervariable wird in die pressedNumber-Variable übertragen.
Vom Pseudo-Code her sehe ich das so.
**
// vars:
char state = 0;
int counterclick = 0;
int pressedNumber = 0;
// interrupts:
ISR(on_digital_in){
if state == 0
state = 1;
counterclick = 1;
else
++counterclick;
sequenz_end_timer
}
main {
loop{
- if(state == 1 && sequenz_end_timer > 101)
pressedNumber = counterclick;
state = 0
.. do something with pressedNumber
}
}
**
Soweit so gut.
Seht ihr hier schon designtechnische Probleme?
Wenn nicht, komme ich zu meinen spezifischen Fragen:
1. wie könnte man den Timer (sequenz_end_timer) realisieren?
2. An welchen PIN würdet ihr das Trigger-Signal anschließen und wie
bekomme ich einen Interruptaufruf hin? (Ich weiß die Frage ist sehr sehr
Basic, aber gibt es unterscheide für die Interrupt und den Pins an denen
ich die Komponenten anschließe?)
3. Meint ihr die Prüfung auf den Timepout im mainloop reicht aus, oder
muss ich den exakten Zeitpunkt der Flanke aus dem Register in der ISR
auslesen um diesen mit dem letzten zu vergleichen?
Vielen Dank für gedanklichen Input!
Peter
Peter Shaw schrieb:> Seht ihr hier schon designtechnische Probleme?
Ja.
Du wirst eine 1 nicht erkennen können.
Du musst den sequenz_end_timer bereits starten, wenn du die 'Sequenz'
als eröffnet ansiehst.
> Wenn nicht, komme ich zu meinen spezifischen Fragen:> 1. wie könnte man den Timer (sequenz_end_timer) realisieren?
Ähm.
Mit einem Timer?
> 2. An welchen PIN würdet ihr das Trigger-Signal anschließen
Ähm.
An jeden Pin deines µC der einen Interrupt bei Auftreten einer Flanke
generieren kann?
> und wie> bekomme ich einen Interruptaufruf hin?
ISR schreiben, spezifischen Interrupt konfigrieren und freigeben,
generellen Interrupt freigeben.
So wie man eben Interrupts in einem Programm benutzt.
> 3. Meint ihr die Prüfung auf den Timepout im mainloop reicht aus
Wenn sonst nicht viel in der mainloop im Millisekundenbereich passiert,
reicht das schon. Alternativ kann ja auch der Timer bei Ablauf der
"Sequence Zeit" seinerseits einen Interrupt auslösen.
>, oder> muss ich den exakten Zeitpunkt der Flanke aus dem Register in der ISR> auslesen um diesen mit dem letzten zu vergleichen?
Kann man auch machen.
Aber bei dir wird es keine allzugroße Rolle spielen, wenn du die Flanke
ein paar µs zu spät detektierst. Wenn du feststellen willst, ob die
Badezimmer Beleuchtung tagsüber kürzer oder länger als 5 Stunden brennt,
dann reicht es völlig aus, wenn du alle 15 Minuten mal nachsiehst ob sie
brennt. Selbst wenn Tochterherz mal kurz für 2 MInuten Haare kämmen
geht, verändert das die Antwort auf die Fragestellung ">5 Stunden"
nicht.
Wenn Du das Zeitraster genau kennst, kannst Du auch so vorgehen, auch
ganz ohne Interrupt:
1) Ziffer=0, polling nach der ersten Signalflanke
2) eins addieren
3) nach 101 ms wieder messen: Gibt es ein Signal? dann weiter bei 2),
sonst bei 4
4) ziffer speichern und weiter bei 1, so oft bis die gewünschte Anzahl
Ziffern beisammen ist.
Hallo Karl Heinz,
das mit den zwei Timern finde ich sehr schön. Was mir Codetechnisch
mangels Erfahrung mit ISR's noch nicht klar ist, ist wie ich im ersten
ISR, der auf die Flanke des Pins anspricht den Timer auf null zurück
setze, Denn ansonsten komme ich ja aus dem sync heraus.
Das mit der 1 ist mir jetzt auch klar. Danke! Setze diesen Aufruf
einfache einen tab nach vorne, dann ist er nicht in der Condition drin
:-)
Ich google mir mal das mit den Timern zusammen und versuche das zu
implementieren.
Velen Dank, auch an Rainer.
Die zweite möglichkeit finde ich nicht so gut, da so die Gefahr besteht,
das ich zwischen zwei Takten messe, oder? Ich weiß nicht wie lange die
Impulse sind.
ps
Peter Shaw schrieb:> Ich gehe (ungeprüft) davon aus,
Schon falsch.
Wilde Vermutungen enden immer in unnützer, weil fehlerhafter Arbeit.
Du mußt wissen:
- min/max Pulsdauer
- min/max Pulspause
- min/max Zahlenpause
- min/max Stringpause
Erst dann kann man anfangen zu überlegen.
Peter
Oder die Bekannten in die Gleichung einsetzen und versuchen ein Setup zu
etablieren um die Unbekannten herauszufinden.
Leider kann man nicht immer davon ausgehen, das die IWV's alle exakt
implementiert sind. Was ich weiß ist, dass die Impulspause 100ms
betragen muss. (laut Wikipedia)
Also, wenn länge der Pause und Umschaltimpuls klar sind, lässt sich die
Länge des Impulses messen, ist aber zum auslesen der gedrückten Nummer
relativ unspannend und kann vernachlässigt werden.
Das Stringende ist in einen Bereich zu legen, der menschlich als
angenehm empfunden wird und über der Tasten-End-Pause ist. >100ms < 5sec
(je nach Anwendungsfall)
Warum soll mich die Pulsdauer interessieren? Selbst wenn ich das per
Buttons lösen würde ist mir in dem Falle egal ob ich lange drücke oder
nur kurz. Ich habe einmal gedrückt. Wichtig ist zu unterscheiden ob es
zu der Sequenz gehört oder nicht.
Klingt als wolltest Du ein Impulswahltelefon abhören.. :-)
Miss doch einfach mal die Impulslänge. Du wirst die Impulse doch nicht
per Hand erzeugen wollen?
> Klingt als wolltest Du ein Impulswahltelefon abhören.
Genau das ist es! Ich brauche die alte Tastatur von dem POST Telefon als
Eingabe für etwas.
> Miss doch einfach mal die Impulslänge.
Zum Beispiel mit einem Modifizierten Code im uC. Ja. Dazu muss ich aus
dem Register den exakten Zeitpunkt des Flankenanstiegs auslesen.
(time = anstieg - last_anstieg)
Ich habe keine Ahnung wie ich das machen soll. Ich weiß, es gibt diesen
Wert im Register, aber worauf bezieht der sich? Auf Cycles des uC's
overall? Welche Timerinformation wird dort abgelegt? Kennt ihr eine gute
Doku/Referenz dazu?
Danke euch sehr!
ps
Peter Shaw schrieb:> Ich habe keine Ahnung wie ich das machen soll.
Daumenregel:
Wann immer in einem AVR-Programm es um Zeiten geht (mit Ausnahme von
sehr kurzen Zeiten im µs Bereich), ist praktisch IMMER ein Timer in
irgendeiner Form involviert!
Peter Dannegger schrieb:> Du mußt wissen:> - min/max Pulsdauer> - min/max Pulspause> - min/max Zahlenpause> - min/max Stringpause
Falls es sich um Impulswahl handelt:
Die FTZ-Richtline 1TR2 (Technische Forderungen an Endeinrichtungen zur
Anschaltung an Anschlüsse mit analogen Anschaltepunkten, Stand 06/1990)
dürfte wohl die exakteste Definition enthalten.
Ein Wahlimpuls war eine Schleifenunterbrechung, in den Pausen zwischen
den Impulsen war die Schleife geschlossen.
Prellzeiten des Kontakts <= 3 ms
Nenndauer:
Puls 60 ms
Pause 40 ms
Verhältnis Puls/Pause 1,6:1 (Nennwerte ergeben 1,5:1, könnte ein Fehler
in der Norm sein)
Toleranzen 1:
Puls 52..71 ms
Pause 32..46 ms
Verhältnis Puls/Pause min 1,4:1 und max 1,8:1
Toleranzen 2:
Puls 54..66 ms
Pause 36..44 ms
Verhältnis Puls/Pause min 1,45:1 und max 1,55:1
Toleranzen 3:
Puls 57..63 ms
Pause 38..42 ms
Verhältnis Puls/Pause min 1,45:1 und max 1,55:1
Ziffer 1: 1 Wahlimpuls
...
Ziffer 9: 9 Wahlimpulse
Ziffer 0: 10 Wahlimpulse
Dauer der Ziffer 0: 1000 ms +/- 100 ms
Pause zwischen zwei Ziffern min 650 ms und max. 1300 ms (der Maximalwert
gilt nur bei Wahl aus einem Speicher, nicht bei manueller Wahl)
Grüße
Stefan
Stefan Wagner schrieb:> Toleranzen 1 (...)
Da fehlt noch was: Der Toleranzbereich 1 war nur zulässig, wenn die
Wahlimpulse an der Vermittlungsstelle noch steilflankig genug ankamen
(kurze und ausreichend niederohmige Anschlussleitung). Je länger die
Anschlussleitung zur VSt, desto genauer musste der Geber sein (also
Toleranzgruppen 2 bzw. 3).
Grüße
Stefan
Stefan Wagner schrieb:> Pause zwischen zwei Ziffern min 650 ms und max. 1300 ms (der Maximalwert> gilt nur bei Wahl aus einem Speicher, nicht bei manueller Wahl)
Und woher weiß der Empfänger, ob die Wahl manuell oder aus einem
Speicher erfolgt? Das geht ihn überhaupt nichts an. Was soll also diese
Einschränkung beim Maximalwert.
Hallo,
vielen Dank für die tollen und mich wirklich weiterbringenden
Informationen.
Ich bin dann erstmal basteln!
Hoffe ich kann mich bald mit Erfolgen zurückmelden.
DANKE!
Michael A. schrieb:> Und woher weiß der Empfänger, ob die Wahl manuell oder aus einem> Speicher erfolgt? Das geht ihn überhaupt nichts an. Was soll also diese> Einschränkung beim Maximalwert.
Eine Begründung dafür steht in der Richtlinie nicht drin. (Siehe
Anlage.)
Als Hintergrund könnte ich mir auf Basis der eigenen Erfahrungen mit dem
FTZ (Zulassung mehrerer Telefone) vorstellen, dass da möglicherweise ein
gewisser unterschwelliger "Wunsch nach Ordnung" bestand.
Grüße
Stefan
Hallo,
ich habe mir ein kleines DEV-Board gebaut und alles so eingerichtet, das
ich arbeiten kann.
Ich denke mein Code ist ein Anfang mit dem ich nun loslegen kann um das
TWB75 auszulesen.
Da haben wir ein neues Problemchen. Ich bekomme es nach nun mehreren
Versuchen und nun völlig dusselig im Kopf nicht spielerisch heraus, wie
ich Weiß, Braun und Grün in eine Schaltung einsetze, das ich saubere
Flanken am uC Pin bekomme.
Testhalber versuche ich erstmal eine LED zum flackern zu bringen, ganz
ohne dev-board.
Dazu setze ich eine LED über 740Ohm an den Emitter eines Transistors.
Liegt nun positive Spannung am Base an, leuchtet das LED.
Gespeist wird der Schaltkreis über einen 9V Block.
Ich habe diesen Schaltkreis vom TWB75 gefunden:
https://dl.dropbox.com/u/4968298/schaltung792oe7.jpg kann damit aber
leider gar nichts anfangen, da ich zu unerfahren bin.
Wie würdet ihr denn vorgehen um herauszufinden, ob a) 9V ausreichen, b)
wie die Käbelchen nun anzuschließen sind, das ich die Unterbrechungen im
Stromkreis abgreifen kann?
Wäre schön, wenn ihr mir einige von euern Ideen schildern könntet.
Ich habe mal weiß an Vcc und braun an die Base angeschlossen, die über
einen 10k-Ohm Wiederstand zu ground fließt. Manchmal flackert das LED so
oft wie es soll, aber unzuverlässig. Ich muss die Taste ein Weilchen
gedrückt halten das es funktioniert, drücke ich zulange bekomme ich zwei
Sequenzen.
Ich habe hier ein Video davon. Währe klasse wenn ihr mir sagen könnt,
wie ich das verbessern kann um ein zuverlässigeres Verhalten zu
erzeugen: http://www.youtube.com/watch?v=lfUu7I-gIDM
Anbei mal mein Code (für später, wenn ich ein Vernümpftiges Flackern der
LED hinbekommen habe): Kritik ist gerne angenommen.
1
//
2
// main.c
3
// TWB75_ReadKey
4
//
5
// Firmware for readaing a TWB75 "impulse encoded keypad" into integer.
6
// - If a sequenz is in detection mode the green led is on
7
// - If a number is detected the red led showing the number n flashing n times
8
//
9
// Created by Peter Shaw
10
// Copyright (c) 2013. No rights reserved.
11
//
12
13
#ifndef F_CPU
14
#define F_CPU 16000000UL /* Quarz mit 16.0000 Mhz */
15
#endif
16
17
#define true 1 // logical TRUE = 1
18
#define false 0 // logical FALSE = 0
19
20
#define LED_RED 0b00000001 // PIN Register for the red led
21
#define LED_GREEN 0b00000010 // PIN Register for the green led
22
23
24
#include<avr/io.h>
25
#include<avr/interrupt.h>
26
#include<util/delay.h>
27
#include<stdint.h>
28
29
inti;// counter, just a incrementing counter.
30
volatileuint8_tcountImpulse;// count how many impules knocks on PIN.4
31
volatileuint8_tdetectedNumber;// Number that is detected from a sequence
32
volatileuint8_ttimerOverflowCount;// count how often the timer.0 overflows
33
// while the sequenz is running. Used to
34
// detect the end phase.
35
volatilecharisSequenceRunning;// Is currently a sequenz is detected ond read from
36
// PIN, or is the sequenz ended/not started?
37
volatilecharisNumberDetected;// is a new number detected and can be print out?
38
39
/**
40
* On the dev-board there are two
41
* static led's a red one and a
42
* green one.
43
* This routine flashes one off
44
* the static leds.
45
* ---------------------------- //
46
*
47
*/
48
voidblink_led(intled){// toggle a PIN on PortB for any blink call
49
PORTB|=led;// LED on
50
_delay_ms(150);
51
PORTB&=~led;// toggle LED off
52
_delay_ms(300);
53
return;
54
}
55
56
/**
57
* This routine turns on one off
58
* the static leds.
59
* ---------------------------- //
60
*
61
*/
62
voidturn_led_on(intled){// set a PIN on PortB for
63
PORTB|=led;// trurn LED on
64
return;
65
}
66
67
/**
68
* This routine turns off one off
69
* the static leds.
70
* ---------------------------- //
71
*
72
*/
73
voidturn_led_off(intled){// set a PIN on PortB for
74
PORTB&=~led;// trurn LED off
75
return;
76
}
77
78
79
/**
80
* Service Interrupt Routine for
81
* state change on PIN.4
82
* ---------------------------- //
83
* On any state change this ISR is called immediately
84
*
85
*/
86
ISR(INT0_vect){
87
isSequenceRunning=true;// turn or hold sequenz running
88
++countImpulse;// Increment
89
90
// Start sequenz-off timer
91
TCNT0=0x00;// set timer.0 to initial 0
92
TCCR0B=(1<<CS02);// start timer0 with /256 prescaler
93
94
return;
95
}
96
97
/**
98
* Service Interrupt Routine for
99
* timer.0 overflow
100
* ---------------------------- //
101
* Timer 0 is a 8 bit timer
102
* 16MHZ, PreScaler 256 are 245.0980 overflows per second, so 24.5098 overflows must detect
103
* in 100ms
104
*
105
* On timer overflow (255 -> 0) this ISR is called immediately
106
*/
107
ISR(TIMER0_OVF_vect){
108
++timerOverflowCount;
109
if(timerOverflowCount>=25&&
110
isSequenceRunning==true){// over 100ms
111
// end of sequenz detected.
112
detectedNumber=countImpulse;// set the detected number
113
isNumberDetected=true;// tell the mainloop that there is a new number available
114
countImpulse=0;// reset the sequence counter
115
timerOverflowCount=0;// reset the overflow counter
116
// stop the timer! the timer will be enable after a new tick
117
// is detected.
118
isSequenceRunning=false;// Tell the mail loop that there is no sequenz running
119
TCCR0B=0;// Stop sequenz-off timer
120
}
121
return;
122
}
123
124
/**
125
* MAIN Routine
126
* ---------------------------- //
127
*
128
*/
129
intmain(void){
130
131
DDRB=0xFF;// set up pin direction PortB as Output
132
PORTB=0xFF;// Turn all LEDs off
133
134
DDRD&=~(1<<DDD2);// Clear the PD2 pin / PIN.4
135
// PD2 (PCINT0 pin) is now an input
136
137
PORTD|=(1<<PORTD2);// turn On the Pull-up
138
// PD2 is now an input with pull-up enabled
139
140
EICRA|=(1<<ISC00);// set INT0 to trigger on ANY logic change
141
EIMSK|=(1<<INT0);// Turns on INT0 interrupt routine
142
143
144
145
TIMSK0|=(1<<TOIE0);// Enable overflow interrupt for timer.0
146
147
sei();// Turn interrupts on
148
149
// Tell the user that i am on - Say hello!
150
for(i=0;i<5;++i){// Blink 3 times
151
PORTB^=0xFF;// toggle PortB
152
_delay_ms(100);
153
}
154
// LED IS OFF
155
156
isSequenceRunning=false;// no sequenz is running
157
isNumberDetected=false;// is a new number available?
158
detectedNumber=0;// set the last detected number to 0
159
160
// MAINLOOP
161
while(1){
162
163
/* Debugging Code */
164
/* Show the last detected number in blinking the control LED once
Peter Shaw schrieb:> Ich habe diesen Schaltkreis vom TWB75 gefunden:> https://dl.dropbox.com/u/4968298/schaltung792oe7.jpg kann damit aber> leider gar nichts anfangen, da ich zu unerfahren bin.
Hallo Peter,
das ist der Stromlaufplan des Telefons "FeAp 79" ("Fernsprechapparat
79"). Der Tastwahlblock ist nur das kleine Modul ganz oben.
Da du wohl kein "Teleföner" bist, hier ein paar "Basics" zum besseren
Verständnis:
1. Die Leitung zur Vermittlungsstelle liegt an den Klemmen La und Lb.
Dort werden (je nach Technik) 48 bis 60 V DC eingespeist. Der
Leitungswiderstand liegt im Bereich mehrerer 100 Ohm bis etwas über 1
kOhm. Hinzu kommt der Innenwiderstand des Telefons. Du hast also eine
Stromschleife, in der (über den Daumen) 30 bis 60 mA fließen.
Normalerweise sollte La den negativen Pol darstellen, durch
Aderntauscher kann das aber auch mal gedreht sein.
2. Für die Impulswahl wird die Leitung durch den "Nummernschalter"
(Wählscheibe bzw. Tastwahlblock) kurzzeitig unterbrochen (Wahlimpuls).
Impulsdauer und Pausen hab ich ja schon genannt. Während der Wahl wird
bei einigen Schaltungen zusätzlich die Sprechschaltung kurzgeschlossen,
um vorübergehend den Schleifenstrom zu maximieren.
Die Anschlüsse des Tastwahlblock sind also a) ein unterbrechender
Kontakt (macht die Wahlimpulse) und b) ein schließender Kontakt
(schließt die Sprechschaltung kurz).
Anschließen musst du ihn über einen Vorwiderstand an das Klemmenpaar des
unterbrechenden Kontakts. Welche das sind, werde ich gleich mal aus dem
etwas verwinkelten Stromlaufplan herauszeichnen.
Grüße
Stefan
Stefan Wagner schrieb:> Welche das sind, werde ich gleich mal aus dem> etwas verwinkelten Stromlaufplan herauszeichnen.
So, das ging schneller, als angenommen.
Klemme 1 (weiße Ader) liegt an La
Klemme 2 (braune Ader) geht weiter an die Sprechschaltung
Klemme 3 (grüne Ader) geht an Lb
Klemme 4 (gelbe Ader) geht an die (optionale) Erdleitung (dazu unten
mehr)
Damit müsste das die minimale Beschaltung sein:
1
____
2
+xx V --| Rv |--+-o Wahlimpuls
3
---- |
4
|
5
--o Kl 1 (ws)
6
o Kl 2 (bn)
7
--o Kl 3 (gn)
8
| o Kl 4
9
|
10
---
Eventuell musst du Klemme 2 zusätzlich über 1,2 kOhm mit Klemme 3
verbinden (Simulation der Sprechschaltung.
Rv solltest du so einstellen, dass der Tastwahlblock noch sicher
funktioniert. Bis zu welchem Schleifenstrom herunter das der Fall ist,
weiß ich nicht. Eventuell wirst du mit 12V nicht hinkommen, denn Rv darf
nicht zu niederohmig werden (Überlastung des Arbeitskontakts!) Kleine
TK-Anlagen speisen mit 28 oder 36 V, das könnte aber schon knapp sein.
48 V sollte eigentlich immer gehen.
Deinen Code schau ich mir nachher an.
Grüße
Stefan
Hi Stefan,
> PS: Sorry für den Monolog...
Nein! Super! :-) Du hast mich gerade sehr glücklich gemacht. Ich "taper"
mal zurück in meine Bastelecke und überlege wie ich nun mit so viel V
umgehen soll.
Mehr als 12 habe ich noch nie benutzt, bzw gar kein Netzteil dafür. Ich
muss mal online-stores abklappern. Tipps gerne zu mir.
Danke für die weitreichende Erklärung. Ich werde sie wohl heute noch
zwei drei mal lesen um sicher ´zugehen auch alles mitnehmen zu können.
Danke,
peter
Hallo Stefan,
ahh ok, jetzt habe ich das schon wesentlich stabiler am Ausgang.
Ich brauch noch etwas (muss mir ein neues Debugging Board bauen) und
gerade irrwitzig viel um die Ohren beruflich. Hoffe ich kann nächste
Woche nochmal auf Dich zukommen mit Detailfragen.
Danke,
ps
Peter Shaw schrieb:> Hoffe ich kann nächste> Woche nochmal auf Dich zukommen mit Detailfragen.
Aber bitte!
Wir wollten ja auch noch über die beste Realisierung der eigentlichen
Auswertung sprechen. Ein Tipp vorab: Vergiss den externen Interrupt. Ein
regelmäßiges Abtasten des des Signals in einem festen Zeitraster (z.B.
1ms) bietet wesentlich mehr Aussicht auf Erfolg. Der Timerinterrupt ist
dein Freund.
Grüße
Stefan
ok, bissel spät, aber ich musste mir noch ein Testgerät bauen und
firmeware (https://github.com/petershaw/AnalyzerDude) schreiben und wie
das eben so ist...
HIer schon mal ein kleiner Erfolg... läuft unter 12V. Ich muss alles
noch ein wenig stabilisieren, aber dann kommt die Zeichnung und das
Löten :-)
Kleines Erfolgsvideo:
https://www.youtube.com/watch?v=Nzu0kjGdvls
ps
Hi Stefan,
so. Nun steht das Board zwischen ATmega und TWB75.Die Funktionsweise ist
stabil und ich bekomme klare und saubere Signale.
Vieleicht kannst du mal drüber schauen, solange ich an der
Codeerweiterung bastel.
Vielen Dank,
peter