WioTerminalで水準器

WioTerminalには、初めから加速度センサがついているので、これを使って…と、なると、とりあえず、水準器あたりからですかねぇ~?
というわけで、水準器、作ってみました。
f:id:manpukukoji:20200711095526j:plain
特に、説明もいらないと思いますが、一応、5つボタンでスケールを変えられるようにしてあります。
上下で5段階変更できます。 これで、フルスケールが変わります。
スケール1のときは、真ん中が水平、一番外の丸が90度、に、なるはず…。
プログラムもほとんどライブラリのサンプルのままです。 角度にするのにちょっとだけ計算してます。

#include"LIS3DHTR.h"
#include "TFT_eSPI.h"
#include <math.h>

LIS3DHTR<TwoWire> lis;
TFT_eSPI tft;

void disp_sight() {
  tft.drawCircle(159,119,90,TFT_WHITE);
  tft.drawCircle(159,119,60,TFT_WHITE);
  tft.drawCircle(159,119,30,TFT_WHITE);
  tft.drawLine(159,29,159,209,TFT_WHITE);
  tft.drawLine(69,119,249,119,TFT_WHITE);
  tft.fillCircle(159,119,3,TFT_RED);  

  tft.fillRoundRect(56,215,206,20,10,TFT_DARKGREEN);
  tft.fillRoundRect(295,16,20,206,10,TFT_DARKGREEN);

}
 
void setup() {
  Serial.begin(115200);
//   while (!Serial);
  pinMode(WIO_5S_UP, INPUT_PULLUP);
  pinMode(WIO_5S_DOWN, INPUT_PULLUP);

  lis.begin(Wire1);
 
  if (!lis) {
    Serial.println("ERROR");
    while(1);
  }
  lis.setOutputDataRate(LIS3DHTR_DATARATE_25HZ); //Data output rate
  lis.setFullScaleRange(LIS3DHTR_RANGE_2G); //Scale range set to 2g

  // Display set up
  tft.begin();
  tft.setRotation(3);
  tft.setTextColor(TFT_YELLOW);
  tft.setTextSize(2);
  tft.fillScreen(TFT_BLACK); 
  disp_sight();
  tft.drawString("Angle", 5, 20);
  tft.drawString("X: ", 10, 40);
  tft.drawString("Y: ", 10, 60);
  tft.drawString("Accel.", 5, 120);
  tft.drawString("X: ", 10, 140);
  tft.drawString("Y: ", 10, 160);
  tft.drawString("Z: ", 10, 180);
  tft.drawString("Scale", 238, 20);
}

  int p_plot_x = 159, p_plot_y = 119;
  int scale = 1, p_scale = 5;
   
void loop() {
  float x_values, y_values, z_values;
  int plot_x, plot_y;
  x_values = lis.getAccelerationX();
  y_values = lis.getAccelerationY();
  z_values = lis.getAccelerationZ();
/* 
  Serial.print("X: "); Serial.print(x_values);
  Serial.print(" Y: "); Serial.print(y_values);
  Serial.print(" Z: "); Serial.print(z_values);
  Serial.println();
*/
  tft.fillRect(50,40,72,35,TFT_BLACK);
  tft.fillRect(50,140,72,55,TFT_BLACK);
  tft.drawString(String(180.0/3.1415*asin(x_values)), 50, 40);
  tft.drawString(String(180.0/3.1415*asin(y_values)), 50, 60);
  tft.drawString(String(x_values), 50, 140);
  tft.drawString(String(y_values), 50, 160);
  tft.drawString(String(z_values), 50, 180);
  if (scale != p_scale) {
  tft.fillRect(260,41,25,20,TFT_BLACK);
  tft.drawString(String(scale), 260, 41);
  }

  tft.fillCircle(p_plot_x,p_plot_y,10,TFT_BLACK);
  tft.fillRect(p_plot_x+3,215,6,20,TFT_DARKGREEN);
  tft.fillRect(295,p_plot_y-3,20,6,TFT_DARKGREEN);
  disp_sight();
  plot_x = 159 + scale*(90.0/3.1415 * 2 * asin(y_values));
  if (plot_x > 249) plot_x = 249;
  if (plot_x < 69) plot_x = 69;
  plot_y = 119 - scale*(90.0/3.1415 * 2 * asin(x_values));
  if (plot_y > 209) plot_y = 209;
  if (plot_y < 29) plot_y = 29;
  tft.fillCircle(plot_x,plot_y,10,TFT_YELLOW);
  tft.fillRect(plot_x-3,215,6,20,TFT_WHITE);
  tft.drawLine(plot_x,215,plot_x,235,TFT_BLACK);
  tft.fillRect(295,plot_y-3,20,6,TFT_WHITE);
  tft.drawLine(295,plot_y,315,plot_y,TFT_BLACK);

   if (digitalRead(WIO_5S_UP) == LOW) {
    scale++;
    if (scale > 5) scale = 5;
    while(digitalRead(WIO_5S_UP) == LOW);
   }
   if (digitalRead(WIO_5S_DOWN) == LOW) {
    scale--;
    if (scale <1) scale = 1;
    while(digitalRead(WIO_5S_DOWN) == LOW);
   }

  p_plot_x = plot_x;
  p_plot_y = plot_y;
  
  delay(50);
}

