フィルターのクリア

Reading Bytes from Arduino to MATLAB

14 ビュー (過去 30 日間)
Nicholas Ross
Nicholas Ross 2024 年 8 月 29 日
編集済み: dpb 2024 年 9 月 5 日
I've been trying to read data from ESP32S-Dev module to MATLAB sending over the data in bytes to make the transmission quicker. As seen below, I convert float data into bytes and then write the data. MATLAB sees the data and then creates a 1x8 array for each float value instead of just 1 value for each float. I've tried other methods, shown in 2nd part of MATLAB code, and it creates 1 value for each float but their wildly off (7-34 orders of magnitude)
I've tried different baud rates and even asked for help from the almighty ChatGPT but have not been able to crack the code. Any thoughts.
Arduino IDE code:
#include <SPI.h>
const int CS_SiPM_pot = 34;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200); //Starting
delay(1000);
SPI.begin();
pinMode(CS_SiPM_pot, OUTPUT);
}
void loop() {
for (int d_pot2 = 55; d_pot2 <= 55; d_pot2 = d_pot2 + 1) //57
{
digitalWrite(CS_SiPM_pot, LOW); //LOW
delay(10); //10
SPI.transfer(d_pot2);
digitalWrite(CS_SiPM_pot, HIGH);
// put your main code here, to run repeatedly:
float newTmp[4] = { 01.00, 02.00, 03.00, 04.00 };
for (int i = 0; i < 4; i++) {
byte *byteData = (byte *)&newTmp[i];
Serial.write(byteData, sizeof(float)); // Send each float as 4 bytes
delay(10);
}
}
}
MATLAB code:
esp = serialport('COM5',152000);
%%
flush(esp)
% Read 16 bytes of data (4 floats * 4 bytes per float)
numBytes = 16;
data = read(esp, numBytes, 'uint8');
% Convert each 4-byte sequence to a float
float1 = typecast(data(1:4)), 'single');
float2 = typecast(data(5:8), 'single');
float3 = typecast(data(9:12), 'single');
float4 = typecast(data(13:16), 'single');
disp([float1, float2, float3, float4]);
% Convert the bytes back to float values
floatValues = typecast(uint8(data), 'single');
% Display the result
disp('Float values:');
disp(floatValues);
disp('Raw bytes received:');
disp(data); % Print the raw bytes
Results from MATLAB:
Float1: 0 0 0 0 0 0 0 0
Float2: 0 3.7480 0 0 0 0 0 0
Float3: 0 2.1250 0 3.7480 0 0 0 0
Float4: 0 0 0 0 0 3.7480 0 0
data: 0 0 0 0 255 0 0 0 3 255 0 0 0 0 255 0
  2 件のコメント
Walter Roberson
Walter Roberson 2024 年 8 月 30 日
float1 = typecast(data(1:4)), 'single');
You have an extra ) in there.
Nicholas Ross
Nicholas Ross 2024 年 8 月 30 日
@Walter Roberson thanks for the heads up!

サインインしてコメントする。

採用された回答

Walter Roberson
Walter Roberson 2024 年 8 月 30 日
data = read(device,count,datatype) reads the number of values specified by count in the form specified by datatype from the serial port connection device. For all numeric datatype types, data is a row vector of double values.
You still need the 'uint8' to specify how to read the data, but you should be using
data = uint8(read(esp, numBytes, 'uint8'));
  1 件のコメント
Nicholas Ross
Nicholas Ross 2024 年 9 月 4 日
Thank you for the code edit. This worked to fix my issue. I also had to make a minor change in my Arduino code (commenting out the Serial.println statement) and now everything reads as @dpb showed in their answer. Thank you both for your contributions to this post

サインインしてコメントする。

その他の回答 (1 件)

dpb
dpb 2024 年 8 月 29 日
編集済み: dpb 2024 年 8 月 30 日
I dunno how to fix the Arduino side, but the data bytes you're returning aren't the right values for the single float values 1 thru 4.
x=single(1:4).';
format hex
disp(x)
3f800000 40000000 40400000 40800000
bytes=reshape(typecast(x,'uint8'),4,[]).'
bytes = 4x4
00 00 80 3f 00 00 00 40 00 00 40 40 00 00 80 40
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
format short
bytes
bytes = 4x4
0 0 128 63 0 0 0 64 0 0 64 64 0 0 128 64
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
arrayfun(@(i)typecast(bytes(i,:),'single'),[1:height(bytes)].')
ans = 4x1
1 2 3 4
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
The data array you received back should have been
data=reshape(bytes.',1,[])
data = 1x16
0 0 128 63 0 0 0 64 0 0 64 64 0 0 128 64
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
  3 件のコメント
dpb
dpb 2024 年 9 月 4 日
編集済み: dpb 2024 年 9 月 5 日
My code isn't really the solution as you've discovered; all I was doing was showing what the internal representation of the four floating point values you were sending/reading are so that you could see/know when you did finally receive the correct bytes -- I wasn't positive whether the issue was on the Arduino side or the MATLAB receiving side; Walter's catch of needing to cast each byte as a uint8 was obviously the real key,
I figured if you saw what the data bytes really should be, it would help you isolate and fix the issue, but also to illustrate that the byte strings you were trying to convert to floating point should not have been the values you were expecting.
I was also thinking (incorrectly, obviously) the default double should still hold the value of the byte; that was the tacit assumption that while read returned everything as a double, it would have had enough smarts internally to return the value of the type it read converted to the double without requiring the specific typecast. But, I've never used MATLAB for such data collection tasks; always had other dedicated hardware for that in my prior life; then simply offloaded the converted data to MATLAB for processing...
Nicholas Ross
Nicholas Ross 2024 年 9 月 5 日
I really appreciate the follow up and the explanation. I've never used MATLAB for this type of data collection either so this is all new to me. I'm also a beginner with Arduino. Add the two newb statuses together and you got one heck of an amateur here!

サインインしてコメントする。

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by