ランダムで予測不可能なアナログコンパレータの動作


10

振幅と周波数が変化する正弦波の周波数を測定する必要がある比較的「単純な」プロジェクトに取り組んでいます。物事を簡単にするために、今のところ、固定周波数(27Hz)の正弦波入力(コンパレーターの負の入力)しか持っていません。コンパレータの正入力はVcc / 2に設定されています。コンパレータの出力は、atmega2560マイクロコントローラの入力キャプチャレジスタに送られ、周波数を測定します。

問題は、入力信号の特定の振幅で、次のような出力で非常に激しいトグル(または場合によってはデッドバンド)が発生することです。

ここに画像の説明を入力してください

予想される出力は次のようになります。

ここに画像の説明を入力してください

これまでに試したこと:

内部atmega2560の内部コンパレータを使用します。外部コンパレータを使用します。ソフトウェアとシュミットトリガー回路を使用したヒステリシスの紹介。固定リファレンスセットアップやデータスライサーセットアップなど、さまざまな入力セットアップを試しました。別のatmega2560を試してみます。さまざまなクロック速度を試します。

一部のソリューションは他のソリューションよりも安定性が高かったが、いずれも許容範囲内ではありませんでした。これまでのところ、最も安定した構成で解決しています。

ここに画像の説明を入力してください

この設定では、特定のものが安定性を改善/変更しますが、まだ完璧に近いものはありません。

R5の値を変更してヒステリシスを増やします。C2を完全に削除する(理由はわかりません)。ブレッドボードのワイヤーに触れます(数本を並べてください)。電源を外部からUSBに、またはその逆に切り替えます。

この時点で、ノイズ、つまり正弦波を生成しているDACか、非常に基本的な何かを誤って実行しています。この回路は問題なく他の人のために働いたので、私の設定や環境に何か問題があるはずです。

何か提案があれば、お時間をいただければ幸いです。

これが私の最小限のソースです:

#include <avr/io.h>

void init(void);

void init(void) {
    /* Setup comparator */
    ACSR = (1 << ACIE) | (1 << ACIS1);
    /* Initialize PORTD for PIND5 */
    DDRD = 0x00;
    PORTD = 0x00;
    /* Enable global interrupts */
    sei();
}

int main(void) {

    init();

    while (1) {}
}

ISR(ANALOG_COMP_vect) {

     if (!(ACSR &  (1<<ACIS0))) { //comparator falling edge
         /* Set PIND5 to 0V */
         PORTD &= ~(1 << PIND5);

         ACSR |= (1<<ACIS0); //set next comparator detection on rising edge
    }
    else  {
       ACSR &= ~(1<<ACIS0); //set next comparator detection on falling edge
       /* Set PIND5 to 5V */
       PORTD |= (1 << PIND5);
    }
}

また、回路図とライブラリ自体へのリンクは次のとおりです。

http://interface.khm.de/index.php/lab/interfaces-advanced/frequency-measurement-library/

更新:

私はあなたの提案をすべて試しましたが、どれもうまくいきませんでした。割り込みフラグをクリアしたり、ISR内外の割り込みを無効にしたりしても、実際には何の影響もありませんでした。チップのコンパレータレジスタの実際の動作を誤解しているようです。

最初に述べたように、私は入力キャプチャを使用して、正弦波から派生した方形波の周波数を測定していました。コンパレータの出力は入力キャプチャピンに送られ、次にタイマーを使用して期間を測定します。

これは、atmega2560 http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2549-8-bit-AVR-Microcontroller-ATmega640-1280-1281-2560-2561_datasheet.pdfの 265ページのアナログコンパレータダイアグラムです。

ここに画像の説明を入力してください

ご覧のとおり、コンパレータにはACOとACIS0 + ACIS1の2つの出力があります。ACOは、+入力>-入力のときに設定され、+入力<-入力のときにクリアされます。ACIS0 + ACIS1はエッジ選択ビットです。

私が最初にやっていたことは、ISRのエッジタイプをチェックすることでした。代わりにISRをこれに変更しました。

    ISR(ANALOG_COMP_vect) {

     if (!(ACSR &  (1<<ACO))) { // + < -
         /* Set PIND5 to 0V */
         PORTD &= ~(1 << PIND5);
    }
    else  {
       /* Set PIND5 to 5V */
       PORTD |= (1 << PIND5);
    }
}

そして、出力は(2番目の図のように)完璧に動作しました。その後、パルス幅の測定に進みましたが、結果はあまり良くありませんでした。LCDディスプレイの激しい切り替え、数値がランダムな値にジャンプする、または信号がクリーンであるにもかかわらず0のままになる。私はさまざまな条件を使用して何度もコードを書き直しましたが、これまでに得た唯一の半安定したソリューションは次のとおりです。

#include <avr/io.h>
#include <util/delay.h>
#include "UART.h"

void init(void);

