यादृच्छिक और अप्रत्याशित अनुरूप तुलनित्र व्यवहार


10

मैं एक अपेक्षाकृत "सरल" परियोजना पर काम कर रहा हूं जहां मुझे एक साइन लहर की आवृत्ति को मापने की आवश्यकता है जो आयाम और आवृत्ति में भिन्न होती है। चीजों को सरल बनाने के लिए, अब तक, मुझे केवल एक निश्चित आवृत्ति (27 हर्ट्ज) साइन वेव इनपुट (तुलनित्र का नकारात्मक इनपुट) मिला है, जो केवल आयाम (एक पोटेंशियोमीटर का उपयोग करके) में भिन्न हो सकता है। तुलनित्र का धनात्मक इनपुट Vcc / 2 पर सेट है। तुलनित्र का उत्पादन फिर आवृत्ति को मापने के लिए atmega2560 माइक्रोकंट्रोलर के इनपुट कैप्चर रजिस्टर में फीड किया जाता है।

समस्या यह है कि इनपुट सिग्नल के कुछ आयामों पर मुझे इस पर लगने वाले आउटपुट पर काफी तीव्र टॉगल (या कभी-कभी मृत बैंड) मिलते हैं:

यहां छवि विवरण दर्ज करें

जहां अपेक्षित आउटपुट कुछ इस तरह दिखना चाहिए:

यहां छवि विवरण दर्ज करें

मैंने अब तक जिन चीजों की कोशिश की है:

आंतरिक atmega2560 के आंतरिक तुलनित्र का उपयोग करना। बाहरी तुलनित्र का उपयोग करना। सॉफ्टवेयर और श्मिट ट्रिगर सर्किट का उपयोग करके हिस्टैरिसीस का परिचय। निश्चित संदर्भ सेटअप और डेटा स्लाइसर सेटअप सहित विभिन्न इनपुट सेटअप की कोशिश की। अलग atmega2560 की कोशिश कर रहा है। अलग-अलग घड़ी की गति की कोशिश करना।

कुछ समाधान दूसरों की तुलना में अधिक स्थिर थे, लेकिन उनमें से कोई भी स्वीकार्य नहीं था। मैंने अब तक के सबसे स्थिर विन्यास के साथ समझौता किया है:

यहां छवि विवरण दर्ज करें

इस सेटअप के साथ, कुछ चीजें स्थिरता में सुधार / परिवर्तन करती हैं, हालांकि अभी भी बिल्कुल सही नहीं हैं:

हिस्टैरिसीस बढ़ाने के लिए R5 का मूल्य बदलना। पूरी तरह से C2 को हटाना (पता नहीं क्यों)। ब्रेडबोर्ड पर तारों को छूना (एक-दूसरे के बगल में काफी कुछ)। बाहरी से यूएसबी और इसके विपरीत बिजली की आपूर्ति स्विचिंग।

इस बिंदु पर, यह या तो शोर है, मेरा डीएसी जिसके साथ मैं साइन लहर उत्पन्न कर रहा हूं या मैं गलत तरीके से कुछ मौलिक काम कर रहा हूं। इस सर्किट ने अन्य लोगों के लिए बिना किसी समस्या के काम किया है, इसलिए मेरे कॉन्फ़िगरेशन या वातावरण में कुछ गलत होना चाहिए।

अगर किसी के पास कोई सुझाव है, तो मैं आपके समय की बहुत सराहना करूंगा।

यहाँ मेरा न्यूनतम स्रोत है:

#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/

अपडेट करें:

मैंने आपके सभी सुझावों की कोशिश की है, उनमें से किसी ने भी काम नहीं किया है। आईएसआर के भीतर या बाहर इंटरप्ट झंडे को साफ करना या बाधित करना वास्तव में कोई प्रभाव नहीं था। मुझे गलतफहमी हो रही है कि चिप का तुलनित्र रजिस्टर वास्तव में कैसे काम करता है।

जैसा कि मैंने शुरू में उल्लेख किया था, मैं साइन लहर से निकले वर्ग तरंग की आवृत्ति को मापने के लिए इनपुट कैप्चर का उपयोग करने वाला था। तुलनित्र का आउटपुट इनपुट कैप्चर पिन में खिलाया जाता है, फिर समयावधि को मापने के लिए टाइमर का उपयोग करें, सरल।

