non vorrei lavorare

昔はおもにプログラミングやガジェット系、今は?

M5StickCがずいぶん前に届いていた件

こんばんは。夏休みもあと少しです。9月からは給食室が工事のため、引き続きお弁当が必要な長男がいる@kjunichiです。

背景

Apple Watchが欲しくてしかたない今日この頃だが、先立つものが無い。 たまたま、AKIBA PC Hotline!

akiba-pc.watch.impress.co.jp

の記事を見て、2千円程度でM5StickCなるデバイスが存在することを知った。 これなら腕にはめて時計スタイルで使用できると思った。

初期不良と思った

画面の明るさの制御ができない。 サンプルのファクトリーアプリを入れて、ボタンを押すと、 本来は液晶が徐々に暗くなるようなコードが見受けられたが、真っ暗に。。。

しかし、どうも、液晶の明るさ以外はWifiも使えるし、画面描画も問題なさそう。

時計を作ってみた

amazonで購入したのだが、アキバPCで紹介されていたものとは異なり、 腕時計用のアタッチメントやバンドは付属していなかったが、 電源入るとWifiに接続しNTPサーバーより時刻を取得して、これを表示するコードを書いてみた。

M5StickC Nixie tube Clockmacsbug.wordpress.com

lang-ship.com

を参考にして、LAN環境が無いと動かない時計が完成した!

// M5StickC Nixie tube Clock: 2019.06.06 
#include <M5StickC.h>
#include <WiFi.h>
#include <WiFiMulti.h>

#include "vfd_18x34.c"
#include "vfd_35x67.c"

const char* ssid       = "ssid";
const char* password   = "password";
const char* ntpServer =  "ntp.jst.mfeed.ad.jp";

RTC_TimeTypeDef RTC_TimeStruct;
RTC_DateTypeDef RTC_DateStruct;

WiFiMulti wifiMulti;

int mode_ = 3; // 3:2Lines 2: 2Lines(YYMM), 1:1Line
const uint8_t*n[] = { // vfd font 18x34
  vfd_18x34_0,vfd_18x34_1,vfd_18x34_2,vfd_18x34_3,vfd_18x34_4,
  vfd_18x34_5,vfd_18x34_6,vfd_18x34_7,vfd_18x34_8,vfd_18x34_9
  };
const uint8_t*m[] = { // vfd font 35x67
  vfd_35x67_0,vfd_35x67_1,vfd_35x67_2,vfd_35x67_3,vfd_35x67_4,
  vfd_35x67_5,vfd_35x67_6,vfd_35x67_7,vfd_35x67_8,vfd_35x67_9
  };
const char *monthName[12] = {
  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};


void setup(void){ 
  M5.begin();
  pinMode(M5_BUTTON_HOME, INPUT);
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setRotation(1);
  
  wifiMulti.addAP(ssid, password);
  if((wifiMulti.run() == WL_CONNECTED)) {
    // Set ntp time to local
    configTime(9 * 3600, 0, ntpServer);
 
    // Get local time
    struct tm timeInfo;
    if (getLocalTime(&timeInfo)) {
      M5.Lcd.print("NTP : ");
      M5.Lcd.println(ntpServer);
 
      // Set RTC time
      RTC_TimeTypeDef TimeStruct;
      TimeStruct.Hours   = timeInfo.tm_hour;
      TimeStruct.Minutes = timeInfo.tm_min;
      TimeStruct.Seconds = timeInfo.tm_sec;
      M5.Rtc.SetTime(&TimeStruct);
   
      RTC_DateTypeDef DateStruct;
      DateStruct.WeekDay = timeInfo.tm_wday;
      DateStruct.Month = timeInfo.tm_mon + 1;
      DateStruct.Date = timeInfo.tm_mday;
      DateStruct.Year = timeInfo.tm_year + 1900;
      M5.Rtc.SetData(&DateStruct);
      // rtc setup end -----------------------------------------------
    }
    //disconnect WiFi
    WiFi.disconnect(true);
    WiFi.mode(WIFI_OFF);
  
  }
  
}

