Search code examples
arduinointegerbytelora

Arduino SAMD Integer to Byte conversion for LoRa


i am writing a piece of code for the MKRWAN LoRa arduino board. Using the MKRWAN library, which is not very well documented.

The goal of this code is to accept some integers, and return the bytes so they can be stored in an array of bytes which i should be able to send over the LoRa network.

on the arduino documentation it describes that arduinos with the SAMD chip store the integers in 4 bytes.

On the Arduino Uno (and other ATmega based boards) an int stores a 16-bit (2-byte) value. This yields a range of -32,768 to 32,767 (minimum value of -2^15 and a maximum value of (2^15) - 1). On the Arduino Due and SAMD based boards (like MKR1000 and Zero), an int stores a 32-bit (4-byte) value. This yields a range of -2,147,483,648 to 2,147,483,647 (minimum value of -2^31 and a maximum value of (2^31) - 1).

Source: https://www.arduino.cc/reference/en/language/variables/data-types/int/

The MKRWAN 1310 board uses a SAMD21 chip.

The MKR WAN 1310, brings in a series of improvements when compared to its predecessor, the MKR WAN 1300. While still based on the Microchip® SAMD21 low power processor, the Murata CMWX1ZZABZ LoRa® module, and the MKR family’s characteristic crypto chip (the ECC508), the MKR WAN 1310 includes a new battery charger, a 2MByte SPI Flash, and improved control of the board’s power consumption.

Source: https://store.arduino.cc/mkr-wan-1310

however when i run my code it spits out some integers as 4 bytes and some as less.

-9001 in BINARY = 11010111 11011100 11111111 11111111 
newInt = -9001
13 in BINARY = 1101 0 0 0 
newInt = 13
-1 in BINARY = 11111111 11111111 11111111 11111111 
newInt = -1
250 in BINARY = 11111010 0 0 0 
newInt = 250
-1950 in BINARY = 1100010 11111000 11111111 11111111 
newInt = -1950
13450 in BINARY = 10001010 110100 0 0 
newInt = 13450

i am using an union to convert from the integers to bytes.

Does the SAMD boards store the integers dynamically? Is my code wrong?

#define ArraySize 4

byte ATA[ArraySize];                      // Air temperature array
byte AHA[ArraySize];                      // Air humidity array
byte GT1A[ArraySize];                     // Ground temperature sensor 1 array
byte GT2A[ArraySize];                     // Ground temperature sensor 2 array
byte GT3A[ArraySize];                     // Ground temperature sensor 3 array
byte GHA[ArraySize];                      // Ground humidty sensor array
byte master[24];                          // message array

union unionForm {                         // werkt naar behoren
  byte myBytes[ArraySize];
  int myInt;
} myUnion;

void setup() {
  // put your setup code here, to run once:
  int int1 = -9001;
  int int2 = 13;
  int int3 = -1;
  int int4 = float_to_int(2.5);
  int int5 = float_to_int(-19.5);
  int int6 = float_to_int(134.5);

  
  
  Serial.begin(115200);
  while(!Serial);

  int_to_bytes(int1, ATA);
  int_to_bytes(int2, AHA);
  int_to_bytes(int3, GT1A);
  int_to_bytes(int4, GT2A);
  int_to_bytes(int5, GT3A);
  int_to_bytes(int6, GHA);

  Combine_Arrays();
  for (int i = 0; i < 24; i++){
    Serial.print(master[i], BIN);
    Serial.print(" ");
  }
  
  Serial.println();
}

void loop(){
  
}

int float_to_int(float floatyboi){
  Serial.print("Float:\t");
  Serial.println(floatyboi);
  int newInt = floatyboi * 100;                     // convert 2 decimal float to int by multiplying by 100 and saving as int
  Serial.print("New Int:\t");
  Serial.println(newInt);
  
  return newInt;
}

void int_to_bytes(int ConvertInt, byte (& MyArray)[ArraySize]){
  myUnion.myInt = ConvertInt;                         // Save int into union
  Serial.print(ConvertInt);
  Serial.print(" in BINARY = ");
  for (int i = 0; i < sizeof(int); i++) {
    Serial.print(myUnion.myBytes[i], BIN);
    Serial.print(" ");

    MyArray[i] = myUnion.myBytes[i];                  // save bits out of union in corresponding array
  }
  Serial.println();
  
  int newInt = myUnion.myInt;
  Serial.print("newInt = ");
  Serial.println(newInt);
}

void Combine_Arrays(){
  Serial.println("Combining Arrays");
  master[0] = ATA[0];
  master[1] = ATA[1];
  master[2] = ATA[2];
  master[3] = ATA[3];
  master[4] = AHA[0];
  master[5] = AHA[1];
  master[6] = AHA[2];
  master[7] = AHA[3];
  master[8] = GT1A[0];
  master[9] = GT1A[1];
  master[10] = GT1A[2];
  master[11] = GT1A[3];
  master[12] = GT2A[0];
  master[13] = GT2A[1];
  master[14] = GT2A[2];
  master[15] = GT2A[3];
  master[16] = GT3A[0];
  master[17] = GT3A[1];
  master[18] = GT3A[2];
  master[19] = GT3A[3];
  master[20] = GHA[0];
  master[21] = GHA[1];
  master[22] = GHA[2];
  master[23] = GHA[3];
}

Kind regards for the help


Solution

  • Using an union in that way is not the best way. It opens you up to undefined behaviour. It is a form of type punning.

    It would be better to bitshift the values out and into the 32 bit words

    byte values[4] = {0xff, 0xff, 0xff, 0xff};
    int output = values[3] << 24 | values[2] << 16 | values[1] << 8 | values[0];
    
    values[0] = output;
    values[1] = output >> 8;
    values[2] = output >> 8;
    values[3] = output >> 8;
    

    You should also look at the signedness of your values as they can cause problems.