Hot!38KHz with Timer0 PIC16F648A

Page: 123 > Showing page 1 of 3
Author
ounvme
Starting Member
  • Total Posts : 65
  • Reward points : 0
  • Joined: 2012/03/10 13:35:40
  • Location: 0
  • Status: offline
2019/03/10 01:05:22 (permalink)
0

38KHz with Timer0 PIC16F648A

I found an IR remote that uses a 16F648A. Unfortunatley it does not use the PWM and only has a 4Mhz crystal. I pulled the chip and I am doing some bench testing. I need to generate a non standard IR code. The IR led is connected to pin 13 so I figure my best shot is using timers. I can't seem to get Timer0 to interrupt properly. I am looking to toggle a pin at 13uS but my logic analyzer is giving me 63.5uS and I can't find why. The interrupt should happen every 13uS unless I suck at math. 153 accounts for the 2 cycles to reset the register. I am testing with an 8Mhz crystal.
 
// CONFIG
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator: High-speed crystal/resonator on RA6/OSC2/CLKOUT and RA7/OSC1/CLKIN)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT enabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = ON // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is MCLR)
#pragma config BOREN = OFF // Brown-out Detect Enable bit (BOD enabled)
#pragma config LVP = OFF // Low-Voltage Programming Enable bit (RB4/PGM pin has PGM function, low-voltage programming enabled)
#pragma config CPD = OFF // Data EE Memory Code Protection bit (Data memory code protection off)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <xc.h>

#define _XTAL_FREQ 8000000


void send_pulse(int pulse_length);


void main(void)
{
  //SYSTEM_Initialize();
  OSCF = 1;
  nRBPU = 0;
   /**
    LATx registers
    */
    PORTA = 0x00;
    CMCON = 0x00;
    VRCON = 0x00;
    
    PORTB = 0x00;
    OPTION_REG = 0b10000000;
    
    
    /**
    TRISx registers
    */
    TRISA = 0b11111111;
    TRISB = 0b01111111;
    
// Timer0 Registers:
// Prescaler=1:1; TMR0 Preset=153; Freq=76,190.47619Hz; Period=13,125 ns
T0CS = 0;// bit 5 TMR0 Clock Source Select bit:0=Internal Clock (CLKO) / 1=Transition on T0CKI pin
T0SE = 0;// bit 4 TMR0 Source Edge Select bit: 0=low/high / 1=high/low
PSA = 1;// bit 3 Prescaler Assignment bit: 0=Prescaler is assigned to the Timer0
PS2 = 0;// bits 2-0 PS2:PS0: Prescaler Rate Select bits
PS1 = 0;
PS0 = 0;
TMR0 = 153; // preset for timer register(2 cycle adjusted)


// Interrupt Registers
  INTCON = 0; // clear the interrpt control register
  TMR0IE = 1; // bit5 TMR0 Overflow Interrupt Enable bit...1 = Enables the TMR0 interrupt
  TMR0IF = 0; // bit2 clear timer 0 interrupt flag
  GIE = 1; // bit7 global interrupt enable
    

    
    while (1)
    {
    
     
        
    }
    
    
    
    
}

void send_pulse(int pulse_length)
{
   
     
  
    
}

void send_code(int code1, int code2, int code3)
{
   
    
}

// Interrupt Handler
void __interrupt() my_isr(void)
{
  // Timer0 Interrupt - Freq = 12987.01 Hz - Period = 0.000077 seconds
  if (TMR0IF ==1) // timer 0 interrupt flag
  {
    RB7 = ~RB7; // Toggle RB7
    TMR0IF = 0; // clear the flag
    TMR0IE = 1; // reenable the interrupt
    TMR0 = 153; // reset the timer preset count
  }

}
 

 
For those that are curious. I here is one of the codes timing. The bold numbers are the only 3 that change in length with any of the codes sent. Very non standard. 1 pulses are at 38KHz for the noted time in uS. This code repeats with an 80.2mS gap.
 
post edited by ounvme - 2019/03/10 01:09:03

Attached Image(s)

#1

