2017年7月20日木曜日

Ubuntu上のVirtualBox仮想マシン(Windows10)のHDDを圧縮


検索するとホストOSがWindowsでゲストOSがUbuntuのケースはいっぱい出てくるのですが逆のケースがほとんど無いので備忘録として記します。

1. SDelete の入手

マイクロソフトが配布している sdelete というツールを使って未使用領域をクリアします。
https://technet.microsoft.com/ja-jp/sysinternals/sdelete.aspx

2. ゲストOS上で未使用領域をクリアします。

C:\SDelete>sdelete -z C:

SDelete v2.0 - Secure file delete
Copyright (C) 1999-2016 Mark Russinovich
Sysinternals - www.sysinternals.com

SDelete is set for 1 pass.
Zeroing free space on C:\: 0%
これ結構時間かかりました。気をつけなければいけないは、画面に100%と表示が出てから本当に処理が終わるまでの時間がものすごく長いことです。また、sdelete64.exe は sdelete.exe の28倍かかったと言っている人もいました。私の場合1TBのHDDを処理するのに金曜の朝から初めて8時間では終わらず土日放置、月曜に見たら終わっていたと言った感じでした。

3. C:\SDELTEMP1 を削除します。

なんか 1. をやる前のHDDの使用量が48GB程度だったのに終わったあとは340GB!なんだ?と思って調べてみるとC:ドライブのルートに巨大なファイルができていました。
なんだかわからないけどとりあえずサクッと削除^^;
※このファイルが残らないこともありました。

4. ゲストOSをシャットダウン


5. ホストOSにて vboxmanager を使って圧縮します。

# UUIDを調べる
kiya@kiya-ubuntu:~$ vboxmanage list hdds
UUID:           ab123456-c7d8-90e1-e2f3-a4567890b12c
Parent UUID:    base
State:          locked write
Type:           normal (base)
Location:       /home/kiya/VirtualBox VMs/vhd/kiya-win10-c.vdi
Storage format: VDI
Capacity:       953869 MBytes
Encryption:     disabled

# 圧縮
kiya@kiya-ubuntu:~$ vboxmanage modifyhd ab123456-c7d8-90e1-e2f3-a4567890b12c --compact
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%

ハマりどころは vboxmanager。私のマシンにはなぜか VBoxManager というものも入っていていくらこれを叩いてもUUIDが取れず???としばらく悩んでしまいました。

2017年7月18日火曜日

Arduino でモールス信号

中華通販で買ったArduino。封も切らずに保管していていざ使おうとした不良品だったなんてことが何回かありまして商品が届くごとにとりあえずLチカだけはしていたわけですが、最初から Blink.ino が入っているものもあるので、見分けるためにちょっと凝った BlinkMorse.ino を作ってみました。

その際にモールス信号を生成するクラスを作成しました。このクラスは KyaMorseBase クラスと KyaMorse というテンプレートから構成されています。

KyaMorseBase は与えられた文字列からモールス信号を作成、ONとすべきタイミングで音にすべき時間を引数として KyaMorseBase::callback() を呼び出します。callback() は virtual となっていますのでこのクラスを基本クラスとしてやることにより LED を点灯するなり ブザーを鳴らすなり自由な処理を行えます。

また、KyaMorse はテンプレートでメンバー変数として KyaMorse<クラス名> とすることによりメンバー関数をコールバックとする事ができます。多重継承がお嫌いな方にはこちらが良いかもしれません。

KyaMorse.h

/**
 * モールス信号処理
 *
 * filename:  KyaMorse.h
 *
 * @package
 * @version   1.0.0
 * @copyright Copyright (C) 2017 Yoshio Kiya
 * @date      2017-07-15
 * @author    木屋 善夫
 */
#ifndef _KyaMorse_h_
#define _KyaMorse_h_
#include

class KyaMorseBase {
public:
  // モールス符号情報
  static const uint16_t morses[59];

  // 短点の時間(msec)
  uint32_t mTime = 100;

  /**
   * 構築
   */
  KyaMorseBase() {
  }

  /**
   * 構築
   * @param  uint32_t time 短点の時間(msec)
   */
  KyaMorseBase(uint32_t time) : mTime(time) {
  }

