Arduino ішінде цикл () қаншалықты жылдам жұмыс істейді

Сәлем, Unity3D-тегі менің тәжірибемді үйрену үшін Arduino Nano пайдаланамын. Unity3D ішіндегі Update() секілді секундына әрбір кадрды іске қосатындығын білемін, бірақ мен білмеймін, өйткені мен электрониканы емеспін, өйткені loop() функциясы Arduino .

Бұл процессор циклдарының санына (Arduino жағдайда микропроцессорлық микросхемаға) немесе неге байланысты? Түсіндіріп беріңізші. Менің ойымда біраз артта қалдым. Мен оларды Arduino-дегі цикл() функциясының қалай жұмыс істейтінін білсеңіз ғана түзете аламын

There ain't a lot of information about loop() in arduino documentation

4
Қысқа жауап - «мүмкіндігінше тезірек».
қосылды автор Jirka Hanika, көзі
«кадрға секундына әрбір кадрды іске қосады», сіз кадрларды толығымен түсінесіз, немесе, мүмкін, жай ғана типо. бірақ Unity3D-де әрбір кадр мүмкіндігінше жылдам жұмыс істейді, олар мақсатты емес, кадрға кешіктірілмейді
қосылды автор Udo G, көзі
қою кадрдағы кідіріс (оны өңдей алмайсыз ба?)
қосылды автор Udo G, көзі

5 жауаптар

Цикл циклды іске қосу қажет болғанда іске қосылады.

Процессордағы нұсқаулар жүйелі түрде орындалады. Неғұрлым көбірек нұсқаулар іске қосылатындай ұзағырақ болады.

Ұзағырақ циклды циклге қойған көбірек код іске қосылады.

Әр циклдің қанша уақытқа созылатындығын білудің екі жолы бар:

  1. Профильдеу: Әрбір итерацияның белсендірек уақыты ескертсе де, уақыттың әрекет етуі қабылданған уақытқа әсер етеді.
  2. Циклды санау. Дереккөзді құрастыруға құрастырыңыз және барлық нұсқауларға (оның ішінде функцияларға қоңырауларға) қажетті сағаттық циклдардың санын толтырыңыз. Кішкентай циклдар үшін күрделі, кез-келген нәрсе үшін күрделі міндет.

Сондай-ақ, көптеген сыртқы факторлар сериялы байланыс жылдамдығы және т.б. сияқты қанша уақыт ішінде жұмыс істейтінін біледі.

8
қосылды
@FilipFranik: 1. millis() мәнін жаңартатын үзіліс әрбір 1024 мкс немесе 16 МГц жиілігі 16384 циклінде жұмыс істейді. 2. Ажырату бағдарламалық қамтамасыз етудің PWM шығу сапасына әсер етеді (мысалы, Servo кітапханасы). Олар аппараттық-жасалатын PWM-ға (мысалы, analogWrite() ) әсер етпейді).
қосылды автор Sprogz, көзі
Үзіліссіздіктерді ұмытпаңыз, мысалы әр 16000 сағаттық циклді милис мәнін жаңарту (16Mhz oscilator үшін). Олар тұрақты түрде бағдарламаның орындалуын тоқтатады және Arduino-дің жақсы PWM көзі болуына жол бермейді. (иә сіз оны өшіре аласыз)
қосылды автор Robert Sibek, көзі

loop() соңындағы нұсқаулық және оның келесі әрекеті рет, jmp және қоңырау болып табылады.

Негізгі функцияны тиімді деп санауға болады:

void main(){

    init();
    while(1) loop();

}

Шындығында millis() және сол сияқты жұмыс жасау үшін init() алдында бірнеше параметрлерді орнату керек.

3
қосылды
@ Маженко үзіліспен жасалмайды ма?
қосылды автор CTKeane, көзі
Ардуинның стандартты жұмыс уақытына көбірек қарай қарайтын болсам, мен көп ойлаймын ...
қосылды автор CTKeane, көзі
@ next-hack: Arduino IDE-дің жаңа нұсқалары сілтеменің уақытын оңтайландыруға мүмкіндік беретін - loop() кодын енгізуге мүмкіндік беретін -flto опциясымен gcc деп аталады. Ескі нұсқалар осы параметрді пайдаланбайды, сондықтан loop() бірнеше кодымен main() деп аталатын нақты функцияға жиналады.
қосылды автор Sprogz, көзі
Сондай-ақ, циклнан кейінгі сериялық оқиғалар коды бар.
қосылды автор Majenko, көзі
Жоқ олай емес. Ол цикл соңында ғана шақырылады. Бұл өте шикі және көптеген адамдар шын мәнінде қаншалықты маңызды екенін түсінбейді.
қосылды автор Majenko, көзі
Менің ойымша, цикл() компилятор арқылы оңтайландырылған, сондықтан нақты jmp немесе қайталау орын алмайды. Код аударылады: while (1) yourLoopCode; функция шақыру жоқ. Бірақ мен GCC-мен қорқынышты жалған нәрселерді көрдім ...
қосылды автор next-hack, көзі

