शून्य-पार सक्रिय रिले


13

मैं एक स्विच प्रोग्रामिंग के बारे में कैसे जा सकता हूं (ठोस-राज्य रिले या एक triac पर आधारित) जो शून्य-क्रॉसिंग पावर पर ट्रिगर करता है?

विषय से परिचित नहीं होने के लिए: 230V बिजली चालू करें, जब बिजली लाइन की साइन लहर शून्य को पार कर जाती है - परिणाम वर्तमान में तेजी से स्पाइक से उत्पन्न विद्युत चुम्बकीय गड़बड़ी को कम कर रहा है।

विशेष रूप से, मैं जितना संभव हो उतना सॉफ़्टवेयर में जाना पसंद करूंगा। डिटेक्शन सर्किट में एक छोटे ट्रांसफॉर्मर, एक डायोड और कुछ प्रतिरोधों को रखा जाता है, जो कि स्तर और धाराओं को बनाए रखने के लिए "1" प्रदान करता है, जब एसी इनपुट पॉवर पॉजिटिव हाफ में "0" होता है, जो इनपुट GPIO पिन से जुड़ा होता है। आउटपुट में कुछ ठोस राज्य रिले और नंगे आवश्यक होते हैं जो उन्हें चालू रखने के लिए (पुल-अप आदि), आउटपुट GPIO पिन से जुड़े होते हैं।

समस्या का समय है: 50 हर्ट्ज एसी के साथ हम एक सेकंड में 100 शून्य-क्रॉसिंग प्राप्त करते हैं, एक आधा चक्र 10ms का होता है। शून्य-क्रॉसिंग से उचित दूरी प्राप्त करने के लिए ईएमआई को कम रखने के लिए हम शून्य-क्रॉसिंग की घटना का उत्पादन 10% से अधिक अतीत (या इससे पहले) को सक्रिय नहीं करना चाहिए, इसका मतलब है कि + -1ms सहिष्णुता। इसका मतलब यह नहीं है कि 1ms प्रतिक्रिया समय - हम अगले शून्य-पार की उम्मीद कर सकते हैं कि पहले एक के बाद ठीक 10ms या चौथे - 40ms। यह ग्रैन्युलैरिटी के बारे में है - अगर हम प्रतिक्रिया के लिए 20ms की अनुमति देते हैं, तो यह 19 और 21ms के बीच होना चाहिए, 18 या 22 के बीच नहीं।

मैं इस तरह के टाइमर को कैसे लागू कर सकता हूं - आउटपुट आउटपुट GPIO या तो 1ms के भीतर चूंकि इनपुट एक किनारे का पता लगाता है, या तब से 10ms के एक निश्चित कई के भीतर - अधिमानतः कुछ नकारात्मक पूर्वाग्रह के लिए भत्ते के साथ (कहते हैं, ट्रांसफार्मर और रिले 1.6ms देरी का परिचय देते हैं; इसलिए मैं चाहता हूं कि इनपुट पल्स के बाद से ट्रिगर 8.4+ (n * 10) एमएस से बाहर हो जाए, इस तरह से पूर्वाग्रह सर्किट द्वारा शुरू की गई देरी का प्रतिकार करता है।) - बेशक "उपयोगकर्ता की मांग पर", उपयोगकर्ता लिखते हैं "1" "a / sys / class / ... फ़ाइल और निकटतम (मोटे तौर पर) अवसर पर आउटपुट" चालू "हो जाता है। उपयोगकर्ता "0" लिखता है, और जब शून्य-क्रॉसिंग आता है, तो विशिष्ट रिले डिसेंगेज होता है।

मेरा मानना ​​है कि इसके लिए कर्नेल मॉड्यूल लिखने या हैक करने की आवश्यकता होगी। क्या आप मुझे इंगित कर सकते हैं कि कर्नेल में रास्पबेरी पाई के जीपीओ पिन को क्या संभालता है, और इस तरह की कार्यक्षमता प्राप्त करने के लिए मैं किस तरह की टाइमर संलग्न कर सकता हूं (जब तक कि कुछ जगह पहले से ही हैं)?


काफी दिलचस्प परियोजना आप के बारे में बात करते हैं! बस एक मोटा अनुमान देने के लिए: मैं पहली बार कुछ schmitt ट्रिगर लॉजिक के माध्यम से GPIO के लिए 50Hz मूल संकेत से साइन लहर को इंटरफ़ेस करेगा। वहां से सिग्नल के बढ़ते या गिरने वाले किनारे पर एक अवरोध उत्पन्न होता है। अब आप 50 हर्ट्ज एसी पर बंद हैं और अगली जीरो क्रॉसिंग होने पर 'भविष्यवाणी' कर सकते हैं। निश्चित रूप से इसमें कुछ कर्नेल ड्राइवर प्रोग्रामिंग शामिल है। Google आपका मित्र :-)
स्पार्कली

