2015-04-18 5 views
6

मैंने इस कोड को एक एसएमएस भेजने के लिए लिखा है यदि कोई इनपुट उच्च है, जैसा कि आप इसमें देख सकते हैं, लेकिन समस्या यह है कि मेरे पास 4 इनपुट हैं और देरी() एस घातक हैं और यदि मुझे आवश्यकता हो तो बहुत गलत एक समय में एक से अधिक चीजें करने के लिए (मैं 4 इनपुट का उपयोग करता हूं)।देरी के बिना टाइमर लिखें()

तो मुझे मिलीस() या शून्य लूप(), Send_SMS() और initia() में कुछ और के साथ देरी() को बदलने की आवश्यकता है।

कोई मेरी मदद कर सकता है, और अग्रिम धन्यवाद।

const int DI = 2; 
const int DT = 3; 
const int DGP1 = 4; 
const int DGP2 = 5; 

int value1_old = 0; 
int value2_old = 0; 
int value3_old = 0; 
int value4_old = 0; 

unsigned long previousMillis = 0; 
unsigned long interval=100; 

#include<SoftwareSerial.h> 
SoftwareSerial SIM900 (7, 8); 

void setup() { 
pinMode(DI, INPUT); 
pinMode(DT, INPUT); 
pinMode(DGP1, INPUT); 
pinMode(DGP2, INPUT); 

SIM900.begin(19200); 
SIM900power(); 
delay(20000); 

} 

void SIM900power(){ 
    digitalWrite(9 ,HIGH); 
    delay(1000); 
    digitalWrite(9 ,LOW); 
    delay(5000); 
} 

void initia(){ 
    SIM900.print("AT+CMGF=1\r"); 
    delay(100); 
    SIM900.println("AT + CMGS = \"+212xxxxxxx\""); 
    delay(100); 
} 

void Send_SMS(){ 
    SIM900.println((char)26); 
    delay(100); 
    SIM900.println(); 
    delay(100); 
    SIM900power(); 
} 

void loop() { 
    int value1 = digitalRead (DI); 
    int value2 = digitalRead (DT); 
    int value3 = digitalRead (DGP1); 
    int value4 = digitalRead (DGP2); 

    if (value2 != value2_old && value2 == HIGH) { 
    initia(); 
    SIM900.println("Station 85: Defaut electrique"); 
    delay(100); 
    Send_SMS(); 
    value2_old = value2; 
    } 

    if (value3 != value3_old && value3 == HIGH) 
    { 
    initia(); 
    SIM900.println("Station 85: DefautGP1"); 
    delay(100); 
    Send_SMS(); 
    value3_old = value3; 
} 

if (value4 != value4_old && value4 == HIGH) 
{ 
    initia(); 
    SIM900.println("Station 85:DD>1000");  
    delay(100); 
    Send_SMS(); 
    value4_old = value4; 
} 
value2_old = value2; 
value3_old = value3; 
value4_old = value4; 

}

+0

आप कहना है कि देरी का उपयोग करके आप चीजों पर इंतजार कर चक्र बर्बाद कर रहे बजाय कर रही है इसका मतलब यह है क्या करना चाहिए अधिक अन्य संभावित (समय महत्वपूर्ण) कार्यों? यदि ऐसा है, तो मुझे लगता है कि आपको इंटरप्ट्स (आईएसआर में समय-महत्वपूर्ण कार्य करने के लिए) या एवीआर पर मौजूद हार्डवेयर टाइमर का उपयोग करने की दिशा में देखने की आवश्यकता है। – initramfs

+1

