1. Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
    Dismiss Notice

square wave pulse detector using PIC16F676

Discussion in 'Homework Help' started by Fabianr18, Nov 30, 2017.

  1. Fabianr18

    Fabianr18 New Member

    Joined:
    Nov 27, 2017
    Messages:
    11
    Likes:
    0
    Now that I gained a bit more experience writing C language a task of mine is to write a program to detect different pulses and represent them with a LEDS. anyone have any suggestions on how to do this. I have done some research and i came to the conclusion of using Timer0 operation to compare it with the internal freq of 4Mhz.
     
  2. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,161
    Likes:
    340
    Location:
    Brisbane Australia
    You can use the ccp (capture, compare) module to do this in hardware.

    Mike.
     
  3. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,310
    Likes:
    914
    Location:
    Rochdale UK
    Not on that chip.... It has less peripherals than the original pic16f84.. Hardly any memory!
     
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,161
    Likes:
    340
    Location:
    Brisbane Australia

    Wow, just looked at the datasheet. A very simple chip indeed.

    Mike.
     
  6. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,161
    Likes:
    340
    Location:
    Brisbane Australia
    To the OP, what kind of signals do you need to detect?

    Mike.
     
  7. Fabianr18

    Fabianr18 New Member

    Joined:
    Nov 27, 2017
    Messages:
    11
    Likes:
    0
    i have to detect different times of a square wave and out put them using an LED (simple if else statement) for example if the input pulse is 200us i should output 0000 or 300us output 0001

    only thing i dont know, is how to implement is the detection of the pulse by using the timer1 or timer0 or maybe theirs an easier way to do this
     
  8. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,310
    Likes:
    914
    Location:
    Rochdale UK
    If your square wave enters by the int pin...
    Code (c):

    void interrupt ISR(void)
       {
       if( INTEDG == rising )
          {
          TMR0=0;
          INTEDG = falling;  
          }
       else
          {
          pulse_time = TMRO;
          INTEDGE = rising;
          }
       INTF = 0;
       }
     
    THIS ISN'T TESTED... Just the idea... You may be better with timer1 as timer0 is an 8 bit and will not do long pulses..
     
  9. jpanhalt

    jpanhalt Well-Known Member Most Helpful Member

    Joined:
    Jun 21, 2006
    Messages:
    6,071
    Likes:
    524
    Location:
    Cleveland, OH, USA
    ONLINE
    As already mentioned, that is a very limited chip. Perhaps that was assigned on purpose.

    Here is one approach: INT on RA2 is edge triggered. Use it for your signal.

    Assuming the pulse idles low, set INT to a rising edge. In the interrupt, read TMR1H:L registers and start TMR1 (TICON,0 =1). Then switch to falling edge for the next interrupt and stop TMT1 (TICON,0 =0). Read your TMR1H:L registers and subtract to find out how long the pulse was.

    As mentioned, if you have capture, it is easier, but for the precision you need, starting and stopping TMR1 is easy to visualize.

    TMR1 has various pre-scale values, so regardless of your clock speed (within reason) you can get a count to equal microseconds or something else. If the counter rolls over just once during the measurement, that won't affect results, if your subtraction is done correctly.
     
  10. Fabianr18

    Fabianr18 New Member

    Joined:
    Nov 27, 2017
    Messages:
    11
    Likes:
    0
    thanks for the advice I'm starting to understand more and more
     
  11. jpanhalt

    jpanhalt Well-Known Member Most Helpful Member

    Joined:
    Jun 21, 2006
    Messages:
    6,071
    Likes:
    524
    Location:
    Cleveland, OH, USA
    ONLINE
    Just one added note. Once you get it to work starting and stopping TMR1, try it without that complication. It will work, but you cannot have more than 1 rollover in each timing period. That's basically what I do.
     
  12. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,161
    Likes:
    340
    Location:
    Brisbane Australia
    I note that the chip suggested has a gate input on timer1. Therefore, if you connect your signal to both the T1G and INT pins (RA4 & RA2) with an interrupt on falling edge only, the timer can be read and reset in that interrupt and it will contain the length of the pulse. Another way is to just connect to RA4 and use the IOC (interrupt on change) to generate the interrupt.

    BTW, you don't have to use interrupts, you can simply wait for RA4 to go low and then read and reset the timer.
    I.E. - untested
    Code (text):

        while(1){
            while(RA4);        //wait for signal to go low
            length = TMR1;
            TMR1=0;
            //do whatever with length
            if(length<2000){
                //length was less than 2000 clock cycles
            }else if(length<4000){
                //between 2000 and 4000
            }else{
                //over 4000
            }
        }
     
    Edit, to use this method you must setup timer1 to use the gate signal.

    Mike.
     
    • Like Like x 1
  13. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,310
    Likes:
    914
    Location:
    Rochdale UK
    Pommie! Trouble here is, he will be writing to an LCD and will need a bit 'o' maths.. The OP being new to all this its going to be tricky!! Waiting for a pin may not work here..
     
  14. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,161
    Likes:
    340
    Location:
    Brisbane Australia
    The OP said LEDs so I assume it's something like an RC servo signal and the LED should light when the pulse is over a certain length.

    Mike.
     
  15. Fabianr18

    Fabianr18 New Member

    Joined:
    Nov 27, 2017
    Messages:
    11
    Likes:
    0
    so i wrote down a code based on a tutorial and changed all f the parameters to work with my problem "reverse engineering " but it doesn't seem to do anything

    Code (C):

    #include <xc.h>
    #pragma config FOSC = INTRCIO// Oscillator Selection bits (INTOSC oscillator)
    #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
    #pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
    #pragma config MCLRE = OFF // RA3/MCLR pin function select
    #pragma config BOREN = OFF // Brown-out Detect Enable bit (BOD disabled)
    #pragma config FOSC = INTRCIO
    #pragma config CP = OFF // Code Protection bit (protection disabled)
    #pragma config CPD = OFF // Data Code Protection bit (protection disabled)
    #define _XTAL_FREQ 4000000 // 4MHz


    #define PulseLimit 30000

    volatile unsigned int PulseValue;
    struct
    {
        volatile unsigned PulseFound :1;
    }flags;

    void interrupt TImer1_GateISR()
    {
        PulseValue =TMR1;
        flags.PulseFound =1;
        TMR1 =0;
        PIR1bits.TMR1IF =0;
        T1CONbits.TMR1CS =1;
    }
    main ()
    {
        unsigned int Timer1Count;
        OSCCAL =0b11111100;
        ANSEL=0b000000;
        ADCON0bits.ADON=0;
        TRISA=0b00010000;
        TRISC=0b00000000;
    T1CON=0b01000011;
        TMR1=0;
        PIR1bits.TMR1IF=0;
        INTCONbits.PEIE=1;
        INTCONbits.GIE=1;
        PIE1bits.TMR1IE=1;
        T1CONbits.TMR1ON=1;
     
        flags.PulseFound=0;
        PulseValue =0;
     
        while(1){
            if(flags.PulseFound ==1)
            {
                di();
                Timer1Count = PulseValue;
                ei();
                if(Timer1Count > PulseLimit){
                PORTC=0b00000000;
            }
                else if(Timer1Count < PulseLimit){
                PORTC =0b00000000;
                }
             flags.PulseFound=0;
                }
             
            }
     
    }
     
     
    Last edited by a moderator: Dec 5, 2017
  16. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,161
    Likes:
    340
    Location:
    Brisbane Australia
    Your code is interrupting on timer1 overflow.

    What I would try first is to simply watch and count.
    I.E.
    Code (text):

    main ()
    {
        ANSEL=0b000000;
        ADCON0bits.ADON=0;
        TRISA=0b00010000;
        TRISC=0b00000000;
        T1CON=0b00000000;
     
        while(1){
            unsigned int Timer1Count;
            TMR1=0;             //clear timer
            while(!RA4);        //wait for high
            T1CONbits.TMR1ON=1; //start timer
            while(RA4);         //wait low
            T1CONbits.TMR1ON=0; //stop timer
            Timer1Count=TMR1;   //copy timer
            // use the timer value here to light LEDs etc.
        }
    }
    The above, untested, code should get the length of the pulse within a few clock cycles.
    Note, no interrupts to complicate things.

    Edit, my earlier suggestion of using the timer1 gate function won't work as the gate is active low. You also haven't told us the length of pulses expected or how often to expect them. For example a radio control receiver puts out a 1 to 2mS pulse every 20mS.

    Mike.
     
    Last edited: Dec 5, 2017
  17. Fabianr18

    Fabianr18 New Member

    Joined:
    Nov 27, 2017
    Messages:
    11
    Likes:
    0
    the length of each pulse is in micro seconds and the waves wont stop coming in and the length of that waves will change manually by another micro controller the block diagram of the project is posted below,
     

    Attached Files:

    • pic.jpg
      pic.jpg
      File size:
      399.2 KB
      Views:
      13
  18. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,161
    Likes:
    340
    Location:
    Brisbane Australia
    If your pulses are between 200 and 250 μS and you have 4 different lengths, that's only around 16 clock cycles difference per pulse. I would, at the very least, increase your oscillator frequency to something like 20MHz so you have a better chance of getting this to work. At 20MHz you will have about 80 cycles different in timer readings.

    If the pulse lengths are very accurate and you don't have stray capacitance then the above code should still work.

    Note, to use interrupts will increase your overhead immensely - to execute an empty interrupt can take over 20 cycles just for entry and context saving.

    BTW, in your code above you appear to be testing for a pulse of 30,000 μS (30mS). If you have control over how long the pulses can be then I would suggest 1 to 4mS with a gap of a couple of mS.

    Actually, I may have misread your diagram. Are the pulses 200, 250, 300 & 350μS? If so and you have a suitable gap between them then the above should work fine.

    Edit, misread your diagram again. Do you have 16 different pulse lengths? Is 200μS equal to zero?

    Mike.
     
    Last edited: Dec 6, 2017
  19. jpanhalt

    jpanhalt Well-Known Member Most Helpful Member

    Joined:
    Jun 21, 2006
    Messages:
    6,071
    Likes:
    524
    Location:
    Cleveland, OH, USA
    ONLINE
    Pommie

    Your last assumption seems correct. See the attachment here: http://www.electro-tech-online.com/threads/pwm-pic16f676.152459/#post-1310770

    200 us =0 ; then count by 50 us units so 250 us =1, 300 us =2 and so forth.

    Edit: Darn it. Just lost a long edit -- guess auto save doesn't work on an edit.

    Unfortunately, I used "interrupt" a bit loosely in my comment above -- probably because that is what I was working on at the time. What I should have said was you can use an interrupt or just monitor the appropriate flag/state change and then read TMR1. One way to read it with your chip is to start and stop the timer as in Pommie's code. That introduces some error which can be corrected by careful timing. The other method is to let TMR1 run and read it on the fly.

    The usual way to do that is to read the high byte (TMR1H) first, then the low byte, then check to see if TMR1L rolled over by checking for a change in the high byte. I used to have a nice article on that method in Assembly, but cannot find it right now. I did find a description of that method in text, and at risk of looking foolish, here it is.

    Source: http://www.picbasic.co.uk/forum/showthread.php?t=4092
    Code (text):

    X var BYTE ' in addition to your variables

    period.highbyte = TMR1H
    period.lowbyte = TMR1L
    X = TMR1H – period.highbyte
    If X = 0 then Continue
    period.highbyte = TMR1H
    period.lowbyte = TMR1L
    Continue:
     
    John

    Edit#2: Corrected "TMR1" to TMR1L -- hope it was clear by context that I was referring to the low byte.
     
    Last edited: Dec 6, 2017
  20. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,310
    Likes:
    914
    Location:
    Rochdale UK
    You may well be doing this exercise to see "If you can" But reading 4 switches down one wire would be a whole lot easier using the built in ADC.. Then only one micro is needed..
     
  21. Daniel Wood

    Daniel Wood Member

    Joined:
    Jun 15, 2012
    Messages:
    71
    Likes:
    9
    Location:
    Derby
    Without a CCP module, it would be rather difficult. One way may be to integrate the signal and peak detect with the analogue pin?
    No doubt i'd get shot down for this suggestion as it would only work well in a very limited pulse timing window. It could work if your pulses are between 200-300uS
     

Share This Page