Reconstruct uV from ADS1299 24-bit value broken into 3 bytes in matlab
Hi there,

Firstly, apologies if I'm breaking the forum rules by asking a question about a non openBCI product. I am using an openBCI board in the project I'm working on, but am currently focusing on passive/active sensor designs.
I have bought an EEG acquisition system which uses active sensors. The software which comes with the device is limited and not of much benefit to me.
For the moment I'm just trying to get the native system working before trying the active sensors with the openBCI board.
The device uses the ADS1299 as well, with a microcontroller (unknown brand/model), and transmits the data over bluetooth to a USB dongle at 3,000,000 baud.
The packet is 21 bytes long. The only bytes of interest to me are:
- Byte 1 = Start byte = 255 (unambiguous value, i.e. can't appear as any other data byte)
- Byte 2 = packet counter
- Byte 3 = ADC Channel 1 - MSB
- Byte 4 = ADC Channel 1 - LSB2
- Byte 5 = ADC Channel 1 - LSB1
In other words, it breaks the 24-bit ADC value into 3 bytes and transmits them in the order MSB, LSB2, LSB1.
I'm writing a Matlab script to parse and interpret the data. Parsing the data is fine:
starts = find(rawData == 255);
ADC_Bytes = rawData([starts+2 starts+3 starts+4]);
My issue arises now when trying to reconstruct the ADC value. The support documentation only gives the following information to obtain the ADC value.
"The formula for reconstructing to a 2's complement, signed int32 is:
data = (MSB << 24 + LSB2 << 17 + LSB1 << 10)
The conversion factor for EEG channel to volts is:
EEG = data*(5/3)*(1/2^32) " % I'd imagine this corresponds to (ADC_Value*Vref)/2^32 but there's a programmable gain of 3 setand Vref is 5, so hence the 5/3.
Using this method in Matlab with the following lines:
ADC_Value = (bytes(:,1)*(2^24)) + (bytes(:,2)*(2^17)) + (bytes(:,3)*(2^10));
ADC_Value_Volts = (ADC_Value*(5/3))*(1/(2^32));
The output of ADC_Value is in the range 416712704 to 420345856.
The output of ADC_Value_Volts is in the range 0.1617 to 0.1631 volts. This should be in the microvolts range instead of this which is is 160 millivolts roughly.
Using the given software, I can record and export an EDF file of the data. Importing the EDF file into Matlab, the range of values are bounded by -16384 and 16384. But the actual EEG data range varies around -100 to 500 (microvolts) depending on the REF and GND contact quality. The picture below shows about 2 mins of EEG recording, starting/finishing with me taking on/off the sensors, hence the bouncing between rails of -16384 to 16384.

Can someone please shed any light on the conversion method?
I don't understand the method of left shifting the bytes 24, 17 and 10 respectively?
I have tried left shift of 16, 8, 0 (which to me makes more sense) and scaling by EEG*(5/3)*(1/2^24) instead. The output values are again in the range of 0.1590 to 0.1597.
Or does any one have any matlab code/ideas for reconstructing a 24-bit ADC value as a precision number?
The only information I have been able to obtain from the provider on this is the 2 lines of code shown above.
Again, apologies if this post disregards any rules. I will be able to compile a comparison of various passive/active sensors used with the openBCI once I am finished though which is of benefit to the openBCI community.
Thanks,
Mark
Comments
A couple comments.
You show the packet layout and say the start byte is "(unambiguous value, i.e. can't appear as any other data byte)". This is not true, at least on OpenBCI. The ADC data values especially the low order bytes, can take on any values. So the start byte is helpful, but not a guarantee you are synced.
re: sample Matlab code, another approach see here,
http://openbci.com/forum/index.php?p=/discussion/359/direct-matlab-serial-interface-vs-lsl
re: decoding bytes and microvolts, see last section of,
http://docs.openbci.com/software/02-OpenBCI_Streaming_Data_Format
The shift values you show (24 etc.) don't look right.
Regards,
William