PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : IR-Schaltung geht nicht



ShadowPhoenix
22.05.2004, 12:40
Hallo!
Ich benutze den ATmega8, und habe eine korrekt angesteuerte IR Sende Diode und einen TSOP1376 IR Empfänger, der auch korrekt angesteuert ist.
Dann habe ich einen 12MHz Quarz, der zwei AVR's versorgt. (Das geht doch, oder?)

Nun hier den SENDECODE:


$regfile = "m8def.dat"
$crystal = 12000000
Const Startbyte = 00000001
Dim Zusenden as byte
Ddrb.1 = 0

Senden:
Zusenden = Startbyte
Portb.1 = Zusenden
Goto senden


Hier der EMPFÄNGERCODE:


$regfile = "m8def.dat"
$crystal = 12000000
Dim gelesen as byte
Ddrd.2 = 0

Do
Gelesen = Portb.2
if gelesen = 00000001 then portb.5 = 1 else portb.5 = 0
loop


Warum funktioniert das nicht?
Die LED an portb.5 flackert nur manchmal, aber das auch, wenn die IR-Strecke unterbrochen ist!
@Gottfreak: Dein Code funktioniert auch irgendwie nicht.
Ich bin total am verzweifeln, es geht garnichts.

MfG,
ShadowPhoenix[/code]

22.05.2004, 12:49
Hallo

Was willst du denn erreichen ??

Bei der Sende Routine solltest du denn Port auch auf Ausgang schalten.

Beim Empfangen solltest du anstatt PORTB.2 mal PINB.2 versuchen.

Ist dir klar, was das Programm macht, wenn es dann läuft ?

Mfg

ShadowPhoenix
22.05.2004, 12:52
@Gast

Sorry, ich kenne mich eben noch nicht so gut aus.
Ja, das Programm sendet dann ständig das Byte "00000001" an den
Empfänger. Dieser lässt dann die LED leuchten.
Wie siehst du das?

MfG,
ShadowPhoenix

22.05.2004, 12:59
Wie kommst du denn darauf ??

"Ja, das Programm sendet dann ständig das Byte "00000001" an den "

Beim senden wird dein dein Port aus 1 gesetzt und das wars.

Modulierst du die LED denn mit 36 KHz ? Sonst empfängt der TSOP 1736 eh nichts.

"Gelesen" kann doch nur 0 oder 1 werden

ShadowPhoenix
22.05.2004, 13:00
Ich dachte, es wird dann 10000000 gesendet!
Wie kann man denn Bytes senden?

MfG,
ShadowPhoenix

22.05.2004, 13:05
Wieso soll er das denn senden ? Weil die Variable zusenden heißt ?

So einfach geht das mit bascom aber auch nicht.

Du mußt deine Variable, die du senden willst, Bit für Bit abfragen, ob 1 oder 0 und dann entsprechend reagieren.

Beim Empfang genau so, da hast du aber noch andere Probleme. Finden des Starts, Timming, Fehler und so.

Versuche erstmal, nur zu senden. So langsam, das du an einer normalen LED sehen kannst ob es klappt.

ShadowPhoenix
22.05.2004, 13:06
Hmm, eigentlich habe ich vor, den ADDLink zu benutzen, und dann bytes zu übertragen.
So hätte ich eine Fernsteuerung mit vielen Kanälen.
Weisst du wie das realisierbar ist?

MfG,
ShadowPhoenix

22.05.2004, 13:11
Habe mit ADD Link noch nicht gearbeitet, ist mir auch zu teuer.

Du kannst auch mit der LED soviele Kanäle steuern wie du willst.

Aber ein paar Grundlagen, mußt du dir schon erabeiten. Dazu gehört halt auch, wie man ein Byte seriell sendet und empfängt. Brauchst du eh immer wieder. Und so schwer ist das nicht. Es hilft dir nichts, wenn das eine nicht klappt, das nächste auszu probieren.

Bleib an der seriellen Übertragung dran. Verbinde doch erstmal die beiden PINs mit einem Draht und versuche, ein Byte zu übertragen.

ShadowPhoenix
22.05.2004, 13:21
Problem ist: WIE sende ich ein byte und empfange es richtig?

MfG,
ShadowPhoenix

22.05.2004, 13:27
Ganz grob als Anregung

