МК неправильно считает

Тема в разделе "Arduino & Shields", создана пользователем Un_ka, 5 фев 2019.

Метки:
  1. Un_ka

    Un_ka Гик

    ...ну или я.
    Вообщем написал код для управления самоходом по ИК связи .
    все данные путем умножения на 10 в нужной степени собираются в 4 байта
    unsigned long--1'180'180'0'19
    .где 1 это статус фар , а 180 это угол поворота сервомашинки , 0 режим моторов , 19 сумма всех разрядов.
    Неполадка в следующем
    должно собираться число
    1'090'000'3'13
    а получается
    1'090'000'3'57
    т.е. выявил
    что при добавлении к agra углов сервомаш.
    в конце добавляется 44 .
    незнаю почему так происходит незнаю
    , может где-небудь в типах переменных или синтаксисе ошибка?
    Код (C++):

    //#include <RCSwitch.h>
    //RCSwitch mySwitch = RCSwitch();
    #include <IRremote.h>
    IRsend irsend;
    bool tig = 0 ;
    unsigned long agra, timer_per = 0, zajat_timerV = 0, zajat_timerG = 0;
    unsigned long per = 100;
    volatile unsigned long last_timer = 0;
    volatile byte state_key = 1;
    byte reader ;
    int vert = 90, curs = 90, pribavka, reade, digit;
    byte Gsum, mot ;
    void setup() {
      Serial.begin(9600);
      Serial.print("Mao niao");
      attachInterrupt(0, status_key, FALLING);
      pinMode( 2, OUTPUT );
    //  mySwitch.enableReceive(12);
      if (digitalRead(4) == 1) {
        tig = 1;
      }
    }
    void loop() {
      if ( millis() - timer_per > per) {
        Gsum = 0;
        agra = 0;
        agra = (unsigned long)state_key * 1000000000;
        Gsum += state_key;
        Serial.println(agra, DEC);
        //--------вертикаль-----------  
        reade = analogRead(A0);
        pribavka=1;
        if (zajat_timerV + (5 * per) > millis()) {
          pribavka = 3;
        }
        if (reade < 900) {
          pribavka = 0 - abs(pribavka);
          zajat_timerV = millis();
        } else if (reade > 2100) {
          pribavka = abs(pribavka);
          zajat_timerV = millis();
        } else {
          pribavka = 0;
        }
        vert += pribavka;
        vert = constrain(vert, 0, 180);
        agra += (vert * 1000000);
      Serial.println(agra, DEC);
        servo_hash(vert);

        //cursIZONT
        reade = analogRead(A1);
        pribavka=1;
        if (zajat_timerG + (5 * per) > millis()) {
          pribavka = 3;
        }
        if (reade < 900) {
          pribavka = 0 - abs(pribavka);
          zajat_timerG = millis();
        } else if (reade > 2100) {
          pribavka = abs(pribavka);
          zajat_timerG = millis();
        } else {
          pribavka = 0;
        }
       
        curs +=pribavka;
        curs = constrain(curs, 0, 180);
        Serial.println(curs, DEC);
        //agra += (curs * 1000);
        //servo_hash(curs);
        //Motors

        reade = analogRead(A3);

        if (reade < 800) {
          mot = 3;
        } else if (reade > 2100) {
          mot = 4;
        } else {
          mot = 0; //stop
        }

        reade = analogRead(A2);
        Serial.println("a ");
        Serial.print(reade, DEC);
        Serial.println("  ");
        if (reade < 800) {
          mot = 1; //go
        } else if (reade > 2100) {
          mot = 2; //back
        }
        //Serial.println(mot,DEC);
        Gsum += mot;
       
        mot = mot*100;
        if(mot!=0){agra += mot;}
        Serial.println(agra, DEC);
        agra += Gsum;
        Serial.println(agra, DEC);
        Serial.println(Gsum, DEC);
        //Serial.println(Gsum, DEC);
        irsend.sendJVC(agra, 32, 0); // hex value, 16 bits, repeat
        delay(50);
        /* if(tig==1){
          if( mySwitch.available() ){
              int value = mySwitch.getReceivedValue();

              if( value == B1000 ){
                  digitalWrite( 13, HIGH );
              }else if( value == B0100 ){
                  digitalWrite( 13, LOW );
              }
              mySwitch.resetAvailable();
          }
          }*/

        timer_per = millis();
      }
    }
    void servo_hash(int val) {
      for (int d = 2; d--; d >= 0) {
        digit = (val / pow(10, d));
        Gsum = Gsum + digit;
        int e = (digit * pow(10, d)) ;
        val -= e;
      }
    }
    void status_key() {
      if ((last_timer + (per / 2)) < millis()) {
        switch (state_key) {
          case 1: state_key = 2; break;
          case 2: state_key = 1; break;
        }
        last_timer = millis();
      }
    }
    [code/]
     
  2. Un_ka

    Un_ka Гик

    Ах да плата Wavgat NANO V3 .
     
  3. Un_ka

    Un_ka Гик

    число 44 в двоичной системе 101100
    это происходит при умножении на 10 в большой степени , где-то слышал , что атмега последние знаки float плохо считает , может и тут так ?
     
  4. parovoZZ

    parovoZZ Гуру

    atmega в принципе не знает, что такое float. И умножать она тоже не умеет. И делить. И уж тем более возводить в степень.
     
  5. Daniil

    Daniil Гуру

    Везде так, где счёт ведётся на машине с ограниченной разрядностью. Советую мельком почитать про представление чисел в ЭВМ.
    Самый сок в операциях, в которых участвуют числа с разными порядками.
    Тут digit и Gsum глобальные переменные. Если предыдущее значение digit не интересно, т.к. заменяется выражением, то для Gsum начальное значение важно. При d=2 (1ая итерация цикла) к Gsum прибавляется digit - не должно ли Gsum быть нулём в самом начале?
    Читать код тяжело мне из-за того, что переменные разбросаны по проекту и без бутылки чая непонятно как и в каких пределах они меняются.