じっと見てると、結構、画面がちらちらして、目が疲れます。

そんなわけで、らびやん さんのLovyanGFX というライブラリを使ってみました。
画面のちらちらは、解消されたようです。 LovyanGFX おそるべし!!
が、いかんせん、加速度の数字そのものが、ちらちらと変化しているものだから、そこんとこはしかたないですね。
値の表示をやめれば、結構、いい感じかも。

#include"LIS3DHTR.h"
#include <LovyanGFX.hpp>
#include <math.h>

#define DARKGREEN24 0x38761DU
#define GREEN24 0x00FF00
#define RED24 0xFF0000U
#define YELLOW24 0xFFFF00U
#define WHITE24 0xFFFFFFU
#define BLACK24 0x000000U

LIS3DHTR<TwoWire> lis;
static LGFX lcd;
//static LGFX_Sprite canvas(&lcd);   
static LGFX_Sprite sight(&lcd);   
static LGFX_Sprite bottom(&lcd);  
static LGFX_Sprite right(&lcd);   
static LGFX_Sprite bubble(&sight);  
static LGFX_Sprite idx_X(&lcd);   
static LGFX_Sprite idx_Y(&lcd);   
static auto transpalette = 0;           
  
void setup() {
  Serial.begin(115200);
//   while (!Serial);
  pinMode(WIO_5S_UP, INPUT_PULLUP);
  pinMode(WIO_5S_DOWN, INPUT_PULLUP);

  lis.begin(Wire1);
 
  if (!lis) {
    Serial.println("ERROR");
    while(1);
  }
  lis.setOutputDataRate(LIS3DHTR_DATARATE_25HZ); //Data output rate
  lis.setFullScaleRange(LIS3DHTR_RANGE_2G); //Scale range set to 2g

  // Display set up
  lcd.init();
  lcd.setRotation(1);
  lcd.setBrightness(128);

//keep memory
  //canvas.createSprite(200, 200);
  sight.createSprite(200, 200);
  bottom.createSprite(206, 20);
  right.createSprite(20, 206);
  bubble.createSprite(20, 20);
  idx_X.createSprite(6, 20);
  idx_Y.createSprite(20, 6);

// create parts
  sight.fillScreen(transpalette);
  bottom.fillScreen(transpalette);
  right.fillScreen(transpalette);
  bubble.fillScreen(transpalette);
  idx_X.fillScreen(transpalette);
  idx_Y.fillScreen(transpalette);

  sight.drawCircle(100,100,90,WHITE24);
  sight.drawCircle(100,100,60,WHITE24);
  sight.drawCircle(100,100,30,WHITE24);
  sight.drawLine(100,10,100,190,WHITE24);
  sight.drawLine(10,100,190,100,WHITE24);
  sight.fillCircle(100,100,3,RED24);

  bottom.fillRoundRect(0,0,206,20,10,DARKGREEN24);
  right.fillRoundRect(0,0,20,206,10,DARKGREEN24);
  bubble.fillCircle(10,10,10,YELLOW24);
  idx_X.fillRect(0,0,6,20,WHITE24);
  idx_X.drawFastVLine(3,0,20,BLACK24);
  idx_Y.fillRect(0,0,20,6,WHITE24);
  idx_Y.drawFastHLine(0,3,20,BLACK24);
  
  lcd.setTextColor(YELLOW24, BLACK24);
  lcd.setTextSize(2);
  sight.pushSprite(59,19);
  
  lcd.drawString("Angle", 5, 20);
  lcd.drawString("X: ", 10, 40);
  lcd.drawString("Y: ", 10, 60);
  lcd.drawString("Accel.", 5, 120);
  lcd.drawString("X: ", 10, 140);
  lcd.drawString("Y: ", 10, 160);
  lcd.drawString("Z: ", 10, 180);
  bottom.pushSprite(56,215);
  right.pushSprite(295,16);
}

  int p_plot_x = 159, p_plot_y = 119;
  float px_values=0.0, py_values=0.0, pz_values=0.0;
  float px_angle=0, py_angle=0; 
  int scale = 1, p_scale = 5;;
  