  /**
   * モールス信号送信処理
   *
   * @access public
   * @param  char* str 送信する文字列
   * @return
   * @throw
   */
  void send(char* str);

  /**
   * コールバック処理
   * ※派生クラス(テンプレート)でオーバーライドするためのメンバー関数
   *
   * @access public
   * @param  uint32_t time 待ち時間(msec)
   */
   virtual void callback(uint32_t time) {}
};

template
class KyaMorse : public KyaMorseBase {
public:
  typedef void (T::*CALLBACK)(uint32_t);

protected:
  T* mObj;
  CALLBACK mMethod;

public:
  /**
   * 構築
   */
  KyaMorse( ) : KyaMorseBase() {
  }

  /**
   * 構築
   * @param  uint32_t time 短点の時間(msec)
   */
  KyaMorse(uint32_t time) : KyaMorseBase(time) {
  }

  /**
   * モールス信号送信処理
   *
   * @access public
   * @param  char* str 送信する文字列
   * @return
   * @throw
   */
  void send(char* str, T* obj, CALLBACK method) {
    mObj = obj;
    mMethod = method;
    KyaMorseBase::send(str);
  }

  /**
   * コールバック処理
   * ※派生クラス(テンプレート)でオーバーライドするためのメンバー関数
   *
   * @access public
   * @param  uint32_t time 待ち時間(msec)
   */
   virtual void callback(uint32_t time) {
    (mObj->*mMethod)(time);
   }
};

#endif

KyaMorse.cpp

/**
 * モールス信号処理
 *
 * filename:  KyaMorse.cpp
 *
 * @package
 * @version   1.0.0
 * @copyright Copyright (C) 2017 Yoshio Kiya
 * @date    2017-07-15
 * @author    木屋 善夫
 */

/**
 * インクルード
 */
#include "KyaMorse.h"

/**
 * モールス信号送信処理
 *
 * @access public
 * @param  char* str 送信する文字列
 * @return
 * @throw
 */
void KyaMorseBase::send(char* str) {
  for (; *str; ++ str) {
    char c = *str;
    if ((c >= ' ') && (c <= 'Z')) {
      uint16_t b = morses[c - 0x20];
      for (; b; b <<= 2) {
        switch (b & 0xC000) {
          // エンドマーク
        case 0x0000:
          b = 0;
          break;
          // 語間 短点7つ分の無音
        case 0x4000:
          delay(mTime * (7-1-3));
          break;
          // 短点
        case 0x8000:
          callback(mTime * 1);
          break;
          // 長点
        case 0xC000:
          callback(mTime * 3);
          break;
        }

        // 文字間 短点1つ分の無音
        delay(mTime * 1);
      }
      // 文字間 短点3つ分の無音
      delay(mTime * 3);
    }
  }
}

