Serial.available serial communication problem on Arduino Uno

조회 수: 9 (최근 30일)
승민 임
승민 임 2022년 3월 24일
There is no problem in communication between MATLAB on the 1st Uno, but it does not satisfy the if(Serial.available()) statement, which is coding in the 2nd Uno in MATLAB.
We also checked the pin numbers and port numbers for all parts. If you have any guesses, please reply. use environment (Arduino IDE 2.0.0 & Uno) (Matlab 2012b)
//arduino_1st code//
#include <Servo.h> // servo motor header
Servo firstServo; // servo motor at the entrance of machine
int trigPin = 12; // trigger pin of ultrasonic sensor
int echoPin = 7; // echo pin of ultrasonic sensor
int CDS = A0; // light sensor pin
int motorPin = 9; // motor pin
int pos = 90; // servo motor initial pos
int light = 0; // ligth value
int go = 0; // Matlab send parameter
int BAUD_RATE = 9600;
void setup() {
// put your setup code here, to run once:
Serial.begin(BAUD_RATE);
pinMode(trigPin,OUTPUT); // set trig pin into OUTPUT mode
pinMode(echoPin,INPUT); // set echo pin into INPUT mode
pinMode(CDS,INPUT); // set light sensor pin into INPUT mode
firstServo.attach(motorPin); // attach motor pin
}
void loop() {
// put your main code here, to run repeatedly:
unsigned int duration; // measured time from ultrasonic pin
int distance; // calculated distance from duration
digitalWrite(trigPin,LOW); // to initialize ultrasonic sensor
delayMicroseconds(2);
digitalWrite(trigPin,HIGH); // generate trigger wave
delayMicroseconds(5);
digitalWrite(trigPin,LOW);
duration = pulseIn(echoPin,HIGH); // measure time while echoPin receives HIGH signal
distance=(duration/2)/29.1; // convert time unit into distance unit
delay(200);
// separate metal
if(distance <= 30 && distance >= 1) { // when the garbage enters the entrance
light = analogRead(CDS); // read light from metal detector
if(light <= 100) { // when metal detector works
for(pos = 90; pos < 180; pos++) {
firstServo.write(pos); // move 1st servo motor to left
delay(10);
}
delay(1000); // wait the garbage falling
pos = 90; // set the servo motor to initial pos
firstServo.write(pos);
}
// if metal detector does not work
else {
firstServo.write(pos);
Serial.println(go); // send paramter to Matlab
for(pos = 90; pos > 0; pos--) {
firstServo.write(pos); // move 1st servo motor to right
delay(10);
}
delay(1000); // wait the garbage falling
pos = 90; // set the servo motor to initial pos
firstServo.write(pos);
}
}
}
//arduino_2nd code//
#include <Servo.h> // servo motor header
Servo secondServo;
int motorPin = 10; // motor pin
int pos = 90; // servo motor at the entrance of machine
const int BAUD_RATE = 9600;
void setup() {
// put your setup code here, to run once:
Serial.begin(BAUD_RATE);
secondServo.attach(motorPin); // attach motor pin
}
void loop() {
// put your main code here, to run repeatedly:
if(Serial.available()) { // read parameter from Matlab
// for(pos=90; pos > 0; pos--) {
// secondServo.write(pos); // 시리얼 통신 확인 서보모터 돌리기
// delay(10);
// }
char ch = Serial.read(); // assign to variable ch
// if the garbage is estimated as plastic
if(ch == '1') {
for(pos=90; pos > 0; pos--) {
secondServo.write(pos); // move 1st servo motor to left
delay(10);
}
delay(1000); // wait the garbage falling
pos = 90; // set the servo motor to initial pos
secondServo.write(pos);
}
// if the garbage is estimated as glass
else if(ch == '2') {
for(pos = 90; pos < 180; pos++) {
secondServo.write(pos); // move 1st servo motor to left
delay(10);
}
delay(1000); // wait the garbage falling
pos = 90; // set the servo motor to initial pos
secondServo.write(pos);
}
}
}
//matlab code//
%% Description
% this code was run in Matlab 2012 ver.
%% Initialize
clc;
clear all;
%% Parameters
A = 2; % check value from arduino
waveFile = 'test.wav'; % sound file
fs = 44100; % sampling rate
duration = 2; % recording time
nbits = 16; % using 16 bits
ard_1st = 'COM3';
ard_2nd = 'COM4';
ard_baud_rate = 9600;
%%
arduino = serial(ard_1st, 'BaudRate', ard_baud_rate);
fopen(arduino);
A = fscanf(arduino, '%s'); % read from 1st arduino
fclose(arduino);
if (A == '0') % run when arduino sends 0
fprintf('Recording...\n');
y = wavrecord(duration*fs, fs); % recording
fprintf('Finished recording.\n');
% fprintf('Press any key to save the sound data to %s...\n', waveFile); % pause and save manually
wavwrite(y, fs, nbits, waveFile); % save into wavefile in sampling rate fs, nbits
fprintf('Finished writing %s\n', waveFile);
[file, Fs] = wavread('test.wav'); % read wav (amplitude and sampling rate)
B = size(file(:,1));
N = B(1);
f = -1 * (Fs/2) + (Fs/N):(Fs/N):(Fs/2); % range of frequency
f_p = 0:(Fs/N):(Fs/2-Fs/N); % 1/2 of frequeny
t = 0:1:B-1; % time range
f_file = fft(file); % do fft
f_file = abs(f_file);
f_file_shift = fftshift(f_file); % domain shift
f_file_shift_p = zeros((N-1)/2,1);
for i = 1:1:(N/2)
f_file_shift_p(i,1) = f_file(i,1);
end % delete f below 0
subplot(2,1,1)
plot(t,file)
subplot(2,1,2)
plot(f_p,f_file_shift_p)
xlim([0 1500])
ylim([0 3000])
a = 2;
for j = 100:1:240 % in 100 ~ 240Hz
if (f_file_shift_p((N/Fs)*j,1) >= 1500) % check if the amplitude over 1500
a = 1; % estimate the garbage as plastic
break;
end
end
for j = 500:1:1200 % in 500~1200Hz
if (f_file_shift_p((N/Fs)*(j),1) >= 1000) % check if the amplitude over 1500
a = 1; % estimate the garbage as plastic
break;
end
end
arduino2 = serial(ard_2nd, 'BaudRate', ard_baud_rate);
fopen(arduino2);
for k=1:1:400000000 % wait few seconds
end
fprintf(arduino2,'%s\n',a); % send to 2nd arduino
fclose(arduino2);
end

