M5Stack vs Wio Terminal

手元にM5Stack BasicとWio Terminalがそろったので、両デバイスの違いをまとめてみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172313/f89d93cd-7e06-602c-68b9-cee7d4cb7bfd.png)


#外観
|     |M5Stack|Wio Terminal|
|:----|:------|:-----------|
|サイズ(mm)|w54 × h54 × d17|w72 × h57 × d12|
|質量(g)|120||
|LCD解像度|320 x 240|320 x 240|

サイズはWio Terminalの方が横長、奥行きは少ないという仕様になっています。ただ、Wio Terminalの方は、バッテリーが付属されていないので、オプションを付けると、M5Stackと変わらない奥行きになると思います。（M5Stack Basicのバッテリー容量は110mAh）
両方とも、背面にはネジ穴があるため、壁掛けにも適しています。
また、M5Stack Basicは、本体を2つ（CoreとBottom）に分け、モジュール拡張するのに対し、Wio Terminalは、背面の40-Pin GPIO Headerに拡張モジュールを追加していく形となっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172313/3a207c6a-a595-fa2b-d14e-65fa291c00f8.png)

#プロセッサー
|     |M5Stack|Wio Terminal|
|:----|:------|:-----------|
|プロセッサー|Espressif ESP32|Microchip ATSAMD51P19|
|クロック周波数|240MHz dual core|120MHz (max 200MHz)|
|RAM|520KB|192KB|
|ROM||512KB||
|Wi-Fi|802.11 b/g/n HT40|802.11 a/b/g/n|
|BLE|5.0|5.0|
プロセッサの違いを[姫野ベンチマーク](http://i.riken.jp/supercom/documents/himenobmt/)のアロケートサイズをカスタムし比較してみました。絶対評価はできませんが、M5StackがMFLOPS=54.076028に対し、Wio TerminalがMFLOPS=25.825812となりました。
####処理速度比較サンプルコード
```performance.c
#include <sys/time.h>

#define MIMAX            9
#define MJMAX            9
#define MKMAX            17

double second();
float jacobi();
void initmt();
double fflop(int,int,int);
double mflops(int,double,double);

static float  p[MIMAX][MJMAX][MKMAX];
static float  a[4][MIMAX][MJMAX][MKMAX],
              b[3][MIMAX][MJMAX][MKMAX],
              c[3][MIMAX][MJMAX][MKMAX];
static float  bnd[MIMAX][MJMAX][MKMAX];
static float  wrk1[MIMAX][MJMAX][MKMAX],
              wrk2[MIMAX][MJMAX][MKMAX];

static int imax, jmax, kmax;
static float omega;

void setup() {
  delay(3000);
  Serial.begin(115200);
  Serial.println("Ready");
  
  int    i,j,k,nn;
  float  gosa;
  double cpu,cpu0,cpu1,flop,target;

  target= 60.0;
  omega= 0.8;
  imax = MIMAX-1;
  jmax = MJMAX-1;
  kmax = MKMAX-1;

  /*
   *    Initializing matrixes
   */
  initmt();
  Serial.printf("mimax = %d mjmax = %d mkmax = %d\n",MIMAX, MJMAX, MKMAX);
  Serial.printf("imax = %d jmax = %d kmax =%d\n",imax,jmax,kmax);

  nn= 3;
  Serial.printf(" Start rehearsal measurement process.\n");
  Serial.printf(" Measure the performance in %d times.\n\n",nn);

  cpu0= second();
  gosa= jacobi(nn);
  cpu1= second();
  cpu= cpu1 - cpu0;

  flop= fflop(imax,jmax,kmax);
  
  Serial.printf(" MFLOPS: %f time(s): %f %e\n\n",
         mflops(nn,cpu,flop),cpu,gosa);

  nn= (int)(target/(cpu/3.0));

  Serial.printf(" Now, start the actual measurement process.\n");
  Serial.printf(" The loop will be excuted in %d times\n",nn);
  Serial.printf(" This will take about one minute.\n");
  Serial.printf(" Wait for a while\n\n");

  /*
   *    Start measuring
   */
  cpu0 = second();
  gosa = jacobi(nn);
  cpu1 = second();

  cpu= cpu1 - cpu0;
  
  Serial.printf(" Loop executed for %d times\n",nn);
  Serial.printf(" Gosa : %e \n",gosa);
  Serial.printf(" MFLOPS measured : %f\tcpu : %f\n",mflops(nn,cpu,flop),cpu);
  Serial.printf(" Score based on Pentium III 600MHz : %f\n",
         mflops(nn,cpu,flop)/82,84);
}

void initmt()
{
  int i,j,k;

  for(i=0 ; i<MIMAX ; i++)
    for(j=0 ; j<MJMAX ; j++)
      for(k=0 ; k<MKMAX ; k++){
        a[0][i][j][k]=0.0;
        a[1][i][j][k]=0.0;
        a[2][i][j][k]=0.0;
        a[3][i][j][k]=0.0;
        b[0][i][j][k]=0.0;
        b[1][i][j][k]=0.0;
        b[2][i][j][k]=0.0;
        c[0][i][j][k]=0.0;
        c[1][i][j][k]=0.0;
        c[2][i][j][k]=0.0;
        p[i][j][k]=0.0;
        wrk1[i][j][k]=0.0;
        bnd[i][j][k]=0.0;
      }

  for(i=0 ; i<imax ; i++)
    for(j=0 ; j<jmax ; j++)
      for(k=0 ; k<kmax ; k++){
        a[0][i][j][k]=1.0;
        a[1][i][j][k]=1.0;
        a[2][i][j][k]=1.0;
        a[3][i][j][k]=1.0/6.0;
        b[0][i][j][k]=0.0;
        b[1][i][j][k]=0.0;
        b[2][i][j][k]=0.0;
        c[0][i][j][k]=1.0;
        c[1][i][j][k]=1.0;
        c[2][i][j][k]=1.0;
        p[i][j][k]=(float)(i*i)/(float)((imax-1)*(imax-1));
        wrk1[i][j][k]=0.0;
        bnd[i][j][k]=1.0;
      }
}

float jacobi(int nn)
{
  int i,j,k,n;
  float gosa, s0, ss;

  for(n=0 ; n<nn ; ++n){
    gosa = 0.0;

    for(i=1 ; i<imax-1 ; i++)
      for(j=1 ; j<jmax-1 ; j++)
        for(k=1 ; k<kmax-1 ; k++){
          s0 = a[0][i][j][k] * p[i+1][j  ][k  ]
             + a[1][i][j][k] * p[i  ][j+1][k  ]
             + a[2][i][j][k] * p[i  ][j  ][k+1]
             + b[0][i][j][k] * ( p[i+1][j+1][k  ] - p[i+1][j-1][k  ]
                              - p[i-1][j+1][k  ] + p[i-1][j-1][k  ] )
             + b[1][i][j][k] * ( p[i  ][j+1][k+1] - p[i  ][j-1][k+1]
                               - p[i  ][j+1][k-1] + p[i  ][j-1][k-1] )
             + b[2][i][j][k] * ( p[i+1][j  ][k+1] - p[i-1][j  ][k+1]
                               - p[i+1][j  ][k-1] + p[i-1][j  ][k-1] )
             + c[0][i][j][k] * p[i-1][j  ][k  ]
             + c[1][i][j][k] * p[i  ][j-1][k  ]
             + c[2][i][j][k] * p[i  ][j  ][k-1]
             + wrk1[i][j][k];

          ss = ( s0 * a[3][i][j][k] - p[i][j][k] ) * bnd[i][j][k];

          gosa+= ss*ss;
          /* gosa= (gosa > ss*ss) ? a : b; */

          wrk2[i][j][k] = p[i][j][k] + omega * ss;
        }

    for(i=1 ; i<imax-1 ; ++i)
      for(j=1 ; j<jmax-1 ; ++j)
        for(k=1 ; k<kmax-1 ; ++k)
          p[i][j][k] = wrk2[i][j][k];
    
  } /* end n loop */
  return(gosa);
}

double fflop(int mx,int my, int mz)
{
  return((double)(mz-2)*(double)(my-2)*(double)(mx-2)*34.0);
}

double mflops(int nn,double cpu,double flop)
{
  return(flop/cpu*1.e-6*(double)nn);
}

double second()
{
  struct timeval tm;
  double t ;

  static int base_sec = 0,base_usec = 0;

  gettimeofday(&tm, NULL);
  
  if(base_sec == 0 && base_usec == 0)
  {
      base_sec = tm.tv_sec;
      base_usec = tm.tv_usec;
      t = 0.0;
  } else {
    t = (double) (tm.tv_sec-base_sec) + 
      ((double) (tm.tv_usec-base_usec))/1.0e6 ;
  }
  return t ;
}

void loop() {}
```

#外部インターフェース
|     |M5Stack|Wio Terminal|
|:----|:------|:-----------|
|USB|Type-C x1|Type-C x1|
|SD|microSDスロット x1|microSDスロット x1|
|GROVEコネクタ|x1|x2|
|I/Oピン|23pin|40pin(RaspberryPi互換)|
|ボタン|Button x3|Button x3 / 5-way Switch x1|
入力のボタンインターフェースとしてWio Terminalは3つのボタンに加え、5-way Switchと呼ばれる5方向のキーが付いていることが特徴的で、画面上のメニュー選択などのアプリケーションで使いやすさが出てくると思います。

#内蔵センサ
Wio Terminalには、加速度センサ、照度センサ、赤外線エミッタが内蔵。M5Stack Basicではないのですが、M5Stack Grayという加速度、ジャイロ、磁気センサ(MPU9250)が搭載されたモデルもあります。
いずれにせよ、拡張モジュールもありますし、内蔵センサ自体はそれほど拘らなくてよさそうですね。

#開発環境
|M5Stack|Wio Terminal|
|:------|:-----------|
|Arduino, MicroPython, UIFlow|Arduino, MicroPython, ArduPy, AT Firmware, Visual Studio Code|
**UIFlow**は、M5Stick社の提供するブロック型のビジュアルプログラミングツール。
**ArduPy**は、AredinoとSeeedによって開発されたプログラミングツール。
どちらも、内部ではMicroPythonが動いているようです。

##お役立ちサイト
###M5Stack
- [M5Stack Docs](https://docs.m5stack.com/)
- [M5Stack library](https://github.com/m5stack/M5Stack)
- [M5Stack 回路図](https://github.com/m5stack/M5-Schematic/blob/master/Core/Basic/M5-Core-Schematic(20171206).pdf)
- [UIFlow](https://m5stack.com/pages/uiflow)

###Wio Terminal
- [Wio Terminalをはじめよう](https://wiki.seeedstudio.com/jp/Wio-Terminal-Getting-Started/)
- [Wio Terminal 回路図](https://files.seeedstudio.com/wiki/Wio-Terminal/res/Wio-Terminal-Schematics.pdf)

[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172313/d6ad10bc-75ba-8124-14d4-f144657c6473.png)](https://twitter.com/ghibi)