यहाँ atmega2560 के अनुरूप तुलनित्र आरेख http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2549-8-bit-AVR-Microcontroller-ATmega440-1280-1281-25-2561_datasheet.pdf , पृष्ठ 265:

यहां छवि विवरण दर्ज करें

जैसा कि आप देख सकते हैं, तुलनित्र के दो आउटपुट हैं, ACO और ACIS0 + ACIS1। 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);
    }
}

और आउटपुट ने स्वयं त्रुटिपूर्ण व्यवहार किया (जैसे दूसरी तस्वीर में)। फिर मैं दालों की चौड़ाई मापने के लिए आगे बढ़ा, लेकिन परिणाम बहुत अच्छे नहीं थे। स्वच्छ संकेत होने के बावजूद, मेरे एलसीडी डिस्प्ले पर भीख माँगना, यादृच्छिक मूल्यों पर कूदना या 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 ... जो कि केवल संदर्भ बदलता है
जॉनर

1
आप एक तुलनित्र से आउटपुट की गुंजाइश तस्वीरें कैसे पैदा कर सकते हैं जो चिप के अंदर है और सुलभ नहीं है?
एंडी उर्फ

2
जब आप ISR दर्ज करते हैं तो क्या आप आगे व्यवधान उत्पन्न कर रहे हैं? आपको यह करने की आवश्यकता हो सकती है - यह हो सकता है कि अधिकांश ISR को दोहरी हिट मिल रही है।
एंडी उर्फ

1
आप हिस्टैरिसीस पिन को टॉगल कैसे कर रहे हैं और क्या आप इसे वर्तमान मूल्य से योग्य बना रहे हैं। बाधा और टॉगल के बीच की देरी आपके साथ खराब हो सकती है।
ट्रेवर_जी

1
आपके योजनाबद्ध में नहीं दिखाया गया है pin5 और pin6 के बीच आंतरिक समाई है, क्या आप अपने hysterisis बनाने के लिए pin7 पर आंतरिक पुल-अप का उपयोग कर सकते हैं?
जैसन

जवाबों:


13

मैंने पढ़ा कि आप साइन लहर सिग्नल उत्पन्न करने के लिए एक डीएसी का उपयोग कर रहे हैं। DAC आउटपुट आउटपुट स्थिति परिवर्तनों पर गड़बड़ कर सकता है, इसलिए आपको अपने तुलनित्र सर्किट में खिलाने से पहले DAC आउटपुट पर कुछ एनालॉग फ़िल्टरिंग लागू करना चाहिए। यह कुछ दोहरे अवरोध ट्रिगर को रोकने में मदद कर सकता है जो होने की संभावना है।

मैं यह भी टिप्पणी करूंगा कि आप वास्तव में इस प्रकार की समस्या के लिए एक बाहरी तुलनित्र का उपयोग करना चाहते हैं ताकि आप सॉफ्टवेयर इंटरैक्शन के उपयोग के बिना प्रतिरोधों के साथ हिस्टैरिसीस को लागू कर सकें। यह बेहतर समस्या अलगाव की भी अनुमति देगा क्योंकि आप सीधे तुलनित्र के आउटपुट की निगरानी कर सकते हैं।

अंतिम टिप्पणी आपके द्वारा उपयोग किए जा रहे हिस्टैरिसीस के प्रकार से संबंधित है। यह देखना थोड़ा कठिन है कि आप किस योजना का उपयोग कर रहे हैं, लेकिन ध्यान दें कि आप जो चाहते हैं वह व्यवहार है जो ऐसा करता है: आप चाहते हैं कि हिस्टैरिसीस जो कि सिग्नल की तुलना में OPPOSITE दिशा में थ्रेशोल्ड वोल्टेज को खींचता है। इसलिए बढ़ती बढ़त के लिए आप चाहते हैं कि थ्रेशोल्ड शून्य बिंदु से थोड़ा अधिक हो और फिर जब स्थिति बदलती है तो थ्रेशोल्ड निचले स्तर तक खिंच जाता है।


