An ultrasonic module mounted on a servo horn would act just like a radar or sonar.
By running the following code, Leo will transmit range and angle data to the TI-Nspire in the format of a space-delimited string, "range angle".
Drawing residual images will make the display appear to be a radar.
.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 / 29.0 / 2.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 -- 1 cm = H/50 pixels fontSize = W/13.25 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 > 255 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:setFont("sansserif", "r", fontSize) gc:setColorRGB(0, 255, 0) -- gc:drawString((RANGE[#RANGE] or "NO DATA").." cm", 0, 0) -- gc:drawString((DEGREE[#DEGREE] or "NO DATA").." °", 0, 30) gc:setPen("thin") for i = 1, #RANGE do gc:setColorRGB(i, 0, 0) gc:drawLine(X0, Y0, polar2screen(50, DEGREE[i], X0, Y0, UNIT)) gc:setColorRGB(0, i, 0) gc:drawLine(X0, Y0, polar2screen(constrain(RANGE[i], 0, 50), DEGREE[i], X0, Y0, UNIT)) end end