How can I read multiple sensors through the serial?
19 vues (au cours des 30 derniers jours)
Afficher commentaires plus anciens
Hello there, I want to read 4 sensor values into arrays and do DSP on them in MATLAB. I've already read the related issues in this platform.
- https://www.mathworks.com/matlabcentral/answers/121378-how-to-read-multiple-sensors-through-the-serial
- https://www.mathworks.com/matlabcentral/answers/197121-how-to-read-multiple-sensors-through-the-serial
- https://www.mathworks.com/matlabcentral/answers/141392-serial-communication-with-arduino-error-index-exceeds-matrix-dimensions?s_tid=answers_rc1-1_p1_BOTH
I suppose my arduino code runs perfectly, but MATLAB throws an error saying "Index in position 2 exceeds array bounds (must not exceed 1)." at the second sensor reading line. Could you please help ? Thx ;)
% MATLAB code is as follows
clear all
clc
delete(instrfind)
arduino=serial('COM9');
set(arduino,'BaudRate',38400);
fopen(arduino);
%Handshake
fprintf(arduino,'R'); % Send Read Request to Arduino
x=linspace(1,500); % 500 samples are recorded
y = {}; % all data is thrown in y.
for i=1:length(x)
data =fscanf(arduino,'%d'); % '%d' get ints
y = char(data); % The incoming data is converted to characters
y = regexp(y, '\s*', 'split'); % The data is split up into spaces and in columns.
% Data format: data1-tab-data2-tab-data3-tab-data4
reading1(i,1)= y(1,1); % reads in column 1
reading2(i,1)= y(1,3); % reads in column 2
reading3(i,1)= y(1,5); % reads in column 3
reading4(i,1)= y(1,7); % reads in column 4
end
% Done reading !
fclose(arduino);
delete(instrfind);
reading1plot = str2double(reading1); % Converts data that is on cell array to double data
figure(1)
plot(reading1plot);
title('sensor 1'); xlabel('Sample Index'); ylabel('Analog Reading1');
reading2plot = str2double(reading2); % Converts data that is on cell array to double data
figure(2)
plot(reading2plot);
title('sensor 2'); xlabel('Sample Index'); ylabel('Analog Reading2');
reading3plot = str2double(reading3); % Converts data that is on cell array to double data
figure(3)
plot(reading3plot);
title('sensor 3'); xlabel('Sample Index'); ylabel('Analog Reading3');
reading4plot = str2double(reading4); % Converts data that is on cell array to double data
figure(4)
plot(reading4plot);
title('sensor 4'); xlabel('Sample Index'); ylabel('Analog Reading4');
end
Arduino Code:
int flag= 0;
int ctr = 0;
int ReadReq=0;
int reading1;
int reading2;
int reading3;
int reading4;
void setup() {
Serial.begin(38400);
cli();//stop interrupts
// Sampling rate is 1000 Hz.
//set timer1 interrupt at 1000 Hz
TCCR1A = 0;// set entire TCCR1A register to 0
TCCR1B = 0;// same for TCCR1B
TCNT1 = 0;//initialize counter value to 0
// set timer count for 100Hz increments
OCR1A = 1999;// = (16*10^6) / (1000*8) - 1
//had to use 16 bit timer1 for this bc 1999>255, but could switch to timers 0 or 2 with larger prescaler
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS11 bit for 8 prescaler
TCCR1B |= (1 << CS11);
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
sei();//allow interrupts
}
void loop(){
if(Serial.available()>0) { // Check if any data has been sent by the PC
ReadReq = Serial.read();
if((ReadReq=='R')&&(flag == 0)){
ctr = 0;
flag= 1;
}
}
}
ISR(TIMER1_COMPA_vect) { // FREQ 1000 Hz.
if(flag == 1)
{ // takes 500 samples and send it to the MATLAB
reading1 = analogRead(A0);
reading2 = analogRead(A1);
reading3 = analogRead(A2);
reading4 = analogRead(A3);
Serial.print(reading1);
Serial.print("\t");
Serial.print(reading2);
Serial.print("\t");
Serial.print(reading3);
Serial.print("\t");
Serial.print(reading4);
Serial.print("\n");
ctr = ctr + 1;
if(ctr == 499)
{
flag = 0;
}
}
};
2 commentaires
Réponse acceptée
Walter Roberson
le 14 Mai 2018
You have
data =fscanf(arduino,'%d'); % '%d' get ints
so data will be a vector of numbers, text representation of decimal having been converted to numeric form
y = char(data); % The incoming data is converted to characters
This implicitly looks up the character codes associated with each numeric value, such as 97 being associated with 'a' . For example '97' received in text form from the arduino would have been converted to 97.0 decimal by the fscanf(), and char(97.0) would be 'a'
y = regexp(y, '\s*', 'split'); % The data is split up into spaces and in columns.
This splits at any number of whitespace, including none. This will happen to work the same as if you had specified '\s+' . But remember for char(data) to match whitespace, the data would have had to be numeric 9 (tab), 10 (newline), 12 (formfeed), 13 (carriage return), 32 (space), and possibly some others. As in if the arduino had sent '49 50 9 51 52 53 9 54' which got parsed to [49 50 9 51 52 53 9 54] and then char() of that became '12\t345\t6' and then regexp split would make it {'12' '345' '6'}
7 commentaires
Walter Roberson
le 14 Mai 2018
I suggest you try with something like Tera Term to see what is being sent on the line.
I also recommend configuring the line terminator specifically instead of trying to remember what the default is; and I recommend setting BytesAvailableFcnMode to 'terminator' for the same reason. Also on the MATLAB side you could try using
temp = fgets(arduino);
If you do not get anything then you know the problem is reading from the device rather than problems with incorrect format to scan the data.
Plus de réponses (0)
Voir également
Catégories
En savoir plus sur MATLAB Support Package for Arduino Hardware dans Help Center et File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!