답변 (2개)

Shreshth
Shreshth 2024년 2월 8일
Hello 승민 ,
We know that the problem is occurring when the 2nd Arduino is getting a command if(Serial.availible()) which to code it to MATLAB.
There are a couple of issues that I can see which might be causing the execution problem.
1.In the MATLAB code, the variable a is an integer, but it's being sent over serial without conversion to a character. This means that the integer 2 is being sent as the string '2' and not as the character with ASCII code 2. This could be causing a mismatch in the Arduino code when it checks for '1' or '2'. To fix this, you should explicitly convert the integer to a character in MATLAB before sending it.
Code snippet:
fprintf(arduino2, '%c\n', char(a + '0'));
2.The second Arduino reads a single character from the serial buffer:
char ch = Serial.read();
However, if there are any extra characters (like a newline or carriage return) sent from MATLAB, these could be read instead of the expected '1' or '2'. To ensure that you're reading the correct character, you might want to read all available characters and look for the expected ones.
while(Serial.available() > 0) {
char ch = Serial.read();
if(ch == '1' || ch == '2') {
// Process the character
break;
}
}
These are specific code-level observations that could be causing the issue. Ensure that the logic in both the Arduino and MATLAB codes aligns with the intended behaviour, and consider the points above to debug the serial communication problem.
You can also refer to the below MathWorks forum link to understand how we can operate 2 Arduino Uno using MATLAB or Simulink.
Hope it helps,
Regards,
Shubham Shreshth

MathWorks MATLAB Hardware Team
MathWorks MATLAB Hardware Team 2024년 2월 16일
Hi,
We suggest leveraging the MATLAB Support Package for Arduino hardware, as it simplifies the process of controlling two Arduino boards and Servo motors with minimal coding required.
Please feel free to contact us if you need any assistance,
Thanks
MATLAB Hardware Team
MathWorks

카테고리

Help CenterFile Exchange에서 Arduino Hardware에 대해 자세히 알아보기

제품

Community Treasure Hunt

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

Start Hunting!

Translated by