Read real time data from Teeny 3.6 into MATLAB

Status
Not open for further replies.

jsherman

New member
Hi,

In short I am trying to read the output of a DC motor using a teensy 3.6 and then send this data to matlab to display! The problem I am having is I dont seem to be getting enough data points in Matlab. Im unsure of where to go next any help would be appreciated!

MATLAB CODE:

%%Clear comm port
if ~isempty(instrfind)
fclose(instrfind);
delete(instrfind);
end

%%Clear all variables

clear all;
close all;

SerialPort='com5'; %serial port

TimeInterval=0.01;%time interval between each input.
loop=15;%count values

%%Set up the serial port object
s = serial(SerialPort,'BaudRate',115200);
fopen(s);

time =now;
voltage = 0;
%% Set up the figure
figureHandle = figure('NumberTitle','off',...
'Name','Voltage Characteristics',...
'Color',[0 0 0],'Visible','off');
% Set axes
axesHandle = axes('Parent',figureHandle,...
'YGrid','on',...
'YColor',[0.9725 0.9725 0.9725],...
'XGrid','on',...
'XColor',[0.9725 0.9725 0.9725],...
'Color',[0 0 0]);
hold on;
plotHandle = plot(axesHandle,time,voltage,'Marker','.','LineWidth',1,'Color',[0 1 0]);
xlim(axesHandle,[min(time) max(time+0.001)]);
xlabel('Time','FontWeight','bold','FontSize',14,'Color',[1 1 0]);
ylabel('Voltage in V','FontWeight','bold','FontSize',14,'Color',[1 1 0]);
title('Real Time Data','FontSize',15,'Color',[1 1 0]);

%% Initializing variables
voltage(1) = 0;
time(1)=0;
count = 2;
k=1;
fwrite(s,1,'int'); %write data

while ~isequal(count,loop)


%Serial data accessing
voltage(count) = fscanf(s,'%f',1);
voltage = a.analogRead(0)
time(count) = count;
set(plotHandle,'YData',voltage,'XData',time);
set(figureHandle,'Visible','on');
datetick('x','mm/DD HH:MM');

pause(TimeInterval);
count = count +1;
end
fwrite(s,2,'int'); %write data

%% Clean up the serial port
fclose(s);
delete(s);
clear s;

ARDUINO CODE:

#include <ADC.h>

int out1 = 0;
int j =0;

ADC *adc = new ADC();
void setup(){
adc->setConversionSpeed(ADC_CONVERSION_SPEED::VERY_HIGH_SPEED);
adc->setSamplingSpeed(ADC_SAMPLING_SPEED::VERY_HIGH_SPEED);
adc->setResolution(8);

Serial.begin(115200);
pinMode(2,OUTPUT) ; //Logic pins are also set as output
pinMode(3,OUTPUT) ;
pinMode(32, INPUT_DISABLE);
}

void loop()
{
j = Serial.read() ;
if(j==1){
digitalWrite(2,LOW) ;
digitalWrite(3,HIGH) ;
out1 = adc->analogRead(32);
Serial.print(out1);
Serial.print('\n');
}
if(j==2){
digitalWrite(2,LOW);
digitalWrite(3,LOW);
}
}
 
Hi,

In short I am trying to read the output of a DC motor using a teensy 3.6 and then send this data to matlab to display! The problem I am having is I dont seem to be getting enough data points in Matlab. Im unsure of where to go next any help would be appreciated!

1) can you please help us by indenting your code and putting it inside "["CODE"]" .... "["/CODE"]"
2) could you describe the hand-shake you would like to implement, or should we really reverse engineer your intention.

What do you mean by "don't seem to getting enough data points" ?
are data missing in the middle or the end but otherwise correct?
are data scrambled?
or what?
 