इसके बजाय मिलिस() फ़ंक्शन का उपयोग करें। ट्यूटोरियल उदाहरण [यहां है] (http://www.arduino.cc/en/Tutorial/BlinkWithoutDelay)। –

+0

मुझे लगता है कि मुझे देरी के स्थान पर मिलिस() का उपयोग करने की आवश्यकता है, लेकिन मुझे नहीं पता कि कैसे, क्योंकि मैं एक नौसिखिया हूं:/ –

उत्तर

-1

समारोह millis() जब मूल्य अतिप्रवाह असफल हो जायेगी। जैसा कि @CPU_Terminator ने कहा, इंटरप्ट का उपयोग करें। इसके लिए उपयोगी Arduino पुस्तकालय हैं, उदाहरण के लिए Timer1

संपादित करें। यह मानते हुए कि आप क्या करना चाहते हैं, यदि आपके कुछ इनपुट बदल गए हैं, तो आप प्रत्येक 100ms में एक एसएमएस भेज सकते हैं, आप इस तरह के कोड का उपयोग कर सकते हैं (मैंने कुछ देरी हटा दी हैं जो मुझे नुकीले लगती नहीं हैं, अगर मैं गलत हूं तो उन्हें दोबारा जोड़ें) :

#include <SoftwareSerial.h> 
#include "TimerOne.h" 

const int DI = 2; 
const int DT = 3; 
const int DGP1 = 4; 
const int DGP2 = 5; 
const long interval = 100000; // in microseconds 

int value1 = 0; 
int value2 = 0; 
int value3 = 0; 
int value4 = 0; 
int value1_old = 0; 
int value2_old = 0; 
int value3_old = 0; 
int value4_old = 0; 
boolean changed1 = false; 
boolean changed2 = false; 
boolean changed3 = false; 
boolean changed4 = false; 

SoftwareSerial SIM900 (7, 8); 

void SIM900power(){ 
    digitalWrite(9, HIGH); 
    delay(1000); 
    digitalWrite(9, LOW); 
    delay(5000); 
} 

void initia(){ 
    SIM900.print("AT+CMGF=1\r"); 
    SIM900.println("AT + CMGS = \"+212xxxxxxx\""); 
} 

void Send_SMS(){ 
    SIM900.println((char)26); 
    SIM900.println(); 
    delay(20); 
    SIM900power(); 
} 

void isr_timer(){ 
    if (changed2) { 
    initia(); 
    SIM900.println("Station 85: Defaut electrique"); 
    Send_SMS(); 
    changed2 = false; 
    } 

    if (changed3) { 
    initia(); 
    SIM900.println("Station 85: DefautGP1"); 
    Send_SMS(); 
    changed3 = false; 
    } 

    if (changed4) { 
    initia(); 
    SIM900.println("Station 85:DD>1000"); 
    Send_SMS(); 
    changed4 = false; 
    } 
} 

void setup() { 
    pinMode(DI, INPUT); 
    pinMode(DT, INPUT); 
    pinMode(DGP1, INPUT); 
    pinMode(DGP2, INPUT); 

    SIM900.begin(19200); 
    SIM900power(); 
    delay(20000); 
    Timer1.initialize(interval); 
    Timer1.attachInterrupt(isr_timer); 
} 

void loop() { 
    value1 = digitalRead (DI); 
    value2 = digitalRead (DT); 
    value3 = digitalRead (DGP1); 
    value4 = digitalRead (DGP2); 

    if (value1 != value1_old && value1 == HIGH) changed1 = true; 
    if (value2 != value2_old && value2 == HIGH) changed2 = true; 
    if (value3 != value3_old && value3 == HIGH) changed3 = true; 
    if (value4 != value4_old && value4 == HIGH) changed4 = true; 

    value1_old = value1; 
    value2_old = value2; 
    value3_old = value3; 
    value4_old = value4; 

    // Here the rest of your code 
} 

इस तरह समारोह isr_timer() प्रत्येक 0.1 सेकंड निष्पादित किया जाएगा।

+0

बढ़िया! मुझे -1 मिला और कोई भी क्यों नहीं बताता। – mclopez

+0

धन्यवाद, क्या आप मुझे मेरे कोड में एक उदाहरण दे सकते हैं? ^^ –

+0

वहां आपके पास है, उम्मीद है कि यह उपयोगी है। यदि यह आपके द्वारा अपेक्षित उत्तर है, तो इसे स्वीकार करें और वोटअप करें, कृपया :) – mclopez

