I could make no sense of your last post! Suffice to say that 00000010 equals 2 not 1
My point was the result of the AND will give either 0 or a non zero value, so why do an equality with 1?
Posted by Sebas06: Sat. May 2, 2015 - 04:00 PM(Reply to #52)
1
2
3
4
5
Total votes: 0
Kartman wrote:
I could make no sense of your last post! Suffice to say that 00000010 equals 2 not 1
My point was the result of the AND will give either 0 or a non zero value, so why do an equality with 1?
I think that was a typo, because on my paper in frotn of me that was clearly a 2.. My bad.
However I have been experimenting with the code and moved the counter out of the sub-if-block:
if(changedbits & (1 << PA1))
{
if( (PINA & (1 << PA1)) == 1 )
{
// Only on high add count
rpmcount[1]++;
}
}
to
if(changedbits & (1 << PA1))
{
rpmcount[1]++;
}
What seemed. The counter is not working.. Seems to me the changedbits is not working as expected. So just testing if I am doing it right, please correct me if I make a misatke:
volatile uint8_t portbhistory = 0xFF;
changedbits = PINA ^ portbhistory;
1st interrupt on port PA3
PA3 = low -> = low because of the pullup
11110111 ^ 11111111 = 00001000
portbhistory = PINA;
11110111
if(changedbits & (1 << PA3))
00001000 & 00001000 -> true
if (~PINA & (1 << PA3))
00001000 & 00001000 -> true execute code rpmcount[3]++
2nd interrupt on port PA3
PA3 = high -> = high because of the pullup (release of pulldown by external device)
11111111 ^ 11110111 = 00001000
portbhistory = PINA;
11111111
if(changedbits & (1 << PA3))
00001000 & 00001000 -> true
if (~PINA & (1 << PA3))
00000000 & 00001000 -> false so NO execute code
3rd interrupt on port PA3
PA3 = high -> = low because of the pullup
11110111 ^ 11110111 = 00001000
portbhistory = PINA;
11110111
if(changedbits & (1 << PA3))
00001000 & 00001000 -> true
if (~PINA & (1 << PA3))
00001000 & 00001000 -> true execute code rpmcount[3]++
This is with the adjustment to only evaluate on true/false.
Have been trying this afternoon, but cant seem to figure out why the changebit part is not entering the PA3, only when PA0 is triggered.
Then I get outout on PA0 and PA3 (rpmcount0 and rpmcount3).
Seems that the real problem is not directly the logic in the IFs...
I moved the rpmcount before all that and connected my fan to PA3 (or an other PA <> PA0). Seems no interrupt is triggered at all on these ports.
Kinda lost at the moment.
Found the problem, after thoroughly investigating the manual (again):
This only enabled the PA0
PCMSK0 |= (1 << PCINT0); // set PCINT0 to trigger an interrupt on state change
So it should have been:
PCMSK0 |= ((1 << PCINT0) | (1 << PCINT1) | (1 << PCINT2) | (1 << PCINT3) | (1 << PCINT4));
I think you could simplify the code a little and make it more reliable.
I gather you want to test for the rising edge - a little comment would help here.
Read PINA once in the isr - reading multiple times could cause strange random results as PINA is 'live' - it is changing whilst your code is running. One read may give you one result, the next may give another.
our_pina = PINA; //read once
//
// for rising edge, the previous bit is 0, the current is 1
// so we flip the previous bits then AND with the current. Rising edges will be a '1'
//
rising_edges = ~porthistory & our_pina;
porthistory = our_pina;
if (rising_edges & (1<<PA1)) //if rising edge on PA1
{
.....
}
Posted by Sebas06: Sun. May 3, 2015 - 07:19 AM(Reply to #55)
1
2
3
4
5
Total votes: 0
Kartman wrote:
I gather you want to test for the rising edge - a little comment would help here.
I think that dropped of while modifying the code. Earlier post show the comment. But indeed should be in there.
Kartman wrote:
Read PINA once in the isr - reading multiple times could cause strange random results as PINA is 'live' - it is changing whilst your code is running. One read may give you one result, the next may give another.
Totally agree, I already modified it with my current code.
Kartman wrote:
rising_edges = ~porthistory & our_pina;
porthistory = our_pina;
if (rising_edges & (1<<PA1)) //if rising edge on PA1
{
.....
}
if (rising_edges & (1<<PA2)) //if rising edge on PA2
00000100 & 00000100 = true
PA3 gets low (high by pullup):
rising_edges = ~porthistory & our_pina;
00001100 & 11111011 = 00001000 ->>> should be 00000000
if (rising_edges & (1<<PA3)) //if rising edge on PA3
00001000 & 00001000 = true
Can it be that your logic contains a mistake? When I have a change on the pin high to low. It also fires the PA3 code. See above example. Might be that I made a mistake.
I think the basis of my logic is sound. You want to detect a 0->1 transition (rising edge). So previous = 0, current = 1. Invert previous to get 1, current = 1. 1 AND 1 = 1
This is how I would solve the logic if I was building it in logic gates.
I think my solution is more direct. Nevertheless, the first step is to get something to work, then optimise.
After some time I restarted my project (converted to xmega), however I am running in a more general problem (not related to x/atmega).
What I see is when running the code with a 4000RPM spec fan that the rpmcount is outputting 127 per second (127*60 = 7620 RPM). This delivers 7620 RPM. Of course way to high, almost double of the fan spec.
Already spend a day looking and recalculating, but so far I havent found the problem, other than the timing issue, the code is running fine...
(Btw I am looking into your last advice for simplifying the code, will come back on that one)
Your suggestion with simplification now also works in my code (result is still off but values are consistent with my other version)
Each time you detect an edge in the input, toggle a port bit. Monitor the port bit with an oscilloscope. This should give a clue where the problem might lie.
Each time you detect an edge in the input, toggle a port bit. Monitor the port bit with an oscilloscope. This should give a clue where the problem might lie.
I feel ashamed I forgot that a FAN will pulse twice a round. Because it has 2 contacts.
So the measured value needs to be divided by 2.
Measured: 127
Rounds: 63.5
RPM: Rounds * 60 = 3810
So the code is correct and working as expected (and now running on a xmega & atmega).
I could make no sense of your last post! Suffice to say that 00000010 equals 2 not 1
My point was the result of the AND will give either 0 or a non zero value, so why do an equality with 1?
- Log in or register to post comments
TopI think that was a typo, because on my paper in frotn of me that was clearly a 2.. My bad.
However I have been experimenting with the code and moved the counter out of the sub-if-block:
What seemed. The counter is not working.. Seems to me the changedbits is not working as expected. So just testing if I am doing it right, please correct me if I make a misatke:
This is with the adjustment to only evaluate on true/false.
Have been trying this afternoon, but cant seem to figure out why the changebit part is not entering the PA3, only when PA0 is triggered.
Then I get outout on PA0 and PA3 (rpmcount0 and rpmcount3).
- Log in or register to post comments
TopSeems that the real problem is not directly the logic in the IFs...I moved the rpmcount before all that and connected my fan to PA3 (or an other PA <> PA0). Seems no interrupt is triggered at all on these ports.Kinda lost at the moment.Found the problem, after thoroughly investigating the manual (again):
ISR code (working as far as I can see):
- Log in or register to post comments
TopI think you could simplify the code a little and make it more reliable.
I gather you want to test for the rising edge - a little comment would help here.
Read PINA once in the isr - reading multiple times could cause strange random results as PINA is 'live' - it is changing whilst your code is running. One read may give you one result, the next may give another.
- Log in or register to post comments
TopI think that dropped of while modifying the code. Earlier post show the comment. But indeed should be in there.
Totally agree, I already modified it with my current code.
A write-out to understand what you propose:
PA3 gets high (low by pullup):
PA2 gets high (low by pullup):
PA3 gets low (high by pullup):
rising_edges = ~porthistory & our_pina; 00001100 & 11111011 = 00001000 ->>> should be 00000000
Can it be that your logic contains a mistake? When I have a change on the pin high to low. It also fires the PA3 code. See above example. Might be that I made a mistake.
Current code (with the 1 time PIN read):
- Log in or register to post comments
TopI think the basis of my logic is sound. You want to detect a 0->1 transition (rising edge). So previous = 0, current = 1. Invert previous to get 1, current = 1. 1 AND 1 = 1
This is how I would solve the logic if I was building it in logic gates.
I think my solution is more direct. Nevertheless, the first step is to get something to work, then optimise.
- Log in or register to post comments
TopAfter some time I restarted my project (converted to xmega), however I am running in a more general problem (not related to x/atmega).
What I see is when running the code with a 4000RPM spec fan that the rpmcount is outputting 127 per second (127*60 = 7620 RPM). This delivers 7620 RPM. Of course way to high, almost double of the fan spec.
Already spend a day looking and recalculating, but so far I havent found the problem, other than the timing issue, the code is running fine...
(Btw I am looking into your last advice for simplifying the code, will come back on that one)Your suggestion with simplification now also works in my code (result is still off but values are consistent with my other version)
- Log in or register to post comments
TopEach time you detect an edge in the input, toggle a port bit. Monitor the port bit with an oscilloscope. This should give a clue where the problem might lie.
- Log in or register to post comments
TopI feel ashamed
I forgot that a FAN will pulse twice a round. Because it has 2 contacts.
So the measured value needs to be divided by 2.
Measured: 127
Rounds: 63.5
RPM: Rounds * 60 = 3810
So the code is correct and working as expected (and now running on a xmega & atmega).
- Log in or register to post comments
TopPages