Milis () dan foydalanib, ichki o'tgan looplarda

Arduino pro mini ustida bir necha chiroqni (neopixels) chayish uchun millis() ni ishlataman. Muammo shundaki, istalgan davrda chiroqlarni o'chira olmayman. Keyinchalik aniqroq, chiroqlar ~ 250 ms uchun yonadi, men esa 9 soniya davomida porlashni xohlayman! Mana, nima qilsam soddalashtirilgan versiyasi.

Loop() da 250 funtga ishlaydigan bir vaqt oralig'ini (loop 1 deb ataymiz) bor. Ichki pastadir 1, men 9 soniya davomida ishlashi kerak bo'lgan flash() funktsiyasini chaqiraman! 1-soniyadan keyin 3 sekundda ishlaydigan yana bitta pastadir (pastadir 2) qo'ydim.

Mana bu katta rasm ... Men aslida radio 250 milodiy uchun uyg'onishni xohlayman. Agar o'sha vaqt oralig'ida biror narsa olinsa, chiroq (9) chaqiriladi va chiroqlar 9 sekundgacha yonadi. Hech narsa qabul qilmasa, u faqat 3 soniya uchun uyquga ketadi, keyin 250 milodiy uchun tiriklayin va shunga o'xshash

void loop() { 
    previousMillis = millis();
    while (millis() - previousMillis < awake_interval) {  //awake_interval = 250 ms    
        flash();  //flash for 9 seconds
    }

    previousMillis = millis();
    while (millis() - previousMillis < sleep_interval);  //sleep_interval = 3 secs
}

Flash() funktsiyasi shu kabi ko'rinadi,

void flash() {
    unsigned long x = millis();
    while(millis() - x < flash_time){  //flash_time = 9 secs 
        lights_on();
        delay(t1);
        lights_off(); 
        delay(t2); 
    }
}

Ichki devorga 2 qo'ydim, chunki u holda chiroqlar abadiy yonib turadi. Buning ma'nosi bor, chunki barcha kodlar cheksiz pastadir - void loop() da.

Disk raskadrovka uchun looplarga kirgandan keyin ketma-ket bosimlarni qo'ydim. Ikki tirgak (ichki (1) ichida) (ikkita millis() dan foydalangan holda) ichki muammolarni hal qilish uchun ishlatiladi. Agar bu to'g'ri bo'lsa, qanday qilib buni qilishim kerak? Agar bu muammo bo'lmasa, har qanday g'oyalar qadrlanadi.

Edit: The suggestions made by @VE7JRO and @ratchet freak are neat but I was still having problems making my thing work. Turns out it was a problem with one my initializations. I am posting my whole code below (that uses LEDs). I guess I should post the correct code as an answer.

const long sleep_interval = 3000; 
const long awake_interval = 250; 
const int ledPin = 3;

const uint8_t flash_time = 9000;  //bug 
const uint16_t t1 = 5; 
const uint16_t t2 = 495;

void flash() {  
    unsigned long x = millis();
    while(millis() - x < flash_time){ 
        digitalWrite(ledPin, HIGH);
        delay(t1);
        digitalWrite(ledPin, LOW);
        delay(t2);
    }   
}   

void setup() {
    Serial.begin(57600);  
    pinMode(ledPin, OUTPUT);
}

void loop() {
    unsigned long x = millis();
    while(millis() - x < awake_interval){
        Serial.println("flash time!");
        flash();  //overflow will occur    
    }

    unsigned long y = millis();; 
    while (millis() - y < sleep_interval) {  //sleep_interval = 3 secs
        Serial.println("Sleep time!");
    }
}
1
To'liq kodingizni yuboring.
qo'shib qo'ydi muallif Hugo, manba
sizning 'while (millis() - previousMillis
qo'shib qo'ydi muallif Juraj, manba
@Juraj "Vaqt jadvalini" bilan nimani anglatishini tushunmayapman. Va men kechikishdan foydalanolmayman, chunki u blokirovka qiladi va bu boshqa (katta) dastur bilan birga bo'lmaydi
qo'shib qo'ydi muallif Demi, manba