Inmojo के AC dimmer मॉड्यूल पर एक नज़र डालें । मैंने उनके ओपन सोर्स डॉक्यूमेंटेशन का उपयोग करते हुए इस प्रोजेक्ट के लिए सफलतापूर्वक क्लोन किया है। कुछ Arduino नमूना कोड भी हैं जो आपके कोड के तर्क के माध्यम से आपकी सहायता कर सकते हैं।
बटर

@ बूटर्स: मुझे डर है कि प्रोग्रामिंग Arduino और प्रोग्रामिंग Linux कर्नेल मॉड्यूल के बीच की खाई मेरे लिए सॉफ्टवेयर को बेकार कर देगी, लेकिन हार्डवेयर स्कीमाटिक्स में मुझे जो भी चाहिए उसका 100% कवर होता है - धन्यवाद, आपने मेरा बहुत काम बचा लिया - दो परियोजनाओं के बीच अंतर केवल सॉफ्टवेयर में है (डिमर को ट्राइक को चक्रीय रूप से स्विच करना चाहिए, जबकि स्विच इसे स्विच को चालू करने के बाद एक बार चालू / बंद करता है।)
एसएफ।

... बेशक हार्डवेयर पक्ष का 100%।
एसएफ।

जवाबों:


6

आपको कर्नेल को हैक करने की आवश्यकता नहीं है। आपको बस प्रक्रिया को शेड्यूलर कतार से बाहर ले जाने की आवश्यकता है।

    #include<sched.h>

    struct sched_param param;               
    param.sched_priority = sched_get_priority_max(SCHED_FIFO);
    if( sched_setscheduler( 0, SCHED_FIFO, &param ) == -1 )
    {
            perror("sched_setscheduler");
            return -1;
    }

अब से हमारी प्रक्रिया cat /proc/sys/kernel/sched_rt_runtime_usप्रत्येक cat /proc/sys/kernel/sched_rt_period_usमिलीसेकंड समय खंड के बाहर मिलीसेकंड प्राप्त करती है , उस समय के दौरान पूर्व-खाली होने के जोखिम के बिना निर्बाध निष्पादन के (व्यवहार में, बेरीबूट पर डिफ़ॉल्ट रूप से: प्रत्येक सेकंड में से 0.95 सेकंड।) यदि आपको अधिक, गड़बड़ चाहिए। इन मूल्यों के साथ, लेकिन मुझे यहाँ अपने उद्देश्य के लिए और अधिक की आवश्यकता नहीं है।

मैं clock_gettime()अपने विलंब को देखने के लिए मिलीसेकंड में टाइमर फ़ंक्शन का उपयोग कर रहा हूं (जो मुझे सटीक होने की आवश्यकता है) ।

कॉलिंग timer(1)रीसेट करता है, timer(0)रीसेट के बाद से रिटर्न का समय बुलाता है।

    #include<time.h>
    typedef unsigned long long ulong64;

    ulong64 timer(unsigned char reset)
    {
            struct timespec t;
            static struct timespec lt={0,0};
            clock_gettime(CLOCK_REALTIME, &t);
            if(reset)
            {
                    lt.tv_sec = t.tv_sec;
                    lt.tv_nsec = t.tv_nsec;
            }

            int r = ((ulong64)(t.tv_sec - lt.tv_sec))*1000 + (t.tv_nsec - lt.tv_nsec)/1000000;

            return r;
    }