Du willst ein Bytes senden, hat ja 8 Bits. Du kannst immer nur ein Bit nach dem sende. Also prüfst du, ob BIT 0 deiner Variablen 1 oder 0 ist.

Wenn1 dann sendest du eine 1, wenn nicht eine 0.

Danach schiebst du die Variable um eine Stelle nach rechts. Damit steht jetzt BIT1 an Stelle BIT0 und du kannst wieder abfragen ob 1 oder 0.

Nach 8 mal schiebben bist du mit deinem Byte durch.

daten = 23
for a = 1 to 8
if daten.0 = 1 then
sende 1
else
sende 0
end if
shift daten , right ,1

next a

So sollte es ganz grob abgehen. Nicht getestet, so aus dem Kopf

ShadowPhoenix
22.05.2004, 13:33
Was meinst du mit "daten = 23" ?
Ich wollte doch bytes versenden .. keine Zahlen. Das verstehe ich nicht :-O

MfG,
ShadowPhoenix

PS: Wie rückt man in einem Byte weiter

22.05.2004, 13:36
daten war ein Beispiel für eine Variable

Weiterrücken kann man mit dem Shift oder rotate

Man kann auch anstatt daten.0 daten.a schreiben, wodei a dann auch ein
Variable sein muß

ShadowPhoenix
22.05.2004, 13:38
Ja, aber kann daten nicht auch "00000001" sein?
Weil wie soll man bei der Zahl "23" abfragen, ob eine ziffer "1" oder "0" ist ?

MfG,
ShadowPhoenix

Flite
22.05.2004, 13:40
Also - du musst deine Sende LED zu erst einmal mit 36kHz modulieren.
D.h. du initialisierst deinen Timer und schaltest die led alle 13,9 us an und alle 13,9 us später wieder aus. Dann sendet das Teil immer eine 1.

Wenn du nun eine Null senden willst, dann musst du die LED einfach ausschalten.

Um nun ein Byte zu übertragen, musst du vom MSB (most significant bit), also das oberste Bit zuerst übertragen, dann rotierst du das Byte eins nach links und sendest dann wieder das MSB. Das machst du insgesamt 8 Mal - dann hast du dein Byte übertragen.

Nun musst du nur noch ein Timing beachten, d.H. zum Beispiel eine 1 bedeutet, wenn die led 200 us lang mit 36 kHz. blinkt. Eine 0 bedeutet, wenn die LEd 200 us lang abgeschaltet ist.

Damit jetzt der Empfänger weiß, wann deine Übertragung beginnt brauchst du noch einen Syncronisationsbefehl. Zum Beispiel sendest du 50 us lang eine 1. (also 50us lang blinkt die LED mit 36 kHz).

Ich würde dir empfehlen das ganze aufzubauen, wie es bei den Phillips Fernsehgeräten ist. Die verwenden RC5. Da ist das alles geregelt.

Hier kriegst du alle Infos über RC5.
http://home.t-online.de/home/Holger.Heinemann/homepage.htm?rc5.htm

Falls dir das nicht ganz so passt kannst du es ja ein bisschen abändern, aber vom Prinzip, ist hier bereits alles vorhanden.

Grüße
Flite

Flite
22.05.2004, 13:43
Naja - hab ein bisschen zu lang gebraucht.

Wie wärs, wenn du dir mal das binäre, hexadezimale und dezimale Zahlensystem zu Gemüte führst. Mit der wissenschaftlichen VErsion des Standard Rechners von Windows (in Zubehör) kannst du 23 ganz einfach in eine binäre Zahl umwandeln:

23 dezimal = 00010111

Grüße
Flite

ShadowPhoenix
22.05.2004, 13:47
@Flite
Danke!

23 = 00010111
Jop, jetzt verstehe ich ;)

Nur:
Wie wird dann nach dem Schema...

daten = 23
for a = 1 to 8
if daten.0 = 1 then
sende 1
else
sende 0
end if
shift daten , right ,1
next a

...wieder EMPFANGEN?

MfG,
ShadowPhoenix

Flite
22.05.2004, 13:54
Also erst mal musst du das ganze verzögern.
Sonst läuft das viel zu schnell ab.

Dann musst du bei sende 1 implementieren, dass die LED mit 36 kHz moduliert wird. Sonst gibt der TSOP immer 0 zurück.

Was dir jetzt noch fehlt ist ein Startbefehl, der vor dem ganzen gesendet wird. Dieser muss eindeutig sein, darf also während der Übertragung nicht nochmals auftreten.

Wenn du nun am Empfänger diesen empfängst, musst du nur soviele us warten, wie du beim Senden auch wartest und dann den Status des TSOPs abfragen.

Also gewissermaßen:

Startbefehl erkannt.
for 1 to 8
Wenn TSOP = 1 Dann
empfang.0 = 1
else
empfang.0 = 0
rotate empfang, left, 1
warte XX us
next

So etwa sollte die empfangsroutine aussehen.
Am besten lässt sich sowas natürlich mit einem Speicheroszi überprüfen, aber ich denke, sowas besitzt du nicht ...

Grüße
Flite

ShadowPhoenix
22.05.2004, 14:15
Danke!
Eine Frage noch:
Kann ein Fehler auch daran liegen, dass mein 12MHz Quarz ZWEI AVR's versorgt?
Oder ist das egal?

MfG,
ShadowPhoenix

Flite
22.05.2004, 14:19
Hm - ein Quarz, der zwei AVRs versorgt sollte eigentlich gar nicht gehen.
Oder ist das ein Quarzoszillator.

Ich würde es mit 2 Quarzen versuchen, aber wenn du beide Programmieren kannst laufen die AVRs ja.

Probier es mal mit dem Code aus, wie ich ihn ober gepostet hab.
Evtl. laufen die AVRs auch noch mit dem inneren Takt (1 MHz), falls du die MEGA Reihe verwendest und die FUsebits noch nicht umgestellt hast.

Grüße
Flite

ShadowPhoenix
22.05.2004, 14:30
Ich meinte natürlich Quarzoszillatoren!
Naja, ich verwende ein externes Programmiergerät.

Hier meine aktuellen Codes, die leider nicht funktionieren:

SENDER:


$regfile = "m8def.dat"
$crystal = 12000000

Dim Daten As Byte
Dim A As Integer

Config Portb = Output

Mainloop:
Daten = 170
For A = 1 To 8
If Daten.0 = 1 Then
Gosub Send1
Else
Gosub Send0
End If
rotate Daten , Right , 1
Waitms 500
Next A
Goto Mainloop

Send1:
Portb.1 = 1
Waitms 500
Portb.1 = 0
Goto Mainloop

Send0:
Portb.1 = 0
Waitms 500
Portb.1 = 0
Goto Mainloop


EMPFANG:


$regfile = "m8def.dat"
$crystal = 12000000

Dim A As Integer
Dim Rxdaten As Byte
Dim Zustand As Integer

Config Portd = Input
Config Portb = Output

Zustand = Pind.2

Mainloop:
For A = 1 To 8
If Rxdaten.0 = 0 Then
Gosub Write0
Else
Gosub Write1
End If
rotate Rxdaten , Left , 1
Waitms 500
Next A
Goto Mainloop

Write1:
Portb.5 = 1
Waitms 500
Portb.5 = 0
Goto Mainloop

Write0:
Portb.5 = 0
Waitms 500
Portb.5 = 0
Goto Mainloop


Was ist da falsch programmiert?
MfG,
ShadowPhoenix[/code]

Flite
22.05.2004, 14:42
Ich habe noch nie in Bascom programmiert und habe mir gerade mal nur den Sendecode angeschaut.
Das kann so nicht funktionieren.
Erstens: Wie ich schon zweimal erwähnt habe. Die Sende LED darf nicht dauernd leuchten. Du musst sie mit 36 kHz modulieren - sonst liefert dein TSOP Empfänger IMMER nur 0 zurück.

In den Sende routinen musst du nicht 500 ms warten (was sogar falsch ist) und du musst auch nicht dien PORTb.0 wieder auf Null zurück setzen.

Zur Modulation.



$regfile = "m8def.dat"
$crystal = 12000000

Dim Daten As Byte
Dim A As Integer

Config Portb = Output

Mainloop:
Daten = 170
For A = 1 To 8
If Daten.0 = 1 Then
Gosub Send1
Else
Gosub Send0
End If
rotate Daten , Right , 1
Waitms 500
Next A
Goto Mainloop

Send1:
Send = 1
Goto Mainloop

Send0:
Send = 0
Goto Mainloop


