我正在使用 Arduino Uno 从编码器收集学位数据,然后使用 USB 将该数据发送到 MATLAB。为了也获得旋转速度,我在每个度数数据点从 Arduino 到 MATLAB 之后生成并发送时间戳。数据在 Arduino 端完美生成——串行监视器上没有任何问题。
然而,在 MATLAB 中,我的数据矩阵充满了相当多的 NaN,以及偶尔缺少第一位数字的整数。例如,不是 216 度,而是 16 度,或者不是 7265900 微秒,而是 265900 微秒。
我已经能够通过使用 Arduino 的 millis() 时钟而不是 micros() 时钟并在编码器读取后添加 50 毫秒的延迟来解决丢失时间数据的问题。如果我在毫秒()时钟之后增加延迟,度数数据丢失的问题就会消失,但是度数数据采集变得太慢而无法使用。
任何帮助将非常感激!
代码粘贴在下面。首先是 Arduino 代码,然后是 MATLAB 代码。
谢谢!
大卫
#include <Adafruit_LEDBackpack.h>
#include <Adafruit_GFX.h>
#include <gfxfont.h>
#include <SPI.h> //Include the SPI library in this sketch.
#include <Wire.h> // Enable this line if using Arduino Uno, Mega, etc.
//#include <TinyWireM.h> // Enable this line if using Adafruit Trinket, Gemma, etc.
#include "Adafruit_LEDBackpack.h"
#include "Adafruit_GFX.h"
Adafruit_7segment matrix = Adafruit_7segment();
//Variables for SPI rotary encoder
boolean knob_detected = false;
byte slave_select = 10; //Slave select pin.
byte mosi = 11; //MOSI pin.
byte miso = 12; //MISO pin.
byte spi_clock = 13; //Clock pin.
byte read_counter = 96;
byte write_mode0 = 137;
byte write_mode1 = 144;
byte count1;
byte count2;
int count;
int val;
int button = 7;
int b = 0;
int degree;
int absolute;
unsigned long time;
// SETUP //
void setup() {
//Connect the 4 communication pins between the Arduino and the quadrature counter.
#ifndef __AVR_ATtiny85__
Serial.begin(9600);
//Serial.println("7 Segment Backpack Test");
#endif
matrix.begin(0x70);
pinMode(slave_select, OUTPUT);
pinMode(mosi, OUTPUT);
pinMode(miso, INPUT);
pinMode(spi_clock, OUTPUT);
// pinMode(button,INPUT);
SPI.begin(); //Begin SPI communication.
SPI.setBitOrder(MSBFIRST); //Bytes read into SPI will be read in MSB style.
SPI.setDataMode(SPI_MODE0); //Set the data to shift on the low clock phase with normal (non-inverted) clock polarity.
digitalWrite(slave_select, HIGH); //Close the SPI communication port.
SPI.setClockDivider(SPI_CLOCK_DIV128); //Set the SPI clock to 125 kHz (This can be changed).
digitalWrite(slave_select, LOW); //Set slave select low to enable communication.
SPI.transfer(write_mode0); //Select mode 0 for modifying.
SPI.transfer(0b01000011); //Write to mode 0: Synchronous Index, disable index, range-limit count mode, x4 quadrature.
digitalWrite(slave_select, HIGH); //Set slave select high to disable communication
digitalWrite(slave_select, LOW); //Set slave select low to enable communication
SPI.transfer(write_mode1); //Select mode 1 for modifying.
SPI.transfer(2); //Write across a 0b01 to mode1 to enable 2 byte data transfers
digitalWrite(slave_select, HIGH); //Set slave select high to disable communication
Serial.begin(9600); //Set the baud rate for serial data transmission.
//Serial.println("READY"); //Print "READY" to the serial line to indicate that initialization is complete.
}
// MAIN LOOP //
void loop() {
digitalWrite(slave_select, LOW); //Set slave_select pin low to begin tranmission .
SPI.transfer(read_counter); //Read from the read_counter register.
count1 = SPI.transfer(0); //Send a null transfer to read byte1 values.
count2 = SPI.transfer(0); //Send a null transfer to read byte2 values.
digitalWrite(slave_select, HIGH); //Set slave_select high to end transmission.
count = word(count1, count2); //Type cast the 2 bytes as a word.
degree = count / 4;
absolute = abs(degree);
//Send back the value of the register over the serial line.
b = digitalRead(button);
if (b == HIGH) {
digitalWrite(absolute,LOW);
}
else {}
if (absolute == LOW)
{
absolute = 0;
}
else {}
Serial.println(absolute); //Send back the value of the register over the serial line.
matrix.print(absolute,DEC);
matrix.writeDisplay();
delay(50); //Pause for 50 milliseconds before re-looping.
time = millis();
Serial.println(time);
delay(10);
}
clear all;
close all;
clc;
delete(instrfind); %delete connected ports
p=getserialport;
[m,n] = listdlg('PromptString','Select Your Bluetooth device:','SelectionMode','single','ListString',p);
com=cell2mat(p(m));
s=serial(com);
fopen(s);
csd = figure;
set(csd,'Name','Plotting Arduino Data on MATLAB','NumberTitle','off'); % open Figure
t=1:100;% total Figure
hAx(1) = subplot(211);
hLine(1) = line('XData',t, 'YData',nan(size(t)), 'Color','b', 'Parent',hAx(1));
xlabel('Samples'), ylabel('Degrees');
hAx(2) = subplot(212);
hLine(2) = line('XData',t, 'YData',nan(size(t)), 'Color','b', 'Parent',hAx(2));
xlabel('Samples'), ylabel('Velocity');
set(hAx, 'Box','on', 'YGrid','on');
axis(hAx(1),[0,100,0,100]);
axis(hAx(2),[0,100,0,100000]);
d=zeros(1,100); %buffer of 100 elements
sm=zeros(1,10); %buffer of 10 elements
t10=zeros(1,10); %buffer of 10 elements
t100=zeros(1,100); %buffer of 100 elements
while(1)
j=1;
while(j<=10)
flushinput(s);
sc=(fscanf(s));
if(length(sc)<6) %1000 degree units = 6 char (was <7 for micros() clock)
sm(j)=str2double(sc);
else %i.e. else, if a timestamp (more than 7 chars)
t10(j)=str2double(sc);
j=j+1;
end
end
t100 = [t100,t10];
t100 = t100(11:end);
d=[d,sm]; %Add new Samples
d=d(11:end); %Remove old Samples
%d(end)
set(hLine(1), 'YData',d); %draw Degrees
set(hLine(2), 'YData',t100); %draw Velocity (currently just timestamps)
drawnow %# force MATLAB to flush any queued displays
end
(getserialport 函数由以下 m 文件定义)
function x=getserialport
serialInfo = instrhwinfo('serial');
x=serialInfo.SerialPorts;
end