ParseInt () неғұрлым жылдам балама дегеніміз не?

Мен Arduino Due және менің компьютеріммен жарықдиодты спектралды анализатор жасап жатырмын. Дыбысты өңдеу компьютерде орындалады, содан кейін Arduino-ге жіберіледі. Жіберілген нақты деректер - «координат» немесе одан да нақты, нақты жолақты білдіретін сан және осы жолақтың максималды амплитудасын білдіретін басқа сан. 11 жолағы бар. Әрбір координатта үтірмен бөлінген x және y мәндері бар, содан кейін жаңа жолға жіберіледі.

Бұл менің кодексім:

void loop() {
  if (Serial.available()) {
    xCoord = Serial.parseInt();
    yCoord = Serial.parseInt();
    if (xCoord != 0) {
      int r, g, b;
      for (int i = 0; i < 8; i++) {
        int fromCoordToIndex = ((xCoord - 1) * 8) + i;
        //
        //do some calculations for the color
        //
        strip.setPixelColor(fromCoordToIndex, strip.Color(r, g, b));
        strip.show();
      }
    }
  }
}

Мәселе parseInt өте өте баяу болып көрінеді (бұл таймаут мәселесі емес, ол 1 деп орнатылды). Көріп отырғанымдай, кейбір деректерді өткізіп жіберген сияқты секілді, әр кезде, содан кейін топ шығып қалады. Мұны шешудің жалғыз жолы - жіберілетін әрбір координат арасындағы кідірісті енгізу. Мен 40 мс-ді жақсы деп таптым, бірақ 11 жолақ бар екендігін есте сақтаңыз, бұл слайд-шоу секілді сезінетін барлық тақтаны жаңарту үшін жарты секундты білдіреді.

Мен жеке таңбаларды енгізуді және содан кейін toInt сөзін қолданып көрдім, parseInt анық көрдім, мен туған USB-ды Боадамдық мөлшерлемелермен ерекшеленеді. Ешқандай нәтиже жоқ сияқты.

1
Деректерді алғаннан кейін жасайтын есептеулердің баяу бөлігі болып табылады. Жүзбелі нүктелердің болмауы салдарынан өзгермелі нүкте операциялары баяу жүреді, орнына орнына тіркелген түрлерді есептеуді таңдап алыңыз.
қосылды автор CTKeane, көзі
түрлендіруге қарағанда жылдамырақ strip.show (); циклінен жылжыту
қосылды автор Alastair, көзі
Сандарыңыз арасында бөлгіш таңбаның кейбір түрін жібересіз бе?
қосылды автор Sprogz, көзі
Неғұрлым тезірек балама - талдауды қажет етпейді. Оның орнына екілік деректерді жіберіңіз.
қосылды автор Ignacio Vazquez-Abrams, көзі
@LookAlterno бұл қатаң емес, бірақ оны қатаң ету үшін 2 секунд кетеді, пішім x, y (үтірді бөлгіш ретінде қосады және ол жол ретінде жіберіледі)
қосылды автор xandriksson, көзі
Мен түсінбеймін
қосылды автор xandriksson, көзі
Бірақ бұл жол ретінде шықпайды, оны пайдалану үшін оны талдауға тура келеді, солай емес пе?
қосылды автор xandriksson, көзі
Менде жоғарыдан шығарылған басқа есептер бар, олар екілік болса, солай ете аламын ба?
қосылды автор xandriksson, көзі
@dandavis жақсы нүкте, рахмет, мен оны көрген едім ...
қосылды автор xandriksson, көзі
Алғашқы нақыш - өңдеу және көрсету алдында барлық деректерді оқу. Сондай-ақ, бұрынғы аяқталғанға дейін қосымша деректерді жібермеңіз. Екіншіден, аппараттық қамтамасыз етудің сериялық іске асырылуын тексеру, ол шын мәнінде үзіліс және буферлік болып табылады.
қосылды автор Mikael Patel, көзі
Деректеріңіз қатаң форматқа ие болса (мысалы, әрқашан 3 цифр, нөлдермен немесе кеңістіктермен толтырылған болса) parseInt жылдамырақ жасауға болады. .
қосылды автор user31481, көзі
Мысалы, барлық мәндер оң 3 сан (нөлмен толтырылған) және олар жұппен, үтірмен бөлінген, 003,456 ... 450,001 сияқты ...
қосылды автор user31481, көзі
Сұраққа қол жеткізу үшін пішіміңіз туралы мәліметтерді жіберіңіз.
қосылды автор user31481, көзі
⇒ Бұл сұрақты басқа жерде сұрап, бірақ бізден жасыруға тырыспаңыз. forum.arduino.cc/index.php?topic=508343.0 сілтемесіне сілтеме беруіңіз керек.
қосылды автор Standback, көзі
@ratchetfreak иә, әрине, және 1ms уақыттың үзілісі parseInt тоқтатады (біз білмейтін белдеуге байланысты). Бірақ алдымен сериялық деректердің хаттамасын анықтау керек.
қосылды автор Standback, көзі
MatthewInglis сіз форматты анықтауыңыз керек. Бұл жерде бастау керек. Қанша сан үлкен байт бола алады, олар теріс болуы мүмкін және т.б. Сіз көрсеткеннен кейін оны @LookAlterno сізге айтуға тырысқандай, оны/ridig форматына айналдырыңыз. Бұдан кейін бақылау сомасын немесе STX және ETX (бастау және аяқтау маркерлері) қосуға болады. Немесе соңында LineFeed немесе CarriageReturn әрқашан бар екенін көрсетіңіз. Бірақ алдымен пішімді көрсетіңіз, сұрақты өңдеңіз және оған қосыңыз.
қосылды автор Standback, көзі

