Проблемы с типами данных в C

Я пробую Arduino Ultimate GPS breakout, где я хочу получить долготу и широту от GPS. Затем я хочу отправить эти две переменные по беспроводной сети через RF. как на изображении ниже: введите описание изображения здесь

Я использую библиотеку для RF-модуля с именем panstamp, чтобы иметь возможность отправлять долготу и широту из Arduino 1 и получать их в Arduino 2, как в приведенном ниже коде:

Передача:

    void send_data() {
    CCPACKET data;
    data.length=2;

    float lon=26.533255;
    float lat=27.533463;


    data.data[0]=lon;
    data.data[1]=lat;
    if(cc1101.sendData(data)){
    Serial.println(data.data[0]);
    Serial.println(data.data[1]);

    Serial.println(" sent ok ");
    return true;
    }else{
    Serial.println("sent failed ");
    return false;
    }

 }

Получение:

void loop(){
        float j = 0;
        lon = packet.data[j];
          Serial.print(lon);
          Serial.print(" ");
        float k = 1;
        lat = packet.data[k];
          Serial.print(lat);
          Serial.println(".");
}

Прекрасно работает при передаче и приёме :)

Проблема в том, что когда я получаю эти две переменные, я получаю просто lon 26.00 и lat 27.00, но не lon 26.533255 lat 27.533463 как я и ожидал.

Я предполагаю, что есть некоторые ошибки с типом данных. Я исследовал библиотеку panstamp, чтобы найти что-нибудь для изменения типа, но безуспешно.

Вот заголовочный файл для CCPACKET:

#ifndef _CCPACKET_H
#define _CCPACKET_H

#include "Arduino.h"

/**
 * Buffer and data lengths
 */
#define CC1101_BUFFER_LEN        64
#define CC1101_DATA_LEN          CC1101_BUFFER_LEN - 3

/**
 * Class: CCPACKET
 * 
 * Description:
 * CC1101 data packet class
 */
class CCPACKET
{
  public:
    /**
     * Data length
     */
    byte length;

    /**
     * Data buffer
     */
    byte data[CC1101_DATA_LEN];

    /**
     * CRC OK flag
     */
    boolean crc_ok;

    /**
     * Received Strength Signal Indication
     */
    byte rssi;

    /**
     * Link Quality Index
     */
    byte lqi;
};

#endif

и исходный код для отправки / получения данных:

boolean CC1101::sendData(CCPACKET packet)
{
  byte marcState;
  bool res = false;

  // Declare to be in Tx state. This will avoid receiving packets whilst
  // transmitting
  rfState = RFSTATE_TX;

  // Enter RX state
  setRxState();

  // Check that the RX state has been entered
  while (((marcState = readStatusReg(CC1101_MARCSTATE)) & 0x1F) != 0x0D)
  {
    if (marcState == 0x11)        // RX_OVERFLOW
      flushRxFifo();              // flush receive queue
  }

  delayMicroseconds(500);

  // Set data length at the first position of the TX FIFO
  writeReg(CC1101_TXFIFO,  packet.length);
  // Write data into the TX FIFO
  writeBurstReg(CC1101_TXFIFO, packet.data, packet.length);

  // CCA enabled: will enter TX state only if the channel is clear
  setTxState();

  // Check that TX state is being entered (state = RXTX_SETTLING)
  marcState = readStatusReg(CC1101_MARCSTATE) & 0x1F;
  if((marcState != 0x13) && (marcState != 0x14) && (marcState != 0x15))
  {
    setIdleState();       // Enter IDLE state
    flushTxFifo();        // Flush Tx FIFO
    setRxState();         // Back to RX state

    // Declare to be in Rx state
    rfState = RFSTATE_RX;
    return false;
  }

  // Wait for the sync word to be transmitted
  wait_GDO0_high();

  // Wait until the end of the packet transmission
  wait_GDO0_low();

  // Check that the TX FIFO is empty
  if((readStatusReg(CC1101_TXBYTES) & 0x7F) == 0)
    res = true;

  setIdleState();       // Enter IDLE state
  flushTxFifo();        // Flush Tx FIFO

  // Enter back into RX state
  setRxState();

  // Declare to be in Rx state
  rfState = RFSTATE_RX;

  return res;
}


byte CC1101::receiveData(CCPACKET * packet)
{
  byte val;
  byte rxBytes = readStatusReg(CC1101_RXBYTES);

  // Any byte waiting to be read and no overflow?
  if (rxBytes & 0x7F && !(rxBytes & 0x80))
  {
    // Read data length
    packet->length = readConfigReg(CC1101_RXFIFO);
    // If packet is too long
    if (packet->length > CC1101_DATA_LEN)
      packet->length = 0;   // Discard packet
    else
    {
      // Read data packet
      readBurstReg(packet->data, CC1101_RXFIFO, packet->length);
      // Read RSSI
      packet->rssi = readConfigReg(CC1101_RXFIFO);
      // Read LQI and CRC_OK
      val = readConfigReg(CC1101_RXFIFO);
      packet->lqi = val & 0x7F;
      packet->crc_ok = bitRead(val, 7);
    }
  }
  else
    packet->length = 0;

  setIdleState();       // Enter IDLE state
  flushRxFifo();        // Flush Rx FIFO
  //cmdStrobe(CC1101_SCAL);

  // Back to RX state
  setRxState();

  return packet->length;
}