0

आप isr_timer में कोड का उपयोग कर कोशिश कर सकते हैं() फ़ंक्शन:

if (changed2) { 
    initia(); 
    SIM900.println("Station 85: Defaut electrique"); 
    delay(100); 
    Send_SMS(); 
    changed2 = false; 
} 

सादर

0

रूप mclopez ने कहा, उनका कहना है के बजाय एक अच्छा जवाब प्रदान करने के लिए केवल क्या खामियां हैं बेहतर है अन्य लोगों की, तो ... हम यहाँ जाते हैं।

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

हालांकि, यह मेरी राय में एक अच्छा समाधान नहीं है। इस समस्या के लिए, मैं एसएमएस भेजने के लिए एक राज्य मशीन के साथ जाऊंगा; चूंकि आपके पास राज्य हैं, इसलिए आप बटन की जांच करने जैसी अन्य चीजें करते समय संक्रमण की प्रतीक्षा कर सकते हैं।

मुझे नहीं पता कि सिम 9 00 एसएमएस भेजता है, इसलिए मैं अपना वर्कफ़्लो ले रहा हूं और इसे एक राज्य मशीन में कार्यान्वित कर रहा हूं। मुझे यकीन नहीं है कि यह इष्टतम समाधान है, विशेष रूप से क्योंकि मुझे नहीं लगता कि आपको हर बार मॉड्यूल को रीबूट करने की ज़रूरत है, लेकिन आप इसे बाद में ट्रिम कर सकते हैं।

अब, वर्कफ़्लो में आपके पास सात क्रियाएं हैं, प्रत्येक के बाद प्रतीक्षा करें। मैं इसे यहाँ लिख तो यह आसान है हर कार्रवाई को देखने के लिए:

SIM900.print("AT+CMGF=1\r"); 
delay(100); 
SIM900.println("AT + CMGS = \"+212xxxxxxx\""); 
delay(100); 
SIM900.println("Message you want"); 
delay(100); 
SIM900.println((char)26); 
delay(100); 
SIM900.println(); 
delay(100); 
digitalWrite(9 ,HIGH); 
delay(1000); 
digitalWrite(9 ,LOW); 
delay(5000); 

तो हम आठ राज्यों है: एक निष्क्रिय एक, पांच के बाद (जब आप राज्य मशीन शुरू करने के लिए, SIM_IDLE नामित के लिए इंतजार कर रहे हैं) "भेजें" राज्य (मैं उन्हें SIM_SEND1..5 नाम देता हूं) और दो राज्यों को पावर रीसेट करने के लिए (SIM_COW1 और SIM_POW2 नाम दिया गया)। आप आम तौर पर निष्क्रिय राज्य में होते हैं; जब एक या अधिक बटन दबाए जाते हैं, तो आप पहले प्रेषण, चक्र के माध्यम से चक्र पर स्विच करते हैं और फिर शक्ति को रीसेट करते हैं और निष्क्रिय होने पर वापस जाते हैं।

दबाए गए बटन केवल राज्य SIM_SEND3 को बदलते हैं (जब आप वास्तव में संदेश भेजते हैं), इसलिए जब भी बटन दबाया जाता है तो एक बूलियन चर सेट होता है (राज्य मशीन निष्पादन के दौरान भी एक बटन प्रेस का पता लगाया जाता है) और केवल रीसेट किया जाता है सही संदेश भेजने के बाद, वह राज्य।

अब, यहाँ कोड है जो इस को लागू करता है:

const uint8_t DI = 2; 
const uint8_t DT = 3; 
const uint8_t DGP1 = 4; 
const uint8_t DGP2 = 5; 

const uint8_t SIMPOW = 9; 

uint8_t value1_old = 0; 
uint8_t value2_old = 0; 
uint8_t value3_old = 0; 
uint8_t value4_old = 0; 

boolean value1_changed = false; 
boolean value2_changed = false; 
boolean value3_changed = false; 
boolean value4_changed = false; 

/********************************/ 
//   SIM STATES 
#define SIM_IDLE 0 
//SEND1: SIM900.print("AT+CMGF=1\r");delay(100); 
#define SIM_SEND1 1 
//SEND2: SIM900.println("AT + CMGS = \"+212xxxxxxx\"");delay(100); 
#define SIM_SEND2 2 
//SEND3: SIM900.println("Message you want");delay(100); 
#define SIM_SEND3 3 
//SEND4: SIM900.println((char)26);delay(100); 
#define SIM_SEND4 4 
//SEND5: SIM900.println();delay(100); 
#define SIM_SEND5 5 
//POW1: digitalWrite(SIMPOW,HIGH);delay(1000); 
#define SIM_POW1 6 
//POW2: digitalWrite(SIMPOW,LOW);delay(5000); 
#define SIM_POW2 7 
/********************************/ 

unsigned long previousMillis; 
uint8_t currentSimState; 

#include<SoftwareSerial.h> 
SoftwareSerial SIM900 (7, 8); 

void setup() 
{ 
    pinMode(DI, INPUT); 
    pinMode(DT, INPUT); 
    pinMode(DGP1, INPUT); 
    pinMode(DGP2, INPUT); 
    pinMode(SIMPOW, OUTPUT); 

    SIM900.begin(19200); 

    digitalWrite(SIMPOW,HIGH); 
    delay(1000); 
    digitalWrite(SIMPOW,LOW); 
    delay(25000); 
    currentSimState = -1; // Force a state transition 
} 

void loop() 
{ 
    uint8_t value1 = digitalRead (DI); 
    uint8_t value2 = digitalRead (DT); 
    uint8_t value3 = digitalRead (DGP1); 
    uint8_t value4 = digitalRead (DGP2); 

    unsigned long currentMillis = millis(); 

    if (value2 != value2_old && value2 == HIGH) 
     value2_changed = true; 
    if (value3 != value3_old && value3 == HIGH) 
     value3_changed = true; 
    if (value4 != value4_old && value4 == HIGH) 
     value4_changed = true; 

    value1_old = value1; 
    value2_old = value2; 
    value3_old = value3; 
    value4_old = value4; 

    // Check if a state transition is needed 
    uint8_t newSimState = currentSimState; 
    switch (currentSimState) 
    { 
    case SIM_IDLE: // Start sending if a value changed 
     if ((value2_changed) || (value3_changed) || (value4_changed)) 
      newSimState = SIM_SEND1; 
     break; 
    case SIM_SEND1: // Wait 100 ms 
     if ((currentMillis - previousMillis) >= 100) 
      newSimState = SIM_SEND2; 
     break; 
    case SIM_SEND2: // Wait 100 ms 
     if ((currentMillis - previousMillis) >= 100) 
      newSimState = SIM_SEND3; 
     break; 
    case SIM_SEND3: // Wait 100 ms 
     if ((currentMillis - previousMillis) >= 100) 
      newSimState = SIM_SEND4; 
     break; 
    case SIM_SEND4: // Wait 100 ms 
     if ((currentMillis - previousMillis) >= 100) 
      newSimState = SIM_SEND5; 
     break; 
    case SIM_SEND5: // Wait 100 ms 
     if ((currentMillis - previousMillis) >= 100) 
      newSimState = SIM_POW1; 
     break; 
    case SIM_POW1: // Wait 1000 ms 
     if ((currentMillis - previousMillis) >= 1000) 
      newSimState = SIM_POW2; 
     break; 
    case SIM_POW2: // Wait 1000 ms 
     if ((currentMillis - previousMillis) >= 1000) 
      newSimState = SIM_IDLE; 
     break; 
    default: 
     newSimState = SIM_IDLE; 
     break; 
    } 

    // If there was a transition, do the appropriate action 
    if (newSimState != currentSimState) 
    { 
     case SIM_IDLE: 
      // Do nothing 
      break; 
     case SIM_SEND1: 
      SIM900.print("AT+CMGF=1\r"); 
      previousMillis = millis(); 
      break; 
     case SIM_SEND2: 
      SIM900.println("AT + CMGS = \"+212xxxxxxx\""); 
      previousMillis = millis(); 
      break; 
     case SIM_SEND3: 
      if (value2_changed) 
      { 
       SIM900.println("Station 85: Defaut electrique"); 
       value2_changed = false; 
      } 
      else if (value3_changed) 
      { 
       SIM900.println("Station 85: DefautGP1"); 
       value2_changed = false; 
      } 
      else if (value4_changed) 
      { 
       SIM900.println("Station 85:DD>1000"); 
       value2_changed = false; 
      } 
      else 
      { 
       // Should never arrive here. Just in case, you 
       // can either abort the SMS sending if you can 
       // or send another message 
      } 
      previousMillis = millis(); 
      break; 
     case SIM_SEND4: 
      SIM900.println((char)26); 
      previousMillis = millis(); 
      break; 
     case SIM_SEND5: 
      SIM900.println(); 
      previousMillis = millis(); 
      break; 
     case SIM_POW1: 
      digitalWrite(SIMPOW,HIGH); 
      previousMillis = millis(); 
      break; 
     case SIM_POW2: 
      digitalWrite(SIMPOW,LOW); 
      previousMillis = millis(); 
      break; 
     } 
    } 

    // Advance state 
    currentSimState = newSimState; 
} 