46 Replies Related Threads

    qhb
    Superb Member
    • Total Posts : 9654
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: offline
    Re: 38KHz with Timer0 PIC16F648A 2019/03/10 01:54:24 (permalink)
    0
    Now, your crystal is 8MHz, so Fosc/4 is 2MHz.
    You've assigned the prescaler to WDT, so it's getting clocked by (Fosc/4)/2 = 2 MHz
     
    If your ISR is writing 153 to TMR0, then it will overflow in 256 - 153 counts = 103
    This will take 103 / 2MHz = 0.0000515s (51.5 us) = 19417 Hz
    (although it will be a bit slower to allow for the ISR entry and the instructions in the ISR before you update TMR0)
    You can automatically allow for those instructions by ADDING 153 to TMR0 rather than just writing it.
     
    Why are you setting TMR0IE in the ISR. It's guaranteed to be set if you got into the ISR at all.
     
    #2
    ounvme
    Starting Member
    • Total Posts : 65
    • Reward points : 0
    • Joined: 2012/03/10 13:35:40
    • Location: 0
    • Status: offline
    Re: 38KHz with Timer0 PIC16F648A 2019/03/10 09:17:06 (permalink)
    0
    I can't get this thing to interrupt at 13uS no matter what I do. I am totally confused at this point.
    With the PS going to WDT timer0 should be FOSC/4 My ISR with TMR0 = 230 cycles at 24.5uS and not 13uS. I am going to check this with a scope to rule out the Logic Analyzer.
    post edited by ounvme - 2019/03/10 09:56:51
    #3
    ounvme
    Starting Member
    • Total Posts : 65
    • Reward points : 0
    • Joined: 2012/03/10 13:35:40
    • Location: 0
    • Status: offline
    Re: 38KHz with Timer0 PIC16F648A 2019/03/10 13:01:31 (permalink)
    0
    The timer0 is just not going to work at 4MHz the overhead is too much for the ISR to toggle at at 76KHz. I have no clue how they were able to generate the carrier frequency and send the pulse lengths on an IO pin. Even at 8MHz I have to set TMR0 =249 to get the carrier frequency and remove the IF (TMR0IF == 1) from the ISR. Stumped at this point.
     
    My next try will be to use a while loop to generate the carrier frequency and use timer0 to control the length.
     
    Anyone have any ideas?
     
    These values were obtained measuring the 38KHz pulses on the IR led in the actual remote.
    Here is what I need on pin RB7:
    1 - 270uS
    0 - 970uS
    1 - 260uS
    0 - 1930uS
    1 - 260uS
    0 - 700uS
    1 - 260us
    0 - 2755uS
    1 - 250uS
    0 - 1810uS
    1 - 240uS
    0 - 1810uS
    1 - 240uS
    0 - 730uS
    1 - 235uS
    0 - 2500uS
    1 - 230uS
    0 - 80.2mS
    #4
    Ian.M
    Super Member
    • Total Posts : 13224
    • Reward points : 0
    • Joined: 2009/07/23 07:02:40
    • Location: UK
    • Status: offline
    Re: 38KHz with Timer0 PIC16F648A 2019/03/10 13:21:53 (permalink)
    0
    At 8MHz Fosc,  13us is only 26 instruction cycles.   It takes two cycles to enter the ISR (see datasheet FIGURE 14-15: INT PIN INTERRUPT TIMING, 'dummy cycle'), and the *MINIMUM* code to successfully save and restore context in an ISR is (MPASM assembler):

    ORG 0x004 ; interrupt vector location
    movwf w_temp ; save off current W register contents
    movf STATUS,w ; move status register into W register
    movwf status_temp ; save off contents of STATUS register
    movf PCLATH,w ; move pclath register into W register
    movwf pclath_temp ; save off contents of PCLATH register
    ; isr code goes here or be located as a call subroutine elsewhere
    movf pclath_temp,w ; retrieve copy of PCLATH register
    movwf PCLATH ; restore pre-isr PCLATH register contents
    movf status_temp,w ; retrieve copy of STATUS register
    movwf STATUS ; restore pre-isr STATUS register contents
    swapf w_temp,f
    swapf w_temp,w ; restore pre-isr W register contents
    retfie ; return from interrupt (2 cycles)

    which takes 13 cycles to execute.  Therefore the rest of the ISR must take less than ten instruction cycles.   If it takes 11, the main program will stall and if it takes more, the rate will be determined by the ISR execution time, not the rate at which the interrupt is triggered.  I believe there's additional context saving when using XC8 which will further decrease the number of available cycles.
     
    Unless you have an XC8 PRO licence, (paid or evaluation) your chances of doing anything useful in ten cycles are minimal, and even with  PRO mode optimisations available it certainly wont be able to generate IR modulation in so few cycles.   Your only chance is to drop in in a 20MHz crystal, which gives you 65 cycles in 13us, so a max of 50 available for your ISR code.  Even so it will be really tight.
     
    If you use a PWM module its considerably easier, as the timer reload is automatic, and you only have to load the duty cycle once per PWM period to enable/ disable the 38KHz pulse in that  period to generate the waveform, which halves the interrupt rate compared to bit-banging it.

    --
    NEW USERS: Posting images, links and code - workaround for restrictions.
    I also support http://picforum.ric323.com because this forum is sometimes too broken to use!
    #5
    pcbbc
    Super Member
    • Total Posts : 816
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: online
    Re: 38KHz with Timer0 PIC16F648A 2019/03/10 13:51:11 (permalink)
    0
    I expect it bitbangs the required waveforms in software, including the 38khz carrier.

    That really is not hard to do in assembler, you only need a handful of pulse widths and delays to make any common consumer IR protocol. I have built simple IR receivers and transmitters using PIC12 parts in the past.

    There is ample quiet time time between codes to do any scanning of the remote keyboard, which is the only other function required.

    So no interrupts required, although I suppose you could use one every 114ms (RC5 repeat rate) and then bitbang out an entire code sequence in the ISR. No problem if the ISR is hung up for 30-40ms doing this as there is no other interrupts to service or time critical processing.
    #6
    dan1138
    Super Member
    • Total Posts : 3040
    • Reward points : 0
    • Joined: 2007/02/21 23:04:16
    • Location: 0
    • Status: offline
    Re: 38KHz with Timer0 PIC16F648A 2019/03/10 15:24:01 (permalink)
    +1 (1)
    It is just possible to do this using XC8 (v2.00) in free mode but it is a hack.
     
    This is my proof of concept code:
    /*
     * File:     main.c
     * Target:   PIC16F648A
     * Compiler: XC8 v2.00
     * IDE:      MPLABX v5.10
     *
     *                       PIC16F648A/P
     *                 ____________  ___________
     *                |            \/           |
     *             1 <> RA2/AN2         AN1/RA1 <> 18
     *                |                         |    
     *             2 <> RA3/AN3         AN0/RA0 <> 17
     *                |                         |    
     *             3 <> RA4            OSC1/RA7 <> 16 8MHz crystal
     *                |                         |    
     * 10K pull-up 4 -> MCLR           OSC2/RA6 <> 15 8MHz crystal
     *                |                         |    
     *         GND 5 -> VSS                 VDD <- 14 5v0
     *                |                         |    
     *             6 <> RB0/INT         PGD/RB7 <> 13 Drive IR LED
     *                |                         |    
     *             7 <> RB1/RXD         PGC/RB6 <> 12
     *                |                         |    
     *             8 <> RB2/TXD             RB5 <> 11
     *                |                         |    
     *             9 <> RB3/CCP1        PGM/RB4 <> 10
     *                |_________________________|
     */
    // CONFIG
    #pragma config FOSC = HS // Oscillator Selection bits (HS oscillator: High-speed crystal/resonator on RA6/OSC2/CLKOUT and RA7/OSC1/CLKIN)
    #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT enabled)
    #pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
    #pragma config MCLRE = ON // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is MCLR)
    #pragma config BOREN = OFF // Brown-out Detect Enable bit (BOD enabled)
    #pragma config LVP = OFF // Low-Voltage Programming Enable bit (RB4/PGM pin has PGM function, low-voltage programming enabled)
    #pragma config CPD = OFF // Data EE Memory Code Protection bit (Data memory code protection off)
    #pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)

    // #pragma config statements should precede project file includes.
    // Use project enums instead of #define for ON and OFF.

    #include <xc.h>

    #define _XTAL_FREQ (8000000ul)
    #define T0_EDGE_RATE (76000ul)
    #define T0_RELOAD_VALUE (_XTAL_FREQ/(4*T0_EDGE_RATE))
    /*
     *
     */
    void Init_PIC( void )
    {
        INTCON     = 0;          // Disable all interrupts
        PIE1       = 0;
        CMCON      = 0x07;       // Disable comparator analog inputs
        VRCON      = 0x00;       // Disable voltage reference analog I/O
        OPTION_REG = 0b11111111; // Set OPTIONS to default value
    }
    /*
     * Drive IR LED at 38KHz.
     *
     * This is a hack to get around the insane amount of
     * context saving that XC8(free mode) does for an ISR.
     *
     * WARNING: The only interrupt allowed is TIMER0. NO OTHER INTERRUPT SOURCES CAN BE HANDLED!
     * WARNING: If the T0_RELOAD_VALUE is too small (<21) this function will lock up.
     */
    unsigned char __at(0x70) WREG_SAVE;
    unsigned char __at(0x71) STATUS_SAVE;
    void __at(0x0004) IR_38KHz_pulse( void )
    {
        __asm("movwf _WREG_SAVE");
        __asm("movf   STATUS,W");
        __asm("movwf _STATUS_SAVE");
        INTCONbits.T0IF = 0;
        TMR0 -= T0_RELOAD_VALUE-3;
        RB7 ^= 1;
        __asm("movf  _STATUS_SAVE,W");
        __asm("movwf  STATUS");
        __asm("swapf _WREG_SAVE,F");
        __asm("swapf _WREG_SAVE,W");
        __asm("retfie");
    }
    /*
     *
     */
    void Init_TIMER0( void )
    {
        INTCONbits.T0IE = 0;        // Disable TIMER0 interrupts
        TRISBbits.TRISB7 = 1;       // Turn off IR LED driver
        OPTION_REGbits.PSA = 1;     // TIMER0 presacle is 1:1
        OPTION_REGbits.T0CS = 0;    // TIMER0 clock source is _XTAL_FREQ/4
        IR_38KHz_pulse();           // Hack to force XC8 to keep the TIMER0 ISR function
    }
    /*
     *
     */
    void PulseOn(void)
    {
        INTCONbits.T0IE = 0;        // Disable TIMER0 interrupts
        PORTBbits.RB7 = 0;
        TRISBbits.TRISB7 = 0;       // Turn on IR LED driver
        TMR0 = (unsigned char)(0-T0_RELOAD_VALUE);
        INTCONbits.T0IF = 0;        // Clear TIMER0 interrupt
        INTCONbits.T0IE = 1;        // Enable TIMER0 interrupts
    }
    /*
     *
     */
    void PulseOff(void)
    {
        INTCONbits.T0IE = 0;        // Disable TIMER0 interrupts
        PORTBbits.RB7 = 0;
        TRISBbits.TRISB7 = 1;       // Turn off IR LED driver
    }
    /*
     *
     */
    void main(void)
    {
        Init_PIC();
        Init_TIMER0();
        while (1)
        {
            PulseOn();
            NOP();
            __delay_ms(10);
            PulseOff();
            NOP();
            __delay_ms(30);
        }
    }

    #7
    qhb
    Superb Member
    • Total Posts : 9654
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: offline
    Re: 38KHz with Timer0 PIC16F648A 2019/03/10 15:54:55 (permalink)
    0
    If the PIC is already out of the board, why not replace it with something a bit less archaic?
    A PIC16F1827 (https://www.microchip.com/wwwproducts/en/PIC16F1827 ) costs less than $2, and will run rings around a PIC16F648.
    It will run at 32MHz without changing the crystal (or needing one at all).
    It has zero overhead for context saving in interrupts (i.e. it's done in hardware in a single clock cycle)
    Same pinout as a PIC16F648.
    (If you don't need all 4K of the FLASH, you can save a few cents by getting a PIC16F1826 instead)
     
     
    #8
    ounvme
    Starting Member
    • Total Posts : 65
    • Reward points : 0
    • Joined: 2012/03/10 13:35:40
    • Location: 0
    • Status: offline
    Re: 38KHz with Timer0 PIC16F648A 2019/03/10 16:07:13 (permalink)
    0
    The problem is this is a non standard sequence and I cannot determine the length of a 1 or 0. I never thought about replacing the chip. That might be an even better approach. I will review the posted sample and see where that gets me.
    post edited by ounvme - 2019/03/10 16:09:05
    #9
    qhb
    Superb Member
    • Total Posts : 9654
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: offline
    Re: 38KHz with Timer0 PIC16F648A 2019/03/10 16:15:13 (permalink)
    0
    The PIC16F1827 actually contains a complete "Data Signal Modulator" module that would make this trivial, but the output is on pin RB3, which is pin#9 in the 18 pin package.
     
    #10
    pcbbc
    Super Member
    • Total Posts : 816
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: online
    Re: 38KHz with Timer0 PIC16F648A 2019/03/10 20:26:03 (permalink)
    0
    ounvme
    The problem is this is a non standard sequence and I cannot determine the length of a 1 or 0.
    You must know what it is though? If you do not know what it is you have zero chance of reproducing it in code, whatever method you use... Different chip, PWM or bitbanged not withstanding.

    Edit: Sorry, see you have posted your timing.
    How were these measured? Lots of the values look similar, I’d be suprised if many of the intervals (270/260 etc) weren’t inaccuracies in measurement, rather than different intervals per se.
    So you only need to reproduce this one code? Not a complete protocol?
    If you had more examples of other codes from the same protocol you’d stand a chance of working out which were inconsistencies in measurement, and what patterns represented the underlying ones and zeros of the actual payload.

    Regardless you can code with bitbanging. Just determine everything in terms of 38khz, then loop the required number of times for 38khz ON followed by a loop of the required cycles for OFF doing nothing.

    I ageee though that a more up to date chip will make your life easier.
    post edited by pcbbc - 2019/03/10 20:51:51
    #11
    ounvme
    Starting Member
    • Total Posts : 65
    • Reward points : 0
    • Joined: 2012/03/10 13:35:40
    • Location: 0
    • Status: offline
    Re: 38KHz with Timer0 PIC16F648A 2019/03/10 22:47:32 (permalink)
    0
    pcbbc
    ounvme
    The problem is this is a non standard sequence and I cannot determine the length of a 1 or 0.
    You must know what it is though? If you do not know what it is you have zero chance of reproducing it in code, whatever method you use... Different chip, PWM or bitbanged not withstanding.

    Edit: Sorry, see you have posted your timing.
    How were these measured? Lots of the values look similar, I’d be suprised if many of the intervals (270/260 etc) weren’t inaccuracies in measurement, rather than different intervals per se.
    So you only need to reproduce this one code? Not a complete protocol?
    If you had more examples of other codes from the same protocol you’d stand a chance of working out which were inconsistencies in measurement, and what patterns represented the underlying ones and zeros of the actual payload.

    Regardless you can code with bitbanging. Just determine everything in terms of 38khz, then loop the required number of times for 38khz ON followed by a loop of the required cycles for OFF doing nothing.

    I ageee though that a more up to date chip will make your life easier.



    Just to be clear, I have an OEM remote and a China clone REDI REMOTE. The REDI had the PIC inside it and of coarse they didn't replicate the signal properly. The oem remote does't use the FFFFFFFF repeat it just sends the code over and over. I assume these things have some tolerance in the receive side so if I am off by a couple uS it will still work. The Logic Analyzer shows some small shift +-3uS when read from the IR receiver module.
     
    I measured at 24MHz the signal from both the IR LED on the actual remote and also using an IR receiver. The signals match with the exception that the LED pulses at the 38KHz frequency and the receiver eliminates the frequency. I measured 3 functions on the remote and they all have the same timing with the exception of what I will call bits 4, 14 and 16. The length on those 0 bits changes depending what button is pushed. I don't know my IR standards, but I assume this is very non standard. See the attached image:
     
    I can take 10 measurements of each code and normalize them if that will help.
    I also ordered a 16F1827
    post edited by ounvme - 2019/03/10 23:02:39

    Attached Image(s)

    #12
    Ian.M
    Super Member
    • Total Posts : 13224
    • Reward points : 0
    • Joined: 2009/07/23 07:02:40
    • Location: UK
    • Status: offline
    Re: 38KHz with Timer0 PIC16F648A 2019/03/11 00:24:48 (permalink)
    +1 (1)
    The PIC16F1827 will make it a lot easier.  Its got enhanced PWM modules with steering and enough peripheral pin reassignment capability to let you can route one of their outputs to the RB7 pin driving the LED.  Set up 38Khz PWM, then all you have to do is load CCPRxL with a value for an approx 50% duty cycle to start a 38KHz pulsetrain or with 0 to stop it (assuming you leave the two duty cycle LSB bits set to zero).
     
    At its crudest you don't even need any ISRs, you can do the lot with simple software delays and assignments to CCPRxL.  However as the XC8 delay macros don't permit variable delays, it would probably be cleaner to use Timer 1,  and poll its interrupt bit to detect the timeout.

    --
    NEW USERS: Posting images, links and code - workaround for restrictions.
    I also support http://picforum.ric323.com because this forum is sometimes too broken to use!
    #13
    pcbbc
    Super Member
    • Total Posts : 816
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: online
    Re: 38KHz with Timer0 PIC16F648A 2019/03/11 04:57:24 (permalink)
    0
    Those are very dirty traces you are capturing.  Try disconnecting the IR diode on the transmitter and capturing the raw bit stream on the output pin.  Ideally from the OEM remote as you know the clone is buggy.
     
    Yes, there will be quite a lot of tolerance at the receiver.  Both in terms of accuracy of 38khz modulation and the actual bit stream.  Remotes are cheap devices and do not contain precision clocks, and the receiver needs to account for the fact the IR receiver will introduce inaccuracies.
     
    My guess from looking at your first trace (assuming the 38KHz is driving the signal low) is that all ON times are all the same width (around 260uS) and the data is conveyed in the OFF periods with more than two different lengths, which probably implies more than one bit encoded per OFF.
     
    At a very rough guess, it seems to me that everything may be based off a 120uS clock (possibly with a slightly longer initial pulse as run in).  In which case you have:
    time(uS) time/120us bits
      270       2.25      2
      970       8.08      8
      260       2.17      2
     1930      16.08     16
      260       2.17      2
      700       5.83      6
      260       2.17      2
     2755      22.96     23
      250       2.08      2
     1810      15.08     15
      240       2.00      2
     1810      15.08     15
      240       2.00      2
      730       6.08      6
      235       1.96      2
     2500      20.83     21
      230       1.92      2

    It may just be pure coincidence, but the total number of bits above is 128.  For the other keys, do they produce fixed lengths (approx 15450uS total) as well?
     
    Edit: Answering my own question, having entered the values in your speadsheet image into my own speadsheet - YES.
    VU = 15467uS
    VD = 15455uS
    MU = 15466uS
    Unfortunatly the MU code have values for bits 4, 14 and 16 which do not fit the 120uS theory :/
    post edited by pcbbc - 2019/03/11 05:15:28
    #14
    ounvme
    Starting Member
    • Total Posts : 65
    • Reward points : 0
    • Joined: 2012/03/10 13:35:40
    • Location: 0
    • Status: offline
    Re: 38KHz with Timer0 PIC16F648A 2019/03/11 07:33:56 (permalink)
    0
    pcbbc
     
    Edit: Answering my own question, having entered the values in your speadsheet image into my own speadsheet - YES.
    VU = 15467uS
    VD = 15455uS
    MU = 15466uS
    Unfortunatly the MU code have values for bits 4, 14 and 16 which do not fit the 120uS theory :/




    I will probe the transistor that switches the LED's to get a cleaner signal. I also initially thought that the 120uS was the magic number but it ended up being 20uS which is common to all of them and that makes no sense in terms of code bits. I am fairly certain that the time lengths are NOT all the same. Tonight I will get all of the main features direct from the remote and put them on a spread sheet. The "1" bits appear to be decreasing by 5. 270 265 260 255 250 245 240 235 230?


    #15
    pcbbc
    Super Member
    • Total Posts : 816
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: online
    Re: 38KHz with Timer0 PIC16F648A 2019/03/11 08:08:40 (permalink)
    0
    Sorry, but I do not think they cannot possibly decrease by exactly 5uS each time, because 38KHz = 26.31579uS per cycle.
    You are claiming to have measured a decrease of 40uS in exact 5uS steps for a signal that probably has a mark space of near 50:50 and so is only on for 13uS at a time.
     
    You captured your traces at the IR receiver?  I suspect something else at play.  AGC in the receiver perhaps?
    #16
    ounvme
    Starting Member
    • Total Posts : 65
    • Reward points : 0
    • Joined: 2012/03/10 13:35:40
    • Location: 0
    • Status: offline
    Re: 38KHz with Timer0 PIC16F648A 2019/03/11 19:13:39 (permalink)
    0
    Here is a nice clean capture of the signal direct from the OEM remote and an accurate timing table. So all of the high pulses are the same and it definitely was some compensation in the RX. The 0 pulses still do not share a large common factor. But the assumed 3 "control" pulses are confirmed. Frequency is 38KHz. I love this cheap logic analyzer it has opened up a whole new world of fun. How I went this long without one is baffling.
    post edited by ounvme - 2019/03/11 19:15:07

    Attached Image(s)

    #17
    pcbbc
    Super Member
    • Total Posts : 816
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: online
    Re: 38KHz with Timer0 PIC16F648A 2019/03/12 02:38:27 (permalink)
    0
    The last pulse is almost certainly padding to make the overall time from start to finish constant.
    All the other OFF intervals are rough multiples of 200us, including the ON times being 192. 192 is very close to 7.5 x 26.3, so I expect that is from 8 bit banged cycles of 38khz. Your capture isn’t good enough for me to see how many cycles there actually are, but it’s not important to the protocol (just perhaps slightly easier to generate in the bitbanging assembler code!).
    Then the Microcontrollers does some other intermediate delays to get rough multiples of 200us intervals for OFF.
    You’ve already seen what the receiver has to deal with in terms of received signal. Accuracy of timing at the transmitter is not really of much concern. Although it is best to be spot on to give the receiver the best fighting chance of dealing with the noise, AGC issues etc.
    I think you now have what you need to recreate. Either using a more advance chip, or some assembler bitbanging. As you only have to generate 200us of 38khz, you can do that in the ISR in code. Then use the timer interrupt to generate only the required delays between ON bits.
    #18
    pcbbc
    Super Member
    • Total Posts : 816
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: online
    Re: 38KHz with Timer0 PIC16F648A 2019/03/12 04:04:18 (permalink)
    0
    Something like...
    #define MAX_DELAYS 8
    uint8_t delays[MAX_DELAYS];
    uint8_t delay_i;

    // Interrupt Handler
    void __interrupt() my_isr(void)
    {
        if (TMR0IF ==1) // timer 0 interrupt flag
        {
            TMR0IF ==0; // clear the flag
            if (delay_i == MAX_DELAYS)
            {
                TMR0IE = 0; // disable the interrupt
            }
            else
            {
                TMR0 -= delays[delay_i++]; // reset the timer preset count
            }
            asm("  banksel 0");
            asm("  movlw 8");
            asm("loop:");
            asm("  bsf PORTB, 7");  //38KHz ON
            asm("  nop");
            asm("  nop");
            //Repeat NOPs as necessary for 13us delay, less 1 tick (25 total?)
            asm("  bcf PORTB, 7");  //38KHz OFF
            asm("  nop");
            asm("  nop");
            //Repeat NOPs as necessary for 13us delay, less 4 ticks (21 total?)
            asm("  addlw 0xFF");
            asm("  skipz");
            asm("  goto loop");
      }
    }

    Of course, using the PWM is easier!
    #19
    ounvme
    Starting Member
    • Total Posts : 65
    • Reward points : 0
    • Joined: 2012/03/10 13:35:40
    • Location: 0
    • Status: offline
    Re: 38KHz with Timer0 PIC16F648A 2019/03/12 09:26:11 (permalink)
    0
    Here are the last few bits of the signal. The duty cycle is not 50% it is about 22%. The new chip will be here tomorrow so I will go with better hardware and PWM as recommended. 
    post edited by ounvme - 2019/03/12 09:28:56

    Attached Image(s)

    #20
    Page: 123 > Showing page 1 of 3
    Jump to:
    © 2019 APG vNext Commercial Version 4.5