Появляется вторая запятая после числа с запятой, кто сталкивался?

Тема в разделе "Arduino & Shields", создана пользователем Romhik, 11 окт 2017.

Метки:
  1. Romhik

    Romhik Нуб

    Здравствуйте.
    В своём проекте использую Arduino Nano и АЦП HX711.
    Использую числа и значения типа float.
    Программа работает нормально, в терминале выводит число с двумя разрядами после запятой, например: "123.00".
    Потом, через некоторое время в конце числа с запятой появляется еще одно число с запятой и еще два числа после неё, которые не меняются, например: "123.001.30", последнее значение в конце "1.30" не изменяется, хотя само число, которое в начале изменяется, то есть как бы добавляется вот этот остаток "1.30", а так всё нормально.
    Если сделать сброс, то всё восстанавливается и снова показывает число с двумя знаками после запятой.
    Что можно сделать, как это вылечить?
     
  2. rkit

    rkit Гуру

    У вас просто отправляется второе число впритык к первому. Приведите код в порядок.
     
  3. Romhik

    Romhik Нуб

    Код (C++):
    #include <EEPROM.h>
    #include <enc28j60.h>
    #include <EtherCard.h>
    #include <net.h>
    #include <IPAddress.h>
    #include <HX711.h>
    #define STATIC 0  // set to 1 to disable DHCP (adjust myip/gwip values below)

    ///HX711///////
    HX711 scale(3, 2);                        

    float calibration_factor;          // калибровка!
    float units;
    float ounces;
    float divider;
    float pluser;
    //////////////

    #if STATIC
    // ethernet interface ip address
    static byte myip[] = { 192,168,182,251 };
    // gateway ip address
    static byte gwip[] = { 192,168,182,111 };
    static byte destip[]= {192,168,182,250};
    static int myport=4220,destport=4020;
    #endif
    static byte mymac[] = { 0x1A,0x2B,0x3C,0x4D,0x5E,0x01 };
    byte Ethernet::buffer[700];
    static uint32_t timer;
    static uint32_t timer1;
    static byte hisip[] = { 192,168,182,250 };
    static byte dnsip[] = { 192,168,182,111 };
    //const char website[] PROGMEM = "192.168.182.220";
    const int dstPort PROGMEM = 4020;

    const int srcPort PROGMEM = 4220;

    String str;
    int num = 0;
    char cstr[20];

    String str1;
    int num1 = 0;
    char cstr1[20];

    float calibr;

    //callback that prints received packets to the serial port
    void udpSerialPrint(uint16_t dest_port, uint8_t src_ip[IP_LEN], uint16_t src_port, const char *data, uint16_t len){
      IPAddress src(src_ip[0],src_ip[1],src_ip[2],src_ip[3]);

      Serial.print("dest_port: ");
      Serial.println(dest_port);
      Serial.print("src_port: ");
      Serial.println(src_port);


      Serial.print("src_ip: ");
      ether.printIp(src_ip);
      Serial.println();
      Serial.print("data: ");
      Serial.println(data);

    String d1;
    float d2;
    d1 = strtok(data,":");
    d2 = atof(strtok(NULL,":"));

    float eeprom_write = d2;

    if (d1 == "CALIBR") {
      EEPROM_float_write(0, eeprom_write);
      calibration_factor = EEPROM_float_read(0);
      scale.set_scale();
      scale.set_scale(calibration_factor);       //Применяем калибровку
      Serial.print("EEPROM calibration_factor: ");
      Serial.println(calibration_factor);
      }

    if (d1 == "DIVIDER") {
      EEPROM_float_write(4, eeprom_write);
      divider = EEPROM_float_read(4);
      Serial.print("EEPROM divider: ");
      Serial.println(divider);
      }
    if (d1 == "PLUSER") {
      EEPROM_float_write(8, eeprom_write);
      pluser = EEPROM_float_read(8);
      Serial.print("EEPROM pluser: ");
      Serial.println(pluser);
      }

    if (d1 == "RESET") {digitalWrite(4, LOW);}
    if (d1 == "TARE") {
      scale.tare();
      pluser=d2;
      }

    }

    void setup () {
    digitalWrite(4, HIGH);
    delay(200);
    pinMode(4, OUTPUT);
      Serial.begin(9600);

      if (ether.begin(sizeof Ethernet::buffer, mymac) == 0)
        Serial.println( "Failed to access Ethernet controller");
    #if STATIC
      ether.staticSetup(myip, gwip);
    ether.copyIp(ether.dnsip, dnsip);
    #else
      if (!ether.dhcpSetup())
        Serial.println(F("DHCP failed"));
    #endif
    ether.copyIp(ether.hisip, hisip);
      ether.printIp("IP:  ", ether.myip);
      ether.printIp("GW:  ", ether.gwip);
      ether.printIp("DNS: ", ether.dnsip);
      ether.printIp("SRV: ", ether.hisip);

      //register udpSerialPrint() to port 4220
      ether.udpServerListenOnPort(&udpSerialPrint, 4220);

    //////HX711//////////
      scale.set_scale();
      scale.set_scale(calibration_factor);       //Применяем калибровку
    ////////////////////
    }
    char tag[] = {"WEIGHT:"};

    void loop () {
        if (millis() > timer1) {
          timer1 = millis() + 250;
    units = scale.get_units(), 10;
    ounces = units * 0.035274;

    float w2 = (ounces/divider)+pluser;
    str1 = tag+String(w2);
    str1.toCharArray(cstr1,20);

    ether.sendUdp(cstr1, sizeof cstr1, 4001, ether.hisip, 4120 );
        }
    ether.packetLoop(ether.packetReceive());
        if (millis() > timer) {
          timer = millis() + 1000;
       
    units = scale.get_units(), 10;
    ounces = units * 0.035274;

    float w1 = (ounces/divider)+pluser;
    str = tag+String(w1);
    str.toCharArray(cstr,20);

         ether.sendUdp(cstr, sizeof cstr, srcPort, ether.hisip, dstPort );
      }

    }///end loop

    void EEPROM_float_write(int addr, float val) // запись в ЕЕПРОМ
    {
      byte *x = (byte *)&val;
      for(byte i = 0; i < 4; i++) EEPROM.write(i+addr, x[i]);
    }

    float EEPROM_float_read(int addr) // чтение из ЕЕПРОМ
    {  
      byte x[4];
      for(byte i = 0; i < 4; i++) x[i] = EEPROM.read(i+addr);
      float *y = (float *)&x;
      return y[0];
    }
    Я думаю, что этого не может быть, потому что второе число отправляется после первого и никак не может прилепляться.
    Я вставлял вывод в терминал значения переменной w2, видно, что искажается она.
    Но спасибо за интересную идею, нужно проверить, сейчас так и сделаю, посмотрю что происходит с обеими переменными. Есть подозрение, что искажается только одна.
    Ну и еще, может ли это быть из-за того, что не успевает сам АЦП измерять?
    Пример неправильного вывода:
    26.51.23
    19.45.23
    26.43.23
    23.68.23
    22.77.23
    Вывод после сброса:
    23.54
    26.51
    21.85
    17.05
    25.02
     
    Последнее редактирование: 11 окт 2017
  4. rkit

    rkit Гуру

    Что? прямо противоречащие вещи пишете.
     
  5. Romhik

    Romhik Нуб

    Оправляются по разным UDP портам, где они прилепляются в кабеле по пути к серверу?))) Шучу))
    Ну не знаю, сейчас разбираюсь, буду отключать функции по очереди и смотреть...
    Я пока интересуюсь, может кто сталкивался с таким...
    Если найду, отпишусь...
     
  6. Romhik

    Romhik Нуб

    Выяснил проблему, во первых не очищается переменная с массивом перед записью в неё нового массива, не знал, что такое вообще может быть.
    И второе, вероятно что функция преобразования toCharArray() не добавляет в конец \0, если данные меньше, чем размер массива.
    Решения есть два, это перед записью в массив новых значений, очищать его как бы, забивать всё нулями или добавлять в конец массива \0

    Код (C++):
    cstr1[str1.length()] = '\0';
           . . . . . .
    cstr[str.length()] = '\0';
     
  7. Tomasina

    Tomasina Сушитель лампочек Модератор


    Ты в коде сам принудительно запретил это делать, указав static.