// MSBから2ビットずつ取り出す(最大8点)
// 00 = 終了
// 01 = 語間 短点7つ分の無音
// 10 = 短点 + 文字間の短点1つ分の無音
// 11 = 長点 短点3つ分 + 文字間の短点1つ分の無音
const uint16_t KyaMorseBase::morses[59] = {
  (B01000000 * 256) + B00000000,    // " "  0x20   xxxxxxx
  (B00000000 * 256) + B00000000,    // "!"  0x21  xxxxxxxx
  (B00000000 * 256) + B00000000,    // """  0x22  xxxxxxxx
  (B00000000 * 256) + B00000000,    // "#"  0x23  xxxxxxxx
  (B00000000 * 256) + B00000000,    // "$"  0x24  xxxxxxxx
  (B00000000 * 256) + B00000000,    // "%"  0x25  xxxxxxxx
  (B00000000 * 256) + B00000000,    // "&"  0x26  xxxxxxxx
  (B00000000 * 256) + B00000000,    // "'"  0x27  xxxxxxxx
  (B00000000 * 256) + B00000000,    // "("  0x28  xxxxxxxx
  (B00000000 * 256) + B00000000,    // ")"  0x29  xxxxxxxx
  (B00000000 * 256) + B00000000,    // "*"  0x2A  xxxxxxxx
  (B00000000 * 256) + B00000000,    // "+"  0x2B  xxxxxxxx
  (B11111010 * 256) + B11110000,    // ","  0x2C  --・・--xx
  (B11101010 * 256) + B10110000,    // "-"  0x2D  -・・・・-xx
  (B10111011 * 256) + B10110000,    // "."  0x2E  ・-・-・-xx
  (B11101011 * 256) + B10000000,    // "/"  0x2F  -・・-・xxx
  (B11111111 * 256) + B11000000,    // "0"  0x30  -----xxx
  (B10111111 * 256) + B11000000,    // "1"  0x31  ・----xxx
  (B10101111 * 256) + B11000000,    // "2"  0x32  ・・---xxx
  (B10101011 * 256) + B11000000,    // "3"  0x33  ・・・--xxx
  (B10101010 * 256) + B11000000,    // "4"  0x34  ・・・・-xxx
  (B10101010 * 256) + B10000000,    // "5"  0x35  ・・・・・xxx
  (B11101010 * 256) + B10000000,    // "6"  0x36  -・・・・xxx
  (B11111010 * 256) + B10000000,    // "7"  0x37  --・・・xxx
  (B11111110 * 256) + B10000000,    // "8"  0x38  ---・・xxx
  (B11111111 * 256) + B10000000,    // "9"  0x39  ----・xxx
  (B00000000 * 256) + B00000000,    // ":"  0x3A  xxxxxxxx
  (B00000000 * 256) + B00000000,    // ";"  0x3B  xxxxxxxx
  (B00000000 * 256) + B00000000,    // "<"  0x3C  xxxxxxxx
  (B00000000 * 256) + B00000000,    // "="  0x3D  xxxxxxxx
  (B00000000 * 256) + B00000000,    // ">"  0x3E  xxxxxxxx
  (B10101111 * 256) + B10100000,    // "?"  0x3F  ・・--・・xx
  (B10111110 * 256) + B11100000,    // "@"  0x40  ・--・-・xx
  (B10110000 * 256) + B00000000,    // "A"  0x41  ・-xxxxxx
  (B11101010 * 256) + B00000000,    // "B"  0x42  -・・・xxxx
  (B11101110 * 256) + B00000000,    // "C"  0x43  -・-・xxxx
  (B11101000 * 256) + B00000000,    // "D"  0x44  -・・xxxxx
  (B10000000 * 256) + B00000000,    // "E"  0x45  ・xxxxxxx
  (B10101110 * 256) + B00000000,    // "F"  0x46  ・・-・xxxx
  (B11111000 * 256) + B00000000,    // "G"  0x47  --・xxxxx
  (B10101010 * 256) + B00000000,    // "H"  0x48  ・・・・xxxx
  (B10100000 * 256) + B00000000,    // "I"  0x49  ・・xxxxxx
  (B10111111 * 256) + B00000000,    // "J"  0x4A  ・---xxxx
  (B11101100 * 256) + B00000000,    // "K"  0x4B  -・-xxxxx
  (B10111010 * 256) + B00000000,    // "L"  0x4C  ・-・・xxxx
  (B11110000 * 256) + B00000000,    // "M"  0x4D  --xxxxxx
  (B11100000 * 256) + B00000000,    // "N"  0x4E  -・xxxxxx
  (B11111100 * 256) + B00000000,    // "O"  0x4F  ---xxxxx
  (B10111110 * 256) + B00000000,    // "P"  0x50  ・--・xxxx
  (B11111011 * 256) + B00000000,    // "Q"  0x51  --・-xxxx
  (B10111000 * 256) + B00000000,    // "R"  0x52  ・-・xxxxx
  (B10101000 * 256) + B00000000,    // "S"  0x53  ・・・xxxxx
  (B11000000 * 256) + B00000000,    // "T"  0x54  -xxxxxxx
  (B10101100 * 256) + B00000000,    // "U"  0x55  ・・-xxxxx
  (B10101011 * 256) + B00000000,    // "V"  0x56  ・・・-xxxx
  (B10111100 * 256) + B00000000,    // "W"  0x57  ・--xxxxx
  (B11101011 * 256) + B00000000,    // "X"  0x58  -・・-xxxx
  (B11101111 * 256) + B00000000,    // "Y"  0x59  -・--xxxx
  (B11111010 * 256) + B00000000,    // "Z"  0x5A  --・・xxxx
};

2017年7月17日月曜日

Arduinoアプリケーション用基本クラス