void loop() {
  float x_values, y_values, z_values, x_angle, y_angle;
  int plot_x, plot_y;
  
  x_values = lis.getAccelerationX();
  y_values = lis.getAccelerationY();
  z_values = lis.getAccelerationZ();

  x_angle = 180.0/3.1415*asin(x_values);
  y_angle = 180.0/3.1415*asin(y_values);

  plot_x = 100 + scale*(90.0/3.1415 * 2 * asin(y_values));
  if (plot_x > 197) plot_x = 197;
  if (plot_x < 3) plot_x = 3;
  plot_y = 100 - scale*(90.0/3.1415 * 2 * asin(x_values));
  if (plot_y > 197) plot_y = 197;
  if (plot_y < 3) plot_y = 3;

  sight.clear();
  sight.drawCircle(100,100,90,WHITE24);
  sight.drawCircle(100,100,60,WHITE24);
  sight.drawCircle(100,100,30,WHITE24);
  sight.drawLine(100,10,100,190,WHITE24);
  sight.drawLine(10,100,190,100,WHITE24);
  sight.fillCircle(100,100,3,RED24);
  sight.fillCircle(plot_x,plot_y,10,YELLOW24);
  sight.pushSprite(59,19);

  bottom.pushSprite(56,215);
  right.pushSprite(295,16);
  idx_X.pushSprite(plot_x-3+60, 215);
  idx_Y.pushSprite(295, plot_y-3+20);

  lcd.setTextColor(BLACK24,BLACK24);
  lcd.drawString(String(px_angle), 50, 40);
  lcd.drawString(String(py_angle), 50, 60);
  lcd.drawString(String(px_values), 50, 140);
  lcd.drawString(String(py_values), 50, 160);
  lcd.drawString(String(pz_values), 50, 180);
  lcd.setTextColor(WHITE24,BLACK24);
  lcd.drawString(String(x_angle), 50, 40);
  lcd.drawString(String(y_angle), 50, 60);
  lcd.drawString(String(x_values), 50, 140);
  lcd.drawString(String(y_values), 50, 160);
  lcd.drawString(String(z_values), 50, 180);
  lcd.drawString("Scl", 260, 20);
  if (scale != p_scale) {
  lcd.fillRect(270,41,25,20,TFT_BLACK);
  lcd.drawString(String(scale), 270, 41);
  }

  p_plot_x = plot_x;
  p_plot_y = plot_y;
  px_values = x_values;
  py_values = y_values;
  pz_values = z_values;
  px_angle = x_angle;
  py_angle = y_angle;

     if (digitalRead(WIO_5S_UP) == LOW) {
    scale++;
    if (scale > 5) scale = 5;
    while(digitalRead(WIO_5S_UP) == LOW);
   }
   if (digitalRead(WIO_5S_DOWN) == LOW) {
    scale--;
    if (scale <1) scale = 1;
    while(digitalRead(WIO_5S_DOWN) == LOW);
   }

  delay(50);
}

じっと、見てると時々 1g を超えたりする。
一応、自宅の重力加速度を調べてみると、9.797と出たので、1g を超えることはないはず…?
ん? 重力異常?
なんか、壁から宇宙人が出てきそう…。
ぐるっと一回りさせて表示させてみたら、0.93g から1.04g まで、ばらついている。
f:id:manpukukoji:20200711105605j:plain
やっぱり、ちゃんと使うには、キャリブレーションとか必要なんでしょうね。

参考サイト
Overview - Seeed Wiki

github.com

重力値推定計算サービス