1
+1 हिस्टैरिसीस दिशा को कैसे काम करना चाहिए, इसके अतिरिक्त विवरण के लिए। अनुच्छेद 2 अच्छी सलाह है लेकिन इसे आंतरिक रूप से करना भी ठीक है, बशर्ते कि यह सही किया गया हो, जो इस उदाहरण में हो, ऐसा प्रतीत नहीं होता।
ट्रेवर_जी

@ ट्रेवर_जी -: ^)
माइकल

1
@ हाइपोमेनिया - मुझे पता है कि आप ISR में सिंगल टाइमर पढ़ सकते हैं। लेकिन जब तक टाइमर डबल बफ़र नहीं हो जाता है, ताकि एक आउटपुट रजिस्टर ट्रिगर से गिनती गिनता रहे, जबकि टाइमर खुद भी गिनती जारी रख सके, तो टाइमर को रोकना आवश्यक हो जाता है ताकि आप इसे पढ़ सकें और फिर इसे पढ़ने के बाद फिर से सक्षम करें । कई MCU टाइमर की तरह डबल बफ़र नहीं किया जाता है और इस प्रकार टाइमर फिर से सक्षम होने पर ISR में आने का प्रोसेसिंग समय अगले आधे चक्र के लिए समय अवधि माप पर खो जाता है। यह कुछ हद तक इस बात पर निर्भर करता है कि टाइमर को कितनी तेजी से देखा जा रहा है (जारी है)
माइकल करास

1
(ऊपर से जारी) लेकिन आप कभी भी इस स्थिति में नहीं रहना चाहते कि आप एक गिनती मूल्य पढ़ रहे हैं जब एक घड़ी एक ही समय में गिनती बदलने के लिए आ रही हो। मैंने उस विशिष्ट MCU पर शोध नहीं किया है जिसे आप यह देखने के लिए उपयोग कर रहे हैं कि आपका टाइमर ट्रिगर कैप्चर ईवेंट पर डबल बफर है या नहीं।
माइकल करस

1
@ हाइपोमेनिया - जिस पर मैंने आपके लिंक किए गए AVR MCU डेटा शीट को देखा और देखा कि टाइमर इनपुट कैप्चर फ़ंक्शन दोहरा है !! वास्तव में इन भागों में टाइमर काफी मजबूत लग रहा है। लगभग 15 साल हो गए हैं जब मैंने किसी भी एवीआर भागों का उपयोग किया है।
माइकल करास

6

इस परिदृश्य के साथ समस्या है कि तुलनित्र स्विचिंग के बीच एक समय की देरी है और बाधा उस बिंदु पर नियंत्रित की जा रही है जहां आप "हिस्टैरिसीस" पिन स्विच करते हैं।

आपका हिस्टैरिसीस बैंड भी उस सिग्नल स्तर के लिए छोटा है, जिस पर विचार करने के लिए आप इसका उपयोग कर रहे हैं। खासकर जब मैं देखता हूं कि आपके स्कोप पर उस स्क्वायर वेव पर कितना शोर है।

उन दोनों कारकों को ध्यान में रखते हुए, एक उच्च संभावना है कि कुछ इनपुट स्तरों पर आपको पहले एक को संभालने से पहले तुलनित्र से कई किनारों को मिलेगा। यह देखने के लिए कि तुलनित्र राज्य उस बाधा हैंडलर के दौरान बहुत मदद नहीं करता है क्योंकि यह या तो राज्य में हो सकता है।

दुर्भाग्य से आप इस प्रश्न में विस्तृत नहीं हैं कि हैंडलर कैसे काम करता है।