Arduino用の実験アプリをあれこれ作っているわけですが、アプリを作る場合、最低限必要な機能があるのでアプリケーション用基本クラスを作成しました。今後公開するアプリはみなこのクラスの派生クラスとして実装しますので、とりあえず公開しておきます。
時間を見てgithubに公開しようと思いますがそれまでの仮です^^;

KyaDefine.h

#ifndef _KyaDefine_h_
#define _KyaDefine_h_
/**
 * 定数定義
 *
 * filename:  KyaDefine.h
 *
 * @package
 * @version   1.0.0
 * @copyright Copyright (C) 2017 Yoshio Kiya
 * @date      2017-05-16
 * @author    木屋 善夫
 */
#define UINT unsigned int

// Arduino15\packages\digistump\hardware\avr\1.6.7\cores\tiny/Print.h で使っている!
//#ifndef BYTE
//  #define BYTE unsigned char
//#endif

#ifndef WORD
  #define WORD unsigned short
#endif

#ifndef DWORD
  #define DWORD unsigned long
#endif

#ifndef PCSTR
  #define PCSTR const char*
#endif

// 要素数を返す
#define numberof( a ) ((sizeof a) / (sizeof a[0]))

#define TRUE 1
#define FALSE 0

#if !defined( D0 ) && defined( ARDUINO_AVR_UNO )
  enum {
    D0  =  0,
    D1  =  1,
    D2  =  2,
    D3  =  3,
    D4  =  4,
    D5  =  5,
    D6  =  6,
    D7  =  7,
    D8  =  8,
    D9  =  9,
    D10 = 10,
    D11 = 11,
    D12 = 12,
    D13 = 13,
  };
#endif

#endif

KyaApp.h

#ifndef _KyaApp_h_
#define _KyaApp_h_
/**
 * アプリケーションの基本クラス
 *
 * filename:  KyaApp.h
 *
 * @package
 * @version   1.0.0
 * @copyright Copyright (C) 2017 Yoshio Kiya
 * @date      2017-05-16
 * @author    木屋 善夫
 */
#include
#ifdef KYA_TIMER_INTERVAL
  #ifndef ESP8266
    #include
  #else
    // ミリ秒をクロック数に換算 (@80MHz)
    #define MSEC2CLOCK(ms)  (ms * 80000L)
  #endif
#endif

#include

#ifdef KYA_DEBUG
#define TRACE KyaApp::trace( __FUNCTION__, __FILE__, __LINE__ );
#else
#define TRACE
#endif

// 3Dベクター
template
class KyaVec3 {
public:
  TYPE x;
  TYPE y;
  TYPE z;
};

// 時刻
typedef union KyaTime {
  DWORD val;
  struct {
    uint8_t s;
    uint8_t m;
    WORD h;
  };
};

//printf で小数を扱うためのマクロ
// ex. printf( "%d.%02d", printfFloat( val, 100 ) );
// 小数点以下2桁が表示される
#define printfFloat( v, c ) (int)v, abs( (int)((v - (int)v) * c) )

//// イベントハンドル
//@@ 関数ポインターではなくメンバー関数へのポインターにしなければならない
//template
//class KyaHandle
//{
//public:
//  void *mFunc( TYPE );
//  int mMilli;
//  TYPE mArg;
//
//  KyaHandle( void *func( TYPE ), int delay, TYPE arg ) {
//    mFunc = func;
//    mMilli = millis() + delay;
//    mArg = arg;
//  }
//}

class KyaApp
{
private:

protected:

public:
  static KyaApp* app;
  static char gPfb[256];

  /**
   * 構築
   *
   * @access public
   */
  KyaApp( ) {
    app = this;
  };

  /**
   * 設定
   *
   * @access public
   */
  virtual void onSetup( ) {
    TRACE
#ifdef KYA_TIMER_INTERVAL
  #ifndef ESP8266
    MsTimer2::set( KYA_TIMER_INTERVAL, timerEntry );  // 割り込みハンドラの設定
    MsTimer2::start();                                // タイマー割り込み開始
    Serial.println( "MsTimer2::start()" );
  #else
    // タイマ割り込みの設定
    noInterrupts();

    timer0_isr_init();

    // ハンドラのエントリを設定
    timer0_attachInterrupt( timerEntry );

    // 次回の割り込みが発生するまでの時間を設定
    timer0_write(ESP.getCycleCount() + MSEC2CLOCK(KYA_TIMER_INTERVAL) ); // 10msec

    interrupts();
  #endif
#endif  // KYA_TIMER_INTERVAL
  }