int showTime = 20;
bool fblank = false;
void loop(void){
  if(showTime<0) {
    if(!fblank) {
      M5.Lcd.fillScreen(BLACK);
      fblank=true;
    }
    if(digitalRead(M5_BUTTON_HOME) == LOW){
      while(digitalRead(M5_BUTTON_HOME) == LOW);
      Serial.println("display.");
      M5.Axp.DeepSleep(SLEEP_MSEC(1));
      showTime=10;
      fblank=false;
      vfd_3_line();
      //if (mode_ == 3){mode_ = 1;M5.Lcd.fillScreen(BLACK);return;}
      //if (mode_ == 2){mode_ = 3;M5.Lcd.fillScreen(BLACK);return;}
      //if (mode_ == 1){mode_ = 2;M5.Lcd.fillScreen(BLACK);return;}
    } else {        
        M5.Axp.LightSleep(SLEEP_MSEC(800));
        //delay(6);
        //M5.Axp.DeepSleep(SLEEP_MSEC(300));
        //M5.Lcd.setCursor(60, 30);
        //M5.Lcd.fillScreen(WHITE);
        //M5.Lcd.setCursor(60, 30);
        //M5.Lcd.print("unsleep");
        //Serial.println("test.");
    }
    delay(100); 
  } else {
    showTime--;
    if ( mode_ == 3 ){ vfd_3_line();}   // hh,mm,ss
    if ( mode_ == 2 ){ vfd_2_line();}   // yyyy,mm,dd,hh,mm,ss
    if ( mode_ == 1 ){ vfd_1_line();}   // mm,ss
    delay(1000);
  }
}
 
void vfd_3_line(){
  M5.Rtc.GetTime(&RTC_TimeStruct);
  M5.Rtc.GetData(&RTC_DateStruct);
  int h1 = int(RTC_TimeStruct.Hours / 10 );
  int h2 = int(RTC_TimeStruct.Hours - h1*10 );
  int i1 = int(RTC_TimeStruct.Minutes / 10 );
  int i2 = int(RTC_TimeStruct.Minutes - i1*10 );
  int s1 = int(RTC_TimeStruct.Seconds / 10 );
  int s2 = int(RTC_TimeStruct.Seconds - s1*10 );
  
  M5.Lcd.pushImage(  2,0,35,67, (uint16_t *)m[h1]);
  M5.Lcd.pushImage( 41,0,35,67, (uint16_t *)m[h2]);
  M5.Lcd.drawPixel( 79,22, ORANGE); M5.Lcd.drawPixel( 79,48,ORANGE); 
  M5.Lcd.drawPixel( 79,21, YELLOW); M5.Lcd.drawPixel( 79,47,YELLOW); 
  M5.Lcd.pushImage( 83,0,35,67, (uint16_t *)m[i1]);
  M5.Lcd.pushImage(121,0,35,67, (uint16_t *)m[i2]);
  M5.Lcd.pushImage(120,45,18,34, (uint16_t *)n[s1]);
  M5.Lcd.pushImage(140,45,18,34, (uint16_t *)n[s2]);
  
  if ( s1 == 0 && s2 == 0 ){ fade();}
}

