PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Ausgang mit 36khz modulieren. Wie?



Accenter
15.08.2013, 13:49
Ich sende mit einem Mega8 IR Codes aus. Die Fernbedienungen habe ich (da sie keinen RC5 Code senden) mit einem Audioprogramm und einer TSOP aufgezeichnen und analysiert. Die 36khz modulation erzeuge ich mittels PWM an einem zweiten Ausgangsport des Mega8. Nun suche ich eine Möglichkeit, dass ich das über nur einen Port hinbekomme. Geht das über PWM?

Hier mein Code:





$regfile = "m8def.dat"
$crystal = 8000000
$hwstack = 100
$swstack = 100
$framesize = 100

Config Pinb.0 = Output
Config Portb.1 = Output
Takt Alias Portb.1 '36khz takt moduliert über einen transistor
Irled Alias Portb.0 '3 IR LED's über einen zweiten transistor gesteuert

Dim Pwmwert As Word
Dim L As Byte
Dim H As Byte
L = 0
H = 1

Config Timer1 = Timer , Prescale = 1 , Compare A = Toggle , Clear Timer = 1
Pwmwert = 110
Compare1a = Pwmwert

Do
Wait 2
Gosub Sendecodeklimaanlage
Loop

Sendecodeklimaanlage:
Irled = H
Waitus 9000
Irled = L
Waitus 4500
Irled = H
Waitus 600
Irled = L
Waitus 600
Irled = H
Waitus 600
Irled = L
Waitus 600
Irled = H
Waitus 600
Irled = L
Waitus 600
Irled = H
Waitus 600
Irled = L
Waitus 600
Irled = H
Waitus 600
Irled = L
Waitus 600
Irled = H
Waitus 600
Irled = L
Waitus 1600
Irled = H
Waitus 600
Irled = L
Waitus 600
Irled = H
Waitus 600
Irled = L
Waitus 600
Irled = H
Waitus 600
Irled = L
Waitus 1600
Irled = H
Waitus 600
Irled = L
Waitus 1600
Irled = H
Waitus 600
Irled = L
Waitus 1600
Irled = H
Waitus 600
Irled = L
Waitus 1600
Irled = H
Waitus 600
Irled = L
Waitus 1600
Irled = H
Waitus 600
Irled = L
Waitus 600
Irled = H
Waitus 600
Irled = L
Waitus 1600
Irled = H
Waitus 600
Irled = L
Waitus 1600
Irled = H
Waitus 600
Irled = L
Waitus 600
Irled = H
Waitus 600
Irled = L
Waitus 1600
Irled = H
Waitus 600
Irled = L
Waitus 600
Irled = H
Waitus 600
Irled = L
Waitus 600
Irled = H
Waitus 600
Irled = L
Waitus 600
Irled = H
Waitus 600
Irled = L
Waitus 600
Irled = H
Waitus 600
Irled = L
Waitus 600
Irled = H
Waitus 600
Irled = L
Waitus 600
Irled = H
Waitus 600
Irled = L
Waitus 1600
Irled = H
Waitus 600
Irled = L
Waitus 600
Irled = H
Waitus 600
Irled = L
Waitus 1600
Irled = H
Waitus 600
Irled = L
Waitus 1600
Irled = H
Waitus 600
Irled = L
Waitus 1600
Irled = H
Waitus 600
Irled = L
Waitus 1600
Irled = H
Waitus 600
Irled = L
Waitus 1600
Irled = H
Waitus 600
Irled = L
Waitus 1600
Irled = H
Waitus 600
Irled = 0
Return

End

Torrentula
15.08.2013, 14:46
Du kannst den pin an dem du die PWM erzeugst auf Eingang schalten um den Ausgangstreiber (push-pull transistoren im IC) auszuschalten, dann dürfte keine PWM mehr am Pin anliegen (bei PICs würde das so funktionieren, bei AVRs bin ich mir da nicht sicher).

Alternativ könntest du die PWM ein- und ausschalten.

Accenter
15.08.2013, 16:38
danke! die pwm nur einzuschalten wenn ich ein high sende war die lösung. somit klappt alles über einen einzelnen port :-)

Searcher
15.08.2013, 17:58
Hallo, wenn Du die PWM über das COMA1 Bit ausschaltest, kann es sein, daß der Pin gerade high ist. Dann leuchtet die Sendediode ständig. Man könnte dann noch ein PORTB.1 = 0 hinterher schicken. Oder eben wie Torrentula schrieb, den Pin als Input konfigurieren. Wie hast Du es gemacht?

Gruß
Searcher

Accenter
15.08.2013, 19:25
Ich hatte genau dieses Problem, dass der Port gelegentlich auf high blieb. Habe mir dann wie im Codebeispiel zu sehen geholfen. Ist sicher nich die feine englische Art aber es läuft perfekt. Es wäre für mich ziemlich wichtig das waitus in einer Variablen zu haben damit ich die Wartezeit zwischen den Bits bei unterschiedlichen Fernbedienungen im Programm ändern kann. Leider klappt das bisher nur mit einer Konstante. Habe gelesen, bei einem schnelleren Quarztakt ist es auch mit einer Variablen möglich. Teste ich noch, bin aber auch für jeden anderen Tipp dankbar.

Hier der abgeänderte Code:




$regfile = "m8def.dat"
$crystal = 8000000
$hwstack = 200
$swstack = 200
$framesize = 200

Config Portb.1 = Output
Irled Alias Portb.1

Dim Pwmwert As Word
Dim L As Byte
Dim H As Byte
Dim Code1 As String * 120 , Stellenzaehler As Byte , Bitwert_str As String * 1 , A As Byte
L = 0
H = 1

Config Timer1 = Timer , Prescale = 1 , Compare A = Disconnect , Clear Timer = 1
Pwmwert = 110
Compare1a = Pwmwert
Const Bitlaenge = 600

Do
Wait 2
Gosub Sendecodeklimaanlage
Loop

Sendecodeklimaanlage:
Code1 = "11111111111111100000001010101010100101010010010010 01001010010010100101010101010100101001001001001001 001"
Gosub Auswertung
Return

Auswertung:
Stellenzaehler = Len(code1)
For A = 1 To Stellenzaehler
Bitwert_str = Mid(code1 , A , 1)
Select Case Bitwert_str
Case "1"
Gosub Sendehigh
Case "0"
Gosub Sendelow
End Select
Next A
Return

Sendehigh:
Config Timer1 = Timer , Prescale = 1 , Compare A = Toggle , Clear Timer = 1
Start Timer1
Waitus Bitlaenge
Stop Timer1
Config Timer1 = Timer , Prescale = 1 , Compare A = Disconnect , Clear Timer = 1
Return
Sendelow:
Waitus Bitlaenge
Return

End

Searcher
15.08.2013, 20:56
Es wäre für mich ziemlich wichtig das waitus in einer Variablen zu haben damit ich die Wartezeit zwischen den Bits bei unterschiedlichen Fernbedienungen im Programm ändern kann. Leider klappt das bisher nur mit einer Konstante.

Mit zB.
DIM Wartezeit as WORD
Wartezeit = 600
WAITUS Wartezeit
sollte es funktionieren. Soll ab BASCOM Version 1.12.. gehen. Bei mir kompilierte es mit Version 2.0.7.5. Hab es aber nicht real ausprobiert.




Sendehigh:
Config Timer1 = Timer , Prescale = 1 , Compare A = Toggle , Clear Timer = 1
Start Timer1
Waitus Bitlaenge
Stop Timer1
Config Timer1 = Timer , Prescale = 1 , Compare A = Disconnect , Clear Timer = 1
Return


Ist die Sendediode nach dem Compare_A = Disconnect wirklich immer aus? Wenn nicht, nach der Config Timer1 mit dem Disconnect Zeile noch PORTB.1 = 0 bzw IRLED = L hinzufügen. START TIMER1 und STOP TIMER1 ist eigentlich nicht notwendig.:confused:

PS. Fand die Idee mit Audioprogramm die Fernbedienung zu analysieren Klasse. Muß ich mir merken.

Gruß
Searcher