  /**
   * ループの中身
   *
   * @access public
   */
  virtual void onLoop() {
  }

  /**
   * タイマーハンドラ
   *
   * @access public
   */
  virtual void onTimer( ) {
  }

  /**
   * ミリ秒を 時分秒でシリアルに出力
   *
   * @param  DWORD ms ミリ秒
   * @param  const char* suffix 時分秒のあとに付ける文字列
   */
  void printMillis( DWORD ms, const char* suffix = NULL );

#ifdef KYA_TIMER_INTERVAL
  /**
   * 17ms毎にここが呼び出される
   */
  static void timerEntry( ) {
  #ifdef ESP8266
    // 次回の割り込みが発生するまでの時間を設定
    timer0_write(ESP.getCycleCount() + MSEC2CLOCK(KYA_TIMER_INTERVAL) ); // 10msec
  #endif

    // 割り込み処理ハンドラを呼び出す
    if ( KyaApp::app ) {
      KyaApp::app->onTimer( );
    }
  }
#endif  // KYA_TIMER_INTERVAL

  /**
   * LED 点滅
   *
   * @access public
   * @param
   */
//  static void blinkLED( UINT port, UINT blight, UINT usec, UINT count = 1, UINT duty = 128 );
  static void blinkLED( uint8_t port, uint8_t usec, uint8_t count = 1, uint8_t blight = 255, uint8_t duty = 128 );

  /**
   * LED 点滅
   *
   * @param  uint8_t port ピン番号
   * @param  WORD counter カウンター
   * @param  WORD high HIGH にする回数
   * @param  WORD low  LOW にする回数
   * @return WORD カウンター
   */
  static WORD blinkLED2( uint8_t port, WORD counter, WORD high, WORD low );

  /**
   * LED 点滅
   *
   * @param  uint8_t port ピン番号
   * @param  int high HIGH の時間(msec)
   * @param  int low  LOW  の時間(msec)
   */
  static void blinkLED3( uint8_t port, int high, int low );

  /**
   * LED 点滅
   *
   * @param  uint8_t port  ポート
   * @param  WORD pos   現在位置
   * @param  WORD speed 速度
   * @return 次の位置
   */
  static WORD winkLED( uint8_t port, WORD pos, WORD speed = 1 );

  /**
   * 書式付きコンソール出力
   *
   * @param  PCSTR format 書式文字列
   */
  static void printf( PCSTR format, ... );

  static void puts( PCSTR str ) {
    Serial.println( str );
  }

  static void putstr( PCSTR str ) {
    Serial.print( str );
  }

  /**
   * ミリ秒から時分秒を取得
   *
   * @access public
   * @param  unsigned long msec ミリ秒
   * @return KyaTime 時分秒
   */
  KyaTime msecToTime( unsigned long msec );

  /**
   * トレース
   *
   * @param
   * @return
   */
  static void trace( PCSTR func, PCSTR file, int line );
};

#endif

KyaApp.cpp

/**
 * アプリケーションの基本クラス
 *
 * filename:  KyaApp.cpp
 *
 * @package
 * @version   1.0.0
 * @copyright Copyright (C) 2017 Yoshio Kiya
 * @date      2017-05-16
 * @author    木屋 善夫
 */
#include "KyaApp.h"

KyaApp* KyaApp::app = NULL;
char KyaApp::gPfb[256];

/**
 * ミリ秒を 時分秒でシリアルに出力
 *
 * @param  DWORD ms ミリ秒
 * @param  const char* suffix 時分秒のあとに付ける文字列
 */
void KyaApp::printMillis( DWORD ms, const char* suffix ) {
  // 起動してからの時間を表示
  int h, m, s;
  s = ms / 1000;
  if ( s >= 60 ) {
    m = s / 60;
    s = s % 60;
    if ( m >= 60 ) {
      h = m / 60;
      m = m % 60;
    } else {
      h = 0;
    }
  } else {
    h = 0;
    m = 0;
  }

  char buff[255];
  sprintf( buff, "%02d:%02d:%02d", h, m, s );
  Serial.print( buff );

  if ( suffix ) {
    Serial.print( suffix );
  }
}