आपके हैंडलर को हालांकि कुछ इस तरह से काम करना चाहिए।

  1. जब उच्च थ्रेशोल्ड अवस्था में हिस्टैरिसीस मूल्य आपको एक नकारात्मक बढ़त के लिए इंतजार कर रहा होना चाहिए।

  2. जब कहा जाता है कि नकारात्मक बढ़त रुकावट आती है, तो हिस्टैरिसीस को कम मूल्य पर टॉगल करें, कुछ चक्रों की प्रतीक्षा करें, फिर किसी भी लंबित रुकावट को साफ करें और सकारात्मक बढ़त के अवरोध की प्रतीक्षा करें।

  3. जब कहा जाता है कि पॉजिटिव एज इंटरप्ट आता है, तो हिस्टैरिसीस पिन को हाई वैल्यू पर वापस टॉगल करें, कुछ साइकल का इंतजार करें, किसी भी तरह की पेंडिंग को क्लियर करें और नेगेटिव एज इंटरप्ट का फिर से इंतजार करना शुरू करें।

  4. चरण 1 से दोहराएँ।

BTW मैं उस तरह से बहुत उत्सुक नहीं हूं जिस तरह आप सिग्नल के लिए पूर्वाग्रह के रूप में तुलनित्र संदर्भ का उपयोग कर रहे हैं। यह संकेत से संदर्भ के लिए और हिस्टैरिसीस से संकेत के लिए, विशेष रूप से कम आवृत्ति संकेतों के साथ, थोड़ा क्रॉस-टॉक होता है। उन मूल्यों के साथ दी गई है, जिनका प्रभाव छोटा होना चाहिए, लेकिन शुद्धता के लिए, संकेत पर एक अलग पूर्वाग्रह बेहतर होगा।

संपादित करें: अपने कोड को पुनः भेजें।

हिस्टैरिसीस को सेट करने से पहले दूसरे कथन में आप इंटरप्ट एज को बदलते हैं।

न तो मामले में, आप लौटने से पहले किसी भी लंबित व्यवधान को रोकते और साफ़ करते हैं। (ध्यान दें, इंटरप्ट कंट्रोल रजिस्टर को बदलने से यह अपने आप बाधित हो सकता है।)

मुझे नहीं पता कि क्या एटमेगा फिर से प्रवेश करता है, अर्थात, यदि बाद के किनारे पिछले किनारे से अभी भी चल रहे हैंडलर को बाधित करेगा। यदि हां, तो आपको उचित रूप से संगामिति को संभालने की आवश्यकता है।

निश्चित नहीं है कि PORTC भाग किस लिए है, लेकिन इसे संभवतः योग्य भाग में ले जाने की आवश्यकता है।


बहुत-बहुत धन्यवाद, मैं कल आपके सुझावों की कोशिश करूंगा और आपको अपडेट दूंगा। मेरे ISR के रूप में, अगर आपके पास वेटिंग को छोड़कर आपके द्वारा वर्णित सटीक परिदृश्य के लिए स्टेटमेंट है, तो मुझे और-और है।
शिब्बल

1
@ हाइपोमेनिया आपको अपना प्रश्न संपादित करना चाहिए और अपना इंटरप्ट हैंडलर कोड पोस्ट करना चाहिए ताकि लोग देख सकें कि क्या आप कहीं गड़बड़ कर रहे हैं। यह सिर्फ शोर हो सकता है, हालांकि, आपके कार्यक्षेत्र के निशान इस तरह दिखते हैं कि वहां पर 50mV से अधिक शोर है। अभी भी शोर के साथ मैं इसे सही करने की उम्मीद करूंगा, सभी इसे संक्रमण के समय कभी-कभी अतिरिक्त दालों के साथ हो सकते हैं।
ट्रेवर_जी

यही मुझे उम्मीद भी थी। जल्द से जल्द करेंगे।
शिब्बल

1
@ हाइपोमेनिया संपादित देखें
ट्रेवर_जी

1
@ हाइपोमेनिया क्योंकि आप उन दो आदेशों के बीच एक और बाधा प्राप्त कर सकते थे। मैंने संपादन संपादित भी किया ...
ट्रेवर_जी

3

यह प्रभाव संपर्क उछाल के समान है, और उसी डेबिट तकनीकों द्वारा शमन किया जा सकता है जो आप पुशबटन के लिए उपयोग करेंगे।

  • बहस के समय पर निर्णय लें Td
  • एक चर में अंतिम किनारे की बाधा का टाइमस्टैम्प रखें
  • यदि वर्तमान व्यवधान और पिछले एक के बीच का समय इससे कम है Td, तो वर्तमान व्यवधान को अनदेखा करें
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.