Blutooth通信によるNXT内部データのロギング

 

リアルタイム制御用組込みソフトウェアのデバッグは容易ではありません。デバッガを用いることで任意のコードをステップ実行することができますが、例えばNXTway-GSの倒立制御アルゴリズムのデバッグに適用することは困難です(ステップ実行では制御自体が成立しません)。そのため、リアルタイム制御用組込みソフトウェアの開発では、プログラム実行中の実機の内部挙動を確認するための専用計測ツールが一般的に用いられます。nxtOSEKではBluetooth通信によるNXT内部データのロギング用API (ecrobot_bt_data_logger)を提供しており、NXT GamePad によるNXT内部データロギングに対応しています。また、データロギングの停止時にはロギングデータを任意のCSVファイルとして保存することができます。

samples\datalogging\data.csv

CSVファイルには次のデータが保存されます。
Time: データ取得タイムスタンプ [msec]
Data1/Data2: ユーザー選択データ
Battery: バッテリ電圧 [mV]
Motor Rev A/B/C: ポートA/B/Cの各モータ回転角度 [度]
ADC S1/S2/S3/S4: ポートS1/S2/S3/S4の各A/Dセンサ生データ
I2C: 超音波センサ距離データ [cm]

CSVファイルに保存されたデータをMicrosoft ExcelやMATLABなどのソフトウェアを用いて解析することも可能です。




samples\datalogging\datalogging.c

/* datalogging.c */
#include "kernel.h"
#include "kernel_id.h"
#include "ecrobot_interface.h"

/* OSEK declarations */
DeclareCounter(SysTimerCnt);
DeclareTask(Task1);

/* nxtOSEK hooks */
void ecrobot_device_initialize()
{
  ecrobot_init_sonar_sensor(NXT_PORT_S2);
  ecrobot_init_bt_slave("LEJOS-OSEK");
}

void ecrobot_device_terminate()
{
  ecrobot_term_sonar_sensor(NXT_PORT_S2);
  ecrobot_term_bt_connection();
}

/* nxtOSEK hook to be invoked from an ISR in category 2 */
void user_1ms_isr_type2(void)
{
  StatusType ercd;

  ercd = SignalCounter(SysTimerCnt); /* Increment OSEK Alarm Counter */
  if (ercd != E_OK)
  {
    ShutdownOS(ercd);
  }
}

/* Task1 executed every 50msec */
TASK(Task1)
{
  static S8 i,j;
  int sonar;

  sonar = ecrobot_get_sonar_sensor(NXT_PORT_S2);

  /* send Sensor/Motors/NXT internal status to the host.
   * NXT GamePad in the host PC accumulates all logging data
   * and later you can save the logging data into a CSV file
   */

  ecrobot_bt_data_logger(i++, j--);

  /* display Sensors/Motors/NXT internal status */
  ecrobot_status_monitor("Data Logging");

  TerminateTask();
}

samples\datalogging\datalogging.oil

#include "implementation.oil"

CPU ATMEL_AT91SAM7S256
{
  OS LEJOS_OSEK
  {
    STATUS = EXTENDED;
    STARTUPHOOK = FALSE;
    ERRORHOOK = FALSE;
    SHUTDOWNHOOK = FALSE;
    PRETASKHOOK = FALSE;
    POSTTASKHOOK = FALSE;
    USEGETSERVICEID = FALSE;
    USEPARAMETERACCESS = FALSE;
    USERESSCHEDULER = FALSE;
  };

  /* Definition of application mode */
  APPMODE appmode1{};

  /* Definition of Task1 */
  TASK Task1
  {
    AUTOSTART = FALSE;
    PRIORITY = 1; /* Smaller value means lower priority */
    ACTIVATION = 1;
    SCHEDULE = FULL;
    STACKSIZE = 512; /* Stack size */
  };

  /* Definition of OSEK Alarm Counter */
  COUNTER SysTimerCnt
  {
    MINCYCLE = 1;
    MAXALLOWEDVALUE = 10000;
    TICKSPERBASE = 1; /* One tick is equal to 1msec */
  };

  /* Definition of Task1 execution timing */
  ALARM cyclic_alarm
  {
    COUNTER = SysTimerCnt;
    ACTION = ACTIVATETASK
    {
      TASK = Task1;
    };
    AUTOSTART = TRUE
    {
      ALARMTIME = 1;
      CYCLETIME = 50; /* Task1 is executed every 50msec */
      APPMODE = appmode1;
    };
  };
};

 

 

 

Back to Samples