/**
 * LED 点滅
 *
 * @param
 * @return
 */
//void KyaApp::blinkLED( UINT port, UINT blight, UINT usec, UINT count, UINT duty )
void KyaApp::blinkLED( uint8_t port, uint8_t usec, uint8_t count, uint8_t blight, uint8_t duty )
{
  while ( (count --) > 0 ) {
    // on
    if ( blight < 255 ) {
      analogWrite( port, blight );
    } else {
      digitalWrite( port, HIGH );
    }
    if ( duty != 0 ) {
      delay( (usec * duty) >> 8 );
    }

    // off
    digitalWrite( port, LOW );
    if ( duty != 255 ) {
      delay( (usec * (255 - duty)) >> 8 );
    }
  }
}

/**
 * LED 点滅
 *
 * @param  uint8_t port ピン番号
 * @param  WORD counter カウンター
 * @param  WORD high HIGH にする回数
 * @param  WORD low  LOW にする回数
 * @return WORD カウンター
 */
WORD KyaApp::blinkLED2( uint8_t port, WORD counter, WORD high, WORD low ) {
  WORD t = (counter ++) % (high + low);

  if ( t < high ) {
    digitalWrite( port, HIGH );
  } else {
    digitalWrite( port, LOW );
  }

  return counter;
}

/**
 * LED 点滅
 *
 * @param  uint8_t port ピン番号
 * @param  int high HIGH の時間(msec)
 * @param  int low  LOW  の時間(msec)
 */
void KyaApp::blinkLED3( uint8_t port, int high, int low ) {
  int t = millis( ) % (high + low);
  if ( t < high ) {
    digitalWrite( port, HIGH );
  } else {
    digitalWrite( port, LOW  );
  }
}


/**
 * LED 点滅
 *
 * @param  uint8_t port  ポート
 * @param  WORD pos   現在位置
 * @param  WORD speed 速度
 * @return 次の位置
 */
WORD KyaApp::winkLED( uint8_t port, WORD pos, WORD speed ) {
  // LEDの点滅
  uint8_t b;
  if ( !(pos & 0x100) ) {
    // < 0x100 is rise
    b = (uint8_t)pos;
  } else {
    // >= 0x100 is set
    b = 0xFF - (uint8_t)pos;
  }
  analogWrite( port, b );

  return pos + speed;
}

/**
 * 書式付きコンソール出力
 *
 * @param  PCSTR format 書式文字列
 */
void KyaApp::printf( PCSTR format, ... ) {
  char buff[256];
  va_list arg;

  va_start( arg, format );
  vsnprintf( buff, sizeof( buff ) - 1, format, arg );
  va_end( arg );

  // 改行で分割しながら描画
  char* p = buff;
  char* f;
  while ( (f = strchr( p, '\n' )) != NULL ) {
    // 終端文字を設定
    *f = 0;
    // 改行付きで主力
    Serial.println( p );
    // 見つけた改行文字の次
    p = f + 1;
  }

  // 文字列が残っていたら主力する
  if ( *p ) {
    Serial.print( buff );
  }
}

/**
 * ミリ秒から時分秒を取得
 *
 * @access public
 * @param  unsigned long msec ミリ秒
 * @return KyaTime 時分秒
 */
KyaTime KyaApp::msecToTime( unsigned long msec )
{
  KyaTime res;

  // 秒単位に変換
  msec = msec / 1000;

  // 秒数を抽出
  res.s = (uint8_t)(msec % 60);

  // 分単位に変換
  msec = msec / 60;

  // 分数を算出
  res.m = (uint8_t)(msec % 60);

  // 時単位に変換
  msec = msec / 60;

  // 時間数を取得
  res.h = (WORD)msec;

  return res;
}


/**
 * トレース
 *
 * @param
 * @return
 */
void KyaApp::trace( PCSTR func, PCSTR file, int line ) {
  Serial.print( func );
  Serial.print( "() " );
  Serial.print( file );
  Serial.print( "(" );
  Serial.print( line );
  Serial.print( ")" );
  Serial.println( );
}

