I am attempting to communicate from my Simblee Rfduino to Matlab, with the following Arduino code:
char testing[] = {1,2,3,4,5,6,7,8,'\0'};
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(6,OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
digitalWrite(6,LOW);
Serial.flush();
testing(EMG);
Serial.flush();
digitalWrite(6,HIGH);
}
In Python I am able to correctly read in the 1-8 in the correct order consistently.
However in Matlab it continuously changes order with no consistency, with the following code:
function serial()
global ser
ser = serial('COM5', 'BaudRate', 9600, 'FlowControl', 'hardware');
fopen(ser);
end
function serial_callback(~, ~)
global ser
time = tic;
fread(ser,1) % pull in data from serial port
toc(time);
end
I think there could be some issue in the Serial buffer.
Could you please provide some guidance as to how to consistently get Matlab to read in the data in order? Have others been able to get Matlab to reliably read from a serial port?
Thank you!
You could set the FlowControl to software (xOn and xOff flags). Hardware is only possible if you have the "hardware ressources".
The input buffer of matlab usually works with fifo principle.
After fopen() you have to wait for one second. Because some microcontrollers (like arduino uno ...) restarts after initialization of the uart interface.
--> pause(1);
Related
I have a very simple code in MATLAB for a laser device which I need to use.
Here's the code:
% creating a serial port object
s = serial('COM3');
% opening the port
fopen(s);
% enabling the port
fprintf(s, 'e');
% sending the power to the laser
fprintf(s, 'a738.8889');
% disabling the port
fprintf(s, 'd');
fprintf(s, 'z');
fclose(s);
delete(s);
The code works perfectly fine when I write them one by one from the command window, but it's not working when I put the whole code in either a script file or a function file.
I don't get any errors or any other messages from MATLAB when I run the script or the function. Any ideas why?
Thank you.
So I tried delaying the commands and the script works now. Apparently when the commands are being executed in the script, it is too fast for the device to read them all and that is why it wasn't working.
I have used a load cell. Arduino is sending the load perfectly. When the load sensed by arduino crossess some value I want to send a simple signal to matlab. Then a MATLAB should capture the image. If someone has already worked on it please share how you have done it!.
You could use the MATLAB Support Package for Arduino or plain old serial communication. The former is pretty straightforward; see the documentation. Below is a simple example of how the latter would work.
Arduino:
void setup() {
Serial.begin(9600);
}
void loop() {
int load = getLoad();
if (Serial.available()) {
Serial.println(load);
}
}
MATLAB:
% Connect to Arduino
s = serial('COM1', 'Baudrate', 9600, 'Parity', 'none', 'Databits', 8, 'Stopbits', 1);
fopen(s);
set(s, 'Timeout', 2000, 'Flowcontrol', 'none');
s.ReadAsyncMode = 'continuous';
% Read data from Arduino
load = fscanf(s, '%d');
% Close connection when done
fclose(s);
Check out the following resources for more details:
"Arduino Serial Data Acquisition" by Ye Cheng on MATLAB Central File Exchange
"Arduino and Matlab: let them talk using serial communication!" by gianluca88 on Instructables
"How To Send Data From The Arduino To MATLAB" by Miguel on AllAboutEE
"How can I communicate from Arduino to MATLAB" by Bill Nace on Arduino Stack Exchange
"Getting Started with Serial I/O" in the MATLAB Documentation
"Write and Read Data" in the MATLAB Documentation
matlabarduino.org
I am trying to send data from MATLAB to ARDUINO using the following code for arduino and the second one for the matlab. Both code work fine and when i press 1 led lights up and when press 2 led become off. But actually what i am trying to do is when matlab run code it automatically send 1 to arduino and the led become on. i have tried may changes but cant able to do. when iam trying to run the third code (given below) the arduino status led blink that show it receive some thing but my actual led which is connected to pin 13 still off.
int ledPin=13;
int matlabData;
void setup()
{
pinMode(ledPin,OUTPUT);
Serial.begin(9600);
}
void loop()
{
if(Serial.available()>0) // if there is data to read
{
matlabData=Serial.read(); // read data
if(matlabData==1)
digitalWrite(ledPin,HIGH); // turn light on
else if(matlabData==2)
digitalWrite(ledPin,LOW); // turn light off
}
}
(MATLAB)
1.
clear all
2.clc
3.
4.answer=1; % this is where we'll store the user's answer
5.arduino=serial('COM4','BaudRate',9600); % create serial communication object on port COM4
6.
7.fopen(arduino); % initiate arduino communication
8.
9.while answer
10. fprintf(arduino,'%s',char(answer)); % send answer variable content to arduino
11. answer=input('Enter led value 1 or 2 (1=ON, 2=OFF, 0=EXIT PROGRAM): '); % ask user to enter value for variable answer
12.end
13.
14.fclose(arduino); % end communication with arduino
(MY edit code)
1.
clear all
2.clc
3.
4.answer=1; % this is where we'll store the user's answer
5.arduino=serial('COM4','BaudRate',9600); % create serial communication object on port COM4
6.
7.fopen(arduino); % initiate arduino communication
8.
9.%while answer
10. fprintf(arduino,'%s',char(answer)); % send answer variable content to arduino
11. answer='1'%('Enter led value 1 or 2 (1=ON, 2=OFF, 0=EXIT PROGRAM): '); % ask user to enter value for variable answer
12.%end
13.
14.fclose(arduino); % end communication with arduino
The difference is the following:
answer = input('bla')
yields an answer that is a number, i.e. answer is of type double. In your third case, you wrote answer='1' which is a char, so in fact, the variable answer is different in both cases. Try and change the code in the third part to this here:
answer = 1;
or change the fprintf command to
fprintf(arduino, '%s', str2num(answer));
I understand there is a way to compile and upload MATLAB Simulink code to an Arduino so you don't have to have the Arduino connected to your computer. Is there a way to compile and upload a MATLAB script file of code that I have written myself to the Arduino so it can work independently from being plugged in. i.e. could I upload something like:
a = arduino('COM3')
a.pinMode(13,'output');
i = 0
while i>0
a.digitalWrite(13,1)
pause(1)
a.digitalWrite(13,0)
pause(1)
end
how would I do this and does it still require code lines like:
a = arduino
and putting the a. in front of the lines of code
I'd like to simultaneously get data from a camera (i.e. an image) and an analog voltage using matlab. For the camera I use the imaq toolbox, for reading the voltage I use the daq toolbox (reading NI-USB device), with a following code:
clear all
% Prepare camera
vid = videoinput('gentl', 1, 'Mono8');
src = getselectedsource(vid);
vid.FramesPerTrigger = 1;
vid.TriggerRepeat = Inf;
triggerconfig(vid, 'hardware', 'DeviceSpecific', 'DeviceSpecific');
src.FrameStartTriggerMode = 'On';
src.FrameStartTriggerActivation = 'RisingEdge';
% prepare DAQ
s=daq.createSession('ni');
s.addAnalogInputChannel('Dev1','ai1','Voltage');
fid = fopen('log.txt','w');
lh = s.addlistener('DataAvailable',#(src,event)SaveData(fid,event));
s.IsContinuous = true;
% Take data
s.startBackground();
start(vid)
N=10;
for ii=1:N
im(:,:,ii)=getsnapshot(vid);
end
% end code
delete(lh );
fclose('all');
stop(vid)
delete(vid)
where the function SaveData is:
function SaveData(fid,event)
time = event.TimeStamps;
data = event.Data;
fprintf(fid, '%f,%f\n ', [time data]);
end
I do get images and a log.txt file with the daq trace (time and data), but how can I use the external triggering (that trigger the camera) or some other clock to synchronize the two?
For this example, the daq reads the camera triggering TTL signal (# 50 Hz), so I want to assign each TTL pulse to an image.
Addendum:
I've been searching and have found a few discussions (like this one) on the subject, and read the examples that are found in the Mathworks website, but haven't found an answer. The documentation shows how to Start a Multi-Trigger Acquisition on an External Event, but the acquisition discussed is only relevant for the DAQ based input, not a camera based input (it is also working in the foreground).
This will not entirely solve your problem, but it might be good enough. Since the synchronization signal you are after in at 50 Hz, you can use clock in order to create time stamps for both types of your data (camera image and analog voltage). Since the function clock takes practically no time (i.e. below 1e-7 sec), you can try edit to your SaveData function accordingly:
fprintf(fid, '%f,%f\n ', [clock time data]);
And in the for loop add:
timestamp(i,:)=clock;
Can you use the sync to trigger the AD board? From the USB-6009 manual...
Using PFI 0 as a Digital Trigger--
When an analog input task is defined, you can configure PFI 0 as a digital trigger input. When the digital trigger is enabled, the AI task waits for a rising or falling edge on PFI 0 before starting the acquisition. To use AI Start Trigger (ai/StartTrigger) with a digital source, specify PFI 0 as the source and select a rising or falling edge.
My experience suggests that delay between trigger and AQ is very short
I'm sorry I use Python or C for this, so I can't give you MatLab code, but you want to look at functions like.
/* Select trigger source */
Select_Signal(deviceNumber, ND_IN_START_TRIGGER, ND_PFI_0, ND_HIGH_TO_LOW);
/* specify that a start trigger is to be used */
DAQ_Config(deviceNumber, startTrig, extConv); // set startTrig = 1
/* start the acquisition */
DAQ_Start(deviceNumber, …)
If you want to take this route you could get more ideas from:
http://www.ni.com/white-paper/4326/en
Hope this helps,
Carl
This is yet no complete solution, but some thoughts that might be useful.
I do get images and a log.txt file with the daq trace (time and data), but how can I use the external triggering (that trigger the camera) or some other clock to synchronize the two?
Can you think of a way to calibrate your setup? I.e. modify your experiment and create a distinct event in both your image stream and voltage measurements, which can be used for synchronization? Just like this ...