Shop OBEX P1 Docs P2 Docs Learn Events
IR Comm Issue — Parallax Forums

IR Comm Issue

thTechiethTechie Posts: 7
edited 2012-01-03 11:51 in Propeller 1
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:
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

  • thTechiethTechie Posts: 7
    edited 2012-01-02 01:35
    I've been doing a bit more work on this and still can't get anything to happen that makes any sense. I've cut out all the rest of the code to try to isolate the problem, but no luck so far. Below is my code and what it's outputting.
    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
  • MagIO2MagIO2 Posts: 2,243
    edited 2012-01-02 03:18
    If I read Jonny's code right he is modulating the output. This is common for IR transmissions like remote controls do it. So, do you have a demodulator connected to the receiving pin? A IR photo-diode alone will not work!

    The demodulated signal will then look like a common serial signal and can be fed into the receiving-pin!
  • JonnyMacJonnyMac Posts: 9,198
    edited 2012-01-02 11:22
    So, do you have a demodulator connected to 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
  • thTechiethTechie Posts: 7
    edited 2012-01-02 13:55
    Sorry guys, I suppose I also should have included how its hooked up. I've got an IR LED connected to pin 11 with a 100 ohm resistor in series. On pin 12 I've got the it receiver that comes with the PEK (which I believe is the same one that you linked to) through a 4.7k ohm resistor. I also know for sure that led is working because I can see it on my phone's camera.

    Thanks again,
    Kenny
  • MagIO2MagIO2 Posts: 2,243
    edited 2012-01-02 23:13
    Ok ... just wanted to make sure ;o)

    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.
  • thTechiethTechie Posts: 7
    edited 2012-01-03 00:58
    It worked! Sorta... I changed the IROut to use tx, as that's what I was actually wanting. And it, somewhat works? I also looked in the FullDuplexSerial object and I think it uses 2 stop bits, but I'm just now learning pasm, so I'm not completely sure as it doesn't say anywhere in the comments that I could find. Anyway, what it's doing now is somewhat erratic. Once again the output is below, and the first line is what I'm trying to get out, and then each group of two lines after it comes each time it transmits the byte (I added in the extra line breaks between them for clarity). A few of the lines are correct, and most are mostly correct, but have some errors in them. I'm not sure if maybe this is just due to it being done over IR/outside interference (which if so, this will definitely not work for what I'm trying) or is some timing issue or another silly thing (like attempting to send it as ASCII...)
    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
  • MagIO2MagIO2 Posts: 2,243
    edited 2012-01-03 04:21
    My guess here is that the IR drivers sends 1 + 8 + 2 bits and the receiving serial driver tries to get 1 + 8 + 1. This would cause that the 2nd end-bit starts a new receive-loop which results in a lot of 1s.

    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.
  • MagIO2MagIO2 Posts: 2,243
    edited 2012-01-03 04:37
                            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 this

    shr 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?
  • MagIO2MagIO2 Posts: 2,243
    edited 2012-01-03 04:46
    PS: Just checked Simple Serial ... No ... can't set number of stop-bits there
    I don't remember where I saw that, maybe someone else remembers?
  • JonnyMacJonnyMac Posts: 9,198
    edited 2012-01-03 11:04
    Stop bits only matter on the TX side as this provides a bit of delay before the next start bit; this delay is used by the receiver to buffer what it just received. My jm_irtxserial object and FDS use 11 bits for transmitting, that is, start, 8 data, 2 stop.

    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
    
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-01-03 11:51
    You can do IR communication using FullDuplexSerial unmodified. The trick is to generate the 38 KHz carrier in the foreground using a counter, outputting to the IRED pin (see listing for correct hookup). Then FullDuplexSerial can modulate the carrier by virtue of its output to the same pin being ORed with the output from the counter. Here's the test program I used to verify the concept:
    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
    ''       &#61463;
    ''       &#9492;&#9472;&#61606;&#61608;&#9472;&#9472;&#9472;&#61629;&#61630;&#9472;&#61620; IR_XMT_PIN
    ''        IRED
    ''
    '' The input and output waveforms look like this:
    ''
    ''                    SPACE      MARK      SPACE
    '' IR_XMT_PIN: &#9472;&#9472;&#9472;&#9472;&#9488;&#9484;&#9488;&#9484;&#9488;&#9484;&#9488;&#9484;&#9488;&#9484;&#9488;&#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;&#9484;&#9488;&#9484;&#9488;&#9484;&#9488;&#9484;&#9488;&#9484;&#9488;&#9484;&#9488;&#9484;&#9472;&#9472;&#9472;&#9472; 
    ''                 &#9492;&#9496;&#9492;&#9496;&#9492;&#9496;&#9492;&#9496;&#9492;&#9496;&#9492;&#9496;        &#9492;&#9496;&#9492;&#9496;&#9492;&#9496;&#9492;&#9496;&#9492;&#9496;&#9492;&#9496;&#9492;&#9496;
    ''
    '' IR_RCV_PIN: &#9472;&#9472;&#9472;&#9472;&#9488;          &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;            &#9484;&#9472;&#9472;&#9472;&#9472;
    ''                 &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;        &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
    
      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
Sign In or Register to comment.