Pages: [1] 2 3   Go Down
Author Topic: Analog Comparator falling edge setup  (Read 3167 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 45
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

this is the first time I'm using the analog comparator. I'm trying to compare AIN0 and AIN1. A pulse is applied to AIN0 and a rising ramp to AIN1. Once the value of AIN1 is higher than the maximum of the pulses on AIN0, no more falling edges should occur, right? So my goal is to trigger an interrupt on every falling edge of the comparator and detect a missing edge to calculate my results.

Setup:
Code:
  // Analog Comparator Multiplexed Input:
  // If ACME is cleared or ADEN is set, AIN1 is applied to the negative input to the Analog Comparator.
  ADCSRB &= ~(1<<ACME);
 
  // Setup of ACSR (Comparator Register)
  // Bit 7(MSB)  : ACD:          Analog Comparator Disable;               When this bit is written logic one, the power to the Analog Comparator is switched off. This bit can be set at any time to turn off the Analog Comparator. This will reduce power consumption in Active and Idle mode. When chang- ing the ACD bit, the Analog Comparator Interrupt must be disabled by clearing the ACIE bit in ACSR. Otherwise an interrupt can occur when the bit is changed.
  // Bit 6       : ACBG:         Analog Comparator Bandgap Select;        When this bit is set, a fixed bandgap reference voltage replaces the positive input to the Analog Comparator. When this bit is cleared, AIN0 is applied to the positive input of the Analog Comparator. When the bandgap reference is used as input to the Analog Comparator, it will take a certain time for the voltage to stabilize. If not stabilized, the first conversion may give a wrong value.
  // Bit 5       : ACO:          Analog Comparator Output;                The output of the Analog Comparator is synchronized and then directly connected to ACO. The synchronization introduces a delay of 1 - 2 clock cycles.
  // Bit 4       : ACI:          Analog Comparator Interrupt Flag;        This bit is set by hardware when a comparator output event triggers the interrupt mode defined by ACIS1 and ACIS0. The Analog Comparator interrupt routine is executed if the ACIE bit is set and the I-bit in SREG is set. ACI is cleared by hardware when executing the corresponding interrupt handling vector. Alternatively, ACI is cleared by writing a logic one to the flag.
  // Bit 3       : ACIE:         Analog Comparator Interrupt Enable;      When the ACIE bit is written logic one and the I-bit in the Status Register is set, the Analog Comparator interrupt is activated. When written logic zero, the interrupt is disabled.
  // Bit 2       : ACIC:         Analog Comparator Input Capture Enable;  When written logic one, this bit enables the input capture function in Timer/Counter1 to be triggered by the Analog Comparator. The comparator output is in this case directly connected to the input capture front-end logic, making the comparator utilize the noise canceler and edge select features of the Timer/Counter1 Input Capture interrupt. When written logic zero, no connection between the Analog Comparator and the input capture function exists. To make the comparator trigger the Timer/Counter1 Input Capture interrupt, the ICIE1 bit in the Timer Interrupt Mask Register (TIMSK1) must be set.
  // Bit 1,0(LSB): ACIS1, ACIS0: Analog Comparator Interrupt Mode Select; These bits determine which comparator events that trigger the Analog Comparator interrupt.
  /*
     ACIS1 | ACIS0 | Interrupt Mode
     0       0       Comparator Interrupt on Output Toggle.
     0       1       Reserved.
     1       0       Comparator Interrupt on Falling Output Edge.
     1       1       Comparator Interrupt on Rising Output Edge.
  */
  ACSR = B00011010;
 
  // Disable digital input buffer
  // AIN1, AIN0 Digital Input Disable: When this bit is written logic one, the digital input buffer on the AIN1/0 pin is disabled. The corresponding PIN Reg- ister bit will always read as zero when this bit is set. When an analog signal is applied to the AIN1/0 pin and the digital input from this pin is not needed, this bit should be written logic one to reduce power consumption in the dig- ital input buffer.
  DIDR1  |=  (1<< AIN0D);
  DIDR1  |=  (1<< AIN1D);

Will this work or am I doing something wrong?
Thanks for your help!
Logged

United Kingdom
Offline Offline
Tesla Member
***
Karma: 220
Posts: 6587
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I don't see anything wrong with that code. Is it working?
Logged

Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

Offline Offline
Newbie
*
Karma: 0
Posts: 45
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I couldn't test it yet, will report back. Thanks!
Logged

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I cannot tell if yours work but this is what I use:

Code:
//reset the comparator
void comp_init(void) {
//ain0/ain1 assumed to be input

//configure output pin

//configure the analog comparator
#if defined(DIDR)
DIDR = (1<<AIN1D) | //disable ain1's digital input
(1<<AIN0D) //disable ain0's digital input
;
#endif

#if defined(DIDR1)
DIDR1 = (1<<AIN1D) | //disable ain1's digital input
(1<<AIN0D) //disable ain0's digital input
;
#endif

//configure ACSRB if available
#if defined(ACSRB)
ACSRB &=~(0<<ACME); //disable analog comparator multiplexer
#endif

//configure ACSR
ACSR &=~(1<<ACIE); //disable interrupt
ACSR = (0<<ACD) | //analog comparator power on
#if defined(ACBG)
(0<<ACBG) | //bandgap reference not selected. Use AIN1 for non-inverting input
#endif
(1<<ACI) | //clear acif by writing '1' to it
(0<<ACIE) | //interrupt not yet enabled
(0<<ACIC) | //analog comparator input capture disabled
(0<<ACIS1) | (0<<ACIS0) //interrupt on output toggle
//(0<<ACIS1) | (1<<ACIS0) //reserved
//(1<<ACIS1) | (0<<ACIS0) //interrupt on falling output edge
//(1<<ACIS1) | (1<<ACIS0) //interrupt on rising output edge
;

ACSR |= (1<<ACIE); //enable the interrupt

//rest comp_ptr
_comp_isr_ptr = _comp_empty_handler;
}

It has other stuff (user-installed interrupt handler) but the basic structure is the same. I was targetted for a bigger chip but should be able to compile for yours as well.
Logged

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Will this work

I can confirm for you that it will work.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 45
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

By the way, I have another question on that topic.
I'm using Timer1 to generate an interrupt every Xµs that triggers the pulse for the comparator. That means that the comparator interrupt will be triggered just before the other interrupt finishes. Somewhere I heard, that interrupts aren't allowed within interrupts. Is that true? If the Arduino "remembers" that there was another(different) interrupt during the timer interrupt and executes it afterwards, that would be fine because the comparator interrupt only increments a value and timing isn't important, as long as it doesn't forget the comparator interrupt.
Logged

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Somewhere I heard, that interrupts aren't allowed within interrupts.

You can nest interrupts. But that's not for the faint of heart.

In your case, the ACI flag will be set while the timer isr is being serviced. The execution will return to where it was before the timer isr was executed, and then jump right back to the analog comparator isr (assuming no other interrupt flags are set).
Logged

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I'm using Timer1 to generate an interrupt every Xµs that triggers the pulse for the comparator.

That's a weird set up.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 45
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I'm using Timer1 to generate an interrupt every Xµs that triggers the pulse for the comparator.

That's a weird set up.

The pulse controls external circuitry and the result of that circuit(very fast) triggers the comparator interrupt. Still weird? How could I improve it?
Logged

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So the timer will trigger an external device to create a voltage which the analog comparator is going to compare against?

What does the whole thing do?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 45
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So the timer will trigger an external device to create a voltage which the analog comparator is going to compare against?

What does the whole thing do?

Measure the ESR of a cap
Logged

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I assume that you aren't using a bridge here.

The typical approach then is to charge up a fully depleted cap and measure the current during the initial charge up. The comparator is probably not a very good tool for this.

Unless you have a different approach?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 45
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I assume that you aren't using a bridge here.

The typical approach then is to charge up a fully depleted cap and measure the current during the initial charge up. The comparator is probably not a very good tool for this.

Unless you have a different approach?

I feed the DUT with a constant current(chopped by the generated pulse), amplify the generated voltage over the DUT and compare it to the voltage of a reference cap that is being charged by a constant current(==> linear rising voltage). If you want to read more, here's a link: http://members.ozemail.com.au/~bobpar/k7214.pdf I basically just added some stuff I wanted and converted it to be Arduino based.

But my question was if you know a better way with only one interrupt smiley-wink
« Last Edit: December 09, 2012, 05:43:34 pm by daywalkerdha » Logged

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
But my question was if you know a better way with only one interrupt

I think his approach is quite convoluted - C10 for example only serves to tell time, which the mcu can do with ease.

The basic theory here is that when you charge up a capacitor with a constant current, the voltage rise

deltaV = I * Tc / C, assuming deltaV is sufficiently small and ESR is sufficiently small.

When  you discharge, the residual voltage at Td is

Vd = deltaV * exp(-Td / (ESR * C)).

So after each charge/discharge cycle, the voltage across the capacitor has gone up by Vd.

If, after n such cycles, the voltage across the capacitor is V, you have

V/n = (I * Tc / C) * exp (-Td / (ESR * C)), assuming of course V is sufficiently small.

If you know V, n, I, Tc, Td, C, you can solve for ESR from the above.

You can take his hardware, and you can rewrite the software:

1) charge the capacitor at I for Tc;
2) discharge the capacitor for Td;
3) go back to 1 for n times;
4) measure the voltage across the capacitor, V;
5) calculate ESR.

No need to have a comparator.

Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 45
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The comparator(and C10) is essentially there for an extremely fast analogRead(), which otherwise wouldn't be possible fast enough.
The goal of an ESR meter is to make measurements in circuit possible and if you charge the capacitor you'd activate other stuff in there.
http://en.wikipedia.org/wiki/Equivalent_series_resistance

If you know V, n, I, Tc, Td, C, you can solve for ESR from the above.
Where should the µC know C from? I don't want to enter it every time.

Anyhow, can I improve my software solution or do I require two interrupts, without changes to the way the measurement is done?
« Last Edit: December 09, 2012, 08:32:56 pm by daywalkerdha » Logged

Pages: [1] 2 3   Go Up
Jump to: