combining 4 bytes into one long int

Hi, recently i tried to interface ADS1299 using Arduino Due. The ADS1299 send only 8 bit data to Arduino make it display in serial monitor only 0 to 255 value. Basically what i tried to do here is i want to take the first 4 8-bit value and combine it into a new one long integer and display it to serial monitor. I tried to make it into array. But still don’t really understand it. I am new to Arduino and I need to complete this project in this mean time.

I found some coding that tried to do similar things as I tried to do. But I can’t fully understand the coding yet. The coding said something related to memcpy and pointer.

char textCopy[] = { '1', '9', '2', '.',
                    '1', '6', '8', ',',
                    '0', '0', '0', '.',
                    '0', '0', '1', '.'};

int octet[4];

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

  textCopy[3] = '\0';
  textCopy[7] = '\0';
  textCopy[11] = '\0';
  textCopy[15] = '\0';
  
  char *ptr = textCopy;
  for(int i=0; i<4; i++)
  {
    Serial.print("ptr points to: [");
    Serial.print(ptr);    Serial.println("]");
    
    octet[i] = atoi(ptr);
    ptr += 4;
  }
  
  for(int i=0; i<4; i++)
  {
    Serial.print("octet[");
    Serial.print(i);    Serial.print("] = ");
    Serial.println(octet[i]);
  }
}

void loop()
{
}

Basically what i tried to do here is i want to take the first 4 8-bit value and combine it into a new one long integer and display it to serial monitor.

Sorry. You are not even in the right city, let alone the right ballpark.

If you are getting 4 bytes from your sensor, you want to use a union containing an unsigned long and a 4 byte array:

union stuff
{
   unsigned long value;
   byte bytes[4];
};

Create an instance of the struct, populate the byte array, and use the long value.

stuff sensorData;
sensorData.bytes[0] = firstValue;
sensorData.bytes[1] = secondValue;
sensorData.bytes[2] = thirdValue;
sensorData.bytes[3] = fourthValue;

The value in sensorData.value is the long created from the 4 bytes.

sorry. can you give me clearer explanation. fyi, i really don't have basic in this kind of thing. sorry again.

first

'1', '6', '8', ',',

should be a . instead of ,

union stuff
{
   unsigned long value;
   byte bytes[4];
};

A union is a variable on a certain memory location that can be accessed in multiple ways. IN the above example of PaulS the union stuff takes 4 bytes and can be accessed through the unsigned long value and through the array bytes[]. If you had

union stuff
{
   unsigned long value;
   byte bytes[4];
   int x;
};

the variable x (which is only 2 bytes) would share (part of) the same memory locations as the array of 4 bytes or the unsigned long of 4 bytes.

By writing the 4 bytes you have to the union through the byte array the fill up the memory of the union. Then you access those 4 bytes as a long . That is approx the working of the union.

Another way to pack 4 bytes in one unsigned long is as follows:

unsigned long value = byte0;
value = value * 256 + byte1;  // effectively shift the first byte 8 bit positions
value = value * 256 + byte2;
value = value * 256 + byte3;

There are several other ways to do this.

Another way of doing it is with an array of bytes and a long pointer…

byte in[4] = {14, 210, 229, 103};
unsigned long *lval = (unsigned long *)in;
Serial.println(*lval); // <-- note the * there to dereference the pointer

Just thought I’d throw that into the mix… So many ways of doing the same thing :wink:

How about this approach?

byte b1 = 7; // representing the high byte from the sensor
byte b2 = 23;
byte b3 = 197;
byte b4 = 12; // representing the low byte from the sensor

long int bignum = 0;
bignum = bignum + b1;
bignum << 8;
bignum = bignum + b2;
bignum << 8;
bignum = bignum + b3;
bignum << 8;
bignum = bignum + b4;

which could become a loop a bit like this

bignum = 0;
for (int x = 0; x < 4; x++ ) {
     bignum = bignum + Serial.read(); // you may need to convert the read to an int
     bignum << 8;
}

…R

Robin2:
which could become a loop a bit like this

bignum = 0;

for (int x = 0; x < 4; x++ ) {
     bignum = bignum + Serial.read(); // you may need to convert the read to an int
     bignum << 8;
}

Except no matter what input you give it, the least significant byte will always be 0

OK, I have one too many shifts - sorry, I didn’t test it. It doesn’t invalidate the concept.

…R

Arrch:

Robin2:
which could become a loop a bit like this

