IR Comm Issue
Hi there everyone! I've been attempting to do IR communication between two props (although right now I'm just trying to get a prop to communicate with itself). I found a previous thread about this (http://forums.parallax.com/showthread.php?120073-IR-Communications) and and trying the method used by JonnyMac and it is sorta working. What I'm attempting to transmit (PlayNo; PlayNoPt is @PlayNo) is %1111000011010100 and what I keep receiving is just %11111110 over and over, although only when the IR transmitting, so I know it's all hooked up right (I think at least...), they're just not talking like they should and I'm probably not well versed enough in IR to be able to spot the problem.
My receive code (which runs in its own cog) is:
and the transmit code (which is called when a button is pushed) is:
Thanks a lot to anyone that can help!
Kenny
My receive code (which runs in its own cog) is:
PUB IRMont | rxByte
Comp.start(115200)
dira[12] := 0
IRIn.start(12, 26, %0000, 2400)
repeat
rxByte := IRIn.rxcheck
if rxByte <> 0 and rxByte <> -1
''Network.IRRecieve(rxByte)
Comp.bin(rxByte, 8)
Comp.NewLine
waitcnt(clkfreq/10_000 + cnt)
and the transmit code (which is called when a button is pushed) is:
PUB fire
dira[11] := 1
if IROut.Start(2_040_109, 11, 2400) == 0
Disp.str(string("Cannot Start IR Send Cog"))
waitcnt(clkfreq/500 + cnt)
IROut.bin(byte[PlayNoPt][0],8)
IROut.bin(byte[PlayNoPt][1],8)
IROut.stop
Thanks a lot to anyone that can help!
Kenny
Comments
CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 OBJ IROut: "jm_irtxserial" IRIn: "FullDuplexSerial" Comp: "Parallax Serial Terminal" DAT stack long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 'Stack space PlayNoPt long 0 PlayNo byte %11010100 PUB main PlayNoPt := @PlayNo Comp.start(115200) Comp.bin(byte[PlayNoPt], 8) Comp.NewLine dira[11] := 1 dira[12] := 0 if (cognew(IRMont, @stack) + 1) == 0 Comp.str(String("Error! Can't start IR Mon")) repeat if IROut.Start(2_066_953, 11, 2400) == 0 Comp.str(string("Cannot Start IR Send Cog!")) waitcnt(clkfreq/200 + cnt) IROut.bin(byte[PlayNoPt], 8) IROut.stop waitcnt(clkfreq * 2 + cnt) PUB IRMont | rxByte dira[12] := 0 IRIn.start(12, 27, %0000, 2400) repeat rxByte := IRIn.rxcheck if rxByte <> -1 Comp.bin(rxByte, 8) Comp.NewLine
Output:
11010100 (note: this is what I'm attempting to send, the following lines is what it's receiving) 00000011 11111100 00000011 11111100 00000011 11111100 00010011 11111100 00000011 11111100 00000011 11111100 00100011 11111100 00001011 11111100 00000011 11111100 00000011 11111100
Any thoughts, suggestions, places to look, or just anything really would be VERY much appreciated!
Thanks,
Kenny
The demodulated signal will then look like a common serial signal and can be fed into the receiving-pin!
MagIO2 is correct: you need a demodulator on the RX side. This one will work:
-- http://www.parallax.com/Store/Components/Optoelectronics/tabid/152/CategoryID/30/List/0/SortField/0/Level/a/ProductID/177/Default.aspx
Thanks again,
Kenny
Next guess:
mov txBitCount, #11 ' start + 8 data + 2 stop
This is part of jm_irtxserial.spin. Do you have the same settings on input-side? I think 2 stop-bits is not very common. (I don't have the Parallax Serial Terminal sources at hand, so you have to verify this by yourself)
But having a closer look something is very obvious:
IROut.bin(byte[PlayNoPt], 8)
here you do not send one byte, you send 8 bytes which are equal to the string "11010100" - one ascii-byte for each character.
rxByte := IRIn.rxcheck
here you receive the string byte by byte
Comp.bin(rxByte, 8)
and here you output one byte again as a binary string.
So, I think together with the wrong stop-bit-settings you get your wrong output.
To fix the send/receive-discrepancy you have 2 options:
1. change send-part to use IROut.tx instead of IROut.bin
2. change receive-part to Comp.tx instead of Comp.bin
It depends on what you want to achieve with your program. In 1. you have the binary data at receiver-side and you can easily use the byte there. In 2. the protocol is human readable but needs to send 8 characters per byte.
11010100 (what I'm after) 10000111 11111111 00110011 (almost right) 11111111 11111011 11111111 11111111 11111111 10010110 (kinda right) 10100011 11111110 10111011 11111111 11000011 11111111 01110111 11111110 00000011 11111110 01000011 11111111 11111101 01110011 11111110 00110111 11111110 00001111 11111110 10001000 00101011 11111111 11100001 00001111 11111111 10001011 11111111 10000011 11111111 01010011 (correct! but inverted) 11111110 01010111 (so close...) 11111110
Thanks so much for catching that mistake, any ideas about what's causing this? lol
Kenny
This explaination would perfectly match with your output. I guess that the Parallax Serial Terminal should give a description on how to start it properly.
IRIn.start(12, 27, %0000, 2400)
I'd expect that you can use a different setting in the %0000-parameter to switch to 2 end-bits-mode.
test rxtxmode,#%001 wz 'wait for start bit on rx pin test rxmask,ina wc if_z_eq_c jmp #receive mov rxbits,#9 'ready to receive byte
this looks to me like the FullDuplexSerial expects 1+8+1 - with 1 bit to start the whole thing and then receiving additionally 9 bits. If you want to change it you have to initialize rxbits with #10 instead of #9 and then at the end of the receive-loop change thisshr rxdata,#32-9 'justify and trim received byte
to #32-10 as well.
But as far as I remember there should be serial drivers which also allow to specify the number of stop-bits. Simple Serial maybe?
I don't remember where I saw that, maybe someone else remembers?
Simple_Serial uses one stop bit which is fine because it only supports baud rates up to 19.2K so the bit timing is quite long (relative to the time it takes to move the just-received byte into a buffer). From Simple_Serial:
PUB tx(txByte) | t {{ Transmit a byte; blocks caller until byte transmitted. }} if txOkay outa[sout] := !inverted ' set idle state dira[sout]~~ ' make tx pin an output txByte := ((txByte | $100) << 2) ^ inverted ' add stop bit, set mode t := cnt ' sync repeat 10 ' start + eight data bits + stop waitcnt(t += bitTime) ' wait bit time outa[sout] := (txByte >>= 1) & 1 ' output bit (true mode) if sout == sin dira[sout]~ ' release to pull-up/pull-down
CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 IR_XMT_PIN = 0 IR_RCV_PIN = 7 OBJ ir : "FullDuplexSerial" sio : "FullDuplexSerial" PUB start | char '' Program to test sending serial comms via IR, using a 38 KHz IR receiver and FullDuplexSerial. '' The 38 KHz carrier is generated in the foreground via a counter in NCO mode on the IR_XMT_PIN. '' FullDuplexSerial modulates the carrier with the serial data, since a high on the pin is ORed '' with the the counter output. This requires the IRED to be wired for negative-going logic: '' '' Vdd ''  '' └───── IR_XMT_PIN '' IRED '' '' The input and output waveforms look like this: '' '' SPACE MARK SPACE '' IR_XMT_PIN: ────┐┌┐┌┐┌┐┌┐┌┐┌────────┐┌┐┌┐┌┐┌┐┌┐┌┐┌──── '' └┘└┘└┘└┘└┘└┘ └┘└┘└┘└┘└┘└┘└┘ '' '' IR_RCV_PIN: ────┐ ┌────────┐ ┌──── '' └──────────┘ └────────────┘ ctra := %00100 << 26 | IR_XMT_PIN frqa := $001f_212d '38000 * (1 << 32) / 80_000_000 dira[IR_XMT_PIN]~~ ir.start(IR_RCV_PIN, IR_XMT_PIN, 0, 2400) sio.start(31, 30, 0, 9600) repeat ir.str(string("Testing 123", 13)) 'Send string on IR_XMT_PIN. repeat until (char := ir.rxcheck) < 0 'Receive bytes on IR_RCV_PIN sio.tx(char) 'Echo received bytes to PC.
-Phil