void vfd_2_line(){
  M5.Rtc.GetTime(&RTC_TimeStruct);
  M5.Rtc.GetData(&RTC_DateStruct);
  //Serial.printf("Data: %04d-%02d-%02d\n",RTC_DateStruct.Year,RTC_DateStruct.Month,RTC_DateStruct.Date);
  //Serial.printf("Week: %d\n",RTC_DateStruct.WeekDay);
  //Serial.printf("Time: %02d : %02d : %02d\n",RTC_TimeStruct.Hours,RTC_TimeStruct.Minutes,RTC_TimeStruct.Seconds);
  // Data: 2019-06-06
  // Week: 0
  // Time: 09 : 55 : 26
  int y1 = int(RTC_DateStruct.Year    / 1000 );
  int y2 = int((RTC_DateStruct.Year   - y1*1000 ) / 100 );
  int y3 = int((RTC_DateStruct.Year   - y1*1000 - y2*100 ) / 10 );
  int y4 = int(RTC_DateStruct.Year    - y1*1000 - y2*100 - y3*10 );
  int j1 = int(RTC_DateStruct.Month   / 10);
  int j2 = int(RTC_DateStruct.Month   - j1*10 );
  int d1 = int(RTC_DateStruct.Date    / 10 );
  int d2 = int(RTC_DateStruct.Date    - d1*10 );
  int h1 = int(RTC_TimeStruct.Hours   / 10) ;
  int h2 = int(RTC_TimeStruct.Hours   - h1*10 );
  int i1 = int(RTC_TimeStruct.Minutes / 10 );
  int i2 = int(RTC_TimeStruct.Minutes - i1*10 );
  int s1 = int(RTC_TimeStruct.Seconds / 10 );
  int s2 = int(RTC_TimeStruct.Seconds - s1*10 );
   
  M5.Lcd.pushImage(  0, 0,18,34, (uint16_t *)n[y1]); 
  M5.Lcd.pushImage( 19, 0,18,34, (uint16_t *)n[y2]);
  M5.Lcd.pushImage( 38, 0,18,34, (uint16_t *)n[y3]);
  M5.Lcd.pushImage( 57, 0,18,34, (uint16_t *)n[y4]);
  M5.Lcd.drawPixel( 77,13, ORANGE); M5.Lcd.drawPixel( 77,23,ORANGE);
  M5.Lcd.pushImage( 80, 0,18,34, (uint16_t *)n[j1]);
  M5.Lcd.pushImage( 99, 0,18,34, (uint16_t *)n[j2]);
  M5.Lcd.drawPixel(118,13, ORANGE); M5.Lcd.drawPixel(119,23,ORANGE);
  M5.Lcd.pushImage(120, 0,18,34, (uint16_t *)n[d1]);
  M5.Lcd.pushImage(140, 0,18,34, (uint16_t *)n[d2]);
                                                    
  M5.Lcd.pushImage( 00,40,18,34, (uint16_t *)n[h1]);
  M5.Lcd.pushImage( 20,40,18,34, (uint16_t *)n[h2]);
  M5.Lcd.drawPixel( 48,54, ORANGE); M5.Lcd.drawPixel( 48,64,ORANGE); 
  M5.Lcd.pushImage( 60,40,18,34, (uint16_t *)n[i1]);
  M5.Lcd.pushImage( 80,40,18,34, (uint16_t *)n[i2]);
  M5.Lcd.drawPixel(108,54, ORANGE); M5.Lcd.drawPixel(108,64,ORANGE);
  M5.Lcd.pushImage(120,40,18,34, (uint16_t *)n[s1]);
  M5.Lcd.pushImage(140,40,18,34, (uint16_t *)n[s2]);
 
  if ( i1 == 0 && i2 == 0 ){ fade();}
}
 
void vfd_1_line(){
  M5.Rtc.GetTime(&RTC_TimeStruct);
  M5.Rtc.GetData(&RTC_DateStruct);
  int i1 = int(RTC_TimeStruct.Minutes / 10 );
  int i2 = int(RTC_TimeStruct.Minutes - i1*10 );
  int s1 = int(RTC_TimeStruct.Seconds / 10 );
  int s2 = int(RTC_TimeStruct.Seconds - s1*10 );
  
  M5.Lcd.pushImage(  2,6,35,67, (uint16_t *)m[i1]);
  M5.Lcd.pushImage( 41,6,35,67, (uint16_t *)m[i2]);
  M5.Lcd.drawPixel( 79,28, ORANGE); M5.Lcd.drawPixel( 79,54,ORANGE); 
  M5.Lcd.drawPixel( 79,27, YELLOW); M5.Lcd.drawPixel( 79,53,YELLOW); 
  M5.Lcd.pushImage( 83,6,35,67, (uint16_t *)m[s1]);
  M5.Lcd.pushImage(121,6,35,67, (uint16_t *)m[s2]);
 
  if ( s1 == 0 && s2 == 0 ){ fade();}
}

void fade(){
  //for (int i=7;i<16;i++){M5.Axp.ScreenBreath(i);delay(25);}
  //for (int i=15;i>7;i--){M5.Axp.ScreenBreath(i);delay(25);}
  //M5.Axp.ScreenBreath(12);
}

残念な点

バッテリーが持たなすぎ。 1時間ももたない。

実は、正常品だった

Arduino IDEでダウンロードしたフォルダをごっそりGithubからクローンしたフォルダに差し替える

macOS環境ではに~/Documents/Arduino/libraries/配下のM5StickCフォルダをクローンしたフォルダに入れ替えることで 対応できた。

関連記事

2年前の記事

1年前の記事