Detecting PWM Input to PIC

Discussion in 'Programmer's Corner' started by jwilk13, Apr 24, 2012.

  1. jwilk13

    Thread Starter Member

    Jun 15, 2011
    228
    12
    I have a 3.3V PWM signal going to a PIC18F45K20 that I would like to simply detect. I don't need to measure frequency or duty cycle. I'm thinking that what would work best is to call a function that would just return a YES or NO boolean value if the PWM is there or not, respectively.

    I've thought about using interrupts, but I can't think of a decent solution. I can't use the CCP modules (they're not available). I'm sure there's a way to do it, I just can't think of a good way to go about it. Maybe detect a rising edge and a falling edge and if both exist, then my value is YES. But then it has to remain in the function long enough for a rising and falling edge to be detected...

    Gah. Any ideas?
     
  2. russ_hensel

    Well-Known Member

    Jan 11, 2009
    818
    47
    The simple way without interrupts:

    You need to know the pwm period input. The subroutine goes into a loop that last one pwm period. During that time it checks the port bit. If it goes high you have pwm input and you are done. If the routine times out you do not. This may not be quick. For 20 ms pwm you may have to wait 20 ms.

    Interupts set on the pin change comnbined with a count down timer would consume less cpu time and be more responsive. Have you ever programmed interrupts?
     
  3. jwilk13

    Thread Starter Member

    Jun 15, 2011
    228
    12
    Not really, but I'm trying it right now.

    The way I'm working it right now (and I think I'm close) is as follows:

    1) When I want to detect PWM, I call a function that sets the interrupt registers to look for change on RB4.
    2) Wait for interrupt and jump to ISR
    3) Set a variable to 1 to indicate PWM is present

    I've tested it and it works, the only problem my variable in Step 3 (within the ISR) is a different memory address despite having the same name as the variable in main().

    Let's call it pwmCheck.

    Here's my very simple ISR:

    Code ( (Unknown Language)):
    1.     if (intcon.0 == 1)
    2.     {
    3.         volatile unsigned int pwmCheck = 1;
    4.         intcon = 0b00000000;
    5.     }
    When it jumps back to main, pwmCheck goes back to 0, and when I watch through the debugger, I can see that they're mapped to different memory addresses.
     
  4. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,395
    1,607
    You have defined a second variable also named "pwmCheck" inside your ISR. Just define it once as a global variable and both main and the ISR can access it.
     
  5. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,395
    1,607
    As far as the basic problem, you are looking for an input to undergo a periodic change (the period of the PWM) to be classified as existent, and this assumes that both a zero and a 100 percent period are illegal.

    If you do not have some sort of timer running you do not know if such is true.
     
  6. jwilk13

    Thread Starter Member

    Jun 15, 2011
    228
    12
    Thanks Ernie.

    I tried the global variable bit, defining it outside of any function, and it didn't work before. Now that you recommended it (of course), the variable is mapped to the same memory address.

    You read my mind with your second post. I have ports available that can do this (I think). I have two separate PWM signals which are not active at the same time, so I still need two channels. I'm thinking about using RB4 and TMR0, and RB3 in capture mode, I'm just not entirely sure how to do it. I have TMR0 set to 256 prescale and I'm clocked at 8 MHz (giving a 2 MHz instruction rate), meaning max period I can measure is 32.64 ms, which is fine for my application.

    I'm going to keep trying to measure the PWM period using TMR0 and RB4 for right now, but any hints would be greatly appreciated.
     
  7. russ_hensel

    Well-Known Member

    Jan 11, 2009
    818
    47
    If you are using an ISR then it should be running all the time. In any other case you may have to wait the 20 ms to be sure. So set an interrupt on the bit you want to monitor. If the ISR is triggered by the bit then set your pwm indicator to 1 and start a 20.001 ms timer also with an interrupt ( if it is already running reset it ). If the ISR is triggered by the expiration of the timer set the pwm indicator to false. Continue forever. If you want to know if you have pwm check the pwm indicator, presumably a global variable. Remember to make all variables changed in the ISR volatile.

    You should not have to measure the pwm period it should be fixed.
     
  8. jwilk13

    Thread Starter Member

    Jun 15, 2011
    228
    12
    Thanks Russ, that's exactly how I did it and I didn't even read your post first :)

    Basically, I start the timer inside a while loop depending on if the PWM signal is high or low. If the timer overflows, the PWM is either 0% or 100% duty cycle. Then I display some stuff on an LCD and disable other outputs, etc. Quite an interesting learning experience.

    Thanks everyone for the help.
     
Loading...