How to make a level detect counter?

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

Please see attached drawing, could this be done?

 

I have tried hard to find how to do this, but with no sucess, any suggestions are welcome.

 

 

 

Attachment(s): 

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

I think what you are looking for is "Input Capture Mode" on one of the timers if you want to count how long a pulse remains high in terms of timer ticks.

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

If you are trying to count the pulses, then you might try:

(Dependent upon the frequencies involved)

 

Fire and ISR on the IDR01 rising edge.

In the ISR turn on a Timer/Counter to count the CLK pulses applied to a hardware pin.

 

Fire the ISR on the IDR01 falling edge.

Turn off the T/C counting, and read the value.

 

Look at the overview for the various Timer/Counters to see which ones can act as a pulse counter.

 

JC

 

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

ejej wrote:
Please see attached drawing, could this be done?  

I have tried hard to find how to do this, but with no sucess, any suggestions are welcome.  

 

That's a gated timer, found on 8051 but less common on AVR.

 

You can get close with a dual capture, so capture on both edges, and take a difference in reading. ie time(=\_) - time(_/=) = time spent high

Read up on the various capture modes in the AVR you are using.

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

To save a mouse click, Use the picture icon (Mountain with blue sky)

 

I have doubts this can be easily done in AVR hardware, a combination of an ISR and software might work.

What is the frequency of those signals?

Up to a few kHz you may expect reasonable results.

 

You will get quite some distance with an external AND gate,  but you may will have glitches on it's output unless IDR01 and CLK are synchronized to each other.

How accurate does it have to be?

Is it OK if yoy miss a pulse every now and then?

 

A good approach may be to use an external interrupt on rising and on the falling edge of IDR01, and a counter for CLK.

On the rising edge of IDR01 you enable the counter,  and on the falling edge of IDR01 you disable & reset the counter.

 

Optimisations:

Keep the interrupts as small as possible.

Preferably use 2 different external interrupts for IDR01. This way you don't have to determine in the ISR whether it was a falling or rising edge, which will keep the ISR's faster and smaller.

The Interrupt for the rising edge probably only have to write a single byte to the timer.

For very small ISR's written in C you may expect to push and pop more registers in the ISR preamble for almost every line added to the ISR routine.

 

If you want to live on the edge in ASM:

The interrupt vector table areually jumps to the actual ISR code.

If the ISR entries after the external interrupt is not used, then you could in theory put the ISR routine directly in the table.

The whole ISR could be 3 ASM insructions, something like:

1). load constant.

2). Write to timer.

3). reti.

 

Maybe you could get it down to 2 with a sbi or cbi instruction, but I'm not sure if those instructions can reach the timer address space. ( I avoid ASM wherever I can).

If you want to see what your interrupt code really does, then make GCC generate .LSS files, which list the asm code generated by the compiler, interspersed with the C code it comes from as comment.

 

 

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

Last Edited: Wed. Aug 8, 2018 - 12:05 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Paulvdh wrote:
To save a mouse click, Use the picture icon

Not only does it save a mouse click - it also means that the image can be seen in the context of the thread.

 

For illustrated instructions, see Tip #1.

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Paulvdh wrote:
I have doubts this can be easily done in AVR hardware, a combination of an ISR and software might work.
Do you mean hardware alone? Surely it can be done in a combination of hardware and software? I don't know Xmega capabilities (though I assume they offer at least what tiny/mega did?) but for the actual pulse counting don't you just have a timer using an asynchronous clock driven from a pin input? After that you just connect IDR01 to an ext-int/pcint or similar. When it goes high you enable the clocked timer and reset its count, when it goes low you take the count and disable the clocked timer.

 

EDIT: actually, thinking about it, the enabling disabling probably isn't even required as long as you reset the count at the rising edge of IDR01.

Last Edited: Wed. Aug 8, 2018 - 12:02 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It certainly depends upon how fast you want to set the count rate, CLK...if it is perhaps few hundred KHz max, you can just fire an IRQ at that rate, and read your signal pin...if high, increase the count, if low, set the count to zero.

Then main will have the current count value to use as needed.  The longer your input pin is held high, the higher the count will grow (until zeroed when pin goes low).

 

When in the dark remember-the future looks brighter than ever.

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

On XMEGA hardware I would handle this with a Timer and two Event channels. Event channel A is tied to the IO pin with the CLK signal. Event channel A is selected as the clock source for the timer. Event channel B is tied to the IO pin with the IDR01 signal. The timer is configured to use event channel B the generate a RESTART event action.

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

In line with above suggestions, set up counter with code such as:

 

//set up for normal mode
	TCC0.CTRLB = TC_WGMODE_NORMAL_gc;

	TCC0.CTRLA = TC_CLKSEL_EVCH2_gc;   // Event channel2

	TCC0.PER   = 20000;//sets top

	TCC0.CTRLD = TC_EVACT_CAPT_gc | TC_EVSEL_CH2_gc;

	PORTB.PIN6CTRL = PORT_OPC_PULLUP_gc | PORT_ISC_FALLING_gc;//input on PORTB pin 6

	EVSYS.CH2MUX = EVSYS_CHMUX_PORTB_PIN6_gc;//increment counter on pin change portb/pin6

	EVSYS.CH2CTRL = EVSYS_DIGFILT_8SAMPLES_gc;

and then set up an interrupt on the falling edge of IDR01 that resets the counter with:

 

TCC0.CTRLFSET = TC0_CMD1_bm;//reset

 

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

Microchip makes a bunch of PIC's with internal programmable hardware.

I have vague memories they are also putting similar in the latest incarnatiion of the Atmel lecacy chips.

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

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

XmegaE5 series has a programmable logic unit.

 

JC