【教學】Processing 結合 LinkIt 7697 互動專題:控雨

作者/攝影 曾吉弘
時間 1小時
難度

★★★☆☆

材料表

這學年我在臺北科大互動設計系上課,上學期使用 LinkIt 7697 來上互動物聯網專題,這學期則是 Processing 與 Python 各半學期。班上人數居然有79人,4個人一組也是有20組,期中看大家的 demo 真的很累啊… 一組5分鐘就兩個小時過去了。有興趣的朋友歡迎參考我的上課講義以及 CAVEDU blog

Processing 一直是我很喜歡的一個主題,使用相對簡易的語法就可以設計出豐富有趣的介面,加上執行在電腦上就很容易透過 USB 來與 Arduino 這類裝置溝通。所以也很高興看到這組同學有不錯的結合:使用 Processing 讀取裝在 LinkIt 7697 的超音波感測器與三軸感測器,超音波用來控制球的移動速度,三軸則是控制方向。

影片

本文範例與影片,感謝班上鄭同學與朱同學協助整理。

https://www.facebook.com/allelujahnissin/videos/10219045492821694/

功能說明

引用這組的期中報告,專題名稱為 [rit.]。就是樂曲上漸慢的意思

我們從電影「出神入化」中一幕控制雨水暫留於空中甚至向上漂浮的畫面獲得靈感,想要將這樣具戲劇張力的畫面實現,讓平凡人也可以擁有控制地心引力或甚至是時間的超能力。我們的功能主要是透過超音波感測器偵測手部,靠近時,畫面中的雨滴會漸慢停止,而遠離時,雨滴會回流向上,手離開感測器則雨滴恢復原行進狀態。

流程圖

程式架構說明

7697端透過 Serial.write(); 語法不斷把超音波與加速度感測器的 Y 軸送出,

Processing 則是語法  serial.read(); 語法把資料讀進來之後控制雨點的速度與方向,

一般人常碰到的問題是 Processing 抓不到 Arduino 而程式閃退,解決方法要讓 Arduino 的程式先跑起來,且不要開 Arduino Serial Monitor 否則會被占住而無法連線(除非你又開一個 SerialX 來顯示資料但不建議這麼做) ,語法: serial = new Serial(this, Arduino.list()[0], 9600);   這裡的 Arduino.list()[0] 是指電腦上抓到的第一片 Arduino,也可以直接用 COMX 來指定。 以這樣的概念來說,PC 上要接多片 7697 / Arduino 當然是可行的,就能讓專題更豐富。

設計背景的同學在進入互動裝置時不一定需要寫很複雜的程式,但通常都會以”場域”的概念來思考專題,例如用很多感測器感測人在一個區域中的動作。這與資電背景同學(通常是做一個裝置) 相比各有其趣。

rit 程式說明 – Processing端程式

Spot[] spots; // Declare array

import processing.serial.*;
import cc.arduino.*;
Serial serial;
Arduino arduino;

int a1=0;
int a2=0;
int sensorValue;

void setup() {
size(700, 700);
serial = new Serial(this, Arduino.list()[1], 9600); //指定 Arduino 位置
int numSpots = 100; // Number of objects
int dia = 15; // Calculate diameter
spots = new Spot[numSpots]; // Create array
for (int i = 0; i < 100; i++) {
float x = 20*random(0, 35); //決定球圓心位置
float rate = random(-1.0, 1.0);

for (int i1 = 0; i1 < 100; i1++) {
float y = 20*random(0, 35); //決定球圓心位置

// Create each object
spots[i] = new Spot(x, y, dia, rate);
}
}
noStroke();
}

void draw() {
fill(0, 15);
rect(0, 0, width, height);
fill(255);

for (int i=0; i < 100; i++) {
spots[i].move(); // Move each object
spots[i].display(); // Display each object
}
}

class Spot { //自定義雨滴
float x, y; // X-coordinate, y-coordinate
float diameter; // Diameter of the circle
float speed; // Distance moved each frame
int direction = 5; // Direction of motion (1 is down, -1 is up)
float diameter1; // Diameter of the circle
float speed1; // Distance moved each frame
int direction1 = 5;
// Constructor
Spot(float xpos, float ypos, float dia, float sp) {
x = xpos;
y = ypos;
diameter = dia;
speed = sp;
}

void move() { //根據Arduino 丟過來的值決定雨滴動作
if ( serial.available() > 0) {
sensorValue = serial.read();

a1=sensorValue/10;
a2=sensorValue;
}
if (a1<5) {

if (a1==0) {
println("a2"+a2);
if (a2==2) {
a2=-1;
}
x += a2*(speed * direction1);
if ((x > (width - diameter1/2)) || (x < diameter1/2)) {
direction1 *= -1;
}
} else {
y += 0.1*a1*(speed * direction);
if ((y > (height - diameter/2)) || (y < diameter/2)) {
direction *= -1;
}
x += 0.1*a1*(speed * direction1);
if ((x > (width - diameter1/2)) || (x < diameter1/2)) {
direction *= -1;
}
}
} else if (a1==5) {
y += (speed * direction);
if ((y > (height - diameter/2)) || (y < diameter/2)) {
direction *= -1;
}
x += (speed * direction1);
if ((x > (width - diameter1/2)) || (x < diameter1/2)) {
direction1 *= -1;
}
}
}

void display() { //顯示雨滴
ellipse(x, y, diameter, diameter);
}
}

rit 程式說明 – Arduino端(7697)程式

#define Y_PIN A1                //加速度 Y軸
int trigPin = 12; //超音波 Trig Pin
int echoPin = 11; //超音波 Echo Pin
long duration, cm, inches;
int a = 0;

float toG(float v) {
return v * 6 / 1023 - 3;
}

void setup() {
Serial.begin (9600); // Serial Port begin
pinMode(trigPin, OUTPUT); //Define inputs and outputs
pinMode(echoPin, INPUT);
}

void loop()
{
int y = analogRead(Y_PIN);
digitalWrite(trigPin, LOW);
delayMicroseconds(5);
digitalWrite(trigPin, HIGH); // 給 Trig 高電位,持續 10微秒
delayMicroseconds(10);
digitalWrite(trigPin, LOW);

pinMode(echoPin, INPUT); // 讀取 echo 的電位
duration = pulseIn(echoPin, HIGH); // 收到高電位時的時間

cm = (duration / 2) / 29.1;
a = cm / 8;

if (a < 5) {
if (a == 0) {
if (y > 360) {
a = a * 10 + 2;
Serial.write(a);
}
else if (y < 300) {
a = a * 10 + 1;
Serial.write(a);
}
else {
a = 0;
Serial.write(a);
}
}
else {
a = a * 10;
Serial.write(a);
}
}
else {
a = 50;
Serial.write(a);
}
delay(100);
}

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *