Open3

SONY Spresense VSCode Sample

hiroe_orz17hiroe_orz17

SONY Spresense のHello World(VSCode版) サンプル

SpresenseのVSCodeでのサンプルコードが少なかったので、ちょっとづつ自分で試していこうと思います。
まずはお約束のHello Worldから始めましょう。

myapps_main.c
#include <sdk/config.h>
#include <stdio.h>

int myapps_main(int argc, char *argv[])
{
  printf("Hello Spresense\n");
  return 0;
}
hiroe_orz17hiroe_orz17

SONY SpresenseのLED制御(Lチカ)サンプル

SpresenseのメインボードにはLEDが4つあり、ピン番号はそれぞれ 97 , 98 , 99 , 100 となっている。

led_main.c
#include <sdk/config.h>
#include <stdio.h>

#include <arch/board/board.h>
#include <arch/board/board_pinconfig.h>

int led_main(int argc, char *argv[])
{
  int array[] = {97, 98, 99, 100};

  for (int pin = 97; pin < 101; ++pin)
  {
    //board_gpio_config(/*ピン番号*/, /*モード*/, /*入力ピン:true*/, /*ドライブ電流大:true*/, /*プルアップ/ダウン設定*/);
    board_gpio_config(pin, 0, false, true, 0);
  }

  while (true)
  {
    for (int pin = 97; pin < 101; ++pin)
    {
      board_gpio_write(pin, 1); //点灯
      usleep(500 * 1000);
      board_gpio_write(pin, 0); //消灯
    }
  }

  return 0;
}

https://www.youtube.com/watch?v=j5q6N6EgEGE

hiroe_orz17hiroe_orz17

SONY Spresenseで位置情報取得サンプル

各国の衛星は各国の測位衛星を参照。
GNSSまわりの定数はここにある。

注意事項として

  • 屋内では、たとえ窓際であっても衛星電波を捕まえるのは難しい。
  • 屋外に出て実行すると数分で位置を取得できる。
  • VSCodeでは Spresense:SDKコンフィグGNSS device (CXD56_GNSS) を有効にしてから設定保存してコンパイル。
gps_main.c
/****************************************************************************
 * Included Files
 ****************************************************************************/
#include <sdk/config.h>
#include <stdio.h>

#include <nuttx/config.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <fcntl.h>
#include <poll.h>
#include <arch/chip/gnss.h>

/****************************************************************************
 * Pre-processor Definitions
 ****************************************************************************/
#define MY_GNSS_SIG 18

/****************************************************************************
 * Private Types
 ****************************************************************************/

struct cxd56_gnss_dms_s
{
  int8_t sign;
  uint8_t degree;
  uint8_t minute;
  uint32_t frac;
};

/****************************************************************************
 * Private Data
 ****************************************************************************/

static uint32_t posfixflag;
static struct cxd56_gnss_positiondata_s posdat;

/****************************************************************************
 * Private Functions
 ****************************************************************************/

static int gnss_setparams(int fd)
{
  int ret = 0;
  uint32_t set_satelite;
  struct cxd56_gnss_ope_mode_param_s set_opemode;

  set_opemode.mode = 1;     /* Operation mode:Normal       */
  set_opemode.cycle = 1000; /* Position notify cycle(msec) */

  ret = ioctl(fd, CXD56_GNSS_IOCTL_SET_OPE_MODE, (uint32_t)&set_opemode);
  if (ret < 0)
  {
    printf("CXD56_GNSS_IOCTL_SET_OPE_MODE failed!\n");
    goto _err;
  }

  /*             日本:みちびき           アメリカ:GPS         ロシア:GLONASS       */
  set_satelite = CXD56_GNSS_SAT_QZ_L1S | CXD56_GNSS_SAT_GPS | CXD56_GNSS_SAT_GLONASS;

  ret = ioctl(fd, CXD56_GNSS_IOCTL_SELECT_SATELLITE_SYSTEM, set_satelite);
  if (ret < 0)
  {
    printf("CXD56_GNSS_IOCTL_SELECT_SATELLITE_SYSTEM failed!\n");
    goto _err;
  }

  printf("Parameter Setting OK.\n");

_err:
  return ret;
}

static void double_to_dmf(double x, struct cxd56_gnss_dms_s *dmf)
{
  int b;
  int d;
  int m;
  double f;
  double t;

  if (x < 0)
  {
    b = 1;
    x = -x;
  }
  else
  {
    b = 0;
  }

  d = (int)x;
  t = (x - d) * 60;
  m = (int)t;
  f = (t - m) * 10000;

  dmf->sign = b;
  dmf->degree = d;
  dmf->minute = m;
  dmf->frac = f;
}

/* 位置情報を取得して標準出力に表示する */
static int read_and_print(int fd)
{
  int ret = 0;
  struct cxd56_gnss_dms_s dmf;

  ret = read(fd, &posdat, sizeof(posdat));
  if (ret < 0)
  {
    printf("read gnss failed.\n");
    goto _err;
  }
  else if (ret != sizeof(posdat))
  {
    ret = ERROR;
    printf("read gnss size error;\n");
    goto _err;
  }
  else
  {
    ret = OK;
  }

  printf("UTC Time %d:%d:%d, usec:%ld\n",
         posdat.receiver.time.hour,
         posdat.receiver.time.minute,
         posdat.receiver.time.sec,
         posdat.receiver.time.usec);

  if (posdat.receiver.pos_fixmode != CXD56_GNSS_PVT_POSFIX_INVALID)
  {
    posfixflag = 1;

    double_to_dmf(posdat.receiver.latitude, &dmf);
    printf("latitude: %d.%d.%04ld\n", dmf.degree, dmf.minute, dmf.frac);

    double_to_dmf(posdat.receiver.longitude, &dmf);
    printf("longitude: %d.%d.%04ld\n", dmf.degree, dmf.minute, dmf.frac);
  }
  else
  {
    printf("No positioning Data.\n");
  }

_err:
  return ret;
}

/* メイン関数 */
int gps_main(int argc, char *argv[])
{
  int ret;
  int fd;
  sigset_t mask;
  struct cxd56_gnss_signal_setting_s setting;

  printf("Hello GPS\n");

  fd = open("/dev/gps", O_RDONLY);
  if (fd < 0)
  {
    printf("device file open error:%d,%d\n", fd, errno);
    return -ENODEV;
  }

  /* Configure mask to notify */
  sigemptyset(&mask);
  sigaddset(&mask, MY_GNSS_SIG);

  ret = sigprocmask(SIG_BLOCK, &mask, NULL);
  if (ret != OK)
  {
    printf("sigprocmask failed%d\n", ret);
    goto _err;
  }

  /* Set the signal to notify GNSS events */
  setting.fd = fd;
  setting.enable = 1;
  setting.gnsssig = CXD56_GNSS_SIG_GNSS;
  setting.signo = MY_GNSS_SIG;
  setting.data = NULL;

  ret = ioctl(fd, CXD56_GNSS_IOCTL_SIGNAL_SET, (unsigned long)&setting);
  if (ret < 0)
  {
    printf("signal error\n");
    goto _err;
  }

  /* Set GNSS parameter */
  ret = gnss_setparams(fd);
  if (ret != OK)
  {
    printf("Set GNSS parameter failed.\n");
    goto _err;
  }

  /* Start GNSS */
  int posperiod = 200;
  posfixflag = 0;

  ret = ioctl(fd, CXD56_GNSS_IOCTL_START, CXD56_GNSS_STMOD_HOT);
  if (ret < 0)
  {
    printf("start GNSS failed.\n");
    goto _err;
  }
  else
  {
    printf("start GNSS ok.\n");
  }

  do
  {
    ret = sigwaitinfo(&mask, NULL);
    if (ret != MY_GNSS_SIG)
    {
      printf("sigwaitinfo failed.\n");
      break;
    }

    ret = read_and_print(fd);
    if (ret < 0)
    {
      break;
    }

    if (posfixflag)
    {
      posperiod--;
    }

  } while (posperiod > 0);

  ret = ioctl(fd, CXD56_GNSS_IOCTL_STOP, 0);
  if (ret < 0)
  {
    printf("stop GNSS failed.\n");
  }
  else
  {
    printf("stop GNSS OK.\n");
  }

_err:
  setting.enable = 0;

  ret = ioctl(fd, CXD56_GNSS_IOCTL_SIGNAL_SET, (unsigned long)&setting);
  if (ret < 0)
  {
    printf("signal error\n");
  }

  sigprocmask(SIG_UNBLOCK, &mask, NULL);
  ret = close(fd);
  if (ret < 0)
  {
    printf("Device file close failed.\n");
  }

  printf("Finish.\n");
  return 0;
}

ちなみに蛇足だけど、僕がはじめてSpresenseで位置情報を取得した本日は、奇しくも「みちびき」の打ち上げに成功した日だった。もしかして今日打ち上げられた「みちびき」から位置情報を受け取ってるかもしれないと思うとロマンですな。

【速報】H2A成功、38機連続 日本版GPS「みちびき」後継機を軌道投入 種子島宇宙センター