Бұл циклда болған нәрсеге байланысты. Бірнеше сағаттық циклден шексіз асуға дейін.

1
қосылды

Main.cpp файлына (менің орнатылымымдағы avr-код үшін) қара:

C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino\main.cpp

Arduino циклін() кезекпен serialEventRun() арқылы шексіз циклда іске қосатынын көрсетеді:

int main(void)
{
    init();
    initVariant();
 #if defined(USBCON)
    USBDevice.attach();
#endif

    setup();

    for (;;) {
        loop();
        if (serialEventRun) serialEventRun();
    }

    return 0;
}

HardwareSerial.cpp инспекциясының көмегімен serialEventRun() сценарийде анықталған болса, serialEvent() деп аталады.

Бұл сіз өзіңіздің шексіз циклды цикл ішінде() сценарийді жазуға болмайынша және сіз жүйелі түрде жұмыс істейтінін күтпестен жаза аласыз.

Бұл сұрақ туындайды: егер serialEvent() циклімен дәйектілікпен аталса (), loop() ешқашан қайтарылмайтын болса, serialEvent() деп аталасыз ба? Басқаша айтқанда, serialEvent() функциясы interrupt-driven, сондай-ақ loop() қайтарылған кезде шақырылады? Төменде жылдам тексеру - бұл емес үзуді басқаратындығын көрсетеді, сондықтан алдыңғы параграф шын.

/*
  Serial Event Checker

  A sketch to see if serialEvent() is interrupt-driven.
  Will serialEvent() be called if loop() never returns?

  This code is based on Tom Igoe's SerialEvent example.

  On (at least) Arduino Uno we find that serialEvent() simply runs
  sequentially with loop().  When loop() never returns serialEvent()
  is never called.

  NOTE: The serialEvent() feature is not available on the Leonardo, Micro, or
  other ATmega32U4 based boards.

  R Symonds-Tayler 2018-02-01

  This example code is in the public domain.

*/

String inputString = "";        //a String to hold incoming data

void setup() {
 //initialize serial:
  Serial.begin(115200);
 //reserve 200 bytes for the inputString:
  inputString.reserve(200);
}

// comment out this definition to allow loop() to return
#define INFINITE_LOOP

void loop() { 
#ifdef INFINITE_LOOP
    while(1);
#endif

}

/*
  SerialEvent occurs whenever a new data comes in the hardware serial RX. This
  routine is run between each time loop() runs, so using delay inside loop can
  delay response. Multiple bytes of data may be available.
*/
void serialEvent() {
  while (Serial.available()) {
   //get the new byte:
    char inChar = (char)Serial.read();
   //add it to the inputString:
    inputString += inChar;
   //if the incoming character is a newline, set a flag so the main loop can
   //do something about it:
    if (inChar == '\n') {
      Serial.print("Got: '");
      Serial.print(inputString);
      Serial.println("'");
     //clear the string:
      inputString = "";
    }
  }
}

Бұл serialEvent() коды сіздің негізгі циклыңызға() келесідей кіреді:

if(serial.available()){
  //your code here...
}

блок.

1
қосылды

arduino функцияларын іздеуге тырысыңыз микро () және delayMicroseconds () Егер сіздің циклыңыз 16000 мкм-нен астам уақыт күтуі қажет болса, онда миллисекундпен орындалатын басқа кешіктіру() функциясын іздеңіз.

Айтпақшы, ішкі сағат өте аз және бөлме температурасымен ерекшеленеді, сондықтан оны қолмен ұстамасыз басқа құрылғыңызға синхрондалуды қаламаңыз.

0
қосылды
micros() және delayMicroseconds() 32 биттік бүтін сандарды ( unsigned long ) пайдаланады және ұзақтығы 2 ² μs дейін немесе шамамен 1,19 сағат .
қосылды автор Sprogz, көзі