Проблеми з типами даних у C

Я намагаюся в кінцевому підсумку Arduino GPS прорив, де я хочу отримати довготу і Latitude від GPS. Тоді я хочу відправити ці дві змінні бездротовим через RF. як на зображенні нижче: введіть опис зображення тут

Я використовую бібліотеку для RF-модуля з ім'ям panstamp, щоб мати можливість відправляти довготу і Latitude від 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;
}

Будь ласка, допоможіть мені хтось :)

The link to the Panstamp library: PanStamp Library

0
Чому ви не можете отримати подвійний номер? Ви втрачаєте точність, це проблема? Крім того, ви вказали, що код бібліотеки може мати помилку
додано Автор ha9u63ar, джерело
Все, що потрібно (якщо це дозволено роботою), - змінити байтові дані [...] на Подвійні дані [...] або дані float [...] . Таким чином ви зберігаєте інформацію, яку ви передаєте та отримуєте.
додано Автор ha9u63ar, джерело
Можливо, це призначення не працює правильно, data.data [0] = lon; data.data [1] = lat, тут ви перетворюєте float в тип байта
додано Автор Abhishek Chandel, джерело
Можливо, це призначення не працює правильно, data.data [0] = lon; data.data [1] = lat, тут ви перетворюєте float в тип байта
додано Автор Abhishek Chandel, джерело
Це проблема, яку я втрачаю в точності. Але що я можу зробити, щоб отримати подвійні або поплавці? Це моє питання.
додано Автор AdiT, джерело
Ви хочете змінити його в заголовному файлі?
додано Автор AdiT, джерело
Ви хочете змінити його в заголовному файлі?
додано Автор AdiT, джерело
Це проблема, яку я втрачаю в точності. Але що я можу зробити, щоб отримати подвійні або поплавці? Це моє питання.
додано Автор AdiT, джерело

6 Відповіді

Наскільки я це бачу, ви втратили свій припис тут:

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

тому що дані є масивом байтів відповідно до цього:

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

Необхідно правильно буферизувати дані.

1
додано
Хм, але як їх правильно буферизувати? Як я вже згадував, я спробував, але без успіху. Чи є у вас якісь ідеї, які допоможуть мені?
додано Автор AdiT, джерело
@AdiT, погляньте на це: stackoverflow.com/questions/24420246/…
додано Автор HighPredator, джерело

Наскільки я це бачу, ви втратили свій припис тут:

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

тому що дані є масивом байтів відповідно до цього:

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

Необхідно правильно буферизувати дані.

1
додано
Хм, але як їх правильно буферизувати? Як я вже згадував, я спробував, але без успіху. Чи є у вас якісь ідеї, які допоможуть мені?
додано Автор AdiT, джерело
@AdiT, погляньте на це: stackoverflow.com/questions/24420246/…
додано Автор HighPredator, джерело

float lon=26.533255; byte *p = (byte *)&lon;

for (int i = 0; i < sizeof(lon); i++){ data.data[i]= p[i]; }

роблять це, якщо він працює, продовжуйте те ж саме з lat або зробити функцію, як floattobyte і використання.

0
додано
float f; memcpy (& f, & data.data, sizeof (f)); Serial.println (f);
додано Автор Nagaraju Badaeni, джерело
це перетворення float в байти .... Ви повинні обробляти байт плавати на кінці приймача .....
додано Автор Nagaraju Badaeni, джерело
Чи можу я надрукувати його так: Serial.println (data.data [i])
додано Автор AdiT, джерело
Хм, на жаль, не працює, я отримав тільки випадкові числа.
додано Автор AdiT, джерело

float lon=26.533255; byte *p = (byte *)&lon;

for (int i = 0; i < sizeof(lon); i++){ data.data[i]= p[i]; }

роблять це, якщо він працює, продовжуйте те ж саме з lat або зробити функцію, як floattobyte і використання.

0
додано
float f; memcpy (& f, & data.data, sizeof (f)); Serial.println (f);
додано Автор Nagaraju Badaeni, джерело
це перетворення float в байти .... Ви повинні обробляти байт плавати на кінці приймача .....
додано Автор Nagaraju Badaeni, джерело
Чи можу я надрукувати його так: Serial.println (data.data [i])
додано Автор AdiT, джерело
Хм, на жаль, не працює, я отримав тільки випадкові числа.
додано Автор AdiT, джерело

HighPredator має рацію!

From the panstamp lib we see that the CCPACKET::data field is a uint8_t array: 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

Вам потрібно зрозуміти тип float, який має довжину 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

Сподіваюся, що це допоможе.

0
додано

HighPredator має рацію!

From the panstamp lib we see that the CCPACKET::data field is a uint8_t array: 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

Вам потрібно зрозуміти тип float, який має довжину 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

Сподіваюся, що це допоможе.

0
додано
IT KPI C/С++ новым годом
IT KPI C/С++ новым годом
747 учасників

Чат обсуждения С/С++. - Вопросы "напишите за меня лабу" - это оффтоп. - Оффтоп, флуд, оскорбления и вбросы здесь не приняты. - За нарушение - предупреждение или mute на неделю. - За спам и рекламу - ban. Все чаты IT KPI: https://t.me/itkpi/1147