把遇到錯誤的、學習到的前端筆記在這邊

總網頁瀏覽量

Copyright © Tzeng Ying-chi. 技術提供:Blogger.

2019/10/10

2019/10/09

[2019鐵人賽] - 24.筆記IoT初練習- 速度與激情? - Johnny Five 之 Accelerometer 三軸加速度計 - 2


續 昨天沒講完的實作和有些不完整的地方.....<(_ _)>

## 補充 - 實作部分
使用 Johnny-Five 的 `Accelerometer` 物件屬性,**`controller` key值為選填**;
Johnny-Five 附表列出目前加速度計有支援的 controller,填上使用的 Accelerometer 字串即可 ;

如果沒填寫特定的 `controller` 參數的話,**預設值為`'ANALOG'`**;
使用特定的 Sensor 若對應到 `controller` Johnny-Five 清單中特定的`controller`字串值,則可以填寫特定選填的物件屬性。

**舉例來說:**
如果物件 `controller` 值為 `'ANALOG'` ,則可以填寫 Analog 選填屬性。

> Accelerometer Parameters - 
> http://johnny-five.io/api/accelerometer/#parameters









2019/10/08

[2019鐵人賽] - 23.筆記IoT初練習- 速度與激情? - Johnny Five 之 Accelerometer 三軸加速度計


Sensor 篇第四彈!今天要介紹的是 (∩^o^)⊃━☆゚.*・。

Accelerometer - 三軸加速度計

迷之音:這個我終於知道了!就是陀螺儀嘛!!
本魯:(X)是有點相似~跟陀螺儀還是有點區別的~( ΘωΘ )  
迷之音:啊?.........ಠ_ಠ


簡介 - 三軸加速度計 ≠ 陀螺儀

