![]() |
Help needed timing a pulse (2004 Robovation)
Hi everyone,
I have been reading about CCP pins and interrupts, and am at a complete loss as to what the -simplest- way of timing an input pulse is. Here are the specifics of my application: -The signal varies from 1mS to 36.99mS -There is a 65mS low signal between pulses -I am currently using, essentially, the default code (added sensor capture and filtering for sonar, but the framework is the same). -It would be best if lag during capture could be avoided (so that the proc. doesn't wait for a signal when it could be filtering, etc.) -I will, obviously, need access to the up-to-date value as stored in a variable. -My PWM generator specifies down to 10uS readability; 100uS would be fine for my purposes. -The signal is 0V or 5V, through a sensor powered by the analog pins. Now, I know interrupts can be used like the sonar code, tracking rising and falling edges of the square wave. I also gather that CCP can do this with one pin, and appears like it will not lag the program. How can I impliment something like this? What code do I need to add to the default code? What pins do I use? Thank you, Josh |
Re: Help needed timing a pulse (2004 Robovation)
Yes, you can use a single CCP module to do this, but it would still create an interrupt you'd have to service, and you'd have to constantly change the mode of the CCP module. So you may not actually gain anything. You could also use 2 CCP modules with a lighter interrupt service rountine, or no interrupt service routine and some educated guessing if your data is valid. In fact, you could also use just one interrupt in the same fashion you'd use just one CCP module. Sadly, I see no real way of doing this without some amount of interrupts. Unless you're fine with making an (very well) educated guess about the validity of your data.
Sooo..... The question would be exactly how much help you're looking for. All the info you actually need is in the data sheet, pages 149-151. And in the Edu-bot programming reference, to put the PWM outs into USER_CCP mode. If you want, I can whip out very rough pseudo code for the scenarios about so you can see the differences. |
Re: Help needed timing a pulse (2004 Robovation)
Thanks for the reply, Kevin -
I have nothing against interrupts per-se. I simply haven't used them, so I'm a bit apprehensive about trying. Will they accomplish what I need, without undue amounts of lag? If you could provide a skeleton code that I can work from, that would be wonderful. I see how to set them up in the software, but their use is a bit beyond me. The overflow/preloading make sense in theory, but I am not positive on how the values for each are derived, or how I can convert the values into a usable time (mS, uS) that may be accessed like a variable. How does Kevin Watson do this in his infrared receiver code? It looked like he might have some usable way of measuring a pulse width. |
Re: Help needed timing a pulse (2004 Robovation)
Quote:
1. find an available timer, 8 or 16 bit, and init it to count such that it counts to max within ur 37ms. Or around that time. Do not set timer overflow to activate an interrupt. Do not start the timer running. 2. take one of ur interrupt pins and set it to activate on to-high and to-low transitions. in the interrupt, read back the pin to differentiate between to-high and to-low events. 3. during to-high event, init timer to 0 and start the timer. 4. during to-low event, stop the timer and copy the 16it value to a 16bit variable 5. now let the pulses come in, have the output printf-ed and see if anything goes wrong.. this is fully pulse-activated interrupt based so you go about doing ur normal routines leaving this to run by its own :), reading the 16bit variable to check for the last pulse recorded. edit: about disabling interrupts when modifying values.. in this scenario u probably wont need to. But you may want to avoid reading the 16bit variable while it is in the midst of being updated... I'm not sure if 16 bit read/write are single instruction (but longer clocks) or multi instruction. Probably multi I guess.. get someone to verify this. |
Re: Help needed timing a pulse (2004 Robovation)
Quote:
In a nutshell: Set up a timer to increment at whatever resolution you need measure your pulse width at. Start timer. Interrupt on each falling edge (or rising, or both depending on what you want). Service the interrupt by checking your timer variable, and reset your timer variable to 0. Lather, Rinse, Repeat... For interrupts, this is a pretty good first project. Just be sure to disable your interrupts temporarily when you modify variables that are modified by other interrupt service routines. In the above example, you'll want to disable interrupts whenever you increment or reset your timer variable, then re-enable them right after. |
Re: Help needed timing a pulse (2004 Robovation)
So, like others have suggested, I'd look at Kevin's code. But I'd specifically look at the 2005 frc_interrupts.zip file. That's a really good interrupt handler, AND it shows you how to set up the timers. As far as actualy implementation:
Use an 1:8 prescale on a 16-bit Timer, anything else is too short. Start the timer, leave it running, it'll save you the bother of starting and stopping it needlessly. Disable the Timer's Interrupt, you don't need it. Use one of the KBI interrupts, handled by Int_3_Handler through Int_6_Handler. These interrupt on rise and fall. The value passed by the Int Handler function tells you what the state of the pin is. On the rising edge, when the value passed is 1, clear the timer. If it's in 16-bit Read Mode, write 0 to TMRxH THEN write 0 to TMRxL. On the falling edge, when the value passed is 0, read TMRxL to a temp variable, read TMRxH to your actual 16-bit variable, shift 8 bits to the left, and add your temp variable. You're done. Stopping the timer is pointless, you have to clear it no matter what, so just clear it at the start and you're fine. Your program should copy the value of the variable this routine saves to to a new variable and work with the new variable, as the routine might change the value halfway through your computation otherwise. I'm pretty sure you don't have to disable interrupts while in the interrupt handler itself in this case. Using the CCPs is a good bit more complicated, but you'll get a much more accurate time measure, as the CCP handles saving the Timer value the instant the of the edge trigger, without the delay of entering the interrupt routine, etc. |
Re: Help needed timing a pulse (2004 Robovation)
Quote:
|
Re: Help needed timing a pulse (2004 Robovation)
Quote:
|
Re: Help needed timing a pulse (2004 Robovation)
Quote:
by the way... if you all examine the assembly code for the add function in C++ you'll find that you don't need to reset the timer to zero all the time.... also remember that the hardware add done by the timer works the same way... ;) have fun. ccp's rock my socks. craziest thing i've done with em is step motor control ~15KHz on the 8722, rate and positional(with accel/decel) control and simultaneous + independent axis motion. :cool: -Q |
Re: Help needed timing a pulse (2004 Robovation)
Quote:
|
Re: Help needed timing a pulse (2004 Robovation)
Quote:
I'm still figuring how to use CCP to do a read of 8 PWM inputs simultaneously w/o causing much cpu load too :( |
Re: Help needed timing a pulse (2004 Robovation)
Quote:
the adds roll over to zero..... :rolleyes: let's for instance take an unsigned integer, 0xFFFF. when we add 0x0001, and perform the "ADD" instruction, the ALU takes the value of the first digit and starts bit shifting, starting the carry to the next digit. but... we don't have any more bits! :ahh: so what basically happens in hardware is: 0xFFFF & 0x0000 //clear already filled digits since we're moving up a place 0x0001 << 0x0005 //working register now 0x0000 with a 1 hanging off to the left and in the end, we're left with 0x0000! :D i think now you understand why you never have to stop+reset the timer. -Q |
Re: Help needed timing a pulse (2004 Robovation)
Quote:
After kevin's post then I realised that you need not stop/start the timer because you can do a reliable 16bit read, so you'd only do a reset-to-zero on a high pulse and a 16bit read on a low pulse :) |
Re: Help needed timing a pulse (2004 Robovation)
Thanks guys,
I think I understand the concept now! I wrote some code that (should) work, but doesn't. It reads random values, even if the sensor is still. I can understand how it might read the same error each time, but if the pulse is right, it shouldn't vary every loop, should it? So I guess, I'm trying to figure out of it's something to do with my wiring, or something in the program itself. I don't have access to an oscilliscope to check it, sadly. Here's the code: From interrupts.c Code:
void Initialize_Timer_1(void) Timer1_Readable is an extern variable declared in interrupts.h. I am using a simple printf of an int from my user_routines. Could it be that the timer is not resetting as it should? I'm going to look for a pattern now... |
Re: Help needed timing a pulse (2004 Robovation)
Quote:
1. get a signal generator/constant pulse source to test, if possible 2. Timer1_Readable is declared as what? Try to avoid things like multiplying by 0.008 .. you may need to define Timer1_Readable as a float or single.. As much as possible when it comes to complex calculations, I'd use a lookup table to speed things up and increase reliability :) |
Re: Help needed timing a pulse (2004 Robovation)
Quote:
-Kevin |
Re: Help needed timing a pulse (2004 Robovation)
Your problem is almost certainly that you're clearing the timer in the wrong order for a 16-bit Read/write mode. In this mode TMR1H is a buffer. so you write to the buffer first, then write to TMR1L. Your code for RB7_State == 1 should be:
TMR1H = 0x00; // MSB-TMR1 TMR1L = 0x00; // LSB-TMR1 As it is, your high bits aren't being cleared, so the value is effectively random, which is what you're seeing. |
Re: Help needed timing a pulse (2004 Robovation)
Switching the clear order worked!
Thank you to everyone! |
Re: Help needed timing a pulse (2004 Robovation)
Good, simple information about CCP programming here http://ww1.microchip.com/downloads/e...Doc/41214a.pdf
|
| All times are GMT -5. The time now is 20:46. |
Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi