View previous topic :: View next topic |
Author |
Message |
buckeyes1997
Joined: 12 May 2005 Posts: 15
|
IS there a clever way to handle this task??? |
Posted: Thu May 12, 2005 8:14 pm |
|
|
suppose i have an event that happens roughly every 10ms (goes high) and i want to continuously check that condition and if it stops going high turn on an LED.
im going to use a cheap 8 pin PIC such as the 12c508a or similar.
my first thought was to poll the input at several times the input pulse duration and keep a running count that increases everytime the check reads a low. once that number exceeds the number that can occure in 10ms i would assume it failed to go high and turn the led on. if it reads a high it simply resets the count. i would then want to keep the LED on until i see the pulse again.
how would you go about doing something like this?
Last edited by buckeyes1997 on Fri May 13, 2005 11:51 am; edited 1 time in total |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1907
|
|
Posted: Thu May 12, 2005 9:09 pm |
|
|
I have no idea what kind of interrupts are available on that pic, but I'd try to utilize an external interrupt (or something like it) along with a timer to do this.
Every time the external interrupt happens (a rising edge), it resets a counter. Every time the timer interrupt happens, it increments the counter. For arguments' sake, let's say the timer increments every 2.5 ms or 5 ms or so.
Then, in the timer interrupt, just check to see if the counter has exceeded a threshold. If it has, then the "heartbeat" has been silent for too long.
Again, sorry if there aren't any suitable interrupts available in that chip, but this is how I'd like to do it. |
|
|
buckeyes1997
Joined: 12 May 2005 Posts: 15
|
good but.... |
Posted: Fri May 13, 2005 11:50 am |
|
|
i dont think the 12c508 has interrupts. i might be wrong and hopefully someone can tell me for sure, but thats why i figured checking for the high at time intervals was the way to go.
its seems like such a simple task but i cannot seem to wrap my mind around it.
just to be clear what i need it to do. using a 12c508a PIC i want to monitor a pin and verify that a high comes about once every 10ms and do nothing as long as it does, but when the pulse goes missing i want to cause an action until the pulse returns.
anyone know of a clever way to do this? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri May 13, 2005 12:12 pm |
|
|
Quote: |
suppose i have an event that happens roughly every 10ms (goes high)
and i want to continuously check that condition and if it stops going high turn on an LED. |
Assuming that the PIC is not doing anything else, except what you stated,
the problem is actually very simple. The code below assumes that
your input normally stays high continuously. It's sampled every 10 ms.
If it ever goes low, the sampling is stopped and a LED is turned on.
It then stays in that condition forever. That's all you requested, so that's
all I've posted. If you want more, then you must figure it out.
I don't have PCB, so this code is for a similar PIC that can be compiled
with PCM.
Code: | #include <12C671.h>
#fuses XT, NOWDT, NOPROTECT
#use delay(clock = 4000000)
#define SENSOR_PIN PIN_A0
#define LED_PIN PIN_A1
void main()
{
output_low(LED_PIN); // Turn off the LED initially
// Check the sensor pin every 10 ms. If it goes low,
// break out of the loop and turn on the LED.
while(1)
{
if(input(SENSOR_PIN) == 0)
break;
delay_ms(10);
}
output_high(LED_PIN);
while(1);
} |
|
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Sun May 15, 2005 8:44 am |
|
|
Quote: | i dont think the 12c508 has interrupts. i might be wrong and hopefully someone can tell me for sure | No, the 12C508A doesn't have interrupts, the 12C671 does.
You said the pulse is comming by every 10ms, but you didn't specify the 'high' time for this pulse. When implementing a polling method (testing the pin) then the polling frequency must be at least two times faster than the pulse duration.
One thing I don't like about the 12C508A is that it can only be programmed only once (One Time Programmable, OTP), so modification after production is impossible without replacing the chip. Also programming a chip during production requires some special handling in production and makes your product expensive.
Why don't you use one of the old and ancient logic building blocks from the past? You know, those funny TTL chips with inbuilt functions like a 'monostable multivibrator'. In fact, a retriggerable monostable (also called one-shot) multivibrator is exactly performing the function you are looking for, it has a stable high output as long as it is triggered every once so often. The maximum time between triggers can be defined by choosing a capacitor value. Doesn't require any programming, is cheap in production and hardly uses any current. Not all problems require a processor to be solved.....
Have a look at the 74HC123 series which contain two of these circuits. The “423” is identical to the “123” but cannot be triggered via the reset input.
http://www.standardics.philips.com/products/multivibrators/ |
|
|
John P
Joined: 17 Sep 2003 Posts: 331
|
|
Posted: Sun May 15, 2005 9:42 pm |
|
|
Well, I won't claim that this is "clever", but something like it ought to work:
Code: |
while (1)
{
if (bit_test(PIN_INPUT)) // Test the input pin
count = 0; // It's high, all is well, flush counter
else if (count < 15) // Don't let the counter wrap!
count++;
if (count >= 15) // Count went up to 1.5 event times,
bit_set(PIN_OUTPUT); // LED on
else
bit_clear(PIN_OUTPUT); // LED off
delay_ms(1);
}
|
You obviously need to set the port pins correctly for input and output. You didn't say how long after a "normal" event should have occurred the program ought to delay before setting the LED on, so I assumed 1.5 event times (i.e. 15msec). Actually it'll be a bit longer as the 1msec delay doesn't encompass the whole loop time, but if it's something to attract the attention of a human, it should be OK. If the compiler won't give you a delay, you'll have to write your own--run some do-nothing loops and look at the LST file to see how many instructions they're taking. |
|
|
buckeyes1997
Joined: 12 May 2005 Posts: 15
|
great advice guys |
Posted: Mon May 16, 2005 7:32 pm |
|
|
hey this is very good.
i am actually replacing an older design which used a cmos timer, which once the code is written will simplify the design.
the pulse comes every 10ms or so and lasts 1ms duration. i would like to make the LED off until the pulse is missed say 3 times in a row. i figured i should sample the signal at least 2x to meet the nyquist rate.
thanks everyone for the great ideas |
|
|
John P
Joined: 17 Sep 2003 Posts: 331
|
|
Posted: Tue May 17, 2005 1:13 pm |
|
|
If the pulse only lasts 1msec then yes, you need to sample more often than a 1msec rate. In my suggestion above, change the delay to delay_us(500) and count up to 60; that way you get a 30msec time with no pulses before there's a response.
Another thing to consider is what you want to happen if there's a minimal set of missed pulses; should there be a minimum period during which the light will be on, so that there's a good chance it'll be seen, say 1/2 second or even more? If so, you need to start another counter when the light turns on, which counts down a period before turning the light off again, assuming pulses have resumed by then. And even if the pulses don't resume, should the light stay on indefinitely, or do you just want a flash to register the end of a long series of pulses? |
|
|
buckeyes1997
Joined: 12 May 2005 Posts: 15
|
good questions |
Posted: Tue May 17, 2005 4:32 pm |
|
|
what id like to happen is for the light to stay on until the pulse is received again. in otherwords the light is off when good pulses are coming in, but lite when the pulses stop, and it remains lite until the pulses start up again.
thanks |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Thu May 19, 2005 2:56 am |
|
|
Ofcourse you are free to use a PIC in your application but I don't see any advantage of using a PIC over a pure CMOS solution. Using a processor is more 'sexy' but for a commercial application I don't see any other advantage than that. CMOS is cheaper in both parts and design, uses less current and has no EMC problems. |
|
|
buckeyes1997
Joined: 12 May 2005 Posts: 15
|
|
Posted: Fri May 20, 2005 7:45 pm |
|
|
BIT_TEST(PIN_B3)
DOESNT WORK IT GIVES AN ERROR ABOUT MISSING COMMA AND WHEN I PUT AVALUE OF 0 FOR BIT ZERO ITGIVES AN ERROR.
sorry about the caps lock |
|
|
Ttelmah Guest
|
|
Posted: Sat May 21, 2005 3:13 am |
|
|
buckeyes1997 wrote: | BIT_TEST(PIN_B3)
DOESNT WORK IT GIVES AN ERROR ABOUT MISSING COMMA AND WHEN I PUT AVALUE OF 0 FOR BIT ZERO ITGIVES AN ERROR.
sorry about the caps lock |
It won't.
'Bit test', is a function to test a single bit in a variable. If you want to use this to access pin B3, you would have to define a variable with the address of portB, access this as a pointer, then use the function to access the third bit.
You are using the wrong function. The command to read the port, is 'input'. So if you use:
if (input(PIN_B3))
You will get the following code executed, if pin_b3 is high (non zero is 'true' in C).
Best Wishes |
|
|
John P
Joined: 17 Sep 2003 Posts: 331
|
|
Posted: Wed May 25, 2005 8:24 am |
|
|
There's a question of philosophy here, how you want to think about the action of your program. I prefer to have all bits set/cleared/tested by the same language, reardless of whether they're in an internal register or appear as external pins. I don't use the output_bit and input_bit commands.
So I've got #define statements for all the port pins in my copy of "16F877.h". I can't remember if the file came that way or if I added them, but they look like this:
#define PIN_B3 51
Then I often re-define a pin in the application program, like this:
#define PIN_TEST_IN PIN_B3
This has to come after the line telling it to inlude "16F877.h"! Once the program knows how to deal with the port pin, you can use the standard commands to set/clear/test it.
So
Code: |
if bit_test( PIN_B3 )
do_something_wonderful();
|
should work. |
|
|
buckeyes1997
Joined: 12 May 2005 Posts: 15
|
thanks everyone |
Posted: Sat May 28, 2005 6:01 am |
|
|
thanks again you were dead on with the input() rather than bit_test() i have fixed that and now have my program running. however i have it driving a peizo buzzer that simply turns on or off. its the type like you would get a radio shack. what i want to do is drive a smaller peizo that is not the on/off type. my guess is that i have to apply voltage in a pulsed manner at about 1-2khz??? how can i apply this signal to the buzzer while my code is running??
in other words if i want it to continute to buzz while i run through the program again and test the inputs etc.
thanks for your help
matt |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Sat May 28, 2005 6:33 am |
|
|
Please, post new questions that are not related to the subject of the first question in a new thread. This will ensure you get much better response because most people only read the thread subject description. It also makes it easier for other people to search this archive. |
|
|
|