यह जटिल लग सकता है, लेकिन यह वास्तव में बहुत सरल है। लूप तीन "ब्लॉक" द्वारा बनाया जाता है।

पहला बटन बटन चेक है। यदि कोई बटन दबाया जाता है, तो संबंधित valueX_changed ध्वज सेट किया गया है। यह एक बहुत ही छोटा हिस्सा है, बस जांचें कि क्या किसी बटन के पास एक अलग राज्य है और फिर ध्वज सेट करें।

दूसरा भाग राज्य संक्रमण के लिए चेक है। इस स्विच स्टेटमेंट में प्रोग्राम निर्धारित करता है कि राज्य मशीन की स्थिति को बदलने की जरूरत है या नहीं। ऐसा तब होता है जब राज्य निष्क्रिय होता है, या यदि एसएमएस भेजने की प्रक्रिया में निर्दिष्ट समय बीत चुका है तो एक बटन दबाया गया था।

तीसरा हिस्सा एक राज्य में परिवर्तन होने पर किया जाने वाला कार्य है। तो अगर राज्य बदल गया है, तो राज्य कार्रवाई करें, जिसका मतलब निष्क्रिय राज्य के लिए कुछ नहीं है, सिम_एसईएनएक्सएक्स राज्यों के लिए कुछ भेजें और सिम_POWx राज्यों के लिए पिन बदलें।

बस एक नोट: सेटअप में आपने 20 सेकेंड देरी को सामान्य वर्कफ़्लो में प्रस्तुत नहीं किया है। अगर आप इसे हटाना चाहते हैं, तो आप रीसेट करने वाले सेटअप से चार लाइनों को हटा सकते हैं औरको को के बजाय newSimState = SIM_POW1; सेट करने के लिए पहले स्विच में संशोधित कर सकते हैं।

छोटे कीड़े, इस कोड में नहीं हो सकता है के बाद से मैं यह परीक्षण नहीं किया है, लेकिन यह है कि तुम क्या चाहते थे

संबंधित मुद्दे