TI-Nspire & Arduino を利用した温度計 4 of 4、グラフ化する。

最後にグラフ化してみる。Graphs アプリケーションをそのまま使う。
var.store() コマンドで lua から nspire へデータを渡して scatter plot で描画する。


.ino

#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS 10

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

DeviceAddress thermo0;
DeviceAddress thermo1;

void setup() {
   Serial.begin(115200);
   sensors.begin();
   sensors.getAddress(thermo0, 0);
   sensors.getAddress(thermo1, 1);
   sensors.setResolution(thermo0, 12);
   sensors.setResolution(thermo1, 12);
}
void loop() {
   if (Serial.read() == 'T') {     
      sensors.requestTemperatures();
      Serial.print("0: ");
      Serial.print(sensors.getTempC(thermo0)); 
      Serial.print(";");
      Serial.print("1: ");
      Serial.print(sensors.getTempC(thermo1));
   }
}


.lua

-- showing graphically
require "asi" require "color"
platform.window:setBackgroundColor(color.dodgerblue)

PORT = nil
rawTime = {}
relativeTime = {}
INTERVAL = 2
numberOfSensors = 2
DATA = {}
for i = 1, numberOfSensors do
   DATA[i] = {}
end
gotInitialData = false

function on.resize()  
   W, H = platform.window:width(), platform.window:height() 
   fontSize = math.min(H/2, 24)
   colSpace = W/1.8
end
function whenNoData()
   for i = 1, numberOfSensors do
      table.insert(DATA[i], 0) 
   end
end

--------------------------------------------------------------------------
-- シリアルデータの読み取り要求函数(合図として文字 "T" を送信する)
--------------------------------------------------------------------------
function requestData()
   if PORT then
      PORT:write('T')
      PORT:read()
   end
end

--------------------------------------------------------------------------------
-- ASI ステートリスナーを定義する(ASI の準備が整ったらポートスキャンを開始する)
--------------------------------------------------------------------------------
function stateListener(state) 
   if state == asi.ON then 
      asi.startScanning(portScanner) 
   end 
   platform.window:invalidate()   
end

----------------------------------------------------------------
-- ポートスキャナーを定義する(見つかったポートに接続要求を出す)
----------------------------------------------------------------
function portScanner(port) 
   port:connect(portConnector) 
end

-----------------------------------------------------------------------------------------------------
-- ポートコネクターを定義する
--(入出力の準備が整ったらポートスキャンを停止し、読み取りリスナーをセットし、データ読み取り要求を出す)
--(接続が外れていたらポートスキャンを開始する)
-----------------------------------------------------------------------------------------------------
function portConnector(port, event)  
   PORT = port 
   if event == asi.CONNECTED then
      asi.stopScanning()
      port:setReadListener(readListener)
      if not gotInitialData then
         gotInitialData = true
         requestData() -- 初回データを取得してからタイマーをスタートする。
         timer.start(INTERVAL)
      end
   else
      whenNoData()
      platform.window:invalidate()
      asi.startScanning(portScanner)
   end
end

----------------------------------------------------------------------------------------
-- 読み取りリスナーを定義する(xx.xx 形式のデータを取得する) 
----------------------------------------------------------------------------------------
function readListener(port)  
   local data = port:getValue()
   table.insert(rawTime, timer.getMilliSecCounter()) -- データを取得したときの内部ミリ秒カウンターの値を取得して、
   relativeTime[#rawTime] = (rawTime[#rawTime] - rawTime[1])/1000 -- 測定開始時を基準とする秒単位に変換する。
   if data then
      local dataList = string.split(data, ";") -- "0: 温度0;1: 温度1" という形式のデータを {0: 温度0, 1: 温度1, ...} というリストに変換する。
      for _, v in ipairs(dataList) do
         local subList = string.split(v, ":") -- さらに {0, 温度0} {1, 温度1} ... というリストに変換し、
         local index = subList[1]
         local value = tonumber(subList[2])
         table.insert(DATA[index + 1] or {{}}, value or nil) -- DATA[1][n] = 温度0、DATA[2][n] = 温度1、... と代入する。
      end
   else
      whenNoData() 
   end
   var.store("x", relativeTime)
   var.store("y0", DATA[1])
   var.store("y1", DATA[2])
--[[
   print(relativeTime[#relativeTime], DATA[1][#relativeTime], DATA[2][#relativeTime])
--]]   
   platform.window:invalidate()
end

---------------------------------
-- ASI ステートリスナーを登録する
---------------------------------
function on.enterKey()
   asi.addStateListener(stateListener) 
end

-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
function on.construction()
   gotInitialData = false
end
function on.timer()
   requestData() 
end
function on.paint(gc) 
   gc:setFont("sansserif", "r", fontSize)
   gc:setColorRGB(color.white)
   for i, v in ipairs(DATA) do
      gc:drawString(string.format(" %d: %4.1f °C", (i - 1), v[#v] or 0), (i - 1) * colSpace, 0)
   end
end


.tns
thermo8.tns - Google ドライブ