5 жауаптар

parseInt() туралы тітіркендіргіш нәрсе жылдамдығы емес, бұл факт ол күту уақытына сүйенеді. Егер күту уақыты тым ұзақ болса, ол сізді баяулатады төмен. Егер ол өте қысқа болса, ол қателерді тудыруы мүмкін.

Сіз пайдаланып жатқан хабарларды талдаудың қауіпсіз әдісі - бәрін аралықпен сақтау кіріс таңбаларды каретки қайтарымын тапқанға дейін тексеріңіз тұтас сызық. Мысалға:

// Just echo the messages with a different separator.
void parse(char *buffer)
{
    char *s = strtok(buffer, ",");
    int x = atoi(s);
    s = strtok(NULL, ",");
    int y = atoi(s);
    Serial.print(x);
    Serial.print(':');
    Serial.println(y);
}

void loop()
{
    static char buffer[BUFFER_SZ];
    static size_t lg = 0;
    while (Serial.available()) {
        char c = Serial.read();
        if (c == '\r') {       //carriage return
            buffer[lg] = '\0'; //terminate the string
            parse(buffer);
            lg = 0;            //get ready for next message
        }
        else if (lg < BUFFER_SZ - 1) {
            buffer[lg++] = c;
        }
    }
}

strtok() деп қоңырау шалғанда қатені тексеруді қосуыңыз керек.

3
қосылды

Мен оны жылдамдықты 115200-ден 9600-ге дейін төмендету арқылы түзетілген шығармын. Бұл жауаптың өзгеруіне шабыт берді. Шамасы, ақпараттың жылдамдығы неғұрлым жоғары болса, қате ықтималдығы неғұрлым жоғары болса, соғұрлым баяу жылдамдығы неғұрлым төмен болса, соғұрлым ол жіберіледі, бірақ ол сенімдірек болады.

0
қосылды

Мерзімді оңтайландыру - бұл барлық зұлымдықтың түбірі (немесе кем дегенде көпшілігі   бағдарламалау кезінде). Дональд Кнут.

Мен қаншалықты жылдам/parseInt() екенін білмеймін. Сіз де емессіз. Алдымен уақытты қажет етеді.

ЖАРАЙДЫ МА. Мүмкін бұл шынымен баяу, бірақ сіздің кодыңыздың ең баяу бөлігі болып табылады ма? Немен салыстырғанда баяу?

parseInt сізге керек пе? parseInt теріс мәндерді түрлендірмейді және ол уақытты жоғалтады (бірақ нөлге тең ... Duh!).

Егер бүкіл жолды Жол ретінде оқып, құндылықтарды талдайтын болсаңыз, уақытты жоюға қатысты ақаулықтан аулақ боласыз және деректердің дұрыс екенін тексере аласыз.

Бұл эскиз деректеріңізді өңдеу әдісін көрсетеді:

void setup() {
  Serial.begin(9600);
  while(!Serial);

  String lines[] = {
    "1,1",
    "10,20",
    "11,1000",
  };
  int channel;
  int value;

  for (int i=0; i < 3; i++) {      
    sscanf(lines[i].c_str(), "%d,%d", &channel, &value);
    Serial.print("channel="); Serial.print(channel);
    Serial.print(" value="); Serial.println(value);
  }
}

void loop() { 
}

Мен sscanf пайдаланамын, бұл parseInt қарағанда сенімді емес, бірақ тапсырма орындалды. Мен сенің (немесе менің) оны жақсарта алатынына күмәнданбеймін, және біздің уақытымызға пайдалы нәрсе бар.

Өңдеу:

Мен профильді

sscanf("0001,0001", "%d,%d", &channel, &value);

БҰҰ-ның Arduino UNO-мен бірге, құндылықтардың бірыңғай айналымын өзгерту үшін 147-ке тартылды.

