Converting int to exactly 16-bit data?

Hi, I need to send data over Serial communication to Arduino MKR Zero board which will send this data over SPI to an SPI controlled potentiometer. The data size is 16 bits or 2 bytes. I can only send the data from my PC over the Serial communication as integers (due to the limitation of using markers in my serial communication) so the value will range from 0 to 65,535 (i.e. from 1 to 5 characters with each character representing one digit). How can I convert this data to a 16-bit value so that I can it send to my potentiometer using SPI.transfer16() function?

My current solution:

int receivedData = atoi(charData); // to convert to integer, charData is a char array containing the received digits from PC
unsigned int val = (unsigned int)receivedData;
/* or */
uint16_t val = receivedData;

I am not sure which one would give me exact 16 bits as documentations for uint16_t is not present in Arduino Reference and unsigned int can be both 16-bit (Uno and ATMEGA) and 32-bit (Due) while MKR Zero is SAMD based.

Is there a better/simpler way to convert an integer into exactly 16-bit value?

uint16_t is not present in Arduino Reference

It is an Arduino reference, not a C/C++ reference

Try this on Arduino boards of different types

int x = 123;
uint16_t y = 123;
void setup()
{
  Serial.begin(115200);
  while (!Serial);
  Serial.println(sizeof(x));
  Serial.println(sizeof(y));
}

void loop()
{
}

On a AVR the output is 2 in both cases but on an ESP32 the output is 4 and 2

a uint16_t variable is, by definition, 16 bit variable

With your board, unsigned int will still be 32 bits

You can use "uint16_t", or "unsigned short"

But, I don't think there will be a problem if you use SPI.transfer16() directly with your int, it will just take the first 16 bits and discard the rest

Thanks @UKHeliBob

@guix.

guix:
But, I don't think there will be a problem if you use SPI.transfer16() directly with your int, it will just take the first 16 bits and discard the rest

If I convert anything in between 0 to 65535 to a 32-bit int, then the first 16 bits will be zero. So if I am sending the 32-bit int directly using SPI.transfer16() function then won't it send all zeros?

chaitanya_:
then the first 16 bits will be zero

No, the last 16 bits :slight_smile:

Use atol:

  uint16_t val = atol("65535");
  Serial.print("Value: ");
  Serial.println(val);

In Arduino UNO, the following sketch provides exactly 16-bit natural binary for the decimal charcaters received from the InputBox of Serial Monitor. (65535 ----> FFFF; 65000 ----> FDE8)

char myData[15];

void setup() 
{
  Serial.begin(9600);
}

void loop() 
{
  byte y = Serial.available();
  if(y !=0)
  {
    byte m = Serial.readBytesUntil('\n', myData, 10);
    myData[m] = '\0';
    unsigned int x = atoi(myData);
    Serial.println(x, HEX);
    memset(myData, 0, 10);
  }
}

SM1234.png

SM1234.png

guix:
No, the last 16 bits :slight_smile:

Better to say "least significant 16 bits", as there's no notion of ordering other than by
significance of each bit.

When, in C/C++, integer types are widened or narrowed the least significant bits stay
as they are and silent truncation may happen. Widening of signed integers will sign-extend,
widening of unsigned integers will zero-extend.

I prefer to use the notation: b15-b0 to mean lower half of 32-bit number.

Good for you.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.