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

總網頁瀏覽量

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

顯示具有 #Arduino 標籤的文章。 顯示所有文章
顯示具有 #Arduino 標籤的文章。 顯示所有文章

2019/10/14

[2019鐵人賽] - 29.筆記IoT初練習- 用 Joystick 讓熊俠飛向鐵人賽終點! - Johnny Five 之 Joystick 搖桿 - 遊戲(?)應用篇


本魯宅:第29篇了~時間真的過的好快啊~
謎之音:(ΦωΦ) 

今天要寫的是~下音樂~
登登楞登~登登~ (多拉A夢的音效)

「邁向終點吧!鐵人熊俠!」ᕙ(˵ ಠ ਊ ಠ ˵)ᕗ 


謎之音:不就是之前的光敏電阻篇改一下嗎....
本魯宅:不!我加了動畫~(被打)

故事是這樣開始的…

本系列結束前,一直讓我念念不忘的留言~
記得有位邦友是這樣說的~


我們的邦友總是那麼熱情的來留言!XD
本魯心之音:但看到這則留言我好害怕RRR.......這....這本魯寫不出來吧.....

好在這位邦友說他明年要寫~我們謝謝他~
真.勇者工程師要創造新的遊戲平台了!!(欸欸!不對吧 X

好吧!那我來為你指引道路吧~(欸!就和你說不對吧(被打~

怎麼做?想法是這樣的~

昨天使用 Joystick 物件 X 軸和 Y 軸變化時會返回 大約 -1~1 的數值 ,
我們就用這個數值來讓熊俠飛起來!

怎麼利用呢?
這次我們用 CSS3 的 transform:translate(x,y); 屬性來改變小熊在頁面上的位置!

先從網頁解構來看~

初始化 - 中心點

這次要讓熊俠飛來飛去,假設遊戲一開始設定在網頁中心點出發
首要我們要取得網頁的中心點位置!

User 的瀏覽器視窗大小不會一樣大,那中心點的數值也會因人而異!
所以這次要用 JavaScript 來取得視窗的寬高數值,
取得總視窗高度後在除上 2 就是中心點位置,XY 軸都使用相同步驟。


熊俠的位置 - 移動變量
移動熊俠需要可變的數值,我們從 Arduino 那邊取得 Joystick 的數值後加以處理,
由昨天可知 Joystick 數值可能為負值,可能為正值 又落在 -1 ~ +1 之間,
故
熊俠的移動量變數 = Joystick 回傳的數值 * 視窗中心點位置
這邊是把 Joystick 移動了多少轉成在視窗上的移動多少的位置

接下來
當前熊俠的位置 =  視窗中心點 + 熊俠的移動量變數
最後只要把剛剛熊俠移動了多少加上視窗中心點的位置,就會變成現在熊俠飛到的位置了!

本魯宅:484很簡單啊~
謎之音:屁啦!!!

恩....只是要腦筋要轉一下而已啦....我也是在紙上畫出來想了一下才想好的....

(燒腦........



由於我們上次就切好版了!這次直接進入程式吧~(๑•̀ㅂ•́)و✧

後端部分

我們取 Joystick 的數值,這次有X軸與Y軸的兩個數值,用 Socket.io 傳給前端接收;
```
  socket.emit('startData', {
    jXAxis: jXAxis,
    jYAxis: jYAxis,
  });
});
```

完整程式碼:
```
  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 joystick = new five.Joystick({
      //   [ x, y ]
      pins: ['A0', 'A1'],
    });

    sio.on('connection', function(socket) {
      joystick.on('change', function() {
        console.log('  x : ', this.x);
        console.log('  y : ', this.y);
        jXAxis = this.x;
        jYAxis = this.y;
        socket.emit('startData', {
          jXAxis: jXAxis,
          jYAxis: jYAxis,
        });
      });
    });
  });
``` 

前端部分

這次有加上看起來像遊戲的元素,
像是鐵人鍊成啦~歷年來我的鐵人鍊成獎牌啊~(不是炫耀X

HTML
```
  <div class="bg">
    <div class="top"></div>
    <div class="someimg">
      <img class="flag" src="img/flag.png" alt="" />
      <img class="iron iron1" src="img/iron1.png" alt="" />
      <img class="iron iron2" src="img/iron2.png" alt="" />
    </div>
    <div class="bear"><img src="img/bear-fly.svg" alt="" /></div>
    <div class="footer"><img src="img/footerbg.png" alt="" /></div>
    <div class="bell">
      <p>訂閱下去 - IoT沒那麼難!新手用JavaScript入門做自己的玩具~</p>
    </div>
  </div>
``` 

CSS Style 
這次我們使用 CSS 的 transform:translate 屬性,來改變熊俠的位置!

```css
// 定義平移 2D 元素
transform:translate(x,y);
``` 

改變的數值就和上面寫的一樣,
joystick移動量轉為元素平移量算出後,利用jQuery 的 .css() 函式改變小熊位置即可!

> translate 的 x 為 Joystick 的 X 軸移動量,
> translate 的 y 為 Joystick 的 Y 軸移動量;

這次還有在一些 HTML 元素加上 CSS 動畫,看起來比較像遊戲~
CSS 動畫取用自
>   Animate.css
https://daneden.github.io/animate.css/

JavaScript

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

  var xCenter = $('.bg').width() / 2; // 取得水平中心點
  var yCenter = $('.bg').height() / 2; // 取得垂直中心點

  socket.on('startData', function(data) {
    // 當socket開始連線時,接收資料
    // console.log(data);
    XAxis = data.jXAxis;
    YAxis = data.jYAxis;

    XVal = XAxis.toFixed(2);  // 取到小數點後兩位數
    YVal = YAxis.toFixed(2);  // 取到小數點後兩位數

    varXVal = XVal * xCenter; // 取 joystick X軸移動量,轉成視窗元素 X軸 移動量
    bearXPos = xCenter + varXVal; // 熊俠 X軸 的位置

    varYVal = YVal * yCenter; // 取 joystick Y軸移動量,轉成視窗元素 Y軸 移動量
    bearYPos = yCenter + varYVal; // 熊俠 Y軸 的位置
   
    // 使用 jQ .css()函式改變熊俠位置
    $('.bear').css(
      'transform',
      'translate(' + bearXPos + 'px, ' + bearYPos + 'px',
    );
  });
```  

開啟網頁 → 利用 `.width()` 和 `.height()` 取得頁面總寬、總高 → 總寬和總高後除上`2`,取得頁面中心點 → 當 Socket 開始與後端連線後 → 取得 Joystick 移動量 → 一連串的轉換與計算後 → 使用jQ.css()函式改變熊俠的位置 → 完成ヽ(・×・´)ゞ



寫到這邊~
鐵人賽也告一段落了,很謝謝一直關注我的邦友、朋友們,
沒有你們的支持與文章留言,回饋給我一些想法或者鼓勵,
也許我不會那麼有動力與好玩的想法出來~

感謝在感謝!那麼明日結語見了!(淚 QQ

2019/10/13

[2019鐵人賽] - 28.筆記IoT初練習- 上上下下左右左右BA~ - Johnny Five 之 Joystick 搖桿 - 簡介篇


搖桿~也就是俗稱的香菇頭!

身為一個魯宅,一定都要有一台遊戲機假日宅在家!
但遊戲控制器你了解多少呢?

今天要來介紹的就是!(∩▲o▲)⊃━☆゚.*・。 
香菇頭搖桿 -  Joystick

~~不關技術文的小抱怨:本魯的任天堂 Switch Joy-Cony 左右搖桿都會出現漂移!齁~氣氣氣氣氣!※後來用民間偏方噴 WD-40 好了~~

簡介 

Joystick 的結構含有自我居中的彈簧,讓操控搖桿放掉時可以回到中心位置,
外蓋則是一個杯型的塑膠蓋,人能用拇指來舒適的操控~

工作原理  


Joystick 是一個類比輸入裝置,能將2軸(X軸 與 Y軸)的運動傳遞給Arduino,
其工作原理為當操控 Joystick 改變方向時,就代表改變該軸的電阻值,也可以用兩顆可變電組來模擬 Joystick 的雙軸動作!

有圖有真相!
本魯使用三用電表來量測改變 Joystick 方向時,電阻值的變化
> PS:但我錄完才發現拿錯方向了Orz...
所以左右為 Y 軸,上下為 X 軸 抱歉抱歉....

### Y 軸

可以看到搖桿在中心點時,初始電阻值為 3KΩ 左右,
當我往右時電阻值會增加(約 1KΩ 左右),當我往左時電阻值減少(約 2.9KΩ 左右)


### X 軸

搖桿在中心點時,初始電阻值為 3KΩ 左右,
當我往上時電阻值會增加,當我往下時電阻值減少。



相關連結:
How 2-Axis Joystick Works & Interface with Arduino + Processing

這樣應該比較清楚了吧~(應該吧.....(ง๑ •̀_•́)ง


硬體部分

電路方面

Joystick 模組的接腳有 

- Vcc - 電壓供給
- GND - 接地
- VRX - X 軸輸出
- VRY - Y 軸輸出
- SW - 按鈕(for 可按下去的 Joystick)

電路圖

接下來我們來介紹 Johnny - Five 的部分~實作吧!
準備需要的東西有~ヽ(・×・´)ゞ

硬體方面

- Arduino Uno 一片 + USB TypeB 線材一條 
- 杜邦線 看你用幾條準備幾條
- Joystick 一個 

軟體方面  

> Johnny-Five - Joystick

參數&寫法


pins 為必要參數,寫法為陣列表示 [ X , Y ]

new five.Joystick({ // [ x, y ] pins: ["A0", "A1"] });



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/03

[2019鐵人賽] - 20.筆記IoT初練習- 小財神啊!你看見那個鐵人在惡搞iT邦熊俠嗎?Johnny Five 之 光敏電阻- 小遊戲(?)應用篇


上篇本來想做中二的小夜燈 ......
但我看到光敏電阻的輸出數值後,突然覺得好像可以做更有(ㄨˊ)趣(ㄩㄥˋ)的東西XDDD

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

Flappy iT Bear (☝ ՞ਊ ՞)☝


謎之音:這蝦.....餃朋友啦XD
本魯:我果然是很無聊的魯宅啊~科科~

不過做出來有莫名的成就感,現在就跟著我一起浪費才能吧~ヽ(・×・´)ゞ

故事是這樣開始的.......

昨天寫完光敏電阻後,心裡覺得有點空虛....
就這麼剛好撇到每天都會看到 iT 邦幫忙鐵人賽 首頁,有個野生的小熊(?)在那邊上上下下的動...


突然靈光一閃 (✪ω✪)
如果用光敏電阻的連續數值,應該可以做的像 Flappy Bird 一樣的遊戲吧XDD

於是....就是決定是你啦!(ΦωΦ) (小財神不要打我 X


身為一個開發者,要抓熊是很簡單的~
把 Dev Tool 打開後一個 Move 小熊就被我 Download 下來了 (  ̄ 3 ̄)y▂ξ

抓完熊後,
身為一個開發者擁有好奇心是 hen 正常的
心之音:這個網頁做(ㄙㄨˋ)的(ㄘㄞˊ)不(ㄏㄣˇ)錯(ㄉㄨㄛ)耶~


嗯~這山 這草 這場景都不錯耶~我全都要了 ლ(╹◡╹ლ)

怎麼玩?想法是這樣的~

我的想法是熊俠會像 flappy bird 的動作機制。

flappy bird需要點擊才會飛一下,

熊俠則是光照一下才會飛一下,如果沒有光照就飛不起來~


想法是這樣的,解構網頁給你們看~


現在我們有草、小熊、背景,就可以做出小熊從草叢飛起來的假象XD
利用 CSS 的 Z 軸 順序,依序把場景物件給定位好~

快速的切好後,網頁長這樣子

---
>工商時間:
想更快速的切好版嗎?每天20分鐘內讓你學到大絕招!
趕快訂閱 Amos 老師的
金魚都能懂的這個網頁畫面怎麼切 - 金魚都能懂了你還怕學不會嗎 系列
讓你切版比我快~
---


接下來要進入程式啦~(๑•̀ㅂ•́)و✧

後端部分

和昨天一樣,我們取光敏電阻的數值加上用 Socket.io 傳給前端接收;
唯一要改的是偵測的頻率可以改快一點,我就設0.25秒輸出一次數值好了~

小熊的動作就由前端來處理 d( ・∀・)b

```
  photoresistor = new five.Sensor({
    pin: 'A0',
    freq: 250,
  });
```


> 程式碼
```
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() {
  photoresistor = new five.Sensor({
    pin: 'A0',
    freq: 250, // 改成0.25秒輸出一次數值
  });

  sio.on('connection', function(socket) {
    photoresistor.on('data', function() {
      pVal = this.value; // 取得數值
   
      //透過socket傳給Clinet端(前端)
      socket.emit('startData', {
        pVal: pVal,
      });
    });
  });
});

```

前端部分


讓小熊飛起來的關鍵是 CSS 的 `position` 定位!
先來看完整的HTML架構

> HTML
```
<body>
  <div class="bg">
    <div class="top"></div>
    <div class="bear"><img src="img/bear-fly.svg" alt="" /></div>
    <div class="footer"><img src="img/footerbg.png" alt="" /></div>
    <div class="bell">
      <p>訂閱下去 - IoT沒那麼難!新手用JavaScript入門做自己的玩具~</p>
    </div>
  </div>
  <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>
```


HTML部分比較簡單,
最外層的 < div class='bg' > 為被定位點,絕對定位在網頁的左上角 top:0 left:0 的地方,
再由 top、bear、footer 定位在 bg 上。

```
<!-- 先設定好絕對定位 position:relative; 讓小熊之後以相對定位來使用-->
<div class="bg">
  <div class="top"></div>
  <div class="bear"><img src="img/bear-fly.svg" alt="" /></div>
  <div class="footer"><img src="img/footerbg.png" alt="" /></div>
  <div class="bell">
    <p>訂閱下去 - IoT沒那麼難!新手用JavaScript入門做自己的玩具~</p>
  </div>
</div>
```

```
<!-- 定位點依附著 <div class="bg"> -->
  <div class="top"></div>
  <div class="bear"><img src="img/bear-fly.svg" alt="" /></div>
  <div class="footer"><img src="img/footerbg.png" alt="" /></div>
```

設置CSS樣式表


> CSS

```
.bg {
  position: relative;
  width: 100vw;
  height: 100%;
  top: 0;
  left: 0;
}
.top {
  position: absolute;
  width: 100%;
  height: 100vh;
  top: 0;
  left: 0;
  background: url('img/background.jpg');
  background-repeat: no-repeat;
  background-origin: border-box;
  background-position: center;
  background-size: cover;
}
.bear {
  position: absolute;
  width: 100px;
  height: auto;
  /* top: 0; */
  left: 50%;
  transition-duration: 0.5s;
}
.footer {
  position: absolute;
  width: 100vw;
  height: auto;
  top: 70%;
  left: 0%;
}
```
把 top、bear、footer 依照相對位置 position: absolute; 定位後
小熊要上下動像超人一樣飛行,利用設定 CSS 的 `top` 屬性讓小熊上下動作~


謎之音:可是小熊看起來 頓ㄉㄟ 頓ㄉㄟ 的欸......
本魯:這就是關鍵啦~

CSS有一個很棒的屬性叫 `transition-duration` -「轉場動畫時間」

> MDN:CSS transition-duration
> https://developer.mozilla.org/zh-TW/docs/Web/CSS/transition-duration

我們變化小熊的 top 定位時設定 `transition-duration` 的時間來延遲轉場動畫,
這樣動作看起來比較順暢~



解決完小熊的飛行動作後,做到這邊也差不多半成品啦~ (  ´Д`)y━・~
接下來是前端 JavaScript 的部分

> JavaScript

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

socket.on('startData', function(data) {
  // 當socket開始連線時,接收資料
  tempData = data.pVal;
  // 把接收到的值變成百分比
  topPosition = tempData / 10;
  // 有時候數值會超過100,可處理可不處理
  if (topPosition >= 100) {
    topPosition = 100;
  }
  // 調用jQuery的.css()函式來改變熊的垂直定位
  $('.bear').css('top', '' + topPosition + '%');
});


```

程式碼比 CSS 還要簡單 XD

昨天已知光敏電阻的數值大約在 1000 ~ 100 之間,
而我們熊的垂直定位單位使用比較彈性的百分比 ,
才不會因為視窗大小、伸縮跑版不見,ㄌㄧ在JavaScript上也比較好寫~

讓數值落在 100 之內,只要把前端接收到的數值除上 10 就可以了。
```
  // 原始數值
  tempData = data.pVal;
  // 把接收到的值變成百分比
  topPosition = tempData / 10;
  // 有時候數值會超過100,可處理可不處理
  if (topPosition >= 100) {
    topPosition = 100;
  }
```
最後一步,
在用 jQuery 的 .css() 函式改變熊的垂直定位數值就可以啦~

```
//第一個參數填CSS屬性名稱(propertyName),第二個參數填上數值(value)
.css(propertyName, value)
```

> jquery - .css()
https://api.jquery.com/css/#css-propertyName-value

這樣就完成啦! (*´∀`)~♥
超簡單又無用的小玩具XD



如果再加上一些障礙物物件讓熊俠像 flappy bird 的水管一樣,例如寫鐵人文的時間啦、寫鐵人賽時會出現的立志句子啦~那就更好玩了XD

甚至,我有個大膽的想法,可以製作各種 Sersor 的闖關遊戲!
因為看到邦友挖洗菜呱的鐵人文 「每日挖個坑,用坑填起耍廢聊天室! 」系列
讓多名User利用Socket連線一起玩,抽 Sensor 闖不同的關卡,是不是一種商機呢?
(才不會勒~(寫文寫到腦洞大開.....

好吧~
前端工程師的生活,往往就是這麼樸實無華,且枯燥~

今天就到這啦~明天又不知道要寫什麼了.....



2019/10/02

[2019鐵人賽] - 19.筆記IoT初練習- 用JS控制Arduino吧!聖光啊!你看見那個鐵人了嗎?Johnny Five 之 光敏電阻 Photoresistor


我絕對不會說我玩過暗黑3  (´∩ω∩`) 

Sensor 篇第二彈!今天要介紹的是

光 敏 電 阻  ~

謎之音:這...可以幹嘛...
本魯宅:做小夜燈.....不!我們要做中二的小夜燈!(●` 艸 ´)

Photoresistor 光敏電阻 介紹

光敏電阻是一種利用「光電導效應」使電阻值變化的特殊電阻。
光敏電阻和入射光強弱有直接關係,
當光強度增加,則電阻減小;光強度減小,則電阻增大。

工作原理

光敏電阻內有處於穩定狀態的電子~
但當有光線照射時,穩定狀態的電子受到激發而成為自由電子,自由電子愈多電阻就會越小。
恩....原理了解一下就好~(大誤

相關資料:
> 維基百科 - 光敏電阻

電路方面

光的強弱也是連續的類比訊號。
所以我們要把光敏電阻的 pin 腳接到 Arduino 的類比輸入腳(Analog IN)。
這邊要注意的是!

因為光敏電阻也是電阻的一種,當光照越強,它的電阻也會越小;
依照歐姆定律來說,電阻也會越小就表示流過的電流就會越大,而導致Arduino板子燒毀...

所以我們必須要在使用之前加上一顆限流電阻,保障板子的不被燒毀。
> 歐姆定律 公式
V = I*R
當電壓不變時,電流和電阻成反比;
電阻越小 電流愈大

手算給你看!

不好意思....字很醜很久沒寫字了.....Orz

> 附上電路圖

介紹完後,我們開始來實作吧~
準備需要的東西有~ヽ(・×・´)ゞ

硬體方面

- Arduino Uno 一片 + USB TypeB 線材一條 (標配!~
- 電阻一顆 10KΩ 電阻色碼:棕黑橙金
- 杜邦線 看你用幾條準備幾條

軟體部分

> Johnny Five - photoresistor
http://johnny-five.io/examples/photoresistor/

開始吧!(  ̄□ ̄)/  <( ̄ㄧ ̄ ) <( ̄ㄧ ̄ )

使用寫法-範例

這次的程式比較簡單,用 Johnny-Five 的 Sensor 元件即可,寫法和昨天一模一樣~

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

board.on('ready', function() {
  // new 一個 Johnny-Five Sensor 物件,宣告為 photoresistor
  photoresistor = new five.Sensor({
    pin: 'A0',
    freq: 1000,
  });

  photoresistor.on('data', function() {
    // 讀取光敏電阻的值
    console.log(this.value);
  });
});

```

一樣 node 執行程式下去~



可以看到 0.5 秒偵測一次數值~
(*限流電阻用110Ω的話)
一開始的環境光數值大概在 700 ~ 800,我遮住光敏電阻後阻斷光線,數值會標高到900多,光敏電阻接收強光後數值降到200 ~ 400之間。

恩~這個數值好像可以拿來做什麼玩具.....嘿嘿嘿~( ≖◞౪◟≖)
明天我們來玩一個好玩的,敬請期待XD