Fastest pin check loop

Go To Last Post
12 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello,

 

i have to measure how long the pin remains on low. The value I read is not in time units, i only need arbitrary values to look for differences in values between different measurements.

So i increment a counter variable(cou) inside a while loop, that is constantly checking if the pin is low and exits once the input pin goes from low to high and displays the counted value.

 

while(!(VPORTC.IN & (1 << 1))){
            cou++;
        }

 

This works 99% fine for me, but is there a function or some process that would do this a bit faster?? From time the pin goes low and then back to high, the "cou" value gets up to 130 or 150, so you can see this is a very short time i measure. The MCU is Atmega 4809 running at 20MHz. The trace of the pin are also as short as possible to eliminate parasitic capacitance.

This topic has a solution.

Last Edited: Wed. Apr 3, 2019 - 06:24 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You can use TCB pulse width measurement.
This gives a resolution of up to 20 MHz (50 ns).

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 is there a function or some process that would do this a bit faster??

Check the asm code produced with "avr-objdump -S *.elf"

 

 

[count] gets up to 130 or 150, so you can see this is a very short time i measure.

300+ cycles isn't "very short" - what size is your cou variable?  The loop would be fastest if it's an 8bit variable, but then you run the risk of overflowing in the case of longer events.

 I think that in the ideal case, you'd get values between ~5 and ~250

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks, input capture would fix this yea, but i need to read it on 25 to 30 pins so this would not work for me.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks i will check asm code and will also test with 8bit integer (atm size of variable is 16bit).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I built:

#include <avr/io.h>

uint16_t cou;

int main(void)
{
	
	while(!(VPORTC.IN & (1 << 1))){
		cou++;
	}	
}

and got:

000000c2 <main>:
uint16_t cou;

int main(void)
{
	
	while(!(VPORTC.IN & (1 << 1))){
  c2:	51 99       	sbic	0x0a, 1	; 10
  c4:	0b c0       	rjmp	.+22     	; 0xdc <main+0x1a>
  c6:	80 91 00 28 	lds	r24, 0x2800	; 0x802800 <_edata>
  ca:	90 91 01 28 	lds	r25, 0x2801	; 0x802801 <_edata+0x1>
		cou++;
  ce:	01 96       	adiw	r24, 0x01	; 1
uint16_t cou;

int main(void)
{
	
	while(!(VPORTC.IN & (1 << 1))){
  d0:	51 9b       	sbis	0x0a, 1	; 10
  d2:	fd cf       	rjmp	.-6      	; 0xce <main+0xc>
  d4:	80 93 00 28 	sts	0x2800, r24	; 0x802800 <_edata>
  d8:	90 93 01 28 	sts	0x2801, r25	; 0x802801 <_edata+0x1>
		cou++;
	}	
  dc:	80 e0       	ldi	r24, 0x00	; 0
  de:	90 e0       	ldi	r25, 0x00	; 0
  e0:	08 95       	ret

 

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think that this shows just how good XMega and 0-series can handle port bits.


	while(!(VPORTC.IN & (1 << 1))){
  d0:	51 9b       	sbis	0x0a, 1	; 10
  d2:	fd cf       	rjmp	.-6      	; 0xce <main+0xc>

If you have 8 inputs on one VPORT,  you can react either by reading the VPORTx.IN register or you could monitor the Pin Change interrupt flag for this particular port.

 

You still have to test individual bits.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Klemko wrote:
Thanks, input capture would fix this yea, but i need to read it on 25 to 30 pins so this would not work for me.

You are monitoring all these pins at the same time?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

i have to measure how long the pin remains on low

Starting from when?  You have a good exit condition, but how do you know when to start counting---that limits your timing accuracy. 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

i start to measure as soon as voltage drops to low(voltage i measure is default at 5V).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

no, 1 after another, but i connected each one to each own pin on atmega. External ultiplexers or anything would cause to much delay or error in measurements, due to transient voltage on the pins i measure (they have some small inherent capacitance)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks all, i used Davids suggestion to monitor for pin change interrupt, also change my variable down to 8bits and it improved my readings by a lot (i configured so the read values are from 200 to 250, so i am at max and still in 8bit range). Thanks all for help, great community :D  

Last Edited: Wed. Apr 3, 2019 - 07:25 AM