Apologies about the sloppy formatting (i'm new), I have formatted it below.

A better explanation of what I am trying to achieve is:

I want to be able to measure the output of the motor from giving it a step input, so I am only interested in its initial movement, so I need as many data points at the start to measure the overshoot or underdamped nature etc.

Currently the output I am getting is a straight line from 0 to the motors steady state, without any overshoot I therefor believe I don't have enough data points to accurately measure the motors response to a step input.

The matlab code below sends a '1' to the teensy to turn the motor on, as soon as the motor is turned on the teensy reads the analogue input from the motor and writes it to the serial port for matlab to then grab and display.

I guess I am asking if this is a logical approach or is the a better way to make this work?

Thanks again for any help.

MATLAB CODE
Code:
%%Clear comm port

if ~isempty(instrfind)
[INDENT]fclose(instrfind);
delete(instrfind);[/INDENT]
end

%%Clear all variables

clear all;
close all;

SerialPort='com5';   %serial port

TimeInterval=0.01;  %time interval between each input.
loop=15;%count values

%%Set up the serial port object
s = serial(SerialPort,'BaudRate',115200);
fopen(s);

time = now;
voltage = 0;

%% Set up the figure 
figureHandle = figure('NumberTitle','off',...
[INDENT]'Name','Voltage Characteristics',...
'Color',[0 0 0],'Visible','off');[/INDENT]

% Set axes
axesHandle = axes('Parent',figureHandle,...
[INDENT]'YGrid','on',...
'YColor',[0.9725 0.9725 0.9725],...
'XGrid','on',...
'XColor',[0.9725 0.9725 0.9725],...
'Color',[0 0 0]);[/INDENT]
hold on;
plotHandle = plot(axesHandle,time,voltage,'Marker','.','LineWid th',1,'Color',[0 1 0]);
xlim(axesHandle,[min(time) max(time+0.001)]);
xlabel('Time','FontWeight','bold','FontSize',14,'C olor',[1 1 0]);
ylabel('Voltage in V','FontWeight','bold','FontSize',14,'Color',[1 1 0]);
title('Real Time Data','FontSize',15,'Color',[1 1 0]);

%% Initializing variables
voltage(1) = 0;
time(1)=0;
count = 2;
k=1;
fwrite(s,1,'int'); %write data

while ~isequal(count,loop) 


[INDENT]%Serial data accessing 
voltage(count) = fscanf(s,'%f',1);
voltage = a.analogRead(0)
time(count) = count;
set(plotHandle,'YData',voltage,'XData',time);
set(figureHandle,'Visible','on');
datetick('x','mm/DD HH:MM');

pause(TimeInterval);
count = count +1;
[/INDENT]
end
fwrite(s,2,'int'); %write data

%% Clean up the serial port
fclose(s);
delete(s);
clear s;

ARDUINO CODE
Code:
#include <ADC.h>

int out1 = 0;
int j =0;

ADC *adc = new ADC();
void setup(){
[INDENT]adc->setConversionSpeed(ADC_CONVERSION_SPEED::VERY_HIG H_SPEED); 
adc->setSamplingSpeed(ADC_SAMPLING_SPEED::VERY_HIGH_SP EED);
adc->setResolution(8);

Serial.begin(115200);
pinMode(2,OUTPUT) ; //Logic pins are also set as output
pinMode(3,OUTPUT) ;
pinMode(32, INPUT_DISABLE);
[/INDENT]}

void loop()
{
[INDENT]j = Serial.read() ;
if(j==1){ 
[INDENT]digitalWrite(2,LOW) ;
digitalWrite(3,HIGH) ; //Turns Motor On
out1 = adc->analogRead(32);
Serial.print(out1);
Serial.print('\n');
[/INDENT]}
if(j==2){
[INDENT]digitalWrite(2,LOW); //Turns Motor Off
digitalWrite(3,LOW);
[/INDENT]}
[/INDENT]}
 
Does this "out1 = adc->analogRead(32);" have the data you are looking for?

As written it will only show that once per Serial.read() when (j==1)?

In setup() add :: setAveraging(2); // for even faster read use (1)

a guess ... If so perhaps something like this will show the value as it changes:
Code:
void loop()
{
  static uint32_t Mon = 0;
  if ( Serial.available() ) {
  j = Serial.read() ;
  if(j==1){ 
    digitalWrite(2,LOW) ;
    digitalWrite(3,HIGH) ; //Turns Motor On
    out1 = adc->analogRead(32);
    Serial.print(out1);
    Serial.print('\n');
  }
  if(j==2){
    digitalWrite(2,LOW); //Turns Motor Off
    digitalWrite(3,LOW);
  }
else{
  uint32_t nMon;
  nMon = adc->analogRead(32);
  if ( nMon != Mon ) {
    Mon = nMon;
    Serial.print(micros());
    Serial.print( "new val =");
    Serial.println(Mon);
    delayMicroseconds( 100 );  // adjust to control output rate
  }
}
 
Does this "out1 = adc->analogRead(32);" have the data you are looking for?

As written it will only show that once per Serial.read() when (j==1)?

In setup() add :: setAveraging(2); // for even faster read use (1)

a guess ... If so perhaps something like this will show the value as it changes:
Code:
void loop()
{
  static uint32_t Mon = 0;
  if ( Serial.available() ) {
  j = Serial.read() ;
  if(j==1){ 
    digitalWrite(2,LOW) ;
    digitalWrite(3,HIGH) ; //Turns Motor On
    out1 = adc->analogRead(32);
    Serial.print(out1);
    Serial.print('\n');
  }
  if(j==2){
    digitalWrite(2,LOW); //Turns Motor Off
    digitalWrite(3,LOW);
  }
else{
  uint32_t nMon;
  nMon = adc->analogRead(32);
  if ( nMon != Mon ) {
    Mon = nMon;
    Serial.print(micros());
    Serial.print( "new val =");
    Serial.println(Mon);
    delayMicroseconds( 100 );  // adjust to control output rate
  }
}

Thanks defragster,

So am I correct in saying that once the teensy has read the '1' sent from matlab and then serial prints, the '1' is now gone?

Upon reflection, I'm thinking it is wiped when I serial print, this would explain everything!
 
Indeed "j = Serial.read() ;" will wait for and read a single character. As written when j==1 the motor will go on and then a single reading will be taken and printed - loop() will exit and return to wait for input. Since an ENTER character may follow entry a second read may happen - but will not match tested values and exit loop - to re-enter and wait on the read.
As written the idea is to ignore the read until there is a character waiting - the else case will happen [ though else could be removed and always read ] and any change in the adc value will be printed. It could be adjusted to do this only for some short time after the motor state is changed to limit output data - you can remove the time value - or perhaps use it to track how quickly the output changes.

The analog read will not likely be stable and change on each read so the delayMicroseconds() is used to limit the print rate to acceptable values.
 
Status
Not open for further replies.
Back
Top