/**
 * 設定エントリ
 */
void setup() {
  Serial.begin( 115200 );
  Serial.println( "" );

  if ( KyaApp::app != NULL ) {
    KyaApp::app->onSetup( );
  } else {
    Serial.println( "KyaApp::app == NULL." );
  }
}

/**
 * ループエントリ
 */
void loop() {
  if ( KyaApp::app != NULL ) {
    KyaApp::app->onLoop( );
  } else {
    Serial.println( "KyaApp::app == NULL." );
    delay( 60 * 1000 );
  }
}

2017年7月7日金曜日

Ubuntu で Digispark Kickstarter

OS を Windows 10 から Ubuntu 17.04 に変えまして、Arduino IDE を使い始めたのですが Digispark Kickstarter に書き込みをしようとしたところエラーが発生しました。このあたりについてに日本語の情報が少ないようなのでメモ書き程度ですが記事にします。

■ スケッチ書き込み時に libusb-0.1-4 が見つからないと言われる

マイコンボードに書き込む」ボタンを押し「> Please plug in the device ... 」と表示されたところでUSBを差すと「error while loading shared libraries: libusb-0.1.so.4: cannot open shared object file: No such file or directory」とエラーが発生します。

最大6012バイトのフラッシュメモリのうち、スケッチが812バイト(13%)を使っています。
グローバル変数は13バイトのRAMを使用しています。
Running Digispark Uploader...
Plug in device now... (will timeout in 60 seconds)
/home/kiya/.arduino15/packages/digistump/tools/micronucleus/2.0a4/micronucleus: error while loading shared libraries: libusb-0.1.so.4: cannot open shared object file: No such file or directory
どうやらライブラリーが足りないようです。

解決策は下記のページに書かれていました。
https://askubuntu.com/questions/311401/libusb-0-1-so-4-shared-lib-error-in-ubuntu-64-bit-system

[kiya@kiya ~]$ sudo apt-get install libusb-0.1-4

■ スケッチ書き込み時に micronucleus で例外が発生したと言われる

これでうまくゆくかと思ったら今度は「micronucleus: library/micronucleus_lib.c:66: micronucleus_connect: Assertion `res >= 4' failed.」というエラーが発生します…

最大6012バイトのフラッシュメモリのうち、スケッチが812バイト(13%)を使っています。
グローバル変数は13バイトのRAMを使用しています。
Running Digispark Uploader...
Plug in device now... (will timeout in 60 seconds)
> Please plug in the device ...
micronucleus: library/micronucleus_lib.c:66: micronucleus_connect: Assertion `res >= 4' failed.
> Press CTRL+C to terminate the program.
Aborted (core dumped)
え〜、ツールの中で例外が発生したの?そんなこと言われたってどうしたいいのかわからないです…

対策は下記のページに書かれていました。どうやらデバイスへのアクセス権が不足しているらしいです。
https://digistump.com/wiki/digispark/tutorials/linuxtroubleshooting

1. 下記の内容の「/etc/udev/rules.d/49-micronucleus.rules」というファイルを作ります。

[kiya@kiya ~]$ sudo vi /etc/udev/rules.d/49-micronucleus.rules
# UDEV Rules for Micronucleus boards including the Digispark.
# This file must be placed at:
#
# /etc/udev/rules.d/49-micronucleus.rules    (preferred location)
#   or
# /lib/udev/rules.d/49-micronucleus.rules    (req'd on some broken systems)
#
# After this file is copied, physically unplug and reconnect the board.
#
SUBSYSTEMS=="usb", ATTRS{idVendor}=="16d0", ATTRS{idProduct}=="0753", MODE:="0666"
KERNEL=="ttyACM*", ATTRS{idVendor}=="16d0", ATTRS{idProduct}=="0753", MODE:="0666", ENV{ID_MM_DEVICE_IGNORE}="1"
#
# If you share your linux system with other users, or just don't like the
# idea of write permission for everybody, you can replace MODE:="0666" with
# OWNER:="yourusername" to create the device owned by you, or with
# GROUP:="somegroupname" and mange access using standard unix groups.
2. ルールをリロードします。
[kiya@kiya ~]$ sudo udevadm control --reload-rules

以上でスケッチを書き込めるようになりました。