SPI Slave
mbed
LPC1114FN28
#include "mbed.h" SPISlave device(dp2,dp1,dp6,dp25); // mosi, miso, sclk, ssel Serial pc(USBTX, USBRX); AnalogIn ain(dp4); int main() { device.format(8,0); device.frequency(1000000); // uint8_t hbyte = 7; // uint8_t lbyte = 208; float fval; int ival; int counter = 0; while(1) { if(device.receive()) { fval = ain.read(); // Converts and read the analog input value (value from 0.0 to 1.0) ival = (int) (fval * 5000); // Change the value to be in the 0 to 3300 range uint8_t hbyte = ival / 256; uint8_t lbyte = ival % 256; int val = device.read(); pc.printf("received1: %d, ",val); device.reply(0xFF); int val2 = device.read(); pc.printf("received2: %d, ",val2); device.reply(hbyte); // Make this the next reply int val3 = device.read(); pc.printf("receive3: %d, ",val3); pc.printf("count: %d\n",counter); device.reply(lbyte); // Make this the next reply counter = counter+1; } } }
master
Arduion Mega2560
#include <SPI.h> const byte btn = 12; // Master button digital I/O pin. const byte led = 13; // Master LED digital I/O pin. const byte cmdADC = 3; unsigned long nextMillis = 0; // Next millis() for master LED update. #define DTIME 1 #define PERIOD 100 void setup() { Serial.begin(9600); pinMode(SCK, OUTPUT); pinMode(MOSI, OUTPUT); pinMode(MISO, INPUT); pinMode(SS, OUTPUT); pinMode(btn, INPUT_PULLUP); pinMode(led, OUTPUT); nextMillis = millis(); } void loop() { if (millis() >= nextMillis) { nextMillis = millis() + PERIOD; digitalWrite(SS, LOW); delay(DTIME); SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0)); byte rx = SPI.transfer(cmdADC); digitalWrite(SS, HIGH); digitalWrite(SS, LOW); delay(DTIME); byte hbyte = SPI.transfer(255); digitalWrite(SS, HIGH); digitalWrite(SS, LOW); delay(DTIME); byte lbyte = SPI.transfer(255); SPI.endTransaction(); digitalWrite(SS, HIGH); int val = (hbyte<<8) + lbyte; Serial.println(val); } }
データ取得用Pythonコード
import matplotlib.pyplot as plt import re import serial # pattern = re.compile(r'\d+\.\d') fout = open("out.csv","w") ser = serial.Serial("/dev/tty.usbmodem1411",9600) i = 0 ii = [] res = [] while (i<1001): snw = ser.readline().rstrip() # snw = pattern.findall(line) if snw: snw = float(snw) # plt.plot(ii,res) # plt.show() print("{},{}\n".format(i,snw)) fout.write("{},{}\n".format(i,snw)) i = i+1 ser.close() fout.close()
解析用Rコード
zerov <- read.table("0.csv",sep=",") names(zerov) <- c("count","voltage") threev <- read.table("3_3.csv",sep=",") names(threev) <- c("count","voltage") fivev <- read.table("5.csv",sep=",") names(fivev)<-c("count","voltage","D") D <- rep("0V",1001) zerov <- cbind(zerov,D) D <- rep("3.3V",1001) threev <- cbind(threev,D) D <- rep("5V",1001) fivev <- cbind(fivev,D) library(ggplot2) df <- merge(zerov,threev,fivev,all=T) df <- merge(df,fivev,all=T) ggplot(df,aes(factor(D),voltage)) ggplot(df,aes(factor(D),voltage))+geom_boxplot(aes(fill=D)) ggplot(df,aes(factor(D),voltage))+geom_boxplot(aes(fill=factor(D))) summary(zerov$voltage) summary(threev$voltage) summary(fivev$voltage) ggplot(df,aes(x=voltage,fill=D))+geom_density()
10Hzで1000サンプル計測したときの結果
[0V計測時] Min. 1st Qu. Median Mean 3rd Qu. Max. 0.00 63.00 73.00 96.13 87.00 4858.00 [3.3V計測時] Min. 1st Qu. Median Mean 3rd Qu. Max. 84 3225 3264 3247 3279 3372 [5V計測時] Min. 1st Qu. Median Mean 3rd Qu. Max. 4696 4824 4848 4838 4863 4951
測定値に誤差があるのでカルマンフィルタを実装
#include <SPI.h> #include <math.h> const byte btn = 12; // Master button digital I/O pin. const byte led = 13; // Master LED digital I/O pin. const byte cmdADC = 3; unsigned long nextMillis = 0; // Next millis() for master LED update. #define DTIME 1 #define PERIOD 100 float x_hat; float x_hat_bar; float sigmax_hat; float sigmax_hat_bar; float sigmax0 = 37.0;//from experiment float sigmaz = 50.0;//given parameter bool isFirst = true; float k; float kalmanFilter(float z){ //initialize if(isFirst){ x_hat = float(z); sigmax_hat = sigmax0; isFirst = false; } //estimate step x_hat_bar = x_hat; sigmax_hat_bar = sqrt(sigmax_hat*sigmax_hat + sigmax0*sigmax0); //filter step k = (sigmax_hat_bar*sigmax_hat_bar) / ((sigmax_hat_bar*sigmax_hat_bar) + (sigmaz*sigmaz)); x_hat = x_hat_bar + k * (z - x_hat_bar); sigmax_hat = (1-k) * sigmax_hat_bar; return x_hat; } void setup() { Serial.begin(9600); pinMode(SCK, OUTPUT); pinMode(MOSI, OUTPUT); pinMode(MISO, INPUT); pinMode(SS, OUTPUT); pinMode(btn, INPUT_PULLUP); pinMode(led, OUTPUT); nextMillis = millis(); } void loop() { if (millis() >= nextMillis) { nextMillis = millis() + PERIOD; digitalWrite(SS, LOW); delay(DTIME); SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0)); byte rx = SPI.transfer(cmdADC); digitalWrite(SS, HIGH); digitalWrite(SS, LOW); delay(DTIME); byte hbyte = SPI.transfer(255); digitalWrite(SS, HIGH); digitalWrite(SS, LOW); delay(DTIME); byte lbyte = SPI.transfer(255); SPI.endTransaction(); digitalWrite(SS, HIGH); int val = (hbyte<<8) + lbyte; Serial.print(val); Serial.print(","); float filtered = kalmanFilter(float(val)); Serial.println(filtered); } }