---
# System prepended metadata

title: 防後倒中柱輪椅
tags: [Arduino]

---

# 防後倒中柱輪椅

###### tags: `Arduino`
[Arduino作品目錄](https://hackmd.io/KH0oMN6ZSiuiogFCy5s_mA)
## 概念簡述
設計一個輪椅輔助裝置，依照傾斜度自動伸出/收回輔助輪。
## 功能設計

### (P)套件需求
1. 傾斜儀 SW-520D
2. 伺服馬達 

### (P)功能描述
當輪椅要爬上坡而傾斜時，放下輔助輪穩定輪椅。
當輪椅回歸平路而歸正時，收回輔助輪還原狀態。

透過傾斜儀偵測坡度變化，根據變化模式結果來讓伺服器馬達轉動輔助輪，以控制輔助輪的伸出與收回兩個動作。

### (P)邏輯設計

從簡述可以得知，放下輔助輪的具體情境有兩種:

    1. 從平地走向有坡度時，需要放下輔助輪
    2. 從有坡度地走向平地時，需要收回輔助輪

由此可知，對於傾斜儀的==瞬間判定==結果，可以簡化為2種 :

    結果A: 傾斜度測定為斜坡地
    結果B: 傾斜度測定為平地

然而瞬間結果不足以判定當下狀況，所以我們讓傾斜儀以每`500ms`的間隔，依照測定5次傾斜度的結果來判定輪椅當下的傾斜狀態，有以下3種狀態 :

```
平地狀態 : 5次都是結果A，所以判定為目前輪椅處於平地
斜坡狀態 : 5次都是結果B，所以判定為目前輪椅處於斜坡地
不穩定狀態 : 5次內結果A跟結果B都有，判定為不穩定狀態
```

透過上述3種狀態，我們就能輕鬆來決定伸出/收回 輔助輪的情形。
```
伸出輔助輪: 上次偵測是平地狀態，但本次偵測是斜坡狀態
收回輔助輪: 上次偵測是斜坡狀態，但本次偵測是平地狀態
```


### (P)示意圖
```mermaid
graph TD;
偵測當前狀態-->判定狀態變化;
判定狀態變化-->平地變斜坡-放出輔助輪;
判定狀態變化-->斜坡變平地-收回輔助輪;
判定狀態變化-->其他狀態變化-不動作;
平地變斜坡-放出輔助輪-->繼續偵測當前狀態;
斜坡變平地-收回輔助輪-->繼續偵測當前狀態;
其他狀態變化-不動作-->繼續偵測當前狀態;
```
## 程式碼:
+ 實際套件組合完成後的接腳配置以程式碼為主
```cpp=
//引入套件所需要的函式庫
#include <Servo.h> 
#include <SoftwareSerial.h>
Servo motor;    //建立Servo物件，命名為motor，來使用裡面的功能(methods)
int sw520d_d0 = 2;    //傾斜儀SW-520D 接Pin2
int last_status = 2;  //全域變數，初始狀態設置為狀態2，即平穩狀態

//初始設定函式，僅會執行一次
void setup(){
  Serial.begin(9600);            //設置監控視窗頻鮑率為9600bps
  pinMode (sw520d_d0,INPUT);    //設置目前為傾斜儀pin2腳位為輸入模式
  motor.attach(9);             //透過 Pin 9 來控制伺服馬達
  motor.write(0);             //初始化伺服馬達角度=0
  delay(2000);               //等兩秒，再進行後續動作
}

//重複執行函式，會重複執行
void loop(){
    
  //呼叫自訂的偵測傾斜儀狀態函數 detect_status5sec()
  int current_status = detect_status5sec(sw520d_d0) ;
      
  //把兩個狀態變數從監控視窗印出來，方便檢測
  Serial.print("上個狀態");Serial.print(last_status);Serial.print("\n");
  Serial.print("目前狀態");Serial.print(current_status);Serial.print("\n");
  
  //both_equal:是否目前狀態與上個狀態不同
  bool both_equal = ( last_status != current_status );
  //both_not3:是否目前狀態與上個狀態都不是不穩定狀態
  bool both_not3  = ( last_status != 3 && current_status != 3 );
    
  if(both_equal && both_not3) //上面兩個條件都滿足
  {
      Rotate( last_status, current_status);//執行轉動功能
   }//if
  
  if(last_status!=3 && current_status!=3)last_status=current_status; //若非狀態三，則儲存狀態。本行極度重要
    
}//loop()



/*函數detect_status5sec:
 * 偵測多次當下結果來評斷傾斜狀態
 * 傾斜儀偵測結果有三種狀態
 * 狀態1: 在偵測期間都是傾斜的，回傳1來表示為狀態1
 * 狀態2: 在偵測期間都是不傾斜，回傳2來表示為狀態2
 * 狀態3: 在偵測期間傾斜不傾斜都有出現，回傳3表示為狀態3
 * */
int detect_status5sec(int sw520d_d0){
    
    int tiltControl = digitalRead(sw520d_d0);
    int count=0;//用來算有幾次偵測為傾斜
    int dt=5; //設置偵測次數
    int ms=500;//設置每次偵測間隔多少毫秒

    //執行迴圈，跑dt次偵測，每次偵測間隔ms秒
    for (int i=0;i<dt;i++)
    {
        //若傾斜則成立
      if (tiltControl == HIGH)
      {
        count+=1 ;
      }
      delay(ms);
    }
    
    if(count==5)
      return 1;//都是傾斜，回傳1
    else if (count==0)
      return 2;//都不傾斜，回傳2
    else 
      return 3;//傾斜不傾斜都有，回傳3
    
  }

/*
 * 函數Rotate:
 * 確認情況後轉動馬達或不轉動馬達，來完成伸出/收回輔助輪
 * 1表示處於斜坡地
 * 2表示處於平地
 * 3表示處於晃動中不穩定的狀態
 * 由1變2:表示要回歸0度，收回輔助輪
 * 由2變1:表示要轉到105度，伸出輔助輪
 */
void Rotate(int last,int now){


  if(last==1 and now==2){
      motor.write(0);
    }
  else if (last==2 and now==1){
      motor.write(105);
    }
    
    delay(2000);//轉完等個2秒
  
  }
 

```
### 測試用影片
>傾斜儀感測不傾斜時亮綠燈，傾斜時不亮綠燈

{%youtube XhxbjlHMQT4 %}