Category tech.


こういう感じでケースにおさめた。

基板

あまり部品はないので片面基板を自力で切削加工して作った。1度目はいろいろとリワークが発生してしまったので2度目の基板。しかし 1PPS の出力をつけわすれていたので、あとからつけくわえている。

MCP4725 だけ少し厳しいピッチだが問題なかった。切削の場合デザインルールで0.3mmぐらいにしないと厳しいが、どうしてもルールをやぶらざるを得ない部分が出てきたりする。

電源に村田製作所製のフルモールド2出力降圧DC-DCコンバータを使っている。MCU など用の 5V と、OCXO 用の 12V を十分余裕を持って出力できる。ただし入力電圧が16V〜40Vと若干高い。24V入力で使っている。

ケース

YONGU Enclosure というところのケース 145*54*150 を
Aliexpress で買った。割と安い。買ったあと「3D CAD ファイルある?」と聞いたらすぐ送ってくれて便利。まぁこれはサイトに載せといてくれれば手間にならないんだけど。

こういう前後パネルがフラットな板のタイプだと加工しやすいので、好んで使っている。

3Dモデルづくり

穴あけやパネルのデザインのため、できるだけ3Dモデルを作るようにしている。パーツごとの干渉を前もって知れたりするので便利。今回はケーブリングもモデリングするようにした。ここを省略すると曲げ半径的に無理があって蓋がしめられないということもあるので……

厳密でなくても良い汎用部品なんかだと、GrabCad で STEP ファイルが得られたりする。SMA コネクタとかは GrabCad からダウンロードしたものに手を加えて使ってる。

Fusion360 の場合、このモデルからさらにパネルのCNC切削Gコードまで持っていけるので楽。Engraving のパスがバグってて困るが……

切削など


文字は30°のVカッターで掘りこみ。これはZ精度が必要なので、加工箇所ごとにわけてGコードを作ってから、加工箇所ごとにZをぴったりあわせたほうが良さげだった。掘っただけで色は入れていないけど、もともと黒のアルマイト加工がされているので、地色を出すだけでコントラスト的に白色に見える。あと、やすりをかけられないのでカッターの切れ味がよくないとつらい。

他の加工はほぼ普通の穴あけ。ただしディスプレイのところだけ傾斜をつける加工をした。これは等高線で降りていく加工にした。0.03mmぐらいで降りるようにしてみたが一切加工段は見えないので、もうちょっと荒くてもよかったと思う。

  1. トップ
  2. photo
  3. GPSDO 10MHz 実装
  1. トップ
  2. tech
  3. GPSDO 10MHz 実装

フランクリン タイトボンド 115mL -

5.0 / 5.0

「木工用ボンド」というと、コニシ社が製造する酢酸ビニルの白いボンドが想像されるが、それと直接競合するボンドにアメリカのフランクリン社が製造する「タイトボンド」というのがある。

比較

「木工用ボンド」はどこでも手に入るので使ったことがない人はいないレベルだと思う。タイトボンドは入手性がかなり悪い。

タイトボンドの良いところ

  • 固定時間が短かい(乾燥がはやい)
  • 乾燥すると固くなる(粘性が残らないので、ノミやスクレーパーでスパっと削れる)
  • キャップが使いやすい

タイトボンドの悪いところ

  • 入手性が悪い
  • 乾燥が速すぎることがある(こういう場合は木工用ボンドを使えばいいと思う)
  • ちょっと高い

何が良いか

個人的な感想だと「固くなる」のが一番良く感じる。これにより余分にはみだしても硬化したあとヤスリで削るのが楽だし、ほぼ木材と近い硬さなので、ノミやカンナにかけることもできる。

そしてキャップが使いやすい。キャップをひっぱるとすぐ塗れる構造になっていて、キャップ自体で塗りひろげできる。これが便利。コニシのやつと比べるといちいちキャップの裏の突起をあわせてねじるみたいな作業をしなくて良い。

  1. トップ
  2. tech
  3. タイトボンドの使い勝手が良すぎる

既にある NMEA のログから、どの衛星が強く受信できているかをプロットしてみる。

ファイルを指定して png を書き出すコードを node で書いた。かなり量の多いログでも中間結果を見ながら生成できるようにしてある。

グラフの見方

上下左右が方角。右まわりに上から北・東・南・西

中心からの距離が仰角。中心が真上(90°)で、円周上が水平線(0°)

SNR によって色がついている。

自宅の状況

GPS の GSV しかとっていないので、このプロットにはGLONASSやQZSSは含まれていない。

