Der Schaltung läuft ab etwa 2,5V und verbraucht (je nach
Betriebsspannung) in Ruhe zwischen 2 und 4 mA. Im Powerdown sind es ca.
25µA.
Weitere Erläuterungen zur Software
Die Ansprechschwelle der Sensoren wird bei Programmstart
festgelegt. Der ADC-Wert am Punktsensor wird ein Mal gemessen und der
Messwert um 96 erhöht. Der Punktsensor darf in dieser Zeit nicht
berührt werden! Falls das doch mal versehentlich passiert sein sollte,
muss man einen Reset auslösen, indem man das Geschwindigkeitspoti kurz
auf Minimum dreht.
So arbeitet die Sensor-Routine:
Der ATtiny hat nur einen ADC, aber vier ADC-Pins. Sie werden
per Registerbefehl ("AdMux") mittels interner FET-Schalter einzeln auf
den ADC durchgeschaltet. Am eigentlichen ADC-Eingang hängt ein kleiner
interner "Sample&Hold"-Kondensator (da eine Messung in mehreren
Teilschritten erfolgt, soll er die Messspannung jeweils kurz
zwischenspeichern).
Der Sample&Hold-Kondensator wird zunächst entladen, indem der ADC
mit dem Befehl "AdMux" auf PB2 durchgeschaltet wird. PB2 wurde am
Anfang des Programms als Ausgang mit Pegel "low" konfiguriert.
Dann wird einer der beiden Sensorpins als Ausgang umgeschaltet
und auf "high" gelegt. Der Pin und die externe Sensorfläche bilden
einen Kondensator, der so auf Betriebsspannung geladen wird. Der Pin
wird nach kurzer Wartezeit als hochohmiger Eingang umkonfiguriert und
"floatet" dann. Die Parasitärkapazität ist aber noch auf
Betriebsspannung geladen.
Nun wird der floatende Pin per "GetADC"-Befehl an den
ADC-Eingang durchgeschaltet und lädt den Sample&Hold-Kondensator
des ADC auf, bis sich die Spannungen angeglichen haben. Da sich die
Ladung nun auf zwei Kondensatoren verteilt, sinkt die Spannung. Sie
wird dann gemessen.
Je nach Parasitärkapazität des Sensorkontaktes fliesst eine
unterschiedliche Ladungsmenge auf den Sample&Hold-Kondensator ab,
die Spannungen und damit die gemessenen ADC-Werte unterscheiden sich.
Im Leerlauf liegen sie z.B. um 600. Bei Berührung des
Sensorkontaktes steigt die resultierende Kapazität aus Sensorpin,
Sensorfläche und menschlichem Finger an. Es wird mehr Ladung
gespeichert und an den Sample&Hold-Kondensator abgegeben, sie
hebt die ADC-Werte gegenüber dem Leerlauf um z.B. 150 Schritte an.
Abfrage des Geschwindigkeitspotis
Der ADC-Wert wird von einer Konstanten abgezogen, um die
Drehrichtung des Potis umzukehren; höhere ADC-Werte führen so zu einer
Verkürzung der Punktdauer. Anschliessend wird der Wert durch 16
geteilt. Die Division erfolgt ressourcensparend per Schiebe-Befehl. Mit
den beiden Operationen ergibt sich ein Einstellbereich von ca. 17 - 50
WpM bzw. 85 -250 ZpM.
Sinuserzeugung
Um Programmspeicher zu sparen, wird der Sinus aus nur 64
PWM-Schritten gebildet. Mit "Waitus 16" ergibt sich eine Frequenz von
ca. 600 Hz. Nach jedem Durchlauf wird die Variable "Sndlen"
dekrementiert (also etwa alle 1,7 ms) bis sie Null ist; dann wird in
die Keyer-Routine zurückgesprungen. Der Wert für "Sndlen" hängt von der
eingestellten Punktlänge "Dit" bzw. dem daraus abgeleiteten Wert "Dah"
ab.
Auch die Pausen zwischen den Zeichenelementen werden über das
Sinus-Unterprogramm erzeugt. Damit die Zeiten für Punkte und
(punktlange) Pausen etwa gleich sind, durchläuft das Unterprogramm die
gleiche For-Next-Schleife, schreibt aber jeweils den Wert Null ins
PWM-Register.
Watchdog
Normalerweise soll ein Watchdog einen Reset auslösen, wenn er
nicht schnell genug periodisch durch ein Programm zurückgesetzt wird.
Dadurch soll gewährleistet werden, dass sich ein Programm nicht
unbemerkt für längere Zeit "aufhängen" kann.
Man kann den Watchdog aber auch über Registerbefehle zu einem
Timer umkonfigurieren (und nebenbei auf die maximale Ansprechzeit von 8
sec setzen).
Durch Ausprobieren stellte sich heraus, dass Bascom den
(undokumentierten?) Befehl "On Watchdog" versteht, mit dem man sehr
einfach die Interrupt-Routine anspringen kann (wie bei einem normalen
Timer-Interrupt). In der Bascom-Duku hatte ich ihn nicht gefunden.
Die Variable "offtimer" wird in der Interrupt-Routine ca. alle
8 Sekunden inkrementiert. Nach 251 Durchläufen wird der ADC
abgeschaltet (sonst verbleibt ein Ruhestrom), alle Ausgänge auf Eingang
geschaltet und der Controller in Powerdown geschickt.
Damit die Taste sich nicht ungewollt während der Benutzung
abschaltet, wird "offtimer" in der Keyer-Punkt-Routine nach jedem
gesendeten Punkt auf Null zurückgesetzt.
Quelltext mit Kommentaren:
' T13A-Sensorkeyer mit Sinusausgang
'
' Pinbelegung ATtiny13A:
' PB0 PWM-Ausgang, PB1 optionaler Schaltausgang fuer TRX-Tastung, PB2 frei (Sensor-ADC-Referenz),
' PB3 Punktsensor, PB4 Strichsensor
'
' Speed-Poti liegt an Adc0 / Reset. Werte unter halber Betriebsspannung loesen also Reset aus. Ist kein Bug,
' sondern Feature; dient zum Neukalibrieren bzw. zum Einschalten des Keyers.
' Ausgeschaltet wird ueber zweckentfremdeten Watchdog nach etwa 30 min Untaetigkeit
' Stromverbrauch mit 5V: 4mA / 6mA
' Stromverbrauch mit 2,5V: 1,7mA / 2,5 mA
'
' Lizenz: WTFPL - http://www.wtfpl.net/about/
' verwendete Programmierumgebung: BASCOM 2.0.7.9 Freeware-Version
$Regfile = "ATtiny13.dat"
$Crystal = 9600000 ' Taktfrequenz: 9,6 MHz
$Hwstack = 8 ' Platz fuer nur 4 Unterprogramme reserviert, spart SRAM
$Swstack = 0 ' wird nicht gebraucht
$Framesize = 0 ' dito
Clkpr = 128 ' Taktumschaltung auf 9,6 MHz
Clkpr = 0
Clkpr = 0
Dim Dit As Word ' Laenge Punkt
Dim Dah As Word ' Laenge Strich
Dim Sndlen As Word ' Zaehlvariable fuer Zeichen-/Pausendauer
Dim P As Byte ' "Punktspeicher"
Dim N As Byte ' Schleifenvariable fuer Sinus-Erzeugung
Dim Anadah As Word ' ADC-Wert fuer Erkennung Dah-Sensor
Dim Anadit As Word ' ADC-Wert fuer Erkennung Dit-Sensor
Dim Sa As Byte ' Amplitudenwert fuer PWM
Dim Refana As Word ' speichert nach Reset den Sensor-Leerlauf-Kalibrierwert
Dim Pause As Byte ' wenn 1, wird in Sinus-Unterprogramm PWM = 0 gesetzt
Dim Offtimer As Byte ' Zaehler fuer Abschaltautomatik
Config Timer0 = Pwm , Prescale = 1 , Compare A Pwm = Clear_up
' ' "Fast PWM" (37,5 kHz) per Registerbits konfigurieren:
Tccr0a.0 = 1 ' wgm00
Tccr0a.1 = 1 ' wgm01
Tccr0b.3 = 0 ' wgm02
Start Timer0
Acsr.acd = 1 ' Analog-Komparator ausschalten, spart etwas Strom
Config Adc = Single , Prescaler = Auto ' AD-Converter konfigurieren und starten
Start Adc
Ddrb = &B0000_0111 ' DDRB.0 ist Tonausgang; DDRB.2 ist der Pin der Sensor-ADC-Referenz
Portb = &B1110_0000 ' koennte man weglassen; ist eh Auslieferungszustand
Didr0 = &B00111111 ' Digitaleingaenge abschalten; spart Strom
On Watchdog Onwdt ' Interrupt-Routine fuer Watchdog-interrupt
' Watchdog als Interrupt-Quelle konfigurieren - WDCR: 7=WDTIF 6=WDIE 5=WDP3 4=WDCE 3=WDE 2=WDP2 1=WDP1 0=WDP0
Wdtcr = &B0001_1111 ' Schreiben auf WDTCR Vorbereiten
Wdtcr = &B0110_0001 ' Interrupt statt Reset, Watchdog- Timer auf 8 sec setzen
Sreg.7 = 1 ' Interrupts global freigeben
Waitms 200 ' Vorlaufzeit fuer den ADC
Gosub Ditsensor ' einmal ADC-Leerlaufwert am Punktsensor messen (Anpassung an Sensor)
Refana = Anadit + 96 ' Referenz 96 hoeher setzen
Do
Gosub Adclesen
Gosub Ditsensor
If Anadit > Refana Or P = 1 Then ' Punktsensor gedrueckt (PB3) oder Punkt gespeichert
P = 0 ' Punktspeicher loeschen
Pause = 0
Sndlen = Dit ' Zeichenelement mit Laenge "Dit" senden
Portb.1 = 1 ' Schaltausgang ein
Gosub Sinus
Portb.1 = 0 ' Schaltausgang aus
Pause = 1
Sndlen = Dit ' Pause nach dem Punkt
Gosub Sinus
Offtimer = 0 ' Watchdog-Zaehler bei Aktivitaet zuruecksetzen
End If
Gosub Dahsensor
If Anadah > Refana Then ' Strichsensor gedrueckt (PB4)
Pause = 0
Sndlen = Dah
PortB.1 = 1
Gosub Sinus
PortB.1 = 0
Gosub Ditsensor
If Anadit > Refana Then ' registrieren, wenn am Strichende bereits Punkt gedrueckt ist
P = 1 ' Punkt speichern
End If
Pause = 1
Sndlen = Dit ' Pause nach Strich
Gosub Sinus
End If
Loop
Sinus:
Do
Restore Sinusdata ' Zeiger auf Anfang der Data-Tabelle setzen
For N = 1 To 64
If Pause = 0 Then
Read Sa ' Tabellenwert lesen
Pwm0a = Sa ' der Wert in PWM0A bestimmt das Puls- / Pausenverhältnis
Else
Pwm0a = 0 ' statt Nachschlagen in Tabelle konstant 0
Waitus 3 ' Ausgleich dafuer, dass Nachschlagen etwas laenger dauert
End If
Waitus 16 ' Frequenz des Tones senken; 16µs -> 600 Hz
Next N
Decr Sndlen ' Software-Timer fuer Punkt- / Strichlaenge
Loop Until Sndlen = 0 ' Zeichenelement fertig
Return
Ditsensor:
Admux = 1 ' ADC1 (Referenz) an ADC-Eingang legen ; der muss auf Low liegen (bereits zu Anfang fest konfiguriert)
Portb.3 = 1 ' Pullup an Punktsensor ein
Ddrb.3 = 1 ' Punktsensor nun Ausgang --> Sensorpin laden
Waitus 32
Ddrb.3 = 0 ' Punktsensor wieder Eingang
Portb.3 = 0 ' Pullup an Punktsensor aus --> Sensorpin floatet
Anadit = Getadc(3) ' Punktsensor auslesen
Return
Dahsensor:
Admux = 1 ' ADC1 (Referenz) an ADC-Eingang legen
Portb.4 = 1 ' Pullup an Strichsensor ein
Ddrb.4 = 1 ' Strichsensor ist nun Ausgang
Waitus 32
Ddrb.4 = 0 ' Strichsensor wieder Eingang
Portb.4 = 0 ' Pullup an Strichsensor aus
Anadah = Getadc(2) ' Strichsensor auslesen
Return
Adclesen:
' Dit = 20: ~40 WpM Dit = 24: 25 WpM Dit = 64 11 WpM
' Mit 1280 und Rechts-Shift um 4: 17 WPM bis 50 WpM
Dit = Getadc(0)
Dit = 1280 - Dit ' 1280 = 1024 + 256
Shift Dit , Right , 4 ' entspricht Teilung durch 16, spart Flash-Speicher
Dah = Dit + Dit ' statt Multiplikation; spart Flash (78 bytes!)
Dah = Dah + Dit
Return
Onwdt:
Incr Offtimer ' alle 8 sec wird Offtimer incrementiert
If Offtimer > 250 Then ' nach 251 * 8 sec. erfolgt Powerdown
Stop Adc
DDRB = 0
' Powerdown
Mcucr = &B0011_0000 ' 4=1, 3=0: Powerdown 5=1 :Sleep enable
!Sleep
End If
Return
End
Sinusdata:
Data 0 , 0 , 2 , 5 , 9 , 14 , 21 , 28 , 36 , 46 , 56 , 66 , 78 , 89 , 101 , 114,
Data 127 , 139 , 151 , 163 , 175 , 186 , 197 , 207 , 216 , 225 , 232 , 238 , 244 , 248 , 251 , 253,
Data 253 , 253 , 251 , 248 , 244 , 239 , 232 , 225 , 216 , 207 , 197 , 187 , 175 , 164 , 151 , 139,
Data 127 , 114 , 102 , 90 , 78 , 67 , 56 , 46 , 37 , 28 , 21 , 15 , 9 , 5 , 2 , 0,
Da das Programm sehr gross ist, sollte beim Kompilieren des
Codes die Codeoptimierung von BASCOM eingeschaltet sein. Notfalls kann
man das beigefügte Hex-File verwenden, statt den Quelltext selber zu
kompilieren.
Betriebserfahrungen
Die Schaltung wurde etwa ein halbes Dutzend mal nachgebaut und
getestet. Die HF-Eigenschaften der "KW-Test-Version" scheinen
überraschend gut zu sein. Ein Tester verwendet eine endgespeiste
Antenne, deren "heisses" Ende direkt ins Shack geführt ist. Er konnte
bei 100W Sendeleistung keine Beeinflussung durch HF feststellen.
Das Geben mit Sensorpaddles ist zunächst etwas ungewohnt, weil schon
eine kleine drucklose Berührung reicht, um einen Sensor auszulösen. Es
gibt unterschiedliche Gebestile: bei manchen "fliegen die Finger" beim
Geben (die haben kaum Probleme), andere halten beim Geben dichten
Abstand zu den Paddles und lösen hier und da unbeabsichtigte Zeichen
aus (ich gehöre zu den letzeren). Das Überkleben mit einer dünnen
selbstklebenden Kunststoff-Folie kann die Empfindlichkeit etwas
reduzieren.
Bestechend finde ich jedoch, dass Sensorpaddles so robust und
einfach aufgebaut sind (und so gut wie nichts kosten). Ich hatte mir
zuvor einen Nachbau des Bencher BY2 Paddles von
MFJ beim
DARC-Verlag
gekauft.
Den MFJ-Nachbau fand ich ziemlich "wacklig" und schwer einzustellen
(allein schon die Inbus-Schrauben empfand ich als Zumutung), aber ich
habe keine Erfahrung mit Squeeze-Paddles anderer Hersteller.
Möglicherweise ist auch die Qualität des Bencher-Originals besser, denn
viele Nutzer "schwören drauf".
Einigen Testern war das Sensorpaddle zu dünn, sie haben das Paddle mit
allerlei kreativen Ideen "aufgepolstert", von Sessel-Teppichgleitern
bis zu alten Armbanduhrendeckeln ;)
Dieters provisorischer Aufbau
Claudios provisorischer Aufbau
Durchaus verwirrend ist, dass der Keyer sich nach etwa einer
halben Stunde Nichtbenutzung "schlafen legt". Wenn die Schaltung nicht
reagiert: erst mal das Geschwindigkeitspoti kurz auf Minimum drehen!
Download des Quellcodes: 0220-sinus-sensorkeyer.zip
Update:
Zu Hause sind die Masse meines Notebooks und die angeschlossene
PC-Peripherie mit dem Schutzleiter verbunden. Auch unterwegs verwende
ich meist ein Notebook-Netzteil mit 3-poligem 230V-Anschluss
(Kleeblatt-Buchse).
Im Urlaub hatte ich jedoch mal ein "no-name" Netzteil mit zweipoligem
230V-Flachstecker-Anschluss verwendet, und mit dem "spielte der
Sensor-Keyer verrückt".
In den Netzteilen sind meist Störschutz-Kondensatoren eingebaut, die
eine oder beide 230V-Anschlüsse mit der Niederspannungs-Masse des Netzteils
verbinden. Das Notebook liegt dann hochohmig auf 230V bzw. 115V
Wechselspannung, die Masse "floatet" also und bringt den Sensorkeyer
durcheinander.
Abhilfe: ich musste die Notebook-Masse provisorisch mit dem Schutzleiter
verbinden (Experimentierkabel mit Krokodilklemmen), danach "spielte"
der Sonsorkeyer wieder einwandfrei.