WioLTEでGroveセンサを使うサンプルをいくつかまとめてみた


[Wio cell lib for Arduino / Wio 3G / Wio LTE M1/NB1(BG96)](https://seeedjp.github.io/Wiki/Wio_cell_lib_for_Arduino/home-ja.html)を使ってGroveセンサを使うサンプルを書いてみました。

## PIRモーションセンサを利用するサンプル

### 配線

WioLTEのD38ポートにセンサを接続

### サンプルスケッチ


```pir.ino
#include <WioCellLibforArduino.h>

#define PIR_MOTION_SENSOR WIO_D38 //D38番ポートを使用
#define DELAYTIME 200 //センサーを検知させる間隔ミリ秒

void setup(){
    SerialUSB.begin(115200);
    pinMode(PIR_MOTION_SENSOR, INPUT);
}

void loop(){
    //センサーが人の動きを検知すると反応
    if(digitalRead(PIR_MOTION_SENSOR)){
        SerialUSB.print("人が来ました!!");
    }else{
        SerialUSB.println("監視中...");
    }
    
    delay(DELAYTIME);
}
```

## ブザーを利用するサンプル

### 配線

WioLTEのD38ポートにセンサを接続

### サンプルスケッチ

```buzzer.ino
#include <WioCellLibforArduino.h>
#define BUZZER_PIN WIO_D38

void setup(){
  pinMode(BUZZER_PIN, OUTPUT);
}

void loop(){
  digitalWrite(BUZZER_PIN, HIGH);
  delay(1000);
  digitalWrite(BUZZER_PIN, LOW);
  delay(1000);
}
```

* A6で利用する

`Wio.PowerSupplyGrove(true);`をすればA6なども使えます。

```buzzer.ino
#include <WioCellLibforArduino.h>
WioCellular Wio;
#define BUZZER_PIN WIO_A6

void setup(){
  SerialUSB.begin(115200);
  SerialUSB.println("--- START ---------");
  SerialUSB.println("### I/O Initialize.");
  Wio.Init();

  SerialUSB.println("### Power supply ON.");
  Wio.PowerSupplyGrove(true);
  delay(500);

  SerialUSB.println("### Sensor Initialize.");
  pinMode(BUZZER_PIN, OUTPUT);
  
  SerialUSB.println("### Setup completed.");
}

void loop(){
  digitalWrite(BUZZER_PIN, HIGH);
  delay(1000);
  digitalWrite(BUZZER_PIN, LOW);
  delay(1000);
}
```

## Tilt Switchを利用するサンプル

### 配線

WioLTEのD38ポートにセンサを接続

### サンプルスケッチ

```tilt.ino
#include <WioCellLibforArduino.h>
#define TILT_PIN WIO_D38

void setup(){
    pinMode(TILT_PIN, INPUT);
    SerialUSB.begin(115200);
}

void loop(){
    if (digitalRead(TILT_PIN)==HIGH){
        SerialUSB.println("検知");
        delay(200);
    }
    
    SerialUSB.println(".");
    delay(500);
}
```

* D20の場合

```tilt.ino
#include <WioCellLibforArduino.h>
WioCellular Wio;

#define TILT_PIN WIO_D20

void setup(){
    SerialUSB.begin(115200);
    SerialUSB.println("--- START ---------");
    SerialUSB.println("### I/O Initialize.");
    Wio.Init();
    
    SerialUSB.println("### Power supply ON.");
    Wio.PowerSupplyGrove(true);
    delay(500);

    SerialUSB.println("### Sensor Initialize.");
    pinMode(TILT_PIN, INPUT);

    SerialUSB.println("### Setup completed.");
}

void loop(){
    if (digitalRead(TILT_PIN)==HIGH){
        SerialUSB.println("検知");
        delay(200);
    }
    
    SerialUSB.println(".");
    delay(500);
}
```

## Lightセンサを利用するサンプル

### 配線

WioLTEのA6ポートにセンサを接続

### サンプルスケッチ

```light.ino
#include <WioCellLibforArduino.h>
WioCellular Wio;

#define LIGHT_PIN WIO_A6

void setup(){
  SerialUSB.begin(115200);
  SerialUSB.println("--- START ---------------------------------------------------");
  SerialUSB.println("### I/O Initialize.");
  Wio.Init();
  
  SerialUSB.println("### Power supply ON.");
  Wio.PowerSupplyGrove(true);
  delay(500);

  SerialUSB.println("### Sensor Initialize.");
  pinMode(LIGHT_PIN, INPUT_ANALOG);

  SerialUSB.println("### Setup completed.");
}

void loop(){
  int value = analogRead(LIGHT_PIN);
  SerialUSB.println(value);
  delay(1000);
}
```

## 3軸加速度センサ1.5gを利用する手順

### 配線

WioLTEのI2Cポートにセンサを接続

### サンプルスケッチ

```3axis.ino
#include <WioCellLibforArduino.h>
#include "MMA7660.h"

#define INTERVAL    (1000)
#define MMA7660TIMEOUT  500         // us

#define ARDUINO_WIO_LTE_M1NB1_BG96

WioCellular Wio;
MMA7660_LOOKUP accLookup[64];

void setup() {
  delay(200);
  
  SerialUSB.begin(115200);
  SerialUSB.println("");
  SerialUSB.println("--- START ---------------------------------------------------");

  SerialUSB.println("### I/O Initialize.");
  Wio.Init();
  
  SerialUSB.println("### Power supply ON.");
  Wio.PowerSupplyGrove(true);
  delay(500);

  SerialUSB.println("### Sensor Initialize.");
  MMA7660init();

  SerialUSB.println("### Setup completed.");
}

void loop() {
  int8_t x;
  int8_t y;
  int8_t z;
  float ax,ay,az;
  getXYZ(&x,&y,&z);
  
  SerialUSB.print("x = ");
  SerialUSB.println(x); 
  SerialUSB.print("y = ");
  SerialUSB.println(y);   
  SerialUSB.print("z = ");
  SerialUSB.println(z);
  
  getAcceleration(&ax,&ay,&az);
  SerialUSB.println("accleration of X/Y/Z: ");
  SerialUSB.print(ax);
  SerialUSB.println(" g");
  SerialUSB.print(ay);
  SerialUSB.println(" g");
  SerialUSB.print(az);
  SerialUSB.println(" g");
  SerialUSB.println("*************");
  delay(INTERVAL);

}


// 以下は加速度センサ（MMA7660）制御用の関数です。
// Arduino Uno向けサンプルライブラリを今回のWio LTEで動作するように移植しています。
// https://github.com/Seeed-Studio/Accelerometer_MMA7660/
//////////////////////////////////////////

/*Function: Write a byte to the register of the MMA7660*/
void MMA7660write(uint8_t _register, uint8_t _data) {
    WireI2C.begin();
    WireI2C.beginTransmission(MMA7660_ADDR);
    WireI2C.write(_register);
    WireI2C.write(_data);
    WireI2C.endTransmission();
}

/*Function: Read a byte from the regitster of the MMA7660*/
uint8_t MMA7660read(uint8_t _register) {
    uint8_t data_read;
    WireI2C.begin();
    WireI2C.beginTransmission(MMA7660_ADDR);
    WireI2C.write(_register);
    WireI2C.endTransmission();
    WireI2C.beginTransmission(MMA7660_ADDR);
    WireI2C.requestFrom(MMA7660_ADDR,1);
    while(WireI2C.available())
    {
        data_read = WireI2C.read();
    }
    WireI2C.endTransmission();
    return data_read;
}

// populate lookup table based on the MMA7660 datasheet at http://www.farnell.com/datasheets/1670762.pdf
void initAccelTable() {
    int i;
    float val, valZ;

    for (i = 0, val = 0; i < 32; i++) {
        accLookup[i].g = val;
        val += 0.047;
    }

    for (i = 63, val = -0.047; i > 31; i--) {
        accLookup[i].g = val;
        val -= 0.047;
    }

    for (i = 0, val = 0, valZ = 90; i < 22; i++) {
        accLookup[i].xyAngle = val;
        accLookup[i].zAngle = valZ;

        val += 2.69;
        valZ -= 2.69;
    }

    for (i = 63, val = -2.69, valZ = -87.31; i > 42; i--) {
        accLookup[i].xyAngle = val;
        accLookup[i].zAngle = valZ;

        val -= 2.69;
        valZ += 2.69;
    }

    for (i = 22; i < 43; i++) {
        accLookup[i].xyAngle = 255;
        accLookup[i].zAngle = 255;
    }
}

void MMA7660init()
{
    initAccelTable();
    setMode(MMA7660_STAND_BY);
    setSampleRate(AUTO_SLEEP_32);
    setMode(MMA7660_ACTIVE);
}

void MMA7660init(uint8_t interrupts)
{
    initAccelTable();
    setMode(MMA7660_STAND_BY);
    setSampleRate(AUTO_SLEEP_32);
    MMA7660write(MMA7660_INTSU, interrupts);
    setMode(MMA7660_ACTIVE);
}
void setMode(uint8_t mode) {
    MMA7660write(MMA7660_MODE,mode);
}
void setSampleRate(uint8_t rate) {
    MMA7660write(MMA7660_SR,rate);
}

/*Function: Get the contents of the registers in the MMA7660*/
/*          so as to calculate the acceleration.            */
bool getXYZ(int8_t *x,int8_t *y,int8_t *z)
{
    
START:

    unsigned char val[3];
    int count = 0;
    val[0] = val[1] = val[2] = 64;
    while(WireI2C.available() > 0)
    WireI2C.read();

    WireI2C.requestFrom(MMA7660_ADDR,3);

    unsigned long timer_s = micros();

    while(WireI2C.available())
    {
        if(count < 3)
        {
            while ( val[count] > 63 )  // reload the damn thing it is bad
            {
                val[count] = WireI2C.read();

                if(micros()-timer_s > MMA7660TIMEOUT)
                {
                    goto START;
                }
            }
        }
        count++;
    }

    *x = ((int8_t)(val[0]<<2))/4;
    *y = ((int8_t)(val[1]<<2))/4;
    *z = ((int8_t)(val[2]<<2))/4;
    
    return 1;
}

bool getAcceleration(float *ax,float *ay,float *az)
{
    int8_t x,y,z;
    if(!getXYZ(&x,&y,&z))return 0;
    *ax = x/21.00;
    *ay = y/21.00;
    *az = z/21.00;
    
    return 1;
}

bool getAcceleration(MMA7660_ACC_DATA *data) {

    unsigned char val[3];
    int count;
    bool error;

    unsigned long timer_s = micros();
    do {
        error = false;
        count = 0;

        while(WireI2C.available() > 0) {
            WireI2C.read();
        }

        WireI2C.requestFrom(MMA7660_ADDR, 3);
        while(WireI2C.available()) {
            if (count < 3) {
                val[count] = WireI2C.read();
                if (val[count] == 0x40) { // alert bit is set, data is garbage and we have to start over.
                    error = true;
                    break;
                }
            }
            count++;
        }
        
        if(micros()-timer_s > MMA7660TIMEOUT)return 0;
    } while (error);

    (*data).x = accLookup[val[0]];
    (*data).y = accLookup[val[1]];
    (*data).z = accLookup[val[2]];
    
    return 1;
}
//////////////////////////////////////
```

### ヘッダ追加

作成したinoファイルと同じフォルダに`MMA7760.h`という名前のファイルを作成し、

![](https://i.gyazo.com/d268b7c855093c5660c65377bb886e8b.png)

以下の内容をコピペ

```MMA7760.h
/*
 * MMA7760.h
 * Library for accelerometer_MMA7760
 *
 * Copyright (c) 2013 seeed technology inc.
 * Author        :   FrankieChu
 * Create Time   :   Jan 2013
 * Change Log    :
 *
 * The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#ifndef __MMC7660_H__
#define __MMC7660_H__

#define MMA7660_ADDR  0x4c

#define MMA7660_X     0x00
#define MMA7660_Y     0x01
#define MMA7660_Z     0x02
#define MMA7660_TILT  0x03
#define MMA7660_SRST  0x04
#define MMA7660_SPCNT 0x05
#define MMA7660_INTSU 0x06
  #define MMA7660_SHINTX 0x80
  #define MMA7660_SHINTY 0x40
  #define MMA7660_SHINTZ 0x20
  #define MMA7660_GINT 0x10
  #define MMA7660_ASINT 0x08
  #define MMA7660_PDINT 0x04
  #define MMA7660_PLINT 0x02
  #define MMA7660_FBINT 0x01
#define MMA7660_MODE  0x07
  #define MMA7660_STAND_BY 0x00
  #define MMA7660_ACTIVE   0x01
#define MMA7660_SR    0x08      //sample rate register
  #define AUTO_SLEEP_120  0X00//120 sample per second
  #define AUTO_SLEEP_64   0X01
  #define AUTO_SLEEP_32   0X02
  #define AUTO_SLEEP_16   0X03
  #define AUTO_SLEEP_8    0X04
  #define AUTO_SLEEP_4    0X05
  #define AUTO_SLEEP_2    0X06
  #define AUTO_SLEEP_1    0X07
#define MMA7660_PDET  0x09
#define MMA7660_PD    0x0A

struct MMA7660_DATA {
  uint8_t X;
  uint8_t Y;
  uint8_t Z;
  uint8_t TILT;
  uint8_t SRST;
  uint8_t SPCNT;
  uint8_t INTSU;
  uint8_t MODE;
  uint8_t SR;
  uint8_t PDET;
  uint8_t PD;
};

struct MMA7660_LOOKUP {
  float g;
  float xyAngle;
  float zAngle;
};

struct MMA7660_ACC_DATA {
  MMA7660_LOOKUP x;
  MMA7660_LOOKUP y;
  MMA7660_LOOKUP z;
};

class MMA7660 {
private:
  void write(uint8_t _register, uint8_t _data);
  uint8_t read(uint8_t _register);
  void initAccelTable();

  MMA7660_LOOKUP accLookup[64];

public:
  void init();
  void init(uint8_t interrupts);
  void setMode(uint8_t mode);
  void setSampleRate(uint8_t rate);

  // get the signed value of x,y,z register
  bool getXYZ(int8_t *x,int8_t *y,int8_t *z);

  // calculate the acceleration from the signed value of x,y,z register
  bool getAcceleration(float *ax,float *ay,float *az);

  // lookup the acceleration from the lookup table from this chip's datasheet
  bool getAcceleration(MMA7660_ACC_DATA *data);

  // get all the register value
  bool getAllData(MMA7660_DATA *data);
};

#endif
```

### コンパイルと書き込み

通常通りにコンパイルと書き込みをしましょう。

## LEDバーを利用する

ライブラリを作ってみたので、こちらのREADMEを参照してみましょう。

> https://github.com/dotstudio/Grove_LED_Bar