5 javoblar

Buning o'rniga davlat mashinasidan foydalaning:

bool  flashing;
unsigned long lastflashingChange;

void loop() { 
    unsigned long currentMillis = millis;
    if(flashing){
        flash();  //update flash state and change IO pin
        if (lastflashingChange - currentMillis >= awake_interval) {  //awake_interval = 250 ms    
            flahsing = false;
            //turn off the led
            lastflashingChange = currentMillis;
        }
    } else {
        if (lastflashingChange - currentMillis >= sleep_interval) {  //awake_interval = 250 ms    
            flashing = true; 
            //possible initialize flash state
            lastflashingChange = currentMillis;
        }
    }
}

And a similar bit of code inside flash()

bool flashOn;
unsigned long lastFlashLightChange;
void flash() {
    unsigned long x = millis();

    if(flashOn){
        if (lastFlashLightChange - x >= t1) {
            flashOn = false;
            lights_off();
            lastFlashLightChange = currentMillis;
        }
    } else {
        if (lastFlashLightChange - x >= t2) {
            flashOn = true;
            lights_on();
            lastFlashLightChange = currentMillis;
        }
    }

}
1
qo'shib qo'ydi
@Tahseen kerak emas.
qo'shib qo'ydi muallif CTKeane, manba
@Tahseen faqat davlatni o'zgartirishning boshqa yo'llarini tanlashingiz mumkin. Faqat agar vaziyatni o'zgartiring. Bundan tashqari, ko'proq holatlarga ega bo'lishingiz mumkin, bumni enumga o'zgartirasiz va if/else ni o'zgartirishga o'zgartirishingiz mumkin.
qo'shib qo'ydi muallif CTKeane, manba
Bu juda chiroyli ko'rinadi ... buni sinab ko'rmoqchiman. Lekin kodning birinchi blokidagi previousMillis = millis (); satri albatta kerak emas, to'g'rimi?
qo'shib qo'ydi muallif Demi, manba
Bu aqlli, lekin chiroqlar 9 soniya davomida yonib turmaydi, lekin faqat 250 milodiy (ya'ni, awake_interval). Mana bu katta rasm ... Men aslida radio 250 milodiy uchun uyg'onishni xohlayman. Agar o'sha vaqt oralig'ida biror narsa olinsa, chiroq (9) chaqiriladi va chiroqlar 9 sekundgacha yonadi. Hech narsa qabul qilmasa, u faqat 3 soniya uchun uyquga ketadi, keyin 250 milodiy uchun tiriklayin va shunga o'xshash
qo'shib qo'ydi muallif Demi, manba

Mana sizga boshlash uchun eskiz. U kechiktirma yoki kutubxonalardan foydalanmaydi. Mening NeoPixel qurilmalarim yo'q, shuning uchun sinov uchun mo'ljallangan LEDni qurgan Arduino foydalangan. Miltillovchi LEDni to'xtatish uchun faqat "myTimer4" funktsiyasini va tegishli kodni/o'zgaruvchini olib tashlang. Foydalanadigan radiokanalni simulyatsiya qilish uchun ketma-ket monitorga kiritilgan belgini ishlatishingiz uchun qaysi "radio" turini bilmayman. Sinov uchun kod bo'yicha bir nechta ketma-ket bosma so'zlar mavjud.

const unsigned long delayTime = 3000;
const unsigned long delayTime2 = 250;
const unsigned long delayTime3 = 9000;
const unsigned long delayTime4 = 500;
unsigned long previousMillis = 0;
unsigned long previousMillis2 = 0;
unsigned long previousMillis3 = 0;
unsigned long previousMillis4 = 0;
byte checkForData = 0;
byte dataReceived = 0;
byte flashLED = 0;
byte doOnce = 0;

void setup(){
  Serial.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
}

void loop(){

 //Get current time.
  unsigned long currentMillis = millis();

 //First event.
  if(checkForData == 0){
    if(myTimer1(delayTime, currentMillis) == 1){
      Serial.println("3 second timer done");
      checkForData = 1;
      previousMillis2 = currentMillis;
    }
  }

 //Second event.
  if(checkForData == 1){

   //Your radio code here to check for data.

   //I'm simulating data input from your device using the serial monitor.
    if(Serial.read() > 0){dataReceived = 1;}

    if(myTimer2(delayTime2, currentMillis) == 1){
      Serial.println("250 ms timer done");
      checkForData = 0;
      previousMillis = currentMillis;
      if(dataReceived == 1){
        flashLED = 1;
        previousMillis3 = currentMillis;
        dataReceived = 0;
      }
    }
  }

 //Third event.
  if(flashLED == 1){
    if(doOnce == 0){
      flash(1);
      doOnce = 1;
    }
    if(myTimer3(delayTime3, currentMillis) == 1){
      Serial.println("9 second timer done");
      flashLED = 0;
      flash(0);
      doOnce = 0;
      digitalWrite(LED_BUILTIN, LOW);
    }
  }

 //Fourth event. 
  if(myTimer4(delayTime4, currentMillis) == 1 && flashLED == 1){
    //Serial.println("500 ms timer done");
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
    previousMillis4 = currentMillis;
  }

}

// Function to send data to the NeoPixel device.
void flash(byte startStop){
  if(startStop == 1){Serial.println("flash function started");}
  if(startStop == 0){Serial.println("flash function ended");}  
}

// First event timer.
byte myTimer1(unsigned long delayTime, unsigned long currentMillis){
  if(currentMillis - previousMillis >= delayTime){previousMillis = currentMillis;return 1;}
  else{return 0;}
}

// Second event timer.
byte myTimer2(unsigned long delayTime2, unsigned long currentMillis){
  if(currentMillis - previousMillis2 >= delayTime2){previousMillis2 = currentMillis;return 1;}
  else{return 0;}
}

// Third event timer.
byte myTimer3(unsigned long delayTime3, unsigned long currentMillis){
  if(currentMillis - previousMillis3 >= delayTime3){previousMillis3 = currentMillis;return 1;}
  else{return 0;}
}

// Fourth event timer.
byte myTimer4(unsigned long delayTime4, unsigned long currentMillis){
  if(currentMillis - previousMillis4 >= delayTime4){previousMillis4 = currentMillis;return 1;}
  else{return 0;}
}
1
qo'shib qo'ydi

chiroqlar 250 ms uchun yonadi, men esa 9 soniya davomida porlashni xohlayman!

bu mantiqqa to'g'ri kelmaydi. Asosan siz 5 soniya ichida 2 soat ovqatlanishni xohlaysiz.

sizning kodingiz bunday mantiqni aks ettiradi: bajarish fleshli() dan chiqqanda, u ham loop ning loop() dan chiqishi kerak.

shuning uchun nima qilishni xohlayotganingizni aniqlang, yozing va unga kodni kiriting.

0
qo'shib qo'ydi

Men butun kodimga nisbatan o'zim ishonch hosil qildim. Odamlar butun kodimni joylashtirishni taklif qilishganda, men buni bajarishim kerak edi !!!

Yaxshiyamki, men qilgan xato. Flash_time o'zgarmaydiganini 8-bit integer sifatida ishga tushirdim. Albatta, 8 bit faqat 255 gacha saqlanishi mumkin. Men 9000 ni saqlashga harakat qilaman !!! Quyidagi kodda bu xato aniqlangan.

const long sleep_interval = 3000; 
const long awake_interval = 250; 
const int ledPin = 3;

const uint16_t flash_time = 9000;  //bug fixed by using uint16_t instead of uint8_t
const uint16_t t1 = 5; 
const uint16_t t2 = 495;

void flash() {  
    unsigned long x = millis();
    while(millis() - x < flash_time){ 
        digitalWrite(ledPin, HIGH);
        delay(t1);
        digitalWrite(ledPin, LOW);
        delay(t2);
    }   
}   

void setup() {
    Serial.begin(57600);  
    pinMode(ledPin, OUTPUT);
}

void loop() {
    unsigned long x = millis();
    while(millis() - x < awake_interval){
        Serial.println("flash time!");
        flash();    
    }

    unsigned long y = millis();; 
    while (millis() - y < sleep_interval) {  //sleep_interval = 3 secs
        Serial.println("Sleep time!");
    }
}

Shunday qilib, soniya shartlarini aniqlash uchun millis() funktsiyasidan foydalanadigan ichki nusxalar juda yaxshi ishlaydi, hatto loop 1 250 ms uchun ishlaydi va 2-loop (1 ning ichki inbu loopi) 9 sekund kabi uzoqroq ishlaydi.

Agar ko'p odamlarning vaqtini sarf qilsam uzr so'rayman.

0
qo'shib qo'ydi

Sizning fikringiz noto'g'ri. Agar oldingi Millisni birinchi satrda millis() funktsiyasini yangilagan bo'lsangiz, sizning kodingizning birinchi va ikkinchi qatorlari o'rtasidagi vaqt farqini chiqarib olishingiz mumkin (bu sizning flash-ichidagi loopda ishlayapsiz). Agar kerak bo'lsa, dastur ishga tushirilgunga qadar vaqtni olish kerak bo'lsa, loop() da har doim yangilash o'rniga setup() da bu uchun doimiy o'zgaruvchiga ega bo'lishingiz kerak.

Shunga qaramay, millis() nima uchun sizning ishingiz uchun kerakligini tushunmayapman. Kechiktirishni ishlatish() juda oddiy va ishni bajarish hali ham mumkin. Misol:

void setup() {
delay(250);
}

void loop(){

    for(int i = 0; i < 9; i++){
        digitalWrite(LED, HIGH);
        delay(time);
        digitalWrite(LED, LOW);
        delay(time);

        delay(1000 - 2*time); //Delays the loop exactly one second per iteraction
    }

}
0
qo'shib qo'ydi
@Tahseen: Siz yozgan " kechikishdan foydalana olmaysiz " va siz buni flash() dan foydalangansiz. Xo'sh, bu qanday shart?
qo'shib qo'ydi muallif Sprogz, manba
Kechikishdan foydalanolmayman, chunki u blokirovka qiladi va bu boshqa (katta) dastur bilan birga bo'lmaydi. O'rnatish() da sobit o'zgaruvchini qo'yish fikringizni biroz ko'proq kengaytira olasizmi? Mening vaqtinchalik ko'chamoqlari ichkarida qolish vaqtini aniqlashga urinmoqdalar.
qo'shib qo'ydi muallif Demi, manba
Yoritgichni yoqish va o'chirishga ta'sir qilish uchun uni flash() da ishlatardim. Lekin, men hozirgi davrda foydalansam, kelajakda birlashishni umid qiladigan boshqa narsalar ishlamaydi. Misol uchun, 250 ms uchun uyg'onadigan radiodan foydalanmoqchiman, har qanday buyruqlar mavjudligini ko'rsatsa, keyin 3 soniya davomida uyquga ketadi. Agar 250 ms.lik oraliqda buyruqlar olinsa, arduino chiroqlarni 9 sekundgacha yonadi
qo'shib qo'ydi muallif Demi, manba
Haqiqatan ham ... Men sizning "buni taqiqlash" degani nimani anglatishini tushunmadim, uni ishlatolmaysan nima sababdan?
qo'shib qo'ydi muallif milton, manba