volatile uint16_t y = 0;
volatile uint16_t x = 0;
volatile uint16_t current_value = 0;
volatile uint16_t previous_value = 0;
volatile uint16_t total = 0;

void init(void) {
    /* Normal mode, 64 prescaler, Rising Edge trigger, Input Capture */
    TCCR1A = 0;
    TCCR1B = (1 << CS10) | (1 << CS11) | (1 << ICES1);
    TIMSK1 = (1 << ICIE1);

    ACSR = (1 << ACIC);
    ADCSRB = 0x00;

    /* This port is used for simulating comparator's output */
    DDRC = 0xFF;
    PORTC = 0xFF;

    DDRD = 0x00;
    PORTD = 0x00;

    USART_Init(UBRR_VALUE);

    sei();
}

int main(void) {

init();

    while (1) {
        if (TCNT1 == 60000) {
            /* Display the values on the LCD */
            USART_Transmit(0xFE);
            USART_Transmit(0x01);

            USART_Transmit_Double(x+y);
        }
    }
}

ISR(TIMER1_CAPT_vect) {

    //ACSR &= ~(1<<ACIC);

    if (!(ACSR & (1 << ACO))) {
        if (!(TCCR1B & (1 << ICES1))) { // check for falling edge
            PORTD |= (1 << PIND5);

            PORTC &= ~(1 << PINC1);

            TCCR1B |= (1 << ICES1);

            current_value = ICR1;
            x = current_value - previous_value;
            previous_value = current_value;
        }
    }        
    else {
        if (TCCR1B & (1 << ICES1)) { // check for rising edge
            PORTD &= ~(1 << PIND5);

            PORTC |= (1 << PINC1);

            TCCR1B &= ~(1 << ICES1);

            current_value = ICR1;
            y = current_value - previous_value;
            previous_value = current_value;
        }
    }

    //ACSR |= (1<<ACIC);
}

半安定とは、1/3の時間で正しい値が得られることを意味します。他の時間の2/3は、正しい値の半分またはランダムな値です。ISRで条件付きステートメントのタイマーのレジスタビットとコンパレーターのレジスタビットを使用してみましたが、これが唯一の構成です。

その日の後半に行ったのは、同じ設定とソース(コンパレータに関連するすべてのラインを除く)の代わりに外部コンパレータを使用することでした。その出力は入力キャプチャピンに供給され、意図したとおりに機能しました(ヒステリシスも必要ありませんでした)。

この時点で、外部コンパレータを使用して解決したと言えますが、内部コンパレータが動作しない理由はわかりません。これに関する多くの投稿とガイドを読んだり、さまざまなライブラリを読んだり、許容できる結果なしにそれらを模倣しようとしました。データシートにはコンパレータユニット全体で5ページしかないので、何度も読み直しましたが、何が間違っているのかわかりません。

それを適切に使用する方法を知りたいのですが、それが失敗した場合は、バックアップを取得しています。他にご意見がありましたら、大歓迎です。


4
まず、出力と+ ve入力の間に1Mの抵抗を追加します。これは、ヒステリシスを作成するものであり、R5ではありません...参照を変更するだけです
JonRB

1
チップ内にあり、アクセスできないコンパレータからの出力のスコープ画像をどのように作成できますか?
アンディ、別名

2
ISRに入るときに、さらに割り込みを無効にしますか?あなたがする必要があるかもしれません-それはほとんどのISRが二重のヒットを得ているかもしれません。
アンディaka

1
ヒステリシスピンをどのように切り替えて、現在の値でそれを修飾していますか。割り込みとトグルの間の遅延が気になる場合があります。
Trevor_G 2018

1
回路図に示されていないのは、ピン5とピン6の間の内部容量ですが、代わりにピン7の内部プルアップを使用してヒステリシスを作成できますか?
Jasen

回答:


13

DACを使用して正弦波信号を生成していると読みました。DAC出力は、出力状態の変化時にグリッチが発生する可能性があるため、コンパレータ回路に供給する前に、DAC出力に何らかのアナログフィルターを適用する必要があります。これは、発生する可能性が高い二重割り込みトリガーの一部を防ぐのに役立ちます。

また、ソフトウェアの相互作用を使用せずに抵抗器でヒステリシスを適用できるように、このタイプの問題に外部コンパレータを使用したいこともコメントします。これにより、コンパレータの出力を直接監視できるため、問題をより適切に分離できます。

最後のコメントは、使用しているヒステリシスのタイプに関連しています。使用しているスキームを正確に確認するのは少し難しいですが、必要なのはこれを行う動作であることに注意してください。したがって、立ち上がりエッジの場合、しきい値をゼロ点よりも少し高くし、状態が変化するとしきい値が低いレベルに引き上げられるようにします。


1
+1は、ヒステリシスの方向がどのように機能するかについての補足説明です。パラグラフ2は良いアドバイスですが、正しく行われている限り、内部で行うことも可能です。この例ではそうではないようです。
Trevor_G 2018