Accenter
15.08.2013, 21:41
Ich habe das mit der Wartezeit in der Variablen jetzt nochmal versucht. Ich höre da leider schon im laufenden Audioprogramm sofort, dass der Code nun anders abgespielt wird. Der Empfänger reagiert auch nicht. Ich werde das ganze mal mit einem 16Mhz Quarz testen, ich habe im Netz gelesen, dass waitus nur mit einer Variablen funktioniert wenn der Takt rasch genug ist. Habe auch versucht eine Schleife mit 1us einfach 600 mal durchzulaufen, leider hörte ich auch da sofort, dass die Tonhöhe der Codeaussendung nun nicht mehr stimmte.

Die IR Led ist immer zuverlässig aus auch ohne PORTB.1=0. Start und Stop Timer1 habe ich erfolgreich entfernt.

Die Idee mit dem Audioprogramm ist Gold wert! Habe so auch schon Funksignale ausgewertet. Es ersetzt einen Logicanalyzer und kostet fast nichts :-) Dank des Zeitlineals und der Werkzeuge wie kopieren, schneiden, einfügen usw. Kann man den Originalcode auf dem Linken Kanal sehen und seine eigenen Kopierversuche mit dem Atmel auf dem rechten (darunter). Man sieht so sofort wenn diese identisch sind.

Edit: Auch mit 16Mhz Takt kann ich keine Variable für waitus verwenden.

Torrentula
15.08.2013, 22:53
Du könntest versuchen einen Timer laufen zu lassen, der eben immer dann einen Overflow-Interrupt erzeugt, wenn du ein neues Bit senden willst. Du überprüfst dann deine Bitfolge (Nachricht) und schaltest die PWM ein oder aus je nachdem welchen Wert das nächste Bit hat.

Dies macht das ganze auch flexibler, du kannst zwischen den Interrupts dann andere Aufgaben mit der CPU erledigen, weil diese dann nicht einfach permanent NOP-Befehle abarbeitet.