0
қосылды

Деректеріңіздің әр арнасы үшін 11 арнасы бар және бір мән. Мәндер графикалық форматта ұсынылады, сондықтан ол презентацияны төмендетпестен 0-255 ауқымына сәйкес келеді. Сіз әрқашан сіздің көрсеткіштеріңізді дисплейдің ажыратымдылығына дейін кеңейте аласыз.

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

Arduino соңында сіз 12 байтты оқып, одан кейін байтты инсталляциялау арқылы циклге айналдырдыңыз.

#define CHANNELS 11

void setup()
{
  Serial.begin(9600);

  while(!Serial);
}

void loop()
{
  char packet[CHANNELS + 1];
  int values[CHANNELS];

 //Read 12 bytes (11 bytes of data + 1 byte delimiter)
  int nBytes = Serial.readBytes(packet, sizeof(CHANNELS + 1));

  if(nBytes == CHANNELS + 1) {
   //Convert bytes to ints;
    for(int i=0; i

Бұл кодта қатені анықтау мүмкін емес. Ол үшін барлық деректер жиынтығының бақылау сомасын қосымша байт қосуға болады.

0
қосылды
Осыған қызықтыратын мәселе, nBytes ешқашан 11 + 1 болмайды, оны тексергенімде әрдайым 4, содан кейін 4, содан кейін 4, ал бірден 12 болмайды. Кез келген идеялар?
қосылды автор xandriksson, көзі
Сіз дерлік жасайсыз. Командалармен жұмыс істегенде (Serial, tcp/ip) ешқашан сіздің барлық байттарыңызды бір оқуда қабылдайсыз деп ойлаңыз. Деректерді бөліктерге оқуға дайын болу керек. Сізде негізгі идея бар; енді қалған мәліметтерді толтыру үшін сізде. Сіздің алдыңыздағы тағы бір проблема екі компьютерді синхрондау болып табылады: деректер жиынының басталуын (немесе соңын) сигнал беру үшін ерекше мәнді (мысалы, 255) сақтауыңыз керек. Қазір жіберілген бірінші байттар жоғалуы мүмкін. Барлық қателерді тексеруді қосқаннан кейін, кодты қалпына келтіру және буферизациялау 5 есе үлкен болады. Бұл қалай жұмыс істейді.
қосылды автор user31481, көзі

Ардуино әдісін пайдаланудың орнына, 11 жолақты деректерді Arduino-ға өте ерекше түрде жіберіңіз, сонда Arduino оны «оңай» бөлуге қабілетті.

Мүмкін, мәтінді жіберу орнына RGB (3) рет 33 байт жіберіңіз 11 жолақтар қатарлы арналардың деңгейлері (0-255). Өйткені конверсия қажет емес (байтты оқудан басқа).

0
қосылды
Жақсы, егер мен «025» атауын сериялы ардуиноға жіберсем, serial.readBytes() қолданамын ба? Егер мен мұны істесем, оны бүтін санға айналдыруға жол берер едік бе?
қосылды автор xandriksson, көзі
Менің надандықты кешіріңіз, бірақ сіз байтпен нені білдіреді? Егер әрбiр жолда (және қоса алғанда) 0 және 13 арасында сан болса, оны байт ретiнде қалай ұсынамын?
қосылды автор xandriksson, көзі
Мен түсімді жіберудің қажеті жоқ, тек әр топтың қаншалықты жоғары екенін білуім керек. Сондықтан қосымша құндылықтар жіберу тек қана ештеңе болмайды.
қосылды автор xandriksson, көзі
Бұл жағдайда 11 байт әрбір жолақ үшін бір мәнге жетеді.
қосылды автор Pat, көзі
Байт - 8 бит (8 нөл немесе он). Байт (8 бит) болғанда 0 мен 255 аралығындағы санды (немесе 256 түрлі мән) сақтауға болады. Мәні1 * 13 + мәнін есептеу арқылы екі мәнді бір байтта 0-13 аралығынан жібере аласыз (бұл әрқашан 256-дан кем болады). Немесе одан да көп сәйкес биттерді: value1 << 4 + value2 ... << оператор төрт есе биттерді төртге ауыстырады, бұл бірдей 16 мәнге көбейтіледі. Value1 сол төртбұрышта (MSB) төрт бит болады, оң (LSB) төрт бит. Егер сіздің жүйеңіз 16 арнаға ауысса, сізге ештеңені өзгертудің қажеті жоқ (11 арнаға қарағанда).
қосылды автор Pat, көзі
Жақсы «025» жіберуге болмайды, себебі бұл 3 таңба (байт). Мысалы, бірінші екіге 0 * 16 + 2 = 2 жібере аласыз ... 2 байтты (2-белгі емес) байтты жіберіңіз.
қосылды автор Pat, көзі