Timer [der alle 1/ 72 000 s aufgerufen wird]:
if send = 1 Then
if toggle = 0 Then
toggle = 1
PORTb.0 = 1
else
toggle = 0
PORTb.0 = 0
end if
else
Portb.0 = 0
end if



So etwa sollte die Senderoutine aussehen.

Ich schau mir gleich noch die Empfangsroutine an.

Grüße
Flite

EDIT: Ach ja: eine Startbedingung fehlt natürlich auch. Sonst empfängt dein Empfänger nachher immer nur müll ...

Flite
22.05.2004, 14:49
Ähnliches gilt auch für deine Empfangsroutine:



$regfile = "m8def.dat"
$crystal = 12000000

Dim A As Integer
Dim Rxdaten As Byte
Dim Zustand As Integer

Config Portd = Input
Config Portb = Output

Zustand = Pind.2 // WAS IST DAS ?!?

Mainloop:

StartLoop:
If NOT Startbedingung = True Then
Goto StartLoop
' Auf Startbedinung warten

For A = 1 To 8
If PINb.0 = 0 Then
Rxdaten.0 = 0
Else
Rxdaten.1 = 1
End If
rotate Rxdaten , Left , 1
Waitms 500
Next A

PORTC = Rxdaten 'Ausgabe des gesendeten Bytes

Goto Mainloop



So könnte es schon eher funktinieren.