peterfido
17.08.2013, 07:34
Ich arbeite mit der Schaltung vorn Lochraster.org. Da gibt es beim Punkt Etherrape nen Schaltplan mit einem optionalen IR-Sender. Diese Schaltung (http://www.lochraster.org/etherrape/images/etherrape-schematic.png) erzeugt bei mir die 36kHz.

Das eine Const anders reagiert als eine Variable liegt daran, dass bei einer Variable die Zeit gestreckt wird. Bei einer Const wird Bitlaenge vom Compiler gegen einen festen Wert getauscht.

Const Bitlänge = 600
waitus Bitlänge
wird zu
warte 600 us

Dim Vari as word
vari = 600
waitus vari
wird zu
Hole Wert aus der Speicheradresse Vari, warte vari us
also musst du die Zeit (Takte), welche der Controller braucht um Vari auszulesen, vorher schon abziehen.
Vari = 600 - Variholzeit

Accenter
17.08.2013, 09:49
Ich habe das ganze jetzt etwas umständlich (codeintensiv) aber dafür sehr genau arbeitend gelöst. Bitlänge und Modulationsfrequenz sind nun auch im Code-String enthalten. Ich kann so nun jeden IR Code von jeder Fernbedienung senden. Das ganze ist Teil meies Haussteuerungsprojektes. Ich kann nun von unterwegs Geräte daheim per Funk und IR Aussendung bedienen.

Da die wenigsten Fernbedienungen mit dem von Bascom unterstützten RC5 Protokoll funktionieren, kann dieser Code vielleicht auch für andere, die an ähnlichen Projekten arbeiten mal hilfreich sein.

Hier mein fertiger Code:




$regfile = "m8def.dat"
$crystal = 8000000
$hwstack = 200
$swstack = 200
$framesize = 200

Config Portb.1 = Output
Config Pinb.0 = Input
Taster Alias Pinb.0
Irled Alias Portb.1
Portb.0 = 1 'pullup'

Dim Pwmwert As Word
Dim L As Byte
Dim H As Byte
Dim Code As String * 120 , Stellenzaehler As Byte , Bitwert_str As String * 1 , A As Byte , Bitlaenge As Word , Bitlaenge_str As String * 3
Dim Khz As Word , Khz_str As String * 3
L = 0
H = 1
Config Timer1 = Timer , Prescale = 1 , Compare A = Disconnect , Clear Timer = 1
Pwmwert = 104 ' 110=36khz, 104=38Khz, 99=40Khz (wert im code string enthalten)

Do
Debounce Taster , 0 , Sendecodeklimaanlage , Sub
Loop

Sendecodeklimaanlage:
Code = "38600111111111111111000000010101010101001010100100 10010010010100100101001010101010101001010010010010 01001001" 'stelle 1-2 modulation in khz, stelle 3-5 bitlänge in us
Gosub Auswertung
Return

Satcodelauter:
Code = "3685011001100110101010011001011" 'stelle 1-2 modulation in khz, stelle 3-5 bitlänge in us
Gosub Auswertung
Return

Fernseherleiser:
Code = "38600111111100000001001001001010101010100100100101 010101010010010100101010101010100101001001001001" 'stelle 1-2 modulation in khz, stelle 3-5 bitlänge in us
Gosub Auswertung
Return

Auswertung:
Khz_str = Mid(code , 1 , 2) 'holt die modulationsfrequenz aus dem string (36,38 oder 40 Khz)
Khz = Val(khz_str)
Select Case Khz
Case 36
Pwmwert = 110
Case 38
Pwmwert = 104
Case 34
Pwmwert = 99
Case Else 'wenn wert unbekannt dann 38 Khz
Pwmwert = 104
End Select
Compare1a = Pwmwert
Bitlaenge_str = Mid(code , 3 , 3) 'holt die bitlänge aus dem string
Bitlaenge = Val(bitlaenge_str)
Stellenzaehler = Len(code) + 5
For A = 6 To Stellenzaehler 'von selle 6 weg die bits des sendecodes lesen und senden
Bitwert_str = Mid(code , A , 1)
Select Case Bitwert_str
Case "1"
Gosub Sendehigh
Case "0"
Gosub Sendelow
End Select
Next A
Config Timer1 = Timer , Prescale = 1 , Compare A = Disconnect , Clear Timer = 1 'am ende einer codeaussendung "disconnect" pwm damit die sendeled niemals an bleiben kann
Return

Sendehigh:
Config Timer1 = Timer , Prescale = 1 , Compare A = Toggle , Clear Timer = 1 'nur bei einem "high" die pulswellenausgabe aktivieren
Gosub Wartezeitbitlaenge 'variable wartezeit = bitlänge
Return

Sendelow:
Config Timer1 = Timer , Prescale = 1 , Compare A = Disconnect , Clear Timer = 1 'bei einem "low" erfolgt keine pwm ausgabe
Gosub Wartezeitbitlaenge 'variable wartezeit = bitlänge
Return

Wartezeitbitlaenge: 'waitus führt mit einer variablen zu starken abweichungen (auch mit 16Mhz takt), darum diese umständliche (aber genaue) lösung
Select Case Bitlaenge 'bitlänge: 850us technisat, 600us klimaanlage
Case 550
Waitus 550
Case 560
Waitus 560
Case 570
Waitus 570
Case 580
Waitus 580
Case 590
Waitus 590
Case 600
Waitus 600
Case 610
Waitus 610
Case 620
Waitus 620
Case 630
Waitus 630
Case 640
Waitus 640
Case 650
Waitus 650
Case 660
Waitus 660
Case 670
Waitus 670
Case 680
Waitus 680
Case 690
Waitus 690
Case 700
Waitus 700
Case 710
Waitus 710
Case 720
Waitus 720
Case 730
Waitus 730
Case 740
Waitus 740
Case 750
Waitus 750
Case 760
Waitus 760
Case 770
Waitus 770
Case 780
Waitus 780
Case 790
Waitus 790
Case 800
Waitus 800
Case 810
Waitus 810
Case 820
Waitus 820
Case 830
Waitus 830
Case 840
Waitus 840
Case 850
Waitus 850
Case 860
Waitus 860
Case 870
Waitus 870
Case 880
Waitus 880
Case 890
Waitus 890
Case 900
Waitus 900
Case 910
Waitus 910
Case 920
Waitus 920
Case 930
Waitus 930
Case 940
Waitus 940
Case 950
End Select
Return

End