Shop OBEX P1 Docs P2 Docs Learn Events
Ir send and receive troubles — Parallax Forums

Ir send and receive troubles

snakiesnakie Posts: 12
edited 2013-09-01 13:10 in Propeller 1
Hi everyone, I have been trying to make a laser tag gun using the propeller, however, I am having troubles with one big part of it. I am having troubles with sending and receiving of the ir signal. I have tried looking at some of the files on object exchange but I am having troubles understanding them. Can anyone help me with this? I'm wanting to be able to push a button (trigger) and then send a playerid. Thanks for any help.

Comments

  • JonnyMacJonnyMac Posts: 9,107
    edited 2013-01-11 20:51
    This will help you understand SIRCS (common protocol). Once you understand the mechanics of the protocol you can create your own.

    -- http://www.parallax.com/Portals/0/Downloads/docs/cols/nv/prop/col/nvp4.pdf

    The article discusses receiving and transmitting.
  • snakiesnakie Posts: 12
    edited 2013-01-12 14:35
    I have looked at that article before but to be honest it confused me a lot more. I understand the protocol but its understanding the code that I am having troubles with. I have seen it in basic and it made sense but I find spin the most confusing language I have used before and when it comes to IR its even worse. I was looking at a file in obex that was kind of helpful but still made me lost. Can anyone kind of give me like a crash course or any good links?
  • JonnyMacJonnyMac Posts: 9,107
    edited 2013-01-12 18:57
    I have looked at that article before but to be honest it confused me a lot more.

    We all learn at different rates and you may need to read that article more than a few times for it to sink in -- I buy a lot of books so I can keep going back to them. Please do not think that the availability of an object is going magically make you understand something (even if you can successfully use it). For many it has the opposite effect: once they have working object they don't bother trying to understand it. I would suggest that you should try to understand SIRCS so that you can use it as a springboard for your laser-tag system. I'm working on a commercial product for that now and have no troubles, but then, I took the time to really understand SIRCS before thinking I could code a commercial laser-tag system (with my own IR protocol).

    All of my articles come with fully-commented object code and demos, though I don't put them all in ObEx. You may have noticed that the article is hosted by Parallax; well, they host the code, too. You can find it on this page (column #4):

    -- http://www.parallax.com/Resources/NutsVoltsColumns/TheSpinZone/tabid/781/Default.aspx

    The reason there are no code comments in what you read is that this is the raw material sent to the magazine which uses a 2-column format; this means each line has to be very short, hence, no comments.

    This is the link to a protocol reference that I use: http://www.sbprojects.com/knowledge/ir/sirc.php
    I find spin the most confusing language I have used

    Henry Ford once said, "If you think you can or you think you can't... you're right!"

    If I may be so bold... perhaps you should change your mindset to, "Spin is an interesting language that I haven't taken the time to master yet." -- this change could be what sets your mind free to master it! There is a BASIC for the Propeller but dare I say you won't find it any easier than Spin. You're still dealing with a multi-core processor and for many programs that requires parallel thinking. Spin is designed specifically for the Propeller and, in my opinion, is by far the easiest language to master for it. You wan't confusion? -- have a look at Forth! :)
  • cavelambcavelamb Posts: 720
    edited 2013-01-12 22:20
    This is Sony remote decoder that I've been playing with.
    IR_Remote_NewCog.spin in the OBEX
    Simplified / reduced to what I thought I could understand and work with.
    It works on my QuickStarts with an IR decoder attached.
    It calls the IR_Remote.spin object's getSonyCode method.
    (Did I say that right?)
    ..which does the Sony Receive trick...

    That's an example of receiving codes from a Sony remote control
    which sounds like half the problem solved?

    But I can't claim to understand the inner workings of that trick.
    It's all timing.


    Jon, your articles are amazing, and I mean that.

    You've covered a lot of stuff in the depth that it takes to learn to work with it.
    But we beginners still need to pull together code.
    That's hard in the beginning.

    I've always wanted to ask one of the real gurus to "read" some piece of code.
    "How do you say that in English?"
    What it's doing, and why.
    Especially Pasm.

    I didn't like Spin all that much at first, either.
    I'd STILL much prefer more traditional structural phrasing.
    But it's workable.

    And you might note:
    The language is ideally suited to the Propeller and it's unique architecture.

    So, snakie, just read it....

    Quckstart board with IR decoder on pin whatever it sez.
    {{
          IR remote control lights up the appropriate LED.
          Numbers 7 through 8
          CH^ increments LED, CHv Decrements LED
          Vol< and VOL> work backwards so the LEDs go in the same direction as the buttons.
          Vol and CH both wrap around.
          PWR runs chase and forth once.
          OK short blink all LEDs once
    }}
    CON
      _CLKMODE = XTAL1 + PLL16X        ' 80 Mhz clock
      _XINFREQ = 5_000_000
      IRdetPin  =    2                   ' IR Receiver - Propeller Pin
      BlinkPin  = 16                     ' Proof of life
        
    OBJ
      ir    : "IR_Remote"
    
    VAR
      byte IRcode , LED,  IVcode, X
      LONG MS001, Twait 
      
    PUB Init | freq, index, cog, lcode
      Twait := ClkFREQ / 20  '/3 for slo-mo   
      MS001 := CLKFREQ / 1_000    ' define count for 1 millisec
      outa[ 16..23 ] := $00       ' all LED pins off    '
      dira[ 16..23 ] := $FF       ' all LED pins outputs   '
      LED := 6
      LEDON(LED)
      cog := ir.Start(IRdetPin, @IRcode)  ' Propeller pin connected to the IR receiver, address of variable
      if cog > 0
         repeat
            If IRcode <> ir#NoNewCode
              lcode := IRcode
              ir.Start(IRdetPin, @IRcode)  ' set up for next code
              case lcode
    'Numbers          
                ir#zero  :          'ignore
                            
                ir#one   :
                  LED := Lcode              
                
                ir#two   :
                  LED := Lcode            
                  
                ir#three :
                  LED := Lcode            
                                          
                ir#four  :
                  LED := Lcode            
                              
                ir#five  :
                  LED := Lcode            
                
                ir#six   :
                  LED := Lcode            
                
                ir#seven :
                  LED := Lcode              
                
                ir#eight :
                  LED := Lcode             
    
                ir#nine  :           'ignore 
                  
    '-----------------------------------------------------
    'Channel
                ir#chUp  :
                 'pst.str(string("chUp "))
                  if LED < 7
                     LED++
                  else              ' wrap around
                     LED := 0
                     
                ir#chDn  :
                 'pst.str(string("chDn "))
                  if LED > 0
                     LED --
                  else
                     LED := 7
    'Volumn
                ir#volUp :
                 'pst.str(string("volUp"))
                  if LED > 0
                     LED--
                  else
                     LED := 7
    
                ir#volDn :
                 'pst.str(string("volDn"))
                  if LED < 7
                     LED++
                  else              ' wrap around
                     LED := 0
    
                ir#ok  :
                 'pst.str(string("ok   "))
                  repeat  1
                    outa [16..23] := 0
                    outa [16..23] := %11111111
                    waitMS(101)              
    
                ir#power :
                 'pst.str(string("power"))
                  X := LED
                  Twait := ClkFREQ / 20  '/3 for slo-mo   
                  dira[16..23] := %11111111
                  outa[16..23] := 0
                  repeat 1
                      repeat  Led FROM 16 to 23
                         outa[LED..LED-2] := %111
                         WaitCnt(Twait+cnt)
                         outa[Led-2]  := 0
                         WaitCnt(Twait+cnt)
                         outa [LED-1] := 0
                         WaitCnt(Twait+cnt)
                      repeat  Led FROM 23 to 16
                         outa[LED..LED+2] := %111
                         WaitCnt(Twait+cnt)
                         outa[Led+2] := 0
                         waitCnt (Twait+cnt)
                         outa [LED+1] := 0
                         WaitCnt(Twait+cnt)
                  LED := X
                  
            LEDON(LED)
            
     
    PRI LEDON(n)
       outa [16..23] := 0
       outa [16+n]:= 1
    
    PRI LEDOFF(n)
       outa [16..32] := 0
       
    PUB WaitMS(W)                      'wait for W milliseconds
      W := W * MS001                
      WaitCNT (W+cnt)
    



    {{
          IR_Remote_NewCog.spin
          Tom Doyle
          2 March 2007
    
          Panasonic IR Receiver - Parallax #350-00014
    
          Receive and display codes sent from a Sony TV remote control.
          See "Infrared Decoding and Detection appnote" and "IR Remote for the Boe-Bot Book v1.1"
          on Parallax website for additional info on TV remotes.
    
          The procedure uses counter A to measure the pulse width of the signals received
          by the Panasonic IR Receiver. The procedure waits for a start pulse and then decodes the
          next 12 bits. The entire 12 bit result is returned. The lower 7 bits contain the actual
          key code. The upper 5 bits contain the device information (TV, VCR etc.) and are masked off
          for the display.
    
          Most TV Remotes send the code over and over again as long as the key is pressed.
          This allows auto repeat for TV operations like increasing volume. The volume continues to
          increase as long as you hold the 'volume up' key down. Even if the key is pressed for a
          very short time there is often more than one code sent. The best way to eliminate the
          auto key repeat is to look for an idle gap in the IR receiver output. There is a period of
          idle time (20-30 ms) between packets. The getSonyCode procedure will wait for an idle period
          controlled by the gapMin constant. This value can be adjusted to eliminate auto repeat
          while maintaining a fast response to a new keypress. If auto repeat is desired the indicated
          section of code at the start of the getSonyCode procedure can be commented out.
    
          The procedure sets a tolerance for the width of the start bit and the logic level 1 bit to
          allow for variation in the pulse widths sent out by different remotes. It is assumed that a
          bit is 0 if it is not a 1.
    
          The procedure to read the keycode ( getSonyCode ) is run in a separate cog. This allows
          the main program loop to continue without waiting for a key to be pressed. The getSonyCode
          procedure writes the NoNewCode value (255) into the keycode variable in main memory to
          indicate that no new keycode is available. When a keycode is received it writes the keycode
          into the main memory variable and terminates. With only 8 cogs available it seems to be a
          good idea to free up cogs rather than let them run forever. The main program can fire off
          the procedure if and when it is interested in a new keycode.
            
    }}
    
    
    CON
    
      _CLKMODE = XTAL1 + PLL16X        ' 80 Mhz clock
      _XINFREQ = 5_000_000
    
      NoNewCode    =  255               ' indicates no new keycode received
    
      gapMin       =   2000             ' minimum idle gap - adjust to eliminate auto repeat
      startBitMin  =   2000             ' minimum length of start bit in us (2400 us reference)
      startBitMax  =   2800             ' maximum length of start bit in us (2400 us reference)
      oneBitMin    =   1000             ' minimum length of 1 (1200 us reference)
      oneBitMax    =   1400             ' maximum length of 1 (1200 us reference)
    
      ' Sony TV remote key codes
      ' these work for the remotes I tested however your mileage may vary
      
      one   =  0
      two   =  1
      three =  2
      four  =  3
      five  =  4
      six   =  5
      seven =  6
      eight =  7
      nine  =  8
      zero  =  9
    
      chUp  = 16
      chDn  = 17
      volUp = 18
      volDn = 19
      ok    = 20
      power = 21
      last  = 59
    
    
    VAR
    
      byte  cog
      long  Stack[20]  
    
    
    PUB Start(Pin, addrMainCode) : result
    {{
       Pin - propeller pin connected to IR receiver
       addrMainCode - address of keycode variable in main memory
    }}
    
        stop
        byte[addrMainCode] := NoNewCode
        cog := cognew(getSonycode(Pin, addrMainCode), @Stack) + 1
        result := cog
    
    
    PUB Stop
    {{
       stop cog if in use
    }}
    
        if cog
          cogstop(cog~ -1)
    
        
    PUB getSonyCode(pin, addrMainCode) | irCode, index, pulseWidth, lockID
    
    {{
       Decode the Sony TV Remote key code from pulses received by the IR receiver
    }}
    
       ' wait for idle period (ir receiver output = 1 for gapMin)
       ' comment out "auto repeat" code if auto key repeat is desired
       
       ' start of "auto repeat" code section
    
       dira[pin]~
       index := 0
       repeat
         if ina[Pin] == 1
           index++
         else
           index := 0
       while index < gapMin
       ' end of "auto repeat" code section
    
       frqa := 1
       ctra := 0
       dira[pin]~
       
       ' wait for a start pulse ( width > startBitMin and < startBitMax  )
       repeat      
          ctra := (%10101 << 26 ) | (PIN)                      ' accumulate while A = 0  
          waitpne(0 << pin, |< Pin, 0)                         
          phsa:=0                                              ' zero width
          waitpeq(0 << pin, |< Pin, 0)                         ' start counting
          waitpne(0 << pin, |< Pin, 0)                         ' stop counting                                               
          pulseWidth := phsa  / (clkfreq / 1_000_000) + 1    
       while ((pulseWidth < startBitMin) OR (pulseWidth > startBitMax))
    
       ' read in next 12 bits
       index := 0
       irCode := 0
       repeat
          ctra := (%10101 << 26 ) | (PIN)                      ' accumulate while A = 0  
          waitpne(0 << pin, |< Pin, 0)                         
          phsa:=0                                              ' zero width
          waitpeq(0 << pin, |< Pin, 0)                         ' start counting
          waitpne(0 << pin, |< Pin, 0)                         ' stop counting                                               
          pulseWidth := phsa  / (clkfreq / 1_000_000) + 1
          
        if (pulseWidth > oneBitMin) AND (pulseWidth < oneBitMax)
           irCode := irCode + (1 << index)
        index++
       while index < 11
    
       irCode := irCode & $7f                                   ' mask off upper 5 bits
    
       byte[addrMainCode] := irCode
    
  • StefanL38StefanL38 Posts: 2,292
    edited 2013-01-13 03:22
    HI Snakie,

    welcome to the propeller-forum. Please give us more information where you have trouble to understand.
    There are a lot of possible reasons why your lasergun isn't working yet.
    So I want to ask some questions:

    Did you do some tests if your IR-Diode is sending anything at all?
    Did you do some tests if your IR-receiver is receiving anything at all?
    What kind of IR-Diode and IR-receiver are you using?

    Working with microcontrollers isn't as easy as working with standard USB-devices (which work plug and play)

    You wrote that you did understand an example in basic. Can you please post this basic-example?
    can you please post your SPIN-code where you have trouble to understand it?

    Keep the questions coming!

    best regards
    Stefan
  • snakiesnakie Posts: 12
    edited 2013-01-13 08:56
    @JonnyMac thanks for the link that did help a little but i have troubles understanding the dat section what in that section should i focus on learning? I have never used this block before so its a little new to me.

    @
    cavelamb that code helps me understand this more

    @
    StefanL38 when using picbasic i can have something like


    send_data:					'send 14 bits 
    	CCP1CON = 12				'send header pulse
        	pauseus mtheader  
    	CCP1CON = 0
    	@ bcf PORTC, 2
    
    main_byte:
    	databyte = p_ID & %01111111     	'(packet_ID=0; shot)  
    	GoSub send_byte
    
    send_byte:						'send 8 bits (databyte)
    	For bit_counter = 1 TO 8                  	
            	pauseus mtspace                      'space between data pulses  
    		IF databyte.7 = 1 Then trans1
    			CCP1CON = 12		       'send zero
                	pauseus mtbit0  
    			CCP1CON = 0
    			@ bcf PORTC, 2
    			@ rlcf	_databyte,F		
    		GoTo bypassx
    trans:
    			CCP1CON = 12		'send one
                	pauseus mtbit1
    			CCP1CON = 0	
    			@ bcf PORTC, 2	
    			@ rlcf	_databyte,F		
    bypassx:
    	Next bit_counter
    	
    	Return
    
    
    
    
    

    is there an easy way to put this into spin or something spin can use?

    I havent been able to get an ir-reciever to get anything at all yet but going to try playing with Jonny
    Mac's code from the link.

    Also i find sometimes my propeller does some odd stuff for example i had an led and a button and i can take the button out and put my hand close to the wires and it will turn on the led anyone have any idea why this is happening and can i stop it?
  • snakiesnakie Posts: 12
    edited 2013-01-13 09:47
    @JonnyMac thanks for the link that helped a lot more. Some of the code still confuses me though. What is the Dat block used for? I dont quite understand that section.

    @cavelamb thanks for the code that helped me understand it more, its better then the file i found previously.

    @StefanL38 i have not been able to recieve or send (atleast i think) i put an led in to tell me when it gets to each step and it doesnt go past before the send bit

    I am using a 56 khz reciever TSOP1256.
    and SFH 4547 high powered emitter

    This code is what I would use on a PIC. Its in PICbasic is there any way to convert this easily to spin?

    [/FONT][/COLOR]send_data:					'send 14 bits 
    	CCP1CON = 12				'send MT header pulse (2.4mS)
        	pauseus mtheader  
    	CCP1CON = 0
    	@ bcf PORTC, 2
    
    
    Main_byte:
    	databyte = P_ID & %01111111     	'(packet_ID=0; shot)  
    	GoSub send_byte
    
    send_byte:						'send 8 bits
    	For bit_counter = 1 TO 8	'send 8 data bits
            	pauseus mtspace     'space between data pulses  
    		IF databyte.7 = 1 Then trans
    			CCP1CON = 12		'send zero
                	pauseus mtbit0  
    			CCP1CON = 0
    			@ bcf PORTC, 2
    			@ rlcf	_databyte,F		
    		GoTo bypassx
    trans:
    			CCP1CON = 12		'send one
                	pauseus mtbit1
    			CCP1CON = 0	
    			@ bcf PORTC, 2	
    			@ rlcf	_databyte,F		
    bypassx:
    	Next bit_counter
    	
    	Return
    
    

    Also my propeller board does some random things sometimes. If i have a program to make a button turn on a led sometimes the led can turn on by itself if your hand is close to it. If you take the button out it still does it why is this and can i fix it?

    Thank you everyone for your help
  • StefanL38StefanL38 Posts: 2,292
    edited 2013-01-14 11:57
    Hello Snakie,

    about the LED-turn on/off phenomen: welcome to the analog part of digital circuits!

    If an IO-pin is configured as input the input-impedance (the input-resistance) is so high that even a short wire
    is enough to trigger the input high through the electromagnetic noise that is in the air evereywhere.

    To avoid this even the simplest switch needs a pull-down-resistor.

    instead of IO-Pin
    switch
    +3.3V you should use

    GND---PullDownResistor----10kOhm---IO-Pin---switch
    +3.3V

    als long as the switch is opened the IO-pin "sees" 0.0V (through the 10 kOhm-resistor) if the switch is closed
    the IO-pin "sees" 3.3V as all voltage drops over the pull-down-resistor.

    So an opened switch creates a low
    a closed switch creates a high.
    But there is another effect. switch-bouncing. mechanical switches open and close in the millisecond area a few times if you change their state.
    So for real proper operation you need debouncing too.

    About the code: If you name your variables less cryptic but much more self-explaining I could write you a spin-equivalent.
    Or you could write the SPIN-equivalent with questions and I will answer them


    As you are using a 56kHz decoder. your diode must "send" a 56kHz signal. This can't be done in SPIN only when using a counter of a cog.
    @JonnyMac: do you have a code-snippet handy for sending a modulated IR-signal?

    For the further progress of your project. chunk down the whole project in small pieces.
    1 piece creating a 56kHz signal.
    2 piece testing if the receiver is reacting on this signal
    3 sending a hardcoded test-bit-stream and checking if the receiver decodes the bitstream

    you might think Oh man that will take a lot of time! I can tell you from my experience: investing this time in the beginning saves you 3 to 10 times later for searching
    small (but "efficient") bugs in a big grown code

    best regards
    Stefan

    P.S: in the meantime I tried to understand your picbasic-code
    but I havesome questions. So my questions are a good demonstration of what you should do in SPIN

    My questions are inserted behind a "!" similar to a comment

    send_data:                                      'send 14 bits 
            CCP1CON = 12                            'send MT header pulse (2.4mS)
            pauseus mtheader !what does this line of code do pausing execution for the value inside mtheader?? 
            CCP1CON = 0
            @ bcf PORTC, 2   !does this define port C pin 2 as output?  
    
    
    Main_byte:
            databyte = P_ID & 111111             '(packet_ID=0; shot)  
            GoSub send_byte
    
    send_byte:                                              'send 8 bits
            For bit_counter = 1 TO 8        'send 8 data bits
                    pauseus mtspace     'space between data pulses  
                    IF databyte.7 = 1 Then trans
                            CCP1CON = 12            'send zero
                    pauseus mtbit0  
                            CCP1CON = 0
                            @ bcf PORTC, 2         !please explain the meaning of "@ bcf"
                            @ rlcf  _databyte,F    !please explain the meaning of "@rlcf  _databyte,F"         
                    GoTo bypassx
    trans:
                            CCP1CON = 12            'send one
                    pauseus mtbit1                 !where does "mtbit1" gets its value??? 
                            CCP1CON = 0     
                            @ bcf PORTC, 2  
                            @ rlcf  _databyte,F             
    bypassx:
            Next bit_counter
            
            Return
    
  • JonnyMacJonnyMac Posts: 9,107
    edited 2013-01-14 12:55
    @JonnyMac: do you have a code-snippet handy for sending a modulated IR-signal?

    For anyone willing to spend a few minutes studying the Propeller, controlling a modulated IR LED becomes trivial.

    1) It's easy to setup a counter for any popular IR modulation frequency
    2) The output of the counter is OR'd with the normal pin driver in that cog

    What this means is that you assign a counter (NCO mode) to a pin and make that pin an output. With this you have your modulation signal. The easiest way to control a IR LED with this scheme is to connect the output pin to the CATHODE side of the IR LED circuit (connect the anode to 3.3v through a suitable resistor). Here's where it gets fun: if you make that pin high you will stop the modulation.

    Why? See #2 above. If either input to an OR gate is high then the output his high. As the output of the OR gate is to the cathode side of the LED circuit the LED will turn off. As soon as you take the pin low counter output will toggle the pin again. Easy-peazy. My SIRCS TX object does exactly this.

    For those just wanting to experiment you can use this Spin method (from my standard template) to set a pin to modulate an LED. To control the LED take that same pin high (off) and low (modulated).
    pub set_freq(ctrx, px, fx)
    
    '' Sets ctrx to frequency fx on pin px (NCO/SE mode)
    '' -- fx in hz
    '' -- use fx of 0 to stop counter that is running
    
      if (fx > 0)                             
        fx := ($8000_0000 / (clkfreq / fx)) << 1            ' convert freq for NCO mode    
        case ctrx
          "a", "A":
            ctra := ((%00100) << 26) | px                   ' configure ctra for NCO on pin
            frqa := fx                                      ' set frequency
            dira[px] := 1                                   ' make pin an output
         
          "b", "B":                         
            ctrb := ((%00100) << 26) | px  
            frqb := fx                    
            dira[px] := 1
    
      else
        case ctrx
          "a", "A":
            ctra := 0                                       ' disable counter
            outa[px] := 0                                   ' clear pin/driver 
            dira[px] := 0                                  
         
          "b", "B":                         
            ctrb := 0 
            outa[px] := 0  
            dira[px] := 0
    
  • snakiesnakie Posts: 12
    edited 2013-01-16 13:44
    [COLOR=#3E3E3E][FONT=Parallax]                        @ bcf PORTC, 2 'clears the IR pin output to insure its off could I use something like outa[irled]~  
    [/FONT][/COLOR][COLOR=#3E3E3E][FONT=Parallax]        @ rlcf  _databyte,F 'This rotates one bit to the left of the carrier flag[/FONT][/COLOR]
    

    mtbit0 CON 600 This is in a file for variables and constants
    [COLOR=#3E3E3E][FONT=Parallax]send_data:                                      'send 14 bits 
    [/FONT][/COLOR][COLOR=#3E3E3E][FONT=Parallax]        CCP1CON = 12                            'send MT header pulse (2.4mS)
    [/FONT][/COLOR][COLOR=#3E3E3E][FONT=Parallax]        pauseus mtheader ![/FONT][/COLOR]mtheader        CON 2400 its waiting for the signal to be sent[COLOR=#3E3E3E][FONT=Parallax] 
    [/FONT][/COLOR][COLOR=#3E3E3E][FONT=Parallax]        CCP1CON = 0 [/FONT][/COLOR][COLOR=#3E3E3E][FONT=Parallax]
    [/FONT][/COLOR][COLOR=#3E3E3E][FONT=Parallax]        @ bcf PORTC, 2 !this clears it[/FONT][/COLOR]
    


    @JonnyMac what would it look like connected I'm not sure I understand that part.

    Thank you guys for the help, I'm slowly getting used to spin and some parts begin to make a little more sense now.
    The main reason I am using the propeller is for the different cogs allowing the ability to do more and be faster.
  • snakiesnakie Posts: 12
    edited 2013-01-16 18:42
    So i started try to convert it to spin and wanted to see if what I have been doing is right so far
    Con
    
      mtheader      = 2400
      mtspace       = 600
      mtbit0        = 600
      mtbit1        = 1200
      P_ID          = x
      IR_LED        = y
    
    
      
    Var
    
    
      byte  bit_counter
    
    
       
    Pub main
    
    
      Dira[IR_LED]~~
    
    
      Repeat
        If ina[trig]
         send_data
    
    
    
    
    Pub send_data                                      'send 14 bits 
            CCP1CON = 12                            'send MT header pulse (2.4mS)
            pauseus mtheader  
            CCP1CON = 0
            Outa[IR_LED]~     
    
    
    
    
    Pub Main_byte
            databyte = P_ID & 111111             '(packet_ID=0; shot)  
            send_byte
    
    
            
    Pub send_byte                                              'send 8 bits
            For bit_counter = 1 TO 8        'send 8 data bits
                    pauseus mtspace     'space between data pulses  
                    IF databyte.7 = 1 Then trans
                            CCP1CON = 12            'send zero
                    pauseus mtbit0  
                            CCP1CON = 0
                            Outa[IR_LED]~         
                            @ rlcf  _databyte,F             
                     bypassx
    
    
                     
    Pub trans
                            CCP1CON = 12            'send one
                    pauseus mtbit1                 
                            CCP1CON = 0     
                            Outa[IR_LED]~  
                            @ rlcf  _databyte,F
    
    
            Return
    
    
                           
    Pub bypassx
            Next bit_counter
            
            Return
    
  • StefanL38StefanL38 Posts: 2,292
    edited 2013-01-16 23:54
    Hi Snakie,

    thank you for posting your code.

    From this I can see you are a basic-guy. Now basic is a programming-language that is quite-non-structural compared to other languages like C, Pascal, Delphi, Java and SPIN.
    (visual basic from microsoft is called "basic" but it is much more structural than old basic versions like the one on the famous C64)

    Structural means here you have a set of predefined commands that can be used do define new commands that can be used (and called) exactly the same way as the basic ones.
    This allowes to code in a way that each part of the code that is a senseful unit will become one new powerful command.

    a small example a command to wait for microses:
    There is no predefined command for that in SPIN. But you can easily expand the set of predefined commands to have one
    PUB PauseUs (p_waitTime)
    
      if p_waitTime < 385
        p_waitTime := 385
         
      WaitCnt(CLkFreq / 1_000_000 * p_waitTime + cnt)
    
    
    PUB PauseMs (p_waitTime)
    
      if p_waitTime < 1
        p_waitTi= 1
        
      WaitCnt(CLkFreq / 1_000 * p_waitTime + cnt)
    

    to use this command you write
      PauseUs(mtheader)
    

    I guess you think SPIN is 99% similar to picbasic. It is only 89% similar. So you have to learn these 11% by going through the PE-Kit lab
    that shows you in small steps how the propeller-chip and SPIN works.

    Download the text http://www.parallax.com/Portals/0/Downloads/docs/prod/prop/PELabsFunBook-v1.1.pdf and the sourcecode-examples
    http://www.parallax.com/Portals/0/Downloads/docs/prod/prop/PELabsFunCode-v1.1.zip

    and work through them. This will need time in the beginning but will speed you up later.

    best regards
    Stefan
  • snakiesnakie Posts: 12
    edited 2013-01-17 04:56
    Ya I know spin is much different, I had left the things in that I did not know yet. I have another question about what the spin equilevent to CCPxCON (the module control register) or how can I make it do a similar task?

    I started learning C a long time ago maybe 6 years ago or so and since then not using it all through college I have forgotten it. The closest I have been since was a language for an industrial robot which was a mixture of c and basic for college.

    Getting there I thank you guys for all the help.
  • StefanL38StefanL38 Posts: 2,292
    edited 2013-01-17 08:14
    Hi Snakie,

    what is the module control-register good for? Or at least can you say wich pic-type does picbasic support?
    So I can lookup the manual what the module control register is good for. (the name is only half selfexplaining)

    Almost 30 years ago I coded a little bit assembler for 6502. Since 2006 I have coded only delphi and with the propeller-chip.

    best regards
    Stefan
  • JonnyMacJonnyMac Posts: 9,107
    edited 2013-01-17 11:27
    It would do you a lot of good to go through the PEK tutorial (you can find it in the Spin Tool Help menu) before you embark on any serious projects. Spin is actually fairly easy if one simply accepts it as-is and not try to compare it to other languages(C, BASIC, etc.). Spin was designed for the Propeller, hence it's the easiest language to use with it.

    That said, high-performance processes really do want to be coded in Assembly which is why my IR code is. Still, you *can* do simple SIRCS in Spin as the attached program demonstrates. I probably wouldn't use this code in a commercial application, but for simple projects and fun and learning, it may serve to help you understand the implantation of an IR protocol in Spin.

    Please understand that the rx_sircs method blocks the program until a code shows up. If your app needs to do other things while waiting on a code then you need to launch another cog that can wait on the code and stuff it into a global variable for you,

    Again, SIRCS is an easy protocol to understand and implement. Once you do, you can modify it and create you own (as I'm presently doing for a shooting gallery game).

    Edit: Renamed file to indicate SIRCS, removed bogus note about pulse timing resolution.
  • snakiesnakie Posts: 12
    edited 2013-08-30 20:28
    i have finally had time to work on my stuff again. Well thanks JonnyMac after doing some smaller stuff and working on making the rest of the project (that I know how to do lol) work I revisited your sircs stuff and it began to make sense I was able to get both my rx and tx working but i'm unable to get them to work together so that neither waits for the other. I'm trying to figure out where i should start a new cog so that i can have both on cogs so that they don't fight with eachother? Thanks for the help by the way :) I must say since I came back I have made many advances on the project.
  • JonnyMacJonnyMac Posts: 9,107
    edited 2013-08-30 22:11
    I wrote the code for the 2012 DEFCON badge that used my IR TX and RX objects. In order to minimize current and prevent interference, I would unload the RX cog when I wanted to TX; when TXing is done, stop it and restart RX. It sounds like a lot of work but in the grand scheme of things it isn't. I also added disable() and enable() methods to my RX object so that I could switch it off (while TXing) without unloading the cog.

    I've attached my PASM RX and TX objects -- they're very easy to use.
  • snakiesnakie Posts: 12
    edited 2013-08-30 22:29
    So I can't have both the TX and RX running at the same time say for instance in my game you would need to TX when you pull the trigger but would still be able to get hits from the RX how can I make it do that or can I?
  • JonnyMacJonnyMac Posts: 9,107
    edited 2013-08-31 08:15
    You can have them running at the same time but there is a very great possibility that you will end up receiving your own transmission. This is why I added the .disable() method to my RX object -- it stops looking for IR until I renable it; that way, I don't have to flush my own transmission out of the receive buffer. Once the transmission is done, use .enable() to allow the receiver to work again. These are simple method calls, and certainly faster than unloading/reloading cogs (which I did to reduce power consumption in the battery-powered badge).

    Obviously, you need to do some empirical testing. Try to transmit with the receiver enabled and see if there is bleed from the TX to RX sides. If there is, use .disable() and .enable() with the receiver side. If there's no bleed, you're good to go -- write the rest of your program. If there is, ignoring your own transmission is this easy:
    [s]irin.disable[/s]
      irout.tx(BULLET, 12, 1)
      repeat while (irtx.busy)
      irin.enable
    


    EDIT: Technically, you don't need to use .disable() in this case. When you use the .enable() method after transmitting, the RX buffer is flushed; even if you RX your own code, this cleans it out.
  • snakiesnakie Posts: 12
    edited 2013-08-31 17:42
    Thank you so much, i'm going to try that a little later and see how it goes. Thanks again for the help, I hope to have a working model in a week or 2.
  • snakiesnakie Posts: 12
    edited 2013-08-31 21:29
    Seems to be working as far as I can tell with only the one board only thing is I don't know if my count is right the clock was at _clockmode = xtal1 + pll16x and _xinfreq = 5_000_000 but I am using a 16 MHz crystal so i have it currently set to _clockmode = xtal1 + pll4x and xinfreq = 16_000_000 is this going to through off my code at all or is it small enough that it doesnt really matter? And thank you for all the help this is great :) works like a charm ;)
  • PublisonPublison Posts: 12,366
    edited 2013-09-01 04:25
    snakie wrote: »
    Seems to be working as far as I can tell with only the one board only thing is I don't know if my count is right the clock was at _clockmode = xtal1 + pll16x and _xinfreq = 5_000_000 but I am using a 16 MHz crystal so i have it currently set to _clockmode = xtal1 + pll4x and xinfreq = 16_000_000 is this going to through off my code at all or is it small enough that it doesnt really matter? And thank you for all the help this is great :) works like a charm ;)

    Your 16 Mhz crystal is out of spec for the Propeller. The Data Sheet , (page 25), specifies the frequency to be between 4 and 8 Mhz. Outside of that range you may get strange results
  • JonnyMacJonnyMac Posts: 9,107
    edited 2013-09-01 08:15
    snakie wrote: »
    Seems to be working as far as I can tell with only the one board only thing is I don't know if my count is right the clock was at _clockmode = xtal1 + pll16x and _xinfreq = 5_000_000 but I am using a 16 MHz crystal so i have it currently set to _clockmode = xtal1 + pll4x and xinfreq = 16_000_000 is this going to through off my code at all or is it small enough that it doesnt really matter? And thank you for all the help this is great :) works like a charm ;)

    As with most of my objects the SIRCS RX and TX code is clock frequency agnostic (though you should head the warning from Publison about the input frequency). While working on the DEFCON badge I tested it at 20MHz (5MHz, PLL = 4x) and it worked fine. SIRCS is a slow protocol, so one doesn't need blazing processor speed to run it. Using a counter to handle the IR LED modulation simplifies things a great deal, as well.
  • snakiesnakie Posts: 12
    edited 2013-09-01 13:10
    oh I had no idea because i say the different values for the xtal values so I just assumed it was able to handle it. So I guess on my next order i should invest in a few 5 MHz crystals. Thanks for the advice and help :)
Sign In or Register to comment.