rtसंकलन करने के लिए आपको लाइब्रेरी के खिलाफ लिंक करना होगा - -lrtअपने gcc कमांड में जोड़ें ।

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

    while(1)
    {
            //when idle, return a lot of CPU time back to the system. 
            //A call every 100ms is perfectly sufficient for responsive reaction.
            usleep(100000); 

            in  = bcm2835_gpio_lev(SWITCH_PIN);
            out = bcm2835_gpio_lev(TRIAC_PIN);

            if(in==out) continue;   //nothing to do; wait user input, return control to system.

            //The output needs to be changed.
            //First, let's wait for zero-crossing event.
            timer(TIMER_RESET);
            zx = bcm2835_gpio_lev(ZEROXING_PIN);

            //We don't want to freeze the system if the zero-xing input is broken.
            //If we don't get the event within reasonable time, 
            // (like three half-sines of the power; ZEROXING_TIMEOUT = 70)
            // we're going to bail.
            while(timer(TIMER_READ) < ZEROXING_TIMEOUT)
            {
                    if(zx != bcm2835_gpio_lev(ZEROXING_PIN))
                    {
                            //Event detected.                  
                            timer(TIMER_RESET);
                            break;
                    }
            }
            if(timer(TIMER_READ) >= ZEROXING_TIMEOUT) continue;     //Zero-crossing detection is broken, try again soon.

            //Now we are mere milliseconds after zero-crossing event arrived
            // (but it could have taken some time to arrive) so let's wait for the next one, making adjustments for the system delay.
            // This is to be worked out using an oscilloscope and trial and error.
            // In my case BIASED_DELAY = 19.

            while(timer(TIMER_READ)<BIASED_DELAY) ;

            //We can reasonably expect if we perform this right now:
            bcm2835_gpio_set_pud(TRIAC_PIN, in);
            //the signal will reach the output right on time.

            // The 100ms delay on return to start of the loop should be enough 
            // for the signals to stabilize, so no need for extra debouncing.
    }

क्या यह कार्य पी / ए के लिए पी-नियंत्रित डिमर स्विच को लागू करने के लिए होगा? मुझे लगता है कि मुझे 1 को करना होगा) रिज़ॉल्यूशन को कुछ छोटे (प्रत्येक 100ms के बजाय) और 2 में बदल TRIAC_PINदें in, केवल सेट करने के बजाय , मुझे TRIAC_PIN1 पर सेट करना होगा , निर्धारित समय की प्रतीक्षा करें (अनुपात में) वांछित dimmer स्तर), और फिर TRIAC_PINवापस 0 पर सेट करें। क्या यह काम करेगा?
रिनोगो

मुझे लगता है कि मुख्य पाश में, मैं भी लाइन if(in==out) continue;को if(out==0) continue;सही में बदलना चाहता हूं ? दरअसल, मैं पीआई के लिए प्रोग्रामिंग में पूरी तरह से नया हूं, इसलिए शायद यह आवश्यक नहीं है - मुझे लगता है कि यह सब तुल्यकालिक रूप से हो रहा है (यानी हमें मुख्य लूप के बारे में चिंता करने की ज़रूरत नहीं है, जबकि नेस्टेड लूप अभी भी निष्पादित हो रहे हैं)
rinogo

(यह सब उपर्युक्त Inmojo dimmer मॉड्यूल का उपयोग कर रहा है, निश्चित रूप से: inmojo.com/store/inmojo-market/item/… )
rinogo

2
उस के साथ एक समस्या है। स्थिर प्रणाली गतिविधि के लिए, आपको समय-समय पर सिस्टम पर नियंत्रण रखना होगा और मुझे वास्तव में संदेह है कि आप इसे समय के भीतर (20 से कम) से भी कम समय में बहाल करेंगे। तो, इन पैदावार का परिणाम मिस्ड दालों के रूप में होगा और परिणामस्वरूप, बल्ब पलक झपकते हैं। मैंने उस बारे में एक सवाल पूछा , लेकिन कोई जवाब नहीं मिला। आप सिस्टम प्री-इमोशन को पूरी तरह से डिसेबल करने के लिए शेड्यूल_ट्रंटटाइम_स और शिड्यूल_पर_ओडियोड_स -1 सेट कर सकते हैं, लेकिन अगर आप शेड्यूल_लाइड (या) बिलकुल नहीं करते हैं, तो यह समस्या पैदा करने के लिए बाध्य है।
एसएफ।

2
वह यह है: एक बार स्लाइस शुरू करने के बाद SCHED_FIFO के साथ, यह तब तक निर्बाध चलता रहता है जब तक कि आप स्वेच्छा से उपज नहीं लेते (या शेड्यूल_आर्ट_रिमेंट_स समाप्त हो जाता है) लेकिन सिस्टम आपको इस बात की गारंटी नहीं देता है कि आपको यह स्लाइस कब मिलेगा। मेरे मामले में मैंने सामान्य ऑपरेशन में देखा कि कॉल के बीच का समय (कार्य के लिए समय स्लाइस देना) अधिकतम सीपीयू लोड के साथ 0.1s तक बढ़ सकता है। हो सकता है कि वह अवधि ठीक-ठाक हो और जबरदस्ती कम हो लेकिन मुझे नहीं पता कि कैसे।
एसएफ।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.