南西向きの窓際にアンテナがあるため、そのあたりのSNRが大きくなる。

北極・南極の上空は衛星の軌道がない。北半球に住んでいる場合、このプロットのように北極上空にあたる部分に空白ができる。

決まった数の衛星が決まった軌道で飛んでいるので、空全体で見ると塗りつぶされないところは多い。

コード

#!/usr/bin/env node

const GPS = require("gps");
const fs = require("fs");
const readline = require("readline");
const { createCanvas, loadImage } = require('canvas');

const WIDTH = 1000;
const HEIGHT = 1000;
const PADDING = 50;

const PLOT_RADIUS = (WIDTH - PADDING * 2) / 2;

const canvas = createCanvas(WIDTH, HEIGHT);
const ctx = canvas.getContext('2d');
ctx.fillStyle = "#ffffff";
ctx.fillRect(0, 0, 1000, 1000);

ctx.translate(WIDTH / 2, HEIGHT / 2);

ctx.strokeStyle = "#999999";
ctx.lineWidth = 2;
ctx.beginPath();
ctx.arc(0, 0, PLOT_RADIUS, 0, 2 * Math.PI);
ctx.stroke();

ctx.beginPath();
ctx.moveTo(0, -PLOT_RADIUS);
ctx.lineTo(0, +PLOT_RADIUS);
ctx.moveTo(-PLOT_RADIUS, 0);
ctx.lineTo(+PLOT_RADIUS, 0);
ctx.stroke();

ctx.font = "20px sans-serif";
ctx.fillStyle = "#666666";
ctx.textAlign = "center";
ctx.textBaseline = "bottom";
ctx.fillText("0°", 0, -PLOT_RADIUS - 5);

ctx.textAlign = "left";
ctx.textBaseline = "middle";
ctx.fillText("90°", PLOT_RADIUS + 5, 0);

ctx.textAlign = "center";
ctx.textBaseline = "top";
ctx.fillText("180°", 0, PLOT_RADIUS + 5);

ctx.textAlign = "right";
ctx.textBaseline = "middle";
ctx.fillText("270°", -PLOT_RADIUS - 5, 0);

ctx.textAlign = "left";
ctx.textBaseline = "bottom";
for (let ele of [75, 60, 45, 30, 15]) {
	const r = elevationToRadius(ele);
	ctx.strokeStyle = "#dddddd";
	ctx.lineWidth = 2;
	ctx.beginPath();
	/*
	ctx.moveTo(r, 0);
	ctx.lineTo(r, 10);
	*/
	ctx.arc(0, 0, r, 0, Math.PI * 2);
	ctx.stroke();
	ctx.fillText(ele, 2, -r-2);
}

const gps = new GPS();

function elevationToRadius(e) {
	return PLOT_RADIUS * (1 - e / 90);
}

function writeToPng() {
	const out = fs.createWriteStream("test.png");
	const stream = canvas.createPNGStream();
	stream.pipe(out);
	out.on('finish', () =>  console.log('The PNG file was created.'));
}

//const prns = new Set();
let count = 0;
gps.on('data', function(parsed) {
	if (parsed.type !== "GSV") return;
	for (let sat of parsed.satellites) {
		if (sat.snr === null) continue;
		// prns.add(sat.prn);
		// console.log(Array.from(prns.keys()));
		const hue = (1 - (sat.snr / 40)) * 240;
		const x = Math.cos(sat.azimuth / 180 * Math.PI - Math.PI / 2) * elevationToRadius(sat.elevation);
		const y = Math.sin(sat.azimuth / 180 * Math.PI - Math.PI / 2) * elevationToRadius(sat.elevation);

		ctx.fillStyle = `hsla(${hue}, 100%, 50%, 0.5)`;
		// ctx.fillRect(x-1, y-1, 3, 3);
		ctx.beginPath();
		ctx.arc(x, y, 3, 0, 2 * Math.PI);
		ctx.fill();

		if (count % 100000 === 0) {
			writeToPng();
		}

		count++;
	}
});


const stream = fs.createReadStream("./log.log", "utf8");

const reader = readline.createInterface({ input: stream });
reader.on("line", (data) => {
	const nmea = data.substring("[2020-01-09T09:33:05.622] [DEBUG] default - ".length);
	if (/^\$GPGSV/.test(nmea)) {
		gps.update(nmea);
	}
});
reader.on("close", () => {
	console.log('done');
	writeToPng();
});
  1. トップ
  2. tech
  3. NMEA ログから衛星のスカイビューを生成する