View previous topic :: View next topic |
Author |
Message |
picman62
Joined: 12 Dec 2014 Posts: 77
|
|
Posted: Thu Feb 12, 2015 5:28 am |
|
|
First, thank you very much.
Your original 'per second value'
Code: |
#define PER_SECOND 125
|
was displaying an offset in the frequency value. 5000Hz signal was shown as 4960Hz.
I changed this value to 126 and 5000Hz came up as 5000-5001. Fine.
Ttelmah wrote: |
If you want to change the LED flash rate, don't change the timer rate, but change the value used to re-load led_count.
|
Regarding the LED flash rate, it is too slow for my purposes.
Code: |
#int_timer2
void TimerLED()
{
static int8 led_count=(PER_SECOND-120);
if (led_count)
--led_count;
else
{
output_toggle(PIN_C1);
led_count=(PER_SECOND-120);
}
if (count)
--count;
}
|
So, I entered the value above to meet my requirements for flashing time. However a slight offset of +8Hz for the frequency counter value appeared.
If I did everything right, is there a way of correcting this offset?
Regards. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Thu Feb 12, 2015 5:41 am |
|
|
You must have changed something else.....
Always look carefully at everything you do. Probably some other tiny thing.
The rate in this doesn't matter at all. The interrupt is called the same number of times each way. I'm really surprised you want to flash an LED that fast. Almost stroboscopic. |
|
|
picman62
Joined: 12 Dec 2014 Posts: 77
|
|
Posted: Thu Feb 12, 2015 5:50 am |
|
|
Please, disconsider what I have said above.
This offset was from PT simulator. Before leaving home now, I did it with the protoboard and it was fine. Reading 4999-5000Hz.
Since we are into this, one question about how the PWM will be implemented.
Can I set PWM to be called from the INT_RB interrupt without interfering in the other functions, eg. led,counter, etc.?
The PWM signal will need to be ON for 1 second and OFF for 2 seconds in a loop till it is finally off along with the rest of the functions when a button is pressed. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Fri Feb 13, 2015 3:38 am |
|
|
I wouldn't use the port B interrupt for a key.
The problem is that keys are not nice on/off signals. When you press a key, it typically makes, breaks, and makes again two or three times before finally deciding it is made. This is 'key-bounce'. If you use the port B interrupt for key(s), you get it being repeatedly being called, and even worse, you then have to work out which is the last call and whether you really should accept the key in this. If you accept it too early, you see the key multiple times. It is complex to do.
You already have a timer, so use this. Something like (for a key on say B4):
Code: |
int1 key_seen = FALSE; //as a global variable
//then in the interrupt
static int8 key_state=0;
if (input(PIN_B4)==0) //assuming key is pull-down, with a pull-up resistor
{
if (key_state==0)
key_state=1;
else if (key_state==1)
{
key_state=2;
key_seen=TRUE;
}
}
else
key_state=0; //restart scanning
|
Then in your 'main' check for 'key_seen', and when this goes true, set it false, and do what you want.
This was the key has to be 'on' for two successive interrupts, before it'll be seen.
The same applies with your PWM. You have a timer. Use it.
Have another counter variable (pwm_count say).
Have code to decrement this the same way as count in the timer.
Then in main, just set this to the value for one second, turn the PWM on. When it gets to zero, turn the PWM off, and set the counter to the value for two seconds. etc.. |
|
|
picman62
Joined: 12 Dec 2014 Posts: 77
|
|
Posted: Fri Feb 13, 2015 6:24 am |
|
|
Thanks, I will try this.
Best regards. |
|
|
picman62
Joined: 12 Dec 2014 Posts: 77
|
|
Posted: Fri Feb 13, 2015 1:59 pm |
|
|
Hi, Ttelmah,
One last help buddy.
Considering your code below which I made slight changes to fit the LED rate for my purposes:
Code: |
#define PER_SECOND 126
int8 count;
#int_timer0
void TimerLED()
{
static int8 led_count=(6);// 126 - 120
if (led_count)
--led_count;
else
{
output_toggle(PIN_C1);
led_count=(6);
}
if (count)
--count;
}
|
It is starting already in a defined flash rate.
But say I want to define the flash rate according to three 'if' conditions in the main code...for instance condition 1:
Code: |
if(value>=counter-(10) && value<=counter+(10))
// what instruction to set the LED rate goes here?//
|
What would that be?
And what would be the change inside the interrupt instruction so that it does not already start with led_count=(6) and do what is inside the conditions? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Fri Feb 13, 2015 2:30 pm |
|
|
Start using your brain a bit.
All you need to do is set the LED rate with a global variable, instead of with a define. Change the value of this variable in your main. |
|
|
picman62
Joined: 12 Dec 2014 Posts: 77
|
|
Posted: Fri Feb 13, 2015 4:14 pm |
|
|
Ttelmah wrote: | Start using your brain a bit.
All you need to do is set the LED rate with a global variable, instead of with a define. Change the value of this variable in your main. |
Ok, this part I understood. I changed the Code: | #define PER_SECOND = 126 | for a variable
I put this in main and set the value of 126, to meet the freq counter requirements. It worked and the counter is reading correctly.
But sorry, I still did not quite get clearly how to do the same with the LED. Leaving your instructions in the interrupt unchanged, you stated Code: | led_count=(PER_SECOND - 1); |
So I set a value for the variable in main:
Code: |
if(value>=counter-(10) && value<=counter+(10))
{
output_toggle(pin_c1);
PER_SECOND = 10;
} |
Is this the correct procedure?
If not, sorry but my brain is a bit fried at this point. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Sat Feb 14, 2015 1:30 am |
|
|
Not really:
Don't change the PER_SECOND value. This wants to be fixed for everthing that is dependant on 'PER_SECOND' timings. Leave this as a define.
Code: |
#define PER_SECOND 125
int8 count;
int led_time;
#INT_TIMER2 //As I said, this is meant to be timer2. This is why the
//PER_SECOND value is wrong. Get rid of timer0 completely. Enable
//INT_TIMER2.
void TimerLED()
{
static int8 led_count=(6); // 126 - 120
if (led_count)
--led_count;
else
{
output_toggle(PIN_C1);
led_count=led_time;
}
//Other interrupt code.
//Then in the main
//For fast LED
led_time=PER_SECOND-120;
//For medium LED
led_time=PER_SECOND-50;
//For slow LED
led_time=PER_SECOND-20;
|
Choose values to give the speed you want.
The time you are using for the LED seems much quicker than I'd have thought suitable (this may be because you are using timer0, not timer2). You are into the flash rate, where if the device was 'commercial', it'd have to carry a warning that it might cause epilepsy.
The whole point about using timer2, is that as programmed it gives _exactly_ 125 interrupts per second. So the timing of the readings will be 'right'. Using Timer0, the timing will at best be 'near'.....
The LED flash rate will be 1/125 * led_time * 2 seconds. So with '6', 0.096seconds = 10.4Hz. Photosensitive epilepsy is triggered typically by rates between 5 and 25Hz..... |
|
|
picman62
Joined: 12 Dec 2014 Posts: 77
|
|
Posted: Sat Feb 14, 2015 3:56 am |
|
|
What a shocker. Of course. 'PER_SECOND' should be fixed since this is what determines the value for the counter. All that was required was a variable to set led_count a rate. Enter led_time.
Regarding TIMER0, I am not using it. I changed since you suggested TIMER2 for this. I only increased the value of 125 to 126 because the prior value was a little bellow in offset for the frequency. '126' corrected this and value in the screen for a 5KHz signal from my generator is now 4999-5000.
If it really needs to be 125 and not 126, then something else is causing this discrepancy and I will have to check it down the line.
Anyway, again, thank you so much for your help, Ttelmah. You added more elements to my learning. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Sat Feb 14, 2015 3:59 am |
|
|
You move forwards. |
|
|
|