TI-Nspire & Arduino、超音波距離計 4 of 4、超音波モジュールをサーボに載せて左右に振る(続き)

A Micro, a servo, and a battery pack can be put together on a longer breadboard. For more information on the ultrasonic module used in this experiment, visit Ultra Sonic range measurement module - Seeed Studio.
If you want to replicate this experiment, it might be a good idea to use a TI-Innovator Hub instead of a Micro/Leonardo.
 
f:id:ti-nspire:20160913151810j:plain:h315
 
Connect the signal pin of the ultrasonic module to D7 of the Arduino. And connect the control pin of the servo to D9 of the Arduino. To connect the handheld to the Micro or Leonardo, use an OTG cable or host cable with the handheld on the host side.
.ino

#include <Servo.h>
#define ultraPin 7
#define servoPin 9
int deg = 0;

class Ultrasonic {
  public:
    Ultrasonic(int pin);
    void DistanceMeasure(void);
    float microsecondsToCentimeters(void);
  private:
    int _pin;
    float duration;
};
Ultrasonic::Ultrasonic(int pin) {
  _pin = pin;
}

void Ultrasonic::DistanceMeasure(void) {
  pinMode(_pin, OUTPUT);
  digitalWrite(_pin, LOW);
  delayMicroseconds(2);
  digitalWrite(_pin, HIGH);
  delayMicroseconds(5);
  digitalWrite(_pin, LOW);
  pinMode(_pin, INPUT);
  duration = (float)pulseIn(_pin, HIGH);
}

float Ultrasonic::microsecondsToCentimeters(void) {
  return duration / 58.0;
}

Ultrasonic ultrasonic(ultraPin);
Servo myservo;

void setup() {
  myservo.attach(servoPin);
  Serial.begin(115200);
}

void loop() {
  while(deg < 160) {
    if(Serial.available() && Serial.read() == 'T') {
      myservo.write(deg);
      ultrasonic.DistanceMeasure();
      Serial.print(ultrasonic.microsecondsToCentimeters());
      Serial.print(" ");
      Serial.println(deg);
      deg = deg + 1;
      delay(0);
    }
  }
  while(deg > 20) {
    if(Serial.available() && Serial.read() == 'T') {
      myservo.write(deg);
      ultrasonic.DistanceMeasure();
      Serial.print(ultrasonic.microsecondsToCentimeters());
      Serial.print(" ");
      Serial.println(deg);
      deg = deg - 1;
      delay(0);
    }
  }
}

.lua

require "asi" require "color"
platform.window:setBackgroundColor(color.black)

function on.resize() 
   W, H = platform.window:width(), platform.window:height()
   X0, Y0 = W/2, H
   UNIT = H/50 -- H/50 pixels = 1 cm  
   fontSize = W/13.25
   maxHistory = 150
end
function map(var, inMin, inMax, outMin, outMax)
   return (var - inMin) * (outMax - outMin) / (inMax - inMin) + outMin
end
function polar2screen(r, deg, x0, y0, unit)
   local rad = math.rad(deg)
   local x, y = r * math.cos(rad), r * math.sin(rad)
   return x0 + x * unit, y0 - y * unit
end
function constrain(var, min, max)
   return math.max(min, math.min(var, max))
end

local PORT
local DATA = 0
local RANGE = {}
local DEGREE = {}

-----------------------------------
-- シリアルデータの読み取り要求函数
-----------------------------------
function requestData()
      PORT:write('T')
      PORT:read()
end

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

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

-----------------------------------------------------------------------------------------------------
-- ポートコネクターを定義する
-----------------------------------------------------------------------------------------------------
function portConnector(port, event)  
   PORT = port
   if event == asi.CONNECTED then
      asi.stopScanning()
      requestData() 
      port:setReadListener(readListener)
   end 
end

----------------------------------------------------------------------------
-- 読み取りリスナーを定義する(データを取得し、またデータ読み取り要求を出す) 
----------------------------------------------------------------------------
function readListener(port)
   DATA = port:getValue() or 0
   RANGE[#RANGE+1], DEGREE[#DEGREE+1] = unpack(string.split(DATA))
   if #RANGE > maxHistory then
      table.remove(RANGE, 1)
      table.remove(DEGREE, 1)
   end 
   platform.window:invalidate()
   requestData() 
end

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

-------------------------------------------------------------------------------
function on.paint(gc)
   gc:setPen("thin")
   for i = 1, #RANGE do
      local dimColor = map(i, 0, #RANGE, 0, 255)
      gc:setColorRGB(dimColor, 0, 0)
      gc:drawLine(X0, Y0, polar2screen(50, DEGREE[i], X0, Y0, UNIT))
      gc:setColorRGB(0, dimColor, 0)
      gc:drawLine(X0, Y0, polar2screen(math.min(RANGE[i], 50), DEGREE[i], X0, Y0, UNIT))
   end
end