ShadowPhoenix
22.05.2004, 15:01
Das funktioniert auch nicht :-(
Was mache ich nur falsch...
Hab die Codes, so wie sie sind, je in einen AVR eingeflashed.
Aber es geht nicht ;-(

MfG,
SHadowPhoenix

...Was könnte ich nur falsch machen...

Flite
22.05.2004, 15:05
Was hast du jetzt als Startbedinung genommen?

Das sie so nicht gehen ist ja klar.
Wann soll die Variable Startbedinung auch auf True gesetzt werden?
Hast du den Timer richtig initialisiert?
Was für einen AVR verwendest du denn?

Grüße Flite

ShadowPhoenix
22.05.2004, 15:08
Startbedingung habe ich noch keine, sorry aber ich weiß nicht, wie ich das programmieren soll.
Ich benutze einen AVR ATmega8.
Der Timer sollte richtig initialisiert sein, habe den Code ja abgeschrieben.

MfG,
ShadowPhoenix

Flite
22.05.2004, 15:14
Also zum senden Startbedingung:

Vielleicht so:



send = 1
waitms 10
send = 0


Zum empfangen der Startbedingung:



startLoop:
if PORTB.0 = 1 Then
waitms(52)
if NOT PORTB.0 = 0 Then
goto startLoop
end if
else
goto startLoop
end if


Ich kann den Code hier nicht ausprobieren.
Versuch ihn zu verstehen und dann reinzukopieren (natürlich an die richtige Stelle).

Zur Initialisierung des Timers.
Kannst du mir mal posten, wie du den Timer initialisert hast?

Grüße
Flite

ShadowPhoenix
22.05.2004, 15:27
Den Timer initialisieren hast du doch eh schon gepostet:

Timer [der alle 1/ 72 000 s aufgerufen wird]:
if send = 1 Then
if toggle = 0 Then
toggle = 1
PORTb.0 = 1
else
toggle = 0
PORTb.0 = 0
end if
else
Portb.0 = 0
end if

So habe ich das auch hingeschrieben!

MfG,
ShadowPhoenix

Flite
22.05.2004, 15:33
Timer [der alle 1/ 72 000 s aufgerufen wird]:

SO HAST DU DAS DA REIN GESCHRIEBEN ?!?!?!

Dat geht logischerweise nicht.
Ich weiß nicht wie man den Timer in BASCOM initialisiert. Aber dazu gibts doch im Netz bestimmt genug Infos (oder auch in der Bedienungsanleitung von Bascom).

Du brauchst eine Funktion, die alle 1 / 72 000 s aufgerufen wird um dein Signal zu modulieren. Diese kann man mit dem Timer machen.

Und das obere Beispiel hast du so rein kopiert und kompiliert. Kann mir irgendwie nicht vorstellen, dass der so einen Schwachsinn überhaupt kompiliert.

Vielleicht solltest du dir erstmal ein wenig die Grundlagen aneignen?

Versuch doch mal eine LED mittels des Timers zum blinken zu kriegen, so dass die jede Sekunde einmal und einmal aus geht ...

Das soll dich nicht von dem Projekt hier abhalten (das ist nämlich echt einfach zu realisieren). Aber wenigstens die Grundfunktionen solltest du beherrschen, weil ich ohne je Bascom programmiert zu haben dir hier kein völlig funktinierendes Proghramm reinstellen kann.

In Codevision C könnte ich dir so ein prgramm schreiben, aber das ist ja nicht Sinn der Sache. Dabei lernst du ja nichts.

grüße
Flite

ShadowPhoenix
22.05.2004, 15:38
Oh sorry, diese Zeile:
Timer [der alle 1/ 72 000 s aufgerufen wird]:
hatte ich natürlich nicht eingefügt. !

Flite, es ist nicht so, dass ich die Grundlagen des AVR's nicht beherrsche.
Eine Led per Taster zum blinken zum bringen ist wohl das einfachste.
7Segment Anzeigen usw. habe ich auch schon angesteuert.
Eh nicht schwer, nur das mit den Bytes usw. kapiere ich leider nicht!
Da bin ich totaler Anfänger, aber da ich nun so etwas für den ADDLink zum fernsteuern meines Roboterfahrzeuges brauche, muss ich langsam
anfangen, mich mit diesen Funktionen vertraut zu machen :-O

MfG,
ShadowPhoenix

PS: Bitte tu mir einen gefallen:
Schreibe mir bitte den kompletten Sendecode sowie den kompletten Empfängercode auf (exklusive der Timer funktion, da blättere ich noch einmal nach, ok?)
Danke, weil dann flashe ich die AVR's mal damit und dann mal sehen !

Flite
22.05.2004, 15:51
So ich habs jetzt mal zusammenkopiert, wie ich mir das vorstelle.
Ich glaube jedoch nicht, dass das jetzt aufs erste Mal funktioniert - vielleicht sieht ja jemand anderes den Thread hier noch und kann schnell mal drüber schauen.

Aber probieren kann mans ja:

Der Sendecode:


$regfile = "m8def.dat"
$crystal = 12000000

Dim Daten As Byte
Dim A As Integer
Dim Send as Byte
Dim toggle as Byte

Config Portb = Output

Mainloop:
Waitms 1000
Daten = 170

'Sende Startbedingung
send = 1
waitms 10
send = 0

For A = 1 To 8
If Daten.0 = 1 Then
Send = 1
Else
Send = 0
End If
rotate Daten , Right , 1
Waitms 500
Next A


Goto Mainloop


[[[[ DIESE FUNKTION MUSS ALLE 1 / 72000 s AUFGERUFEN WERDEN ]]]]]
if send = 1 Then
if toggle = 0 Then
toggle = 1
PORTb.0 = 1
else
toggle = 0
PORTb.0 = 0
end if
else
Portb.0 = 0
end if


Und der Empfangscode:



$regfile = "m8def.dat"
$crystal = 12000000

Dim A As Integer
Dim Rxdaten As Byte
Dim Zustand As Integer

Config Portd = Input
Config Portb = Output


Mainloop:


startLoop:
if PORTB.0 = 1 Then
waitms(52)
if NOT PORTB.0 = 0 Then
goto startLoop
end if
else
goto startLoop
end if

waitms 10

For A = 1 To 8
If PINb.0 = 0 Then
Rxdaten.0 = 0
Else
Rxdaten.0 = 1
End If
rotate Rxdaten , Left , 1
Waitms 500
Next A

PORTD = Rxdaten 'Ausgabe des gesendeten Bytes

Goto Mainloop



Der Sendecode sendet alle 5050 ms die Befehle.
Dabei dauert ein Bit 500 ms und die Startbedinung 50 ms.
Vor jedem senden wird 1000 ms gewartet.

Das empfangene Byte wird an PORT D angelegt. D.h. den musst du noch auf Ausgang schalten (weiß ich nicht wie ...).

Grüße
Flite

ShadowPhoenix
23.05.2004, 08:20
Danke,funktioniert so in etwa.
Ich werde mich nun an das ADDLink Modul ranmachen,

MfG,
ShadowPhoenix

Flite
23.05.2004, 11:09
Kein Problem!

Aber was funktioniert denn jetzt genau nicht? Würde mich einfach nur interessieren.

Grüße
Flite