bignum = 0;

for (int x = 0; x < 4; x++ ) {
     bignum = bignum + Serial.read(); // you may need to convert the read to an int
     bignum << 8;
}

Except no matter what input you give it, the least significant byte will always be 0

OK, I have one too many shifts

You have the right number. The order of operations is wrong. Shift first, then add the new value.

I'm having difficulty understand what should be printed from your conversion given - (yes this is slightly different than your posted code)

char textCopy[][4] =
{
      { '1', '9', '2', '.' }    // 0
    , { '1', '6', '8', '.' }    // 1
    , { '0', '0', '0', '.' }    // 2
    , { '0', '0', '1', '.' }    // 3
};

What would be the result using the first 4 entries at index 0.

No answer so perhaps this’ll confuse the issue -

char textCopy[][4] =
{
      { '1', '9', '2', '.' }    // 0
    , { '1', '6', '8', '.' }    // 1
    , { '0', '0', '0', '.' }    // 2
    , { '0', '0', '1', '.' }    // 3
};


// utility function given the address of an array and its length reverses the
// array contents

void memrev(uint8_t* const p, size_t c)
{
    uint8_t*    lhs = p - 1; 
    uint8_t*    rhs = p + c; 
    uint8_t     t;
    while ( ++lhs < --rhs )
    {
        t       = *lhs;
        *lhs    = *rhs;
        *rhs    = t;
    }
}

...

// CODE FRAGMENT 

// Arduino Ateml based processors are little endian, meaning the least
// significant byte of a multi-byte data type is at the lowest address occupied
// by the data type -
//
// copy the first 4 bytes of the array 'textCopy' into the uint32_t value 'v'
// 'memcpy' returns the destination provided it as the address of the array to
// reverse in this case it should be 4 bytes (the size of 'uint32_t') which the
// same length as the value 'v'.

size_t      cb  = sizeof(textCopy[0]);
uint32_t    v;
memrev((uint8_t*)memcpy(&v, &textCopy[0], cb), cb);
Serial.print(v);

Yes.

That’s the problem with “writing code” in a vacuum.

…R

PaulS:

OK, I have one too many shifts

You have the right number. The order of operations is wrong. Shift first, then add the new value.

Can anyone figure out how to get the “Ever Helpful IDE®” to compile this valid code.

I so often find the damn thing throwing road blocks in my path when trying post responses.

#define ENTRIES(ARRAY)      (sizeof(ARRAY) / sizeof(ARRAY[0]))

char textCopy[][4] =
{
      { '1', '9', '2', '.' }    // 0
    , { '1', '6', '8', '.' }    // 1
    , { '0', '0', '0', '.' }    // 2
    , { '0', '0', '1', '.' }    // 3
};

template<typename T>
T endian_swap(T data)
{
    T           value = data;
    uint8_t*    lhs = (uint8_t*)(&value) - 1;
    uint8_t*    rhs = (uint8_t*)(&value) + sizeof(T);
    uint8_t     t;
    while ( ++lhs < --rhs )
    {
        t       = *lhs;
        *lhs    = *rhs;
        *rhs    = t;
    }

    return value;
}

void loop()
{}

void setup()
{
    Serial.begin(9600);
    for ( size_t i = 0; i < ENTRIES(textCopy); i++ )
    {
        Serial.println(endian_swap(*(unsigned long*)&textCopy[i]));
    }
}

Can anyone figure out how to get the "Ever Helpful IDE®" to compile this valid code.

Put the template definition in a header file, where it belongs.

Hello-
Please note that the ads1299 (and ads1294, ads1296, ads1298) measure data as 24-bit SIGNED integers, not 32-bit integers. The solution is to bit-shift the 3 bytes to be the most significant bytes of a 32-bit singed integer (padded 8-bits, so that the signed bit is preserved). You can then bit-shift the 32-bit signed value by 8-bits to get the intended 24-bit value:
long var = (adc[1] << 24) + (adc[2] << 16) + (add[3] << 8);
var = var >> 8;

If you are interested in Arduino code for communicating with the ads129n series, you may find this page interesting:
http://www.mccauslandcenter.sc.edu/CRNL/ads1298
The sample Arduino Sketch simply converts the ads129n SPI signals to a bluetooth or USB serial communication for display using the example Processing or Matlab scripts. However, the Sketch does identify that the ads129n is working correctly and sets up the device, so it would be very easy to have the Arduino do a lot more (the page includes links for other similar projects).