@Trevor_G-:^)
マイケルカラス

1
@Hypomania-ISRで単一のタイマーを読み取ることができることを知っています。ただし、タイマー自体がカウントを継続できる一方で、出力レジスターがトリガーからのカウントを保持するようにタイマーがダブルバッファーされない限り、タイマーを停止して、読み取り後に読み取りを再度有効にできるようにする必要があります。 。多くのMCUタイマーはそのようにダブルバッファーされないため、タイマーが再度有効になるまでISRに入るまでの処理時間は、次の半サイクルの周期時間測定で失われます。タイマーのクロック速度にある程度依存します(続き)
Michael Karas

1
(上から続きます)しかし、クロックが同時に来てカウントを変更している可能性があるときに、カウント値を読み取っている状況になりたくはありません。タイマーがトリガーキャプチャイベントでダブルバッファリングされているかどうかを確認するために使用している特定のMCUについては調査していません。
マイケルカラス2018

1
@Hypomania-気まぐれに、リンクされたAVR MCUデータシートを見て、タイマー入力キャプチャ機能がダブルバッファリングされていることを確認しました!! 実際、これらのパーツのタイマーは非常に堅牢に見えます。AVRパーツを使用してから15年近くになります。
マイケルカラス

6

このシナリオの問題は、「ヒステリシス」ピンを切り替えるポイントまで、コンパレータの切り替えと処理される割り込みの間に時間遅延があることです。

ヒステリシスバンドは、使用目的を考慮すると、その信号レベルに対してもかなり小さくなります。特に、あなたのスコープの方形波にどれほどのノイズがあるかを見たとき。

これらの要因の両方を考慮して、特定の入力レベルでは、最初のエッジを処理する前にコンパレータから複数のエッジを取得する可能性が高くなります。その割り込みハンドラーの間にコンパレーターの状態が何であるかを確認することは、どちらの状態にもなり得るので、あまり役に立ちません。

残念ながら、ハンドラーがどのように機能するかという質問には詳しくありません。

ただし、ハンドラは次のように機能する必要があります。

  1. 高しきい値状態のヒステリシス値は、ネガティブエッジ割り込みを待機している必要があります。

  2. 上記のネガティブエッジ割り込みが到着したら、ヒステリシスを低い値に切り替え、数サイクル待ってから、保留中の割り込みをクリアして、ポジティブエッジ割り込みの待機を開始します。

  3. 上記のポジティブエッジ割り込みが到着したら、ヒステリシスピンを高値に戻し、数サイクル待って、保留中の割り込みをクリアし、ネガティブエッジ割り込みの待機を再開します。

  4. 手順1から繰り返します。

ところで、信号のバイアスとしてコンパレータのリファレンスを使用している方法にはそれほど熱心ではありません。その結果、信号からリファレンスへ、およびヒステリシスから信号へのクロストークが発生します。特に、低周波数信号ではそうです。これらの値が与えられれば、その影響は小さいはずですが、純粋さのためには、信号に個別のバイアスをかける方が良いでしょう。

編集:コードを再編集します。

elseステートメントでは、ヒステリシスを設定する前に割り込みエッジを変更します。

どちらの場合も、戻る前に一時停止して保留中の割り込みをクリアします。(割り込み制御レジスタを変更すると、それ自体で割り込みが作成される可能性があることに注意してください。)

Atmegaが割り込みを再入可能にするかどうか、つまり次のエッジがまだ実行中のハンドラーを前のエッジから中断するかどうかはわかりません。その場合、並行性を適切に処理する必要があります。

PORTCパーツの用途がわからないが、おそらく認定パーツに移行する必要がある。


どうもありがとうございました。明日提案を試して、最新情報をお届けします。私のISRに関しては、待機を除いて、あなたが説明した正確なシナリオのif-else ifステートメントがあります。
Shibalicious

1
@Hypomaniaあなたは質問を編集して割り込みハンドラーコードを投稿する必要があります。そうすれば、誰かがどこかで失敗しているかどうかを確認できます。それは単なるノイズかもしれませんが、スコープのトレースはそこに50mV以上のノイズがあるように見えます。それでもノイズがあれば、トランジションで時々余分なパルスが発生しても、それ自体が修正されると思います。
Trevor_G 2018

私もそう思っていました。できるだけ早くそれを行います。
Shibalicious

1
@Hypomania編集を参照してください
Trevor_G

1
@Hypomania 2つのコマンドの間に別の割り込みが発生する可能性があるためです。私も編集を編集しました...
Trevor_G 2018

3

この効果は接触バウンスに似ており、押しボタンに使用するのと同じデバウンス技術で軽減できます。

  • デバウンス時間を決定する Td
  • 最後のエッジ割り込みのタイムスタンプを変数に保持します
  • 現在の割り込みと最後の割り込みの間の時間がより小さい場合Td、現在の割り込みを無視します
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.