Arduinoとフォトダイオードで光の強さ (PFD) を測定する簡易測器を作る with Python

小さな容器の中の温度・湿度・光環境などを測定したい場合には、市販の測器だと大きすぎてうまく測定できない場合がある
操作性の悪い測器を使うのが面倒な場合もある
こういうとき、Arduinoという小型マイコンと各種センサを使えば簡易な測定可能な場合がある
もっぱらセンサとしてフォトダイオードを使って、可視外の光の強さ (PFD) の測定に使用している
フォトダイオードは1つ数百円程度、波長選択性が高いなど、なかなか便利
光の強さに応じて出力電流が変わるので適当な抵抗をかませて電圧をとる

Arduinoでシリアル通信

Arduinoのマイコン上にコードを載せて操作するのが一般的な使用法
この場合、言語がC/C++ライクなものになる (ちょっとやったけどしんどかった)
すぐに逃げた

Rでシリアル通信

こちらのサイトなどをみた
ぱっとみ難しい
ちょっと迷って逃げた

Pythonでシリアル通信

pyserialというモジュールでいけそう

import csv
import serial

ser = serial.Serial(3) # Arduino uses COM4 in my environment
smoothing = 100 # log 100 data to confirm stability later

with open('ArduinoRead.csv', 'w') as f:
  writer = csv.writer(f)
  a = [ser.read(smoothing)]
  writer.writerow(a)
  f.close()

print("csv wrote")

出力値を記録するだけならこれで機能する
Arduinoからserialポートへ流れてくる値を100文字読み込み、ArduinoRead.csvというファイルに書き込む
ArduinoをUSBポートに挿して、py Write_Python.pyでおしまい

Rで可視化

データを可視化する

# path to the csv file generated by Python
ArdOutput <- "~/Dropbox/working.dir/ArduinoRead.csv"

Ard_graph <- function(InputType){
  slope <- switch(InputType, X =  0.31703, Y = 0.28209, Z = 0.286312)
  intercept <- switch(InputType, X =  4.95123, Y = -1.34458, Z = -0.479106)
  
  ArdData <-
    read.csv(ArdOutput, sep = ":", header = FALSE) %>%
    unlist %>%
    { used_data <-  2:(length(.) - 1)
      
      data.frame(raw = .) %>%
      slice(used_data) %>%
      mutate(calibrated =  as.numeric(as.character(raw)) * slope + intercept,
             time = 1:length(used_data))
    }
  
  Meas.Time <- 
    file.info(ArdOutput)$mtime %>%
    format("%Y/%m/%d %H:%M:%S") %>%
    paste0("@", .)
  
  aveSD <-
    paste0("ave: ", sprintf("%.1f", mean(ArdData$calibrated)),
           ", SD: ", sprintf("%.2f", sd(ArdData$calibrated)))
  
  Ymax <- max(ceiling(ArdData$calibrated/10) * 10)
  Ymin <- min(floor(ArdData$calibrated/10) * 10)
  
  Fig_value <-
    ArdData %>%
    ggplot(aes(x = time, y = calibrated)) +
    geom_line() +
    geom_point() +
    ylim(c(Ymin, Ymax)) +
    annotate("text", label = Meas.Time,
             x = 0, y = Ymin, hjust = 0, vjust = 0, size = 10) +
    annotate("text", label = aveSD,
             x = 0, y = Ymax, hjust = 0, vjust = 1, size = 10)

  Fig_value %>%
    return
}


Ard_graph(InputType = "X") # InputType: Temperature, Weight... (calibrated before)

plot of chunk Read_R

RからPythonを動かしたい

“PythonでRを動かす”系は多いが逆は少ない
コンパイルなる作業が必要な言語はどうしても避けてしまう

参考ページ

Arduino
pyserial
シリアル通信用のパッケージ作りてえ (盆栽日記@Hatena::Diary)

session_info()
##  setting  value                       
##  version  R version 3.2.3 (2015-12-10)
##  system   x86_64, darwin14.5.0        
##  ui       X11                         
##  language (EN)                        
##  collate  en_US.UTF-8                 
##  tz       Asia/Tokyo                  
##  date     2016-03-05                  
## 
##  package    * version date       source        
##  assertthat   0.1     2013-12-06 CRAN (R 3.1.0)
##  chron        2.3-47  2015-06-24 CRAN (R 3.1.3)
##  colorspace   1.2-6   2015-03-11 CRAN (R 3.1.3)
##  data.table * 1.9.6   2015-09-19 CRAN (R 3.1.3)
##  DBI          0.3.1   2014-09-24 CRAN (R 3.1.1)
##  devtools   * 1.9.1   2015-09-11 CRAN (R 3.2.0)
##  digest       0.6.8   2014-12-31 CRAN (R 3.1.2)
##  dplyr      * 0.4.3   2015-09-01 CRAN (R 3.1.3)
##  evaluate     0.8     2015-09-18 CRAN (R 3.1.3)
##  formatR      1.2.1   2015-09-18 CRAN (R 3.1.3)
##  ggplot2    * 2.0.0   2015-12-18 CRAN (R 3.2.3)
##  gtable       0.1.2   2012-12-05 CRAN (R 3.1.0)
##  knitr      * 1.11    2015-08-14 CRAN (R 3.2.3)
##  labeling     0.3     2014-08-23 CRAN (R 3.1.1)
##  lazyeval     0.1.10  2015-01-02 CRAN (R 3.1.2)
##  magrittr   * 1.5     2014-11-22 CRAN (R 3.1.2)
##  memoise      0.2.1   2014-04-22 CRAN (R 3.1.0)
##  munsell      0.4.2   2013-07-11 CRAN (R 3.1.0)
##  plyr       * 1.8.3   2015-06-12 CRAN (R 3.1.3)
##  R6           2.1.1   2015-08-19 CRAN (R 3.1.3)
##  Rcpp         0.12.2  2015-11-15 CRAN (R 3.1.3)
##  scales       0.3.0   2015-08-25 CRAN (R 3.1.3)
##  stringi      1.0-1   2015-10-22 CRAN (R 3.1.3)
##  stringr    * 1.0.0   2015-04-30 CRAN (R 3.1.3)
##  tidyr      * 0.3.1   2015-09-10 CRAN (R 3.2.0)