Recording incoming logic signal duration, both edges - how to?


Closed Thread
Results 1 to 7 of 7
  1. #1
    Join Date
    Aug 2006
    Location
    SWITZERLAND (french speaking)
    Posts
    891

    Default Recording incoming logic signal duration, both edges - how to?

    Hello,

    I'm struggling with a stupid problem for a while now and maybe someone has a good idea out there.

    The goal is to record, for every high and low state of an incoming logic signal, its duration.

    I'm capturing an incoming IR signal through a receiver module (i.e. TSOP32228) so I don't worry about the carrier frequency and the signal is "loud and clear" for the PIC (no bounce or any other disturbance).

    Common IR remote protocols signals can last from 300µs up to around 10ms long.

    Since I want to know how long each logic state (high and low) lasts, I first used RCTIME.

    With this command, I easily measure half-a-pulse duration. Unfortunately, because of the power supply of the PIC (3V) and the max Xtal speed (8MHz), the resolution (5µs) doesn't permit a precision "good enough". With this method, a 300µs state (low or high) will return a RCTIME value between 50 and 70 which is around ±33% (!). By experience, acceptable values (< ±3%) can be measured starting with measures of incoming signals over 1ms.

    I have also tried to "look" at a state change on a PORT. I made it with WHILE and with IF loops. The result is better but still not good enough especially for short signals (less than 1ms).

    I then had a look to use INTERRUPTS, RB0/INT. Problem: I can catch only either the falling or the rising edge.

    Same happens when I thought about using the Capture Mode of my PIC16LF88 where I have to choose either edge too.

    Can anyone give me some advice on the best way for me to go?

    Shall I change PIC with a higher Xtal frequency @ low voltage (like PIC16F1827)?

    For sure, I don't want to buy an already-made self-learning universal IR remote!
    Roger

  2. #2
    Join Date
    Dec 2005
    Posts
    1,073


    Did you find this post helpful? Yes | No

    Default

    What type of accuracy are you after? I've had a lot of experience with both IR and RF and have found ±10% is adequate as most of the protocols were developed for battery operation where there can be a lot of variation. What protocol are you trying to capture?

    Here's code that I use with X-10 RF signals (which are essentially the same as NEC IR signals) as well as with several other RF protocols. It can handle almost all PDM/PWM signals. The resolution is only limited by the timer prescaler. If you want better resolution, use a faster oscillator. I was replacing a 12C508A in an existing module so had to use the internal 4Mhz oscillator. You can modify this to capture both pulses and spaces. I only needed the time between rising edges here.
    Code:
     'MR26X509.BAS
    'PIC12F509 @ 4MHz          663 words		uses MPASM
    
    'Pin 1 - Vdd
    'Pin 2 - GPIO.5
    'Pin 3 - GPIO.4
    'Pin 4 - GPIO.3
    'Pin 5 - GPIO.2 RS232 output @ 9600bps
    'Pin 6 - GPIO.1 Receives up to 48 bits of PDM/PWM RF with lead-in of 2-9mS
    'Pin 7 - GPIO.0
    'Pin 8 - Vss
    
    'TMR0 1:64 29=1.9mS,145=9.3mS - 1:16 49=0.8mS,93=1.5ms,155=2.5ms
    '===============================================================
    
    @ __config _IntRC_OSC & _WDT_OFF & _MCLRE_OFF & _CP_OFF
     
    DEFINE OSC 4
    DEFINE DEBUG_REG GPIO
    DEFINE DEBUG_BIT 2 				
    DEFINE DEBUG_MODE 1 				
    DEFINE DEBUG_BAUD 9600	
    
    RF      VAR 	byte[6]
    i       VAR 	byte  
    period  VAR     byte
    bytes	VAR	byte           	
    sof  	VAR 	byte
    x       VAR     byte
    	
    	OPTION_REG=%11000101		'TMR0 1:64 prescaler, disable TOCKI
            TRISIO=%000010                  'make GPIO.1 an input, rest outputs                 
            GPIO=%000000                    'all outputs low
            Debug "MR26X",13,10
            Debug "Copyright ",169," 2009 dlh",13,10
            Goto init
            
    hexout: If x>>4<10 Then
              Debug x>>4+48
            Else  
              Debug x>>4+55
            EndIf
            if x//16<10 Then  
              Debug x//16+48
            Else    
              Debug x//16+55
            EndIf
            Return        
    
    init:	RF[0]=0:RF[1]=0:RF[2]=0:RF[3]=0:RF[4]=0:RF[5]=0
            While GPIO.1=0:Wend		'wait rising edge	
            TMR0=0		                'clear TMR0
            OPTION_REG=%11000101		'TMR0 prescaler=64
            While GPIO.1=1:Wend             'wait falling edge
            sof=TMR0			'read TMR0
            If (sof<29) Then init		'1920µS
            OPTION_REG=%11000011		'TMR0 prescaler=16
            While GPIO.1=0:Wend		'wait rising edge
            TMR0=0				'reset TMR0
            OPTION_REG=%11000011		'TMR0 prescaler=16
            i=0
            Repeat
              While GPIO.1=1                'wait falling edge
    	    If TMR0>175 Then break  	'2800µS  
              Wend				'falling edge
              While GPIO.1=0                'wait rising edge
    	    If TMR0>175 Then break  	'2800µS  
              Wend				'rising edge       
              Period=TMR0:TMR0=0            'clear TMR0
              OPTION_REG=%11000011		'TMR0 prescaler=16
              If (period<49) Then init	'800µS
              If (period>93) Then		'1500µS		
                RF.0(i)=1				
              EndIf
              i=i+1
            Until (i>47)
    break:  If (i<12) Then init  
            bytes=i/8
            If i//8 Then
    	  bytes=bytes+1
            EndIf
            x=i:GoSub hexout
            For i = 0 to bytes-1
      	  x=RF[i]:GoSub hexout
            Next
            Debug 13,10
            GoTo init
            
            End
    Last edited by dhouston; - 5th January 2010 at 16:47.

  3. #3
    Join Date
    Jul 2003
    Posts
    2,405


    Did you find this post helpful? Yes | No

    Default

    If you have an 18F2431 on-hand you can do it all in hardware with the motion feedback
    module capture. It will record the time for every state change. Very handy for learning
    different remote control encoders, IR signals, etc..

    I have a code example if you're interested.
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

  4. #4
    Join Date
    Aug 2006
    Location
    SWITZERLAND (french speaking)
    Posts
    891


    Did you find this post helpful? Yes | No

    Default

    Hi Dave,

    I'm recording all kind of remotes like ones for TVs as well as garage-door openers, electric-shades and so on. My remote is ment to be really "universal", well at least I dream it will be so.

    As where most TV protocols work fine with my code, the other ones don't use "standard" protocols and that's the reason why I have to record both signal's state durations with, appearently, a little more precision.

    This is the "learning sequence" of the code I currently work on:
    Code:
    <html><head></head><body><!--StartFragment--><pre><code><font color="#000000">LEARN:
    <b>PULSIN </b>IRM_Out, 0, l_Bit[0]        <font color="#000080"><i>'get the first Low pulse
    </i></font><b>TOGGLE </b>C_Led                       <font color="#000080"><i>'indicate the &quot;waiting state&quot; to user
    </i></font><b>IF </b>l_Bit[0] = 0 <b>THEN </b>LEARN:        <font color="#000080"><i>'wait for the first pulse to start recording
    </i></font>C_Led = 1                          <font color="#000080"><i>'led is ON, learn has started
    </i></font><b>RCTIME </b>IRM_Out, 1, h_Bit[0]        <font color="#000080"><i>'get first High pulse from IR Module
    </i></font><b>FOR </b>Ctr_A = 1 <b>TO </b>(Max_Bit - 1)
       <b>RCTIME </b>IRM_Out, 0, l_Bit[Ctr_A] <font color="#000080"><i>'get Low pulse (1 to 38) from IR Module
       </i></font><b>RCTIME </b>IRM_Out, 1, h_Bit[Ctr_A] <font color="#000080"><i>'get High pulse (1 to 38) from IR Module
    </i></font><b>NEXT </b>Ctr_A
    <b>RCTIME </b>IRM_Out, 0, l_bit[Max_Bit]  <font color="#000080"><i>'get last Low pulse from IR Module
    </i></font><b>RCTIME </b>IRM_Out, 1, H_bit[Max_Bit]  <font color="#000080"><i>'get last High pulse from IR Module
    </i></font>C_Led = 0
    <b>END</b></code></pre><!--EndFragment--></body></html>
    Full code is in attached ZIP file.

    I'll try to adapt your code to my usage and see what I get. Thanks a lot for that.

    Bruce,

    I have only some 10F, 12F and 16F in my drawer

    Nevertheless, I'm going to grab the datasheet of this particular PIC and see what this function does. Something new to learn
    Attached Files Attached Files
    Roger

  5. #5
    Join Date
    Dec 2005
    Posts
    1,073


    Did you find this post helpful? Yes | No

    Default

    Roger,

    My code is for RF so you'll need to change polarities. I'm checking for timeout during the initial pulse of each bit but am not recording the duration. It shouldn't take much modification.

    Is this a commercial project? If it's just a one-off for your own use, you might want to consider a ZX328n from ZBasic. At $10 (plus some supporting components), it comes with a bootloader preloaded. ZBasic (free compiler) has built-in functions (InputCapture and InputCaptureEx) that will do what you wish with 37.8nS resolution.

    However, I doubt you need better than 50µS resolution. Years ago I did what you're doing only instead of doing it in real-time, recorded codes as .WAV files using a soundcard and then decoded them afterwards. As I recall I was able to automatically handle all of the protocols I came across.

    You might also consider USB-UIRT which not only captures the codes (as Philips Pronto CCF files) but also measures the IR carrier frequency.

  6. #6
    Join Date
    Jan 2009
    Posts
    22


    Did you find this post helpful? Yes | No

    Default capture IR remote

    I've had some luck using the capture function of the CCP module.

    Set up an interrupt (or just poll the CCP1 flag) and alternate between setting CCP1CON=$04 and CCP1CON=$05 to capture TMR1 to CCPR1H:CCPR1L on falling and rising edges, respectively. As TMR1 runs, you can save as many transitions as memory allows. (You may be able to use just the highbyte, depending on the resolution you need.)

    To transmit the recorded signal, set up as compare mode CCP1CON=$0A and toggle the output on and off.

  7. #7
    Join Date
    Aug 2006
    Location
    SWITZERLAND (french speaking)
    Posts
    891


    Did you find this post helpful? Yes | No

    Default

    Thanks bruce.

    This is absolutely non-commercial. It is more about to see how "far" I can go using PICs. I will adapt your code; it is always worth a try

    gmglickman,

    Would you have some code snippet to share? I did something similar but didn't work well.

    BTW, I have already made some remotes for friends of mine; all remotes are working fine. You can see how one look like here http://home.citycable.ch/flotulopex/...I_Frames_e.htm
    Last edited by flotulopex; - 6th January 2010 at 07:58. Reason: spelling
    Roger

Similar Threads

  1. Replies: 24
    Last Post: - 1st December 2009, 08:01
  2. Decoding an incoming infrared signal: need advice
    By xnihilo in forum mel PIC BASIC Pro
    Replies: 10
    Last Post: - 9th May 2008, 16:28
  3. PIC16F684 + LCD to use the 256bytes of EEPROM - HELP
    By xnihilo in forum mel PIC BASIC Pro
    Replies: 3
    Last Post: - 7th March 2008, 14:19
  4. Help with sound command in 2 programs
    By hyperboarder in forum mel PIC BASIC Pro
    Replies: 4
    Last Post: - 5th July 2007, 20:36

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts