Bye Bye Moore

PoCソルジャーな零細事業主が作業メモを残すブログ

C標準ライブラリtime.hのclock_gettime関数

C標準ライブラリtime.hはその名とおり、時間を扱う関数です。
これのclock_gettime関数は内部時刻を呼び出す機能を持ちます。
類似した関数にgettimeofday関数がありますが、これは2008年段階から将来廃止予定に指定されています。

実際のところ

clock_gettime

引数はclockid_t型、timespec構造体の順番。
clockid_t型はクロックの識別子

  struct timespec tp;
  result = clock_gettime(CLOCK_REALTIME, &tp);

timespec構造体の定義は以下の通り。
ナノ秒までサポートしております。

struct timespec {
    time_t   tv_sec;        /* seconds */
    long     tv_nsec;       /* nanoseconds */
};

gettimeofday

getimeofdayは引数に時間を扱うtimeval構造体とタイムスタンプ指定をもちます。

廃止予定のgettimeofday関数で呼び出させる時間用構造体timevalは
秒以下をsuseconds_tで取り扱っており、long型で扱っているtimespecとはちょっと構造が違います。

struct timeval {
    time_t      tv_sec;     /* 秒 */
    suseconds_t tv_usec;    /* マイクロ秒 */
};

RasPi上にLive Streaming 環境(保存つき)を作る その1:お手本先行プロジェクトをきめる

遠隔でRasPi上にLive Streaming 環境(保存つき)を作る必要ができたので技術調査がてら。

まるでメディア系に興味をもたず来たので、色々下調べしたところ
実装も軽く、意図した構成にちかい以下の動画を見つけました。
www.youtube.com

これからしばらく、この動画のコードを読んだり部分実行したりして勉強しようと思います。

実際のところ

では早速中身をみてみます。

まずはメインの実行スクリプトcam-rec-strm.shから。

#!/bin/bash

while [ 1 ]
do
raspivid -o - -t 0 -hf -vf -w 1080 -h 768 -fps 20 | ./split.o | cvlc -vvv stream:///dev/stdin --sout '#standard{access=http,mux=ts,dst=:8160}' :demux=h264 &
sleep $1
kill $!
done

raspividはRaspbian標準のカメラポートから動画をとるコマンドです。


Cの方(split.c)はこんな感じ。
……一応C言語使ってる方だと思ってたのですが
知らんライブラリがありますね……??

/* This file implements a data splitter
 * for data coming in to STDIN.
 * Data is split to be written to a 
 * file as well as written back out
 * to STDOUT for streaming.
 *
 * All code provided is as is and
 * is not fully tested.
 *
 * Author: Aadil Rizvi
 * Date Created: 11/25/2016
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>
#include <unistd.h>
#include <stropts.h>
#include <signal.h>

#define MAX_FILENAME_SIZE 100

//File descriptor for currently open data file
static int fd_out;

void sig_handler(int signum) {

  if (fd_out >= 0) {    
    // Flush all write queues
    ioctl(fd_out, I_FLUSH, FLUSHW);

    // Close data file
    close(fd_out);
  }

  exit(0);
}

int main(void) {
  char in_array[1024];
  int nBytes;
  char filename[MAX_FILENAME_SIZE];
  struct timeval ts;  

  // Register signal handler
  signal(SIGINT, sig_handler);

  // Initialize fd_out
  fd_out = -1;

  // Get current time for unique filename
  gettimeofday(&ts, NULL);

  // Generate filename
  snprintf(filename, MAX_FILENAME_SIZE, "raspiVid-%u-%u.h264", ts.tv_sec, ts.tv_usec);

  // Open file to write data
  fd_out = open(filename, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);

  // Read data from STDIN
  nBytes = read(STDIN_FILENO, in_array, sizeof(in_array));

  // Read data from stdin in a loop
  // while writing data to file and
  // stdout as well
  while(nBytes > 0) {

    // Write data to file
    write(fd_out, (const void*)in_array, nBytes);

    // Write data to stdout as well
    write(STDOUT_FILENO, (const void*)in_array, nBytes);

    // Flush all write queues
    ioctl(fd_out, I_FLUSH, FLUSHW);

    // Read next available chunk of data from stdin
    nBytes = read(STDIN_FILENO, in_array, sizeof(in_array)); 
  }

  // Close data file
  close(fd_out);
  fd_out = -1;

  return 0;
}

cvlcはVLCちう動画再生ソフトについてくるサブコマンドでVLCGUIなし版。
画像におけるImageMagickめいた立場の使い方で、CLI上でメディアデータを取り扱いできるようです。

Arduino用の超速CRCチェッカー

CRC(Cyclic Redundancy Check / 巡回冗長符号)は、自前でパケットを作るなら必須の項目です。
これがないと、ダメパケットも受け取ってデータがゴミだらけになったりします。
非力な軽量無線やシリアル線直付けな構成なんかだと、特に。

実際のところ

ただ一々仕様みて実装するのは
Arduino用の超速CRCチェッカーがありました
……いままで泥臭く自力で作っていた僕は一体……??

使い方は、こんな感じ。

/*
  FastCRC-Example
  (c) Frank Boesing 2014
*/

#include <FastCRC.h>

FastCRC32 CRC32;

uint8_t buf[9] = {'1', '2', '3', '4', '5', '6', '7', '8', '9'};

void setup() {

  delay(1500);
  Serial.begin(115200);

  Serial.println("CRC Example");
  Serial.println();

  Serial.print("CRC32 of \"");

  for (unsigned int i = 0; i < sizeof(buf); i++) {
    Serial.print((char) buf[i]);
  }

  Serial.print("\" is: 0x");
  Serial.println( CRC32.crc32(buf, sizeof(buf)), HEX );

}

種類

CRC7、MODBUS、XMODEM用といったよくあるパターンもそのまんま書いてくれているので
態々地獄実装をしなくてすみます。

たとえばPOSIX準拠32bitCRCは
CKSUM, CRC-32/POSIX (poly=0x04c11db7 init=0x00000000 refin=false refout=false xorout=0xffffffff check=0x765e7680)
だそうです。

興味がある方は実装を読んでみても面白いでしょう。

【読書メモ】サイゼリヤ おいしいから売れるのではない 売れているのがおいしい料理だ (日経ビジネス人文庫)

【読書メモ】2040年全ビジネスモデル消滅 (文春新書)

2040年全ビジネスモデル消滅 (文春新書)

2040年全ビジネスモデル消滅 (文春新書)

煽りタイトルが実に香ばしい、経済系新書です。
著者は主に不動産領域のマーケ屋さんのようで、土地まわりの話題を話題を軸にしつつ、
高度経済成長期から現在にかけてのユーザー関心の変化を論じています。

曰く……
顧客にリーチする方法がマスから個別に変わった。
マスの代表がマクドナルドで、個別の代表がディズニーランド。

この方に限らず、なぜかマーケ系の学者さんはどういうわけかディズニーランドがお嫌い。
洗脳の道具だ云々とかフカしているわけですが、恋人でも殺されたんですかね……?
あるいは自分野の理想を実現してる様が妬ましいのか……。

紙面が後半になり若者論に以降するといよいよ内容が香ばしくなってきます。
曰く、若者のバーチャル恋愛*1偏重は
家庭を持つ責任からの逃げとかいう……もう紀元前から延々と繰り返してる老害ムーブで失笑。

と、まぁこんな感じで各論は役に立っても総論は多少頭がまわる……というかそれこそ週刊文春を愛読してるオッサンの居酒屋トークみたいな本でした。

*1:どうもスマホゲーの事をいっているらしい

RasPiでステッピングモーターを動かす その3:二つ動かす

Raspberry Pi 3BにはハードウェアPWMが実装されています。
2チャンネル各2ピンが割り当てられているので合計4ピンあるわけですが、
同じチャンネルのピンは同時に駆動できません。
たとえばXY平面で斜めに動かしたいなら、XとYはCH1とCH2に分離する必要があります。

ハードウェアPWMのCH0はBCM12,18、CH1はBCM12,19に割り当てられています。

さてこのまま馬鹿正直に以下の様に割り当てると……同時には動きません。

import RPi.GPIO as GPIO

# import the library
from RpiMotorLib import RpiMotorLib
    

# 分解能を設定する MS1 ~ MS3はHIGH固定 = 1/16
# 方向とステップを指定するGPIOピンをBCNで指定
GPIO_pins = (14, 15, 18)
direction_A = 20
step_A        = 12  #CH0
direction_B = 21
step_B        = 13  #CH1


# ステッピングモーターのインスタンスを作成
mymotor_A = RpiMotorLib.A4988Nema(direction_A, step_A, GPIO_pins, "A4988")
mymotor_B = RpiMotorLib.A4988Nema(direction_B, step_B, GPIO_pins, "A4988")


# 駆動。FULLの場合200ステップで1周なので100ステップで半周。
mymotor_A.motor_go(False, "Full" , 100, .01, False, .05)
mymotor_B.motor_go(False, "Full" , 100, .01, False, .05)

#使い終わったらお片づけ
GPIO.cleanup()

というわけで……美しくないですが、for文でやる方法でやってみます。
先ほどの駆動の部分を以下の様に変更。

# 駆動。FULLの場合200ステップで1周なので100ステップで半周。
for i in range(100):
  mymotor_A.motor_go(False, "Full" , 1, .01, False, .05)
  mymotor_B.motor_go(False, "Full" , 1, .01, False, .05)

無事、(見た目には)二つ同時に動いている風になりました。