Пожалуйста, помогите мне кто-нибудь :)

Ссылка на библиотеку Panstamp: Библиотека PanStamp


person AdiT    schedule 28.10.2014    source источник
comment
Почему вы не можете получить дубль? Вы теряете точность, в чем проблема? Кроме того, вы указали, что в коде библиотеки может быть ошибка.   -  person ha9u63ar    schedule 28.10.2014
comment
Проблема в том, что я теряю точность. Но что я могу сделать, чтобы получить удвоения или поплавки? Это мой вопрос.   -  person AdiT    schedule 28.10.2014
comment
Вероятно, это назначение работает неправильно, data.data [0] = lon; data.data [1] = lat, здесь вы конвертируете float в байтовый тип   -  person Abhishek Chandel    schedule 28.10.2014
comment
Все, что вам нужно (если это разрешено вашим объемом работы), - это изменить byte data[...] на Double data[...] или float data[...]. Таким образом вы сохраняете информацию, которую передаете и получаете.   -  person ha9u63ar    schedule 28.10.2014
comment
Вы хотите изменить это в заголовочном файле?   -  person AdiT    schedule 28.10.2014


Ответы (3)


Насколько я понимаю, здесь вы потеряли свою проницательность:

float lon=26.533255;
float lat=27.533463;
data.data[0]=lon;
data.data[1]=lat;

потому что данные представляют собой массив байтов в соответствии с этим:

/**
 * Data buffer
 */
byte data[CC1101_DATA_LEN];

Вам необходимо правильно буферизовать данные.

person HighPredator    schedule 28.10.2014
comment
Хм, а как их правильно буферизовать? Как я уже упоминал, я пробовал, но безуспешно. У тебя есть идеи, которые мне помогут? - person AdiT; 28.10.2014
comment
@AdiT, взгляните на это: stackoverflow.com/questions/24420246/ - person HighPredator; 28.10.2014

float lon = 26,533255; байт * p = (байт *)

для (int i = 0; i ‹sizeof (lon); i ++) {data.data [i] = p [i]; }

сделайте это так, если он работает, продолжайте то же самое с lat или создайте функцию, такую ​​как floattobyte, и используйте.

person Nagaraju Badaeni    schedule 28.10.2014
comment
Хм, к сожалению, не работает, я получил просто случайные числа. - person AdiT; 28.10.2014
comment
Могу я распечатать это так: Serial.println (data.data [i]) - person AdiT; 28.10.2014
comment
это преобразование числа с плавающей точкой в ​​байты .... Вам нужно преобразовать байт в число с плавающей точкой на стороне получателя ..... - person Nagaraju Badaeni; 30.10.2014
comment
float f; memcpy (& f, & data.data, sizeof (f)); Serial.println (f); - person Nagaraju Badaeni; 30.10.2014

HighPredator прав!

Из библиотеки panstamp мы видим, что поле CCPACKET :: data представляет собой массив uint8_t: https://github.com/panStamp/panstamp/wiki/CCPACKET#data

В основном, когда вы пишете:

float lon=26.533255;
float lat=27.533463;
data.data[0]=lon;
data.data[1]=lat;

Компилятор, по сути, делает:

data.data[0]=uint8_t(lon); // So 26.533255f just becomes 26
data.data[1]=uint8_t(lat); // So 27.533463just becomes 27

Вам нужно понимать тип с плавающей запятой, длина которого составляет 4 байта, поэтому вам нужно сделать свой пакет длиной 8 байтов и передавать необработанные байты следующим образом:

data.length = 8;
data.data[0] = ((uint8_t*)(&lon))[0]; // Transfer first byte of the float
data.data[1] = ((uint8_t*)(&lon))[1];
data.data[2] = ((uint8_t*)(&lon))[2];
data.data[3] = ((uint8_t*)(&lon))[3]; // Transfer last byte of the float

data.data[4] = ((uint8_t*)(&lat))[0]; // Transfer first byte of the float
data.data[5] = ((uint8_t*)(&lat))[1];
data.data[6] = ((uint8_t*)(&lat))[2];
data.data[7] = ((uint8_t*)(&lat))[3]; // Transfer last byte of the float

На принимающей стороне вы можете перекомпоновать поплавки следующим образом:

float lon, lat;
((uint8_t*)(&lon))[0] = data.data[0]; // Place first byte
((uint8_t*)(&lon))[1] = data.data[1];
((uint8_t*)(&lon))[2] = data.data[2];
((uint8_t*)(&lon))[3] = data.data[3]; // Place last byte

((uint8_t*)(&lat))[0] = data.data[4]; // Place first byte
((uint8_t*)(&lat))[1] = data.data[5];
((uint8_t*)(&lat))[2] = data.data[6];
((uint8_t*)(&lat))[3] = data.data[7]; // Place last byte

Надеюсь, это поможет.

person Patapom    schedule 29.10.2017