加速度計(Accelerometer主要是以重力(G力)來感測,也稱為重力感測器(G-Sensor);
透過測量的元件在某個軸向的受力大小、狀況來得到數值,也就是三軸運動的情況;
三軸加速度計可以量測X、Y、Z三個方向

而陀螺儀(Gyroscop),也稱為角速度計、地感器(GYRO-Sensor),
主要結構內部有個陀螺,利用陀螺轉子的運動來量測三維座標的夾角與角速度
三軸陀螺儀可以同時量測前、後、左、右、上、下六個方向

兩者都屬於微機電系統(Microelectromechanical Systems,簡寫:MEMS),即將微電子技術與機械工程融合到一起的一種工業技術;
目前的消費性電子產品和行動裝置都能看到MEMS的身影,例如智慧型手機內的電子羅盤、陀螺儀等

相關連結:

> 加速規 -
https://zh.wikipedia.org/wiki/%E5%8A%A0%E9%80%9F%E8%A6%8F
> 加速度計和陀螺儀感測器:原理、檢測與應用 -
https://reurl.cc/qDNKpD
> 微機電系統 -
https://w.wiki/9d6
> 加速計/陀螺儀/磁力計是什麼,3軸/6軸/9軸感測器又是什麼? -
https://reurl.cc/QpbVV0
> 關於加速度計和陀螺儀傾角測量的物理分析 -
https://kknews.cc/zh-tw/education/lnaaxy9.html

工作原理:

剛剛提到加速度計屬於MEMS,他的構成可分成固定電極和可移動物體,透過可移動物體在固定電極片移動產生電容值差值,進而得物體重心的位移和方向


畫出來用看圖的方式了解工作原理,希望比較好理解一點~(。>﹏<)a

> 本魯的加速度計模組是使用「ADXL345」IC組合而成的
> 搖搖模組還會發出碰撞聲「喀啦~喀啦~」的,應該是 IC 裡面的移動物體的碰撞聲。


後面還有很多需要理解的東西,話不多說趕快來實作吧!
準備需要的東西有~ヽ(・×・´)ゞ

硬體部分

### 電路方面

ADXL345 有 I2C 和 SPI 兩種通訊協定可以選擇,三軸加速度的接腳有

- VCC - Supply voltage range: 2.0 V to 3.6 V 電壓供給
- GND - 接地
- CS - Chip Select. 選擇晶片
- INT1 - Interrupt 1 Output. 中斷輸出 1
- INT2 - Interrupt 2 Output. 中斷輸出 2
- SDO - Serial Data Output. 串列資料輸出 (SPI通訊)
- SDA - Serial Data. 串列資料線
- SCL - Serial Communications Clock. 串列通訊時脈線

> Data Sheet - https://www.analog.com/media/en/technical-documentation/data-sheets/ADXL345.pdf

因為 Johnny-Five 的 Accelerometer API ADXL345 使用 I2C通訊,故我們只要接 SDA 和 SCL資料線即可。

> 接線圖
> 附上電路圖
介紹完後,我們開始來實作吧~
準備需要的東西有~ヽ(・×・´)ゞ


## 硬體方面
- Arduino Uno 一片 + USB TypeB 線材一條 (標配標配!
- 杜邦線 看你用幾條準備幾條
- 加速度計 一個 這邊使用 ADXL345

## 軟體方面 
> Johnny-Five - Accelerometer
http://johnny-five.io/api/accelerometer/ 

### 使用寫法 - ADXL345 範例
要使用 Accelerometer 的話,需要呼叫 Johnny-Five 的 Accelerometer 物件,
物件參數 `controller` 指定加速度計型號,這邊使用ADXL345,故 Value 填寫 'ADXL345'字串;
把 ADXL345 的 SDA、SCL 接腳連接到 Arduino 的 I2C 接腳 A4、A5。 

## API
> Johnny-Five - Accelerometer API
> http://johnny-five.io/api/accelerometer/#api

- hasAxis(name) Does the device support the axis?
偵測Sensor是否支援 X / Y / Z 軸。
寫法:
```
// 檢測 Sensor 是否有支援 Z 軸
if (accelerometer.hasAxis("z")) {
  console.log(accelerometer.z)
}
```

- enable()
啟動 Device 偵測和 Events 事件,如果 Device 支援休眠狀態,呼叫 enable() 會將其喚醒。

- disable()
停用 Device 偵測和 Events 事件,如果 Device 支援休眠狀態,呼叫 disable() 會將其進入休眠狀態。


## Events
> Johnny-Five - Accelerometer Events
> http://johnny-five.io/api/accelerometer/#events

Events 也是 `change` 和 `data` 事件和之前介紹的一樣,就不贅述了~
  
## 實作 - 

```
var five = require('johnny-five');
var board = new five.Board();

board.on('ready', function() {
  var accelerometer = new five.Accelerometer({
    controller: 'ADXL345',
  });

  accelerometer.on('change', () => {
    const { acceleration, inclination, orientation, pitch, roll, x, y, z } = accelerometer;
    console.log('Accelerometer:');
    console.log('  x            : ', x);
    console.log('  y            : ', y);
    console.log('  z            : ', z);
    console.log('  pitch        : ', pitch);
    console.log('  roll         : ', roll);
    console.log('  acceleration : ', acceleration);
    console.log('  inclination  : ', inclination);
    console.log('  orientation  : ', orientation);
    console.log('--------------------------------------');
  });
});
```

2019/10/07

[2019鐵人賽] - 22.筆記IoT初練習看- 偵測老闆的一個Move!薪水小偷必備 - Johnny Five 之 Motion 動作感測器-


本文只做教學用途,不負任何責任

昨天主要講解PIR的工作原理和測試、實驗一下,
今天要來作一點小應用 ヽ(・×・´)ゞ

下音樂 again ~
登登楞登~登登~ (多拉A夢的音效)

「老  闆  移  動  偵  測  器」~ ( σ՞ਊ ՞)σ 

※使用前請詳閱公開說明書,請保證工作進度超前在使用本產品,本產品不負被抓包相關責 任。(被打)

謎之音:這有什麼好做的....不就人體偵測嗎...ಠ_ಠ
本魯:當然要加一點花樣騙騙人啊...欸不對...應該是發揮才能才對 ...


故事是這樣開始的…

因為我的 PIR Sensor 是從 Webduino 買豪華套件包來的,
發現我的 PIR Sensor 不能調觸發模式,就不能做更好玩的應用了....嗚嗚 QQ
( 以後會改善的Orz )

所以既然不能調觸發模式,那就想別的方法吧~

又是靈光一閃過!(✪ω✪)
科技始於人性,人性始於墮性(?
像我們開發者整天坐在辦公室,需求一直改一直改,不如等到完全定案之後再開發
等待的時間又要假裝有在上班,實際上我就不說了...XD
所以研發了這個東西!

我想的功能是:
當薪水小偷可以不用很緊張,老闆快走過來時即時開啟 Stack overflow 或是 MDN 假裝在查Doc!

發生事件情境設定:
先設定好「看起來認真上班的網頁」 → 設定好之後開始當薪水小偷EX:上班看YT、巴哈姆特等....

當老闆快要走到我的位子的時候 → 人體感測器感測到老闆 → `motionstart`事件 → 透過 Socket 給前端資料 → 紀錄資料並開啟預設「看起來認真上班的網頁」。

恩~ 計画通り!


接下來跟著我一起浪費才能吧~ヽ(・×・´)ゞ 
謎之音:又來了....(ㆆᴗㆆ)


補充說明 - Events

首先補充一下昨天的沒有仔細說到的Events部分
觸發 Johnny-Five Motion 物件後,會 retrun 資料物件

```json
{
  // 時間戳
  timestamp: 1570416994150,
  // 偵測動作狀態,若有動作則返回布林值 `true` , 反則返回布林值 `false`
  detectedMotion: true,
  // 是否校準,已校準則返回布林值 `true` , 反則返回布林值 `false`
  isCalibrated: true
}
```

處理精度為毫秒的時間戳!

這邊要注意的 Johnny-Five 返回的 timestamp 是13位數的時間戳
> 13位數的時間戳精度為「毫秒」,
> 10位數的時間戳精度則是「秒」;

但 JavaScript 處理的是10位的時間戳,要怎麼辦呢?
本魯宅:因為現在用不到毫秒等級那麼細的時間戳,只好切掉了!(≖_≖)✧

使用 Javascript 的字串處理 substr 函式 ,截取從 0~10 的字元就好
```
// 返回一個從指定位置開始的指定長度的子字串
String.substr(指定開始位置,截取長度)
```
> MDN - String.prototype.substr()
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substr

但這邊又要注意了~
因為 Johnny-Five 回傳的 timestamp 型別是 `Number` 而不是 `String` ,
直接用 substr() 函式擷取字元的話,會因為型別不對而報錯!

範例說明:
```
motion.on('motionstart', function(data) {
  timestamp = data.timestamp;
  console.log(typeof timestamp); // Number
});
```


轉型

所以我們要把 Johnny-Five 吐出的時間戳轉為字串型別(String),在用 substr() 截取時間戳字串!



這樣就可以取出時間戳來轉換成人讀的時間了~(ง๑ •̀_•́)ง

下個步驟!拆解各個事件返回值

剛剛提到物件中, Johnny-Five 還會返回 `isCalibrated` 和 `detectedMotion` 物件,
這兩個物件的值都是布林值 true / false 。

我們先了解物件的意義:

isCalibrated
`isCalibrated` 和 `motion.on('calibrated', function() { });` 一樣都只會在一開始做一次,當第一次發生目標物移動時則偵測訊號成功,`isCalibrated` 返回就會 true 值;
之後觸發的 motion 動作,不管是 start 還是 end 的都會看到 `isCalibrated` 值都是 true。

detectedMotion 
當目標物有移動動作,PIR Sensor 偵測到時便會回傳 `detectedMotion` 為ture,就字面上的意思來說就是「偵測到動作了!」;

當目標物停止移動動作,會回傳 `detectedMotion` 為false,意思來說就是「剛剛的偵測到的動作停止了!」。

不同的事件返回物件值

但每個觸發不同的事件,回傳的也會不一樣,

> 'calibrated' 校準事件
> function data 不會回傳物件值,事件 'calibrated' 就表示只是一個狀態!

```
motion.on('calibrated', function(data) {
   console.log(data);
   console.log('calibrated');
 });
```
> 'motionstart' 偵測到動作事件
>

```
motion.on('motionstart', function(data) {
  console.log(data);
  console.log('motionstart');
});
```
此事件會 function data 返回
- 偵測到動作的時間戳
- detectedMotion 返回 true
- isCalibrated 返回 true
```
{
  timestamp: 1570420021897,
  detectedMotion: true,
  isCalibrated: true
}
```

> 'motionend' 沒有偵測到動作了
>

```
motion.on('motionend', function(data) {
  console.log(data);
  console.log('motionstart');
});
```
此事件會 function data 返回
- 動作停止的時間戳
- detectedMotion 返回 false
- isCalibrated 返回 true
```
{
  timestamp: 1570420021897,
  detectedMotion: false,
  isCalibrated: true
}
```

完整的一個循環~



講好多....終於要來實作啦~


程式碼很簡單,我們透過JavaScript window.open() 事件來實現這個應用(ง๑ •̀_•́)ง
後端部分:
```
var io = require('socket.io');
var express = require('express');
var five = require('johnny-five');

var board = new five.Board();
var app = express();

app.use(express.static('www'));
var server = app.listen(3000, function() {
  console.log('connected!');
});

var sio = io(server);

board.on('ready', function() {
  var motion = new five.Motion({
    pin: '7',
    freq: 250,
  });

  sio.on('connection', function(socket) {
    motion.on('calibrated', function() {
      //PIR Sensor Ready
      console.log('準備好啦!');
    });

    motion.on('motionstart', function(data) {
      // 偵測到有生物在動,觸發事件
      console.log('偵測到老闆!');
      socket.emit('startData', {
        // socket 傳送資料給前端
        isAction: data,
      });
    });
  });
});
```

前端部分

HTML
網頁就隨便裝飾一下,目的只是要開啟Socket連線而已
我有做老闆出現的話會append出老闆出現的時間,也就是偵測到動作的時間戳。
```
<body>
  <div class="container">
    <h2 class="p-5">老 闆 移 動 偵 測</h2>
  </div>
  <nav class="navbar navbar-light bg-light fixed-bottom">
    IoT沒那麼難!新手用JavaScript入門做自己的玩具 系列文 Tzeng,Ying-Chi
  </nav>
  <script src="/socket.io/socket.io.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
  <script src="index.js"></script>
</body>
```

JavaScript
```
var socket = io.connect();

socket.on('startData', function(data) {
  //接收到偵測資料
  motionData = data.isAction;
  // 時間戳處理
  timestamp = parseInt((motionData.timestamp + '').substr(0, 10));
  // 取得是否偵測到動作
  isMotion = motionData.detectedMotion;
  // 轉換成人看的時間格式
  humanCanReadTime = getTime(timestamp);

  if (isMotion === true) {
    // 當老闆來時,在新分頁打開裝認真的網頁
    window.open(
      'https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Array',
      '_blank',
    );
    // 印出時間點
    $('.container').append(
      '<div class="alert alert-danger boss-alert" role="alert">老闆出現於 <span class="time">' +
        humanCanReadTime +
        '</span> !</div>',
    );
  }
  // 時間戳格式轉換
  function getTime(timestamp) {
    var time = new Date(timestamp * 1000);
    var h = time.getHours();
    var min = time.getMinutes();
    var s = time.getSeconds();

    h = checkTime(h);
    min = checkTime(min);
    s = checkTime(s);

    timeStr = h + ':' + min + ' ' + s + '秒';

    return timeStr;
  }
  function checkTime(i) {
    if (i < 10) {
      i = '0' + i;
    } // add zero in front of numbers < 10
    return i;
  }
});

```

> Demo



2019/10/05

[2019鐵人賽] - 21.筆記IoT初練習看- 偵測一個Move!Hold住你的動作 - Johnny Five 之 Motion 動作感測器


tags: iT邦幫忙鐵人賽2019

[Day 21]用JS控制Arduino吧!偵測一個Move!Hold住你的動作 - Johnny Five 之 Motion 動作感測器

Sensor 篇第三彈!今天要介紹的是
PIR Sensor - Passive Infrared Sensor
無源紅外線感測器,
世面上有個通俗的名字叫 -「人體感測器
但其實他不只可以感測人體,還可以感測動物等~
本魯:我是覺得它叫「動作感測器」會比較好啦~ ( •́ _ •̀)?

PIR Sensor 介紹

而 PIR Sensor 模組為「熱釋電傳感器(Pyroelectric sensor)」和「菲涅耳透鏡(Frenzel Lens)」所組成。
本魯的 PIR Sensor -
白色的鏡頭蓋為菲涅耳透鏡(Frenzel Lens)
在透鏡裡頭的 Sensor 就是 熱釋電傳感器(Pyroelectric sensor)

工作原理

世界上所有的物體都會發出熱能又稱「遠紅外線 - (Far Infrared,縮寫FIR)」
遠紅外線為不可見光,當中生物體可以以「熱」的形式感受存在。
因為人或動物(下簡稱目標物)都會發出熱能,
當目標物進入傳感器範圍,所發出的熱能會以紅外線的形式散發出來,
傳感器檢測到熱能與環境的溫度差,便開始輸出電位訊號,檢測目標物是否有運動的事件發生。
PIR 的全名為 Passive infrared sensor
其中 passive 術語名稱叫「無源」,又有被動的意思;

有源傳感器?無源傳感器?

斯斯有兩種,傳感器也有分兩種~
從工作原理來看,****
有源傳感器自身會輸出能量來檢測被測對象
無源傳感器則不會發出任何的能量,靠的是透過接收被測物發出的能量來檢測
PIR Sensor 就是透過接收人、動物發出來的熱能,因此「passive」便是這個意思~
(  ̄□ ̄) /    <( ̄ㄧ ̄ ) <( ̄ㄧ ̄ )

模組上的圓形塑膠蓋 - 「菲涅耳透鏡」

可以觀察模組上有一個白色的圓形塑膠物,那個是「菲涅耳透鏡」,
主要用來將外在的紅外線信號聚焦到熱釋電傳感器。

PIR 模組的結構

PIR 模組有兩個可變電阻,一個用來調整傳感器的靈敏度,另外一個用來調整延時時間
  • 靈敏度 (Sensitivity) - 有關觸發的距離
  • 延時時間 (Delay time) - 和觸發模式有關係

PIR 模組的兩種觸發模式

PIR 模組有兩種觸發的模式,
  • repeat-mode 可重複觸發模式
    Sensor 觸發輸出 high 訊號後,在延時時間內,
    如果有目標物在感應範圍內活動,會一直保持 high 訊號,
    直到目標物動作停止 Sensor 不再觸發,開始再算一次延時時間,延時時間結束訊號才會從 high 到 low。
  • non-repeat-mode 不可重複觸發模式
    即感應輸出 high 訊號後,會持續一段時間,
    這段期間內不會有進行任何偵測觸發的動作,時間結束後訊號自動從 high 到 low ;
PIR Sensor的模組後面有三個隻 Pin 腳,我們可以用跳線(Jumper)選擇觸發模式。

截圖自 - Youtube - How PIR Sensor Works and How To Use It with Arduino
相關連結:
本魯宅:痾…這個Sensor有點複雜…找了好多資料啊…(●▼●; )
原來這麼小小的一個感測器原理這麼複雜,好險電路方面很簡單…

硬體部分 - PIR 電路

電路方面

由於已經模組化,接線部分就只有3隻Pin腳分別是
  • VCC
  • Output
  • GND
PIR Sensor 的輸出腳選擇數位接腳即可。
介紹完後,我們開始來實作吧~
準備需要的東西有~ヽ(・×・´)ゞ

硬體方面

  • Arduino Uno 一片 + USB TypeB 線材一條 (標配~
  • PIR Sensor
  • 杜邦線 看你用幾條準備幾條

軟體部分

Johnny Five - Motion
http://johnny-five.io/examples/motion/
GO~ GO~( • ̀ω•́ )

使用寫法-範例

要使用 PIR Sensor 的話,需要呼叫 Johnny-Five 的 Motion 物件,
物件參數 pin 填連接 Arduino 的數位腳。

var motion = new five.Motion({
  pin: 7,
  // controller:XXX //  選填
});

如果使用特殊型號的 Sensor,controller則填寫如 Controller Alias Table 相對應的字串。
Johnny-Five 的 Motion 物件如果參數只有 pin 腳的話,則也可以簡寫成

new five.Motion(7);

Events

Johnny-Five Motion Events
http://johnny-five.io/api/motion/#events
event 除了有介紹過的 changedata,還多了
  • calibrated
    校準事件,當傳感器準備好在可觀察範圍內檢測運動時,將觸發 calibrated 事件。
  • motionstart
    運動開始事件,當在可觀察範圍內目標物發生運動時,觸發 motionstart 事件。
  • motionend
    停止運動事件,當在可觀察範圍內目標物停止運動時,觸發 motionend 事件。

實作 -

這邊要注意的是 calibrated 事件
當程式執行 board ready 後,傳感器會處於校準狀態
主要因為熱釋電傳感器物理性特徵的關係
因為傳感器需要幾秒的時間來預熱,才能開始感測接收目標物散發出的紅外線

var five = require('johnny-five');
var board = new five.Board();

board.on('ready', function() {
  var motion = new five.Motion({
    pin: '7',
    freq: 250,
  });

  // 開始時 Sensor 會處於校準狀態,最一開始的偵測到動作即觸發 calibrated 事件
  // calibrated 事件只會發生一次。
  motion.on('calibrated', function() {
    console.log('calibrated');
  });

  // 在calibrated 事件結束後,
  // 當在可觀察範圍內目標物發生運動時,觸發`motionstart`事件。
  motion.on('motionstart', function() {
    console.log('motionstart');
  });

  // 如果若干X毫秒內未發生移動時,
  // 將在`motionstart`事件之後觸發`motionend`事件
  motion.on('motionend', function() {
    console.log('motionend');
  });
});

可以看到執行程式,當 board on ready 後,初始化觸發 calibrated 事件,直到觸發 motionstart 事件後,calibrated 事件就不會在觸發了!
一個完整的觸發事件當
motionstart 事件開始 → 經過一段時間後 → 觸發motionend → 結束。

(欸~有貓亂入?)
PIR Sensor 就介紹到這囉~
今天講到這邊了~感謝收看~(๑´ㅂ`๑)

文後

今天去抓寶可夢走的好累…Orz

本系列的程式碼皆會上傳到 GitHub 上開源
喜歡按個星星吧~乾蝦乾蝦<(_ _)>

團隊系列文:

同步連載於blogger-King 學習前端之人生