KiCAD BGA基板設計①回路編

試してみる。
ダメかもしれないけど。

www.digikey.jp
これを使う

PCBGOGOに注文するつもりだが、
2019年1月時点のデザインルールでは、
0.8mm pitchのBGA基板ならギリギリ製造できる気がする。

Capabilities | PCB Online | Low volume pcb assembly | PCBGOGO
を参考にすると

BGAパッド径 	≥0.3mm
導体幅/導体間隔 	外層パターン:≥4mil ≂ 0.1016mm

パッドと配線の間は0.2mm必要らしいので
パッド間に一本通せる?

f:id:katakanan:20190209014657p:plain

ライブラリ

まずKiCADのライブラリというところだが、昔と違ってdigikeyが最強になりつつあるので、
そこからCADに適した部品ライブラリとフットプリント、ついでに3Dモデルもダウンロードしておく。
f:id:katakanan:20190120211031p:plain
0.8mmピッチであることを確かめて3D modelとKiCADを選択
右下の単位をMetricにしたほうがいい気がする。
f:id:katakanan:20190120211631p:plain

適当な回路を作る

BluePillのピンをまねて、余ったピンにBluetoothとSDカードをつけとく
wiki.stm32duino.com
回路図
https://wiki.stm32duino.com/images/c/c1/Vcc-gnd.com-STM32F103C8-schematic.pdf

本当に簡単にシステムを作りたいならBluePillやuncleo買えばいいんだけども


回路図ができた。
f:id:katakanan:20190203155141p:plain

次はレイアウト

STM32マイコン徹底入門 (TECH I Processor)

STM32マイコン徹底入門 (TECH I Processor)

Ryzen 電力測定⑥

e-tipsmemo.hatenablog.com

e-tipsmemo.hatenablog.com

グラフ表示できるようになったので、
Rustで書いたWebsocketのサーバーから送られてくるjsonでグラフを更新する。
jsonは以下のような形

{
	"time":2019/01/14 02:50:07,
	"voltage":102.396,
	"current":108.74219,
	"wattage":5.335
}

よって、

var t = [];
var v = [];
var c = [];
var p = [];
var maxsize = 100;

.....

sock.addEventListener('message', function(e){
	var jsonstr = JSON.parse(e.data);
	if(t.length >= maxsize)
	{
		t.push(jsonstr['time']);
		t.splice(0,1);
		v.push(jsonstr['voltage']);
		v.splice(0,1);
		c.push(jsonstr['current']);
		c.splice(0,1);
		p.push(jsonstr['wattage']);
		p.splice(0,1);
	}
	else
	{
		t.push(jsonstr['time']);
		v.push(jsonstr['voltage']);
		c.push(jsonstr['current']);
		p.push(jsonstr['wattage']);
	}
	vchart.data.label = t;
	cchart.data.label = t;
	pchart.data.label = t;
	vchart.data.datasets[0].data = v;
	cchart.data.datasets[0].data = c;
	pchart.data.datasets[0].data = p;
	vchart.update();
	cchart.update();
	pchart.update();
});

電力のグラフだけに注目すれば

var pctx;
var pchart;

pctx = $('#powerChart').get(0).getContext('2d');
.....

const pchartDataSet = {
	type: 'line',
	data: {
	  labels: t,
	  datasets: [{
		label: 'power',
		data: p,
		tension: graph_tension,
		backgroundColor: 'rgba(0, 0, 125, 0.3)',
		borderColor: 'blue'
	  }]
	},
	options: {
	  responsive: true,
	  maintainAspectRatio: false,
	   animation:false,
	   scales: {
		  yAxes: [
			{
			  ticks: {
				beginAtZero: true,
				min: 0,
				max: 200
			  }
			}
		  ]
		}
	}
};

pchart= new Chart(pctx, pchartDataSet);

こんな感じでcurrentもvoltageも書いた。

パソコン構成は以下で、

型番
CPU Ryzen5 2600X
マザボ Asrock X470 MASTER SLI
GPU GF-GTX660-E2GHD/DF/OC(流用)
メモリ CMK16GX4M2A2666C16
電源 Corsair CX550M 80PLUS
ケース JONSBO U4
SSD MZVPV256HDGL-00000
HDD DT01ACA300

f:id:katakanan:20190119023050p:plain
グラフから
スリープの時は5Wぐらい。
何もしてない起動時は約80W
シネベンチ(CPU)回して190Wぐらい

でも、CPU自体は
スリープ時(たぶんほぼ0W)
何もしてないとき、2W~3W
シネベンチ(CPU)で90Wか(?)

今後はサーバー側のほうで一ヶ月ごとのcsvファイルでもログしようかと考えている。

Data Visualization with JavaScript

Data Visualization with JavaScript

Ryzen サーバー 電力測定⑤/Chart.js

前回はjsonで電力測定値をクライアントに送れるようになった。
e-tipsmemo.hatenablog.com
これをきれいにグラフ化したい。
そこでChart.jsを使う。
Chart.jsによる折線グラフ作成<Chart.js<Javascript<木暮仁

とりあえず必要

<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.min.js"></script>

表示部分は

  <body>
    <input type="text" name="message" value="">
    <input type="button" name="buttonMsg" value="send message">
    <input type="button" name="buttonDiscon" value="disconnect">
	<div class="contents">
    <canvas id="voltageChart"></canvas>
	</div>
	<div class="contents">
    <canvas id="currentChart"></canvas>
	</div>
	<div class="contents">
    <canvas id="powerChart"></canvas>
	</div>
  </body>

divで囲んでおかないとサイズをいい感じに変更できない。

とりあえずテストデータとして、

var testdata = ["{\"time\":\"2019/01/14 02:50:00\",\"voltage\":102.209,\"current\":108.00781,\"wattage\":5.3}",
		"{\"time\":\"2019/01/14 02:50:02\",\"voltage\":102.271,\"current\":111.39844,\"wattage\":5.53}",
		"{\"time\":\"2019/01/14 02:50:04\",\"voltage\":102.258,\"current\":106.765625,\"wattage\":5.315}",
		"{\"time\":\"2019/01/14 02:50:07\",\"voltage\":102.396,\"current\":108.74219,\"wattage\":5.335}",
		"{\"time\":\"2019/01/14 02:50:09\",\"voltage\":102.541,\"current\":107.453125,\"wattage\":5.49}",
		"{\"time\":\"2019/01/14 02:50:11\",\"voltage\":102.285,\"current\":106.94531,\"wattage\":5.3}",
		"{\"time\":\"2019/01/14 02:50:13\",\"voltage\":102.409,\"current\":107.10156,\"wattage\":5.245}",
		"{\"time\":\"2019/01/14 02:50:15\",\"voltage\":102.432,\"current\":107.921875,\"wattage\":5.26}",
		"{\"time\":\"2019/01/14 02:50:17\",\"voltage\":102.257,\"current\":106.21875,\"wattage\":5.275}",
		"{\"time\":\"2019/01/14 02:50:19\",\"voltage\":102.519,\"current\":109.40625,\"wattage\":5.45}",
		"{\"time\":\"2019/01/14 02:50:21\",\"voltage\":102.267,\"current\":107.38281,\"wattage\":5.255}",
		"{\"time\":\"2019/01/14 02:50:23\",\"voltage\":102.383,\"current\":106.03125,\"wattage\":5.245}",
		"{\"time\":\"2019/01/14 02:50:25\",\"voltage\":102.499,\"current\":108.07031,\"wattage\":5.265}",
		"{\"time\":\"2019/01/14 02:50:27\",\"voltage\":102.413,\"current\":106.65625,\"wattage\":5.27}"];

var hoge = [];
var v = [];
var c = [];
var p = [];
for(var i=0;i<testdata.length;i++)
{
	var t = JSON.parse(testdata[i]);
	hoge.push(t['time']);
	v.push(t['voltage']);
	c.push(t['current']);
	p.push(t['wattage']);
}

その後、chartを作成する。
電圧、電流、電力のグラフを作ったがとりあえず一つだけ。

var vctx;

vctx = $('#voltageChart').get(0).getContext('2d');

const vchartDataSet = {
type: 'line',
data: {
  labels: hoge,
  datasets: [{
	label: 'voltage',
	data: v,
	tension: 0.3,
	backgroundColor: 'rgba(125, 0, 0, 0.3)',
	borderColor: 'red'
  }]
},
options: {
  responsive: true,
  maintainAspectRatio: false
}
};

new Chart(vctx, vchartDataSet);

f:id:katakanan:20190115003352p:plain
次はこれをwebsocketのon_messageで更新するようにする。

KiCAD 5 パッド 一括 変更

KiCAD 4から5へ移行するためにいろいろいじっていたら
ちょっとした機能を見つけた。

QFPやBGAでパッドがたくさんあるときとりあえず
パッドを大量に置くが、それらのサイズを一気に変更するのは
大変だった。
とくにある選択したパッドだけを変更したいときなどは4,0にそれをする方法はなかった気がする。

f:id:katakanan:20190120231832p:plain

100個の特定パッドをB1のサイズからA1のサイズにしたい。

1つのパッドを編集する。

この場合A1だけを小さいサイズに変更した。

パッドプロパティのコピー

右クリック下の「パッドプロパティのコピー」を行う。
f:id:katakanan:20190120232050p:plain

変更したいパッドを選択する

f:id:katakanan:20190120232143p:plain

パッドプロパティの適用

f:id:katakanan:20190120232209p:plain

一瞬で終わった。

Rust websocket/Ryzen サーバー電力測定④

e-tipsmemo.hatenablog.com
の続きで
e-tipsmemo.hatenablog.com
ができるようになったので。

測定された時刻、電圧、電流、ワット数をserde_jsonシリアライズして送信
Cargo.toml

serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
#[derive(Serialize, Deserialize, Debug)]
struct Measdata{
    time: String,
    voltage: f32,
    current: f32,
    wattage: f32,
}

fn parse_data(d: Vec<u8>) -> Measdata
{
    let t = format!("20{:02}/{:02}/{:02} {:02}:{:02}:{:02}", d[19], d[18], d[17], d[16], d[15], d[14]);
    let c = ((d[7] as u32) << 16)|((d[6] as u32) << 8)|((d[5] as u32));
    let v = ((d[10] as u32) << 16)|((d[9] as u32) << 8)|((d[8] as u32));
    let p = ((d[13] as u32) << 16)|((d[12] as u32) << 8)|((d[11] as u32));
    Measdata{time:t,
            voltage:(v as f32)/1000.0,
            current:(c as f32)/128.0,
            wattage:(p as f32)*5.0/1000.0}
}

メインループ

while running.load(Ordering::SeqCst)
{
	match wc.request_measure() {
		Ok(data) => {
			let m = parse_data(data);
			let json_str = serde_json::to_string(&m).unwrap();
			println!("{}", json_str);
			sender.send(json_str);
		},
		Err(e) => eprintln!("{:?}", e),
	}
	thread::sleep(Duration::from_millis(2000));
}

serde_jsonは非常に便利。

f:id:katakanan:20190112003449p:plain

OK
あとはこのjsonからグラフ化してみる予定。

Ryzenは(Ryzen5 2600Xを使用している)エンコ爆速なんだけどアイドル高めだという噂なので気になる。

PLEX 地上デジタル・BS・CS対応TVチューナー PX-W3PE4

PLEX 地上デジタル・BS・CS対応TVチューナー PX-W3PE4

AMD CPU Ryzen 5 2600X with Wraith Spire cooler YD260XBCAFBOX

AMD CPU Ryzen 5 2600X with Wraith Spire cooler YD260XBCAFBOX

rust websocket server sender clone

e-tipsmemo.hatenablog.com

e-tipsmemo.hatenablog.com
を組み合わせて、
Serverがlistenするスレッドとは別のスレッドからも、sendしたかった。

extern crate ws;

use ws::{listen, Sender, Handler, Error, ErrorKind, Result, Message, Handshake};

use std::time::Duration;
use std::thread;
use std::sync::mpsc::Sender as TSender;

enum Event{
    Connect(Sender),
    Disconnect,
}

struct Server {
    ws_out: Sender,
    thread_out: TSender<Event>,
}

impl Handler for Server {
    fn on_open(&mut self, _ : Handshake)->Result<()>{
        println!("on_open");
        self.thread_out.send(Event::Connect(self.ws_out.clone()))
            .map_err(|err| {
                Error::new(
                    ErrorKind::Internal,
                    format!("Unable to communicate between threads: {:?}", err),
                )
            })
    }
    fn on_message(&mut self, msg : Message)->Result<()>{
        println!("{:?}", msg);
        Ok(())
    }
}

fn main() {
    let (tx, rx) = std::sync::mpsc::channel();
    let server = thread::spawn(move || {
        listen("192.168.0.14:3000", |out| {
            Server{
                ws_out: out,
                thread_out: tx.clone(),
            }
        }).unwrap();
    });

    if let Ok(Event::Connect(sender)) = rx.recv()
    {
        for i in 0..5{
        sender.send(format!("{}", i));
        thread::sleep(Duration::from_millis(2000));
        }
    }
}

クライアントは前回のjavascriptのままでServerに別スレッドと、Eventをやり取りするSenderを入れておく。
クライアントからアクセスされたらon_openが呼ばれるので、そこでwsのsenderを送ってやることで、
main関数のほうのスレッドはサーバーが持ってるsenderのcloneをもらうことができる。

rust websocket

サーバーアプリ

extern crate ws;

use ws::{listen, Sender, Handler, Result, Message, CloseCode, Handshake};
use ws::Message::Text;
use ws::Message::Binary;
use ws::util::Token;

struct Server {
   out: Sender,
}

impl Handler for Server {
  fn on_open(&mut self, _shake: Handshake) -> Result<()> {
	  println!("on_open");
	  Ok(())
  }
  fn on_message(&mut self, msg: Message) -> Result<()> {
	  println!("{:?}", msg);
	  Ok(())
  }
}

fn main() {
  listen("[IP]:[PORT]", |out| Server { out: out }).unwrap();
}
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>hello node.js!</title>
    <script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
    <script>
	$(document).ready(function(){
	console.log("hello");
	var sock = new WebSocket('ws://:[IP]:[PORT]');

	sock.addEventListener('open', function(e){
		console.log('Socket open');
	});

	sock.addEventListener('message', function(e){
		console.log(e.data);
	});

	$(':button[name=buttonMsg]').click(function(){
		var msg = $(':text[name=message]').val();
		console.log(msg);
		sock.send(msg);
	});
	});
    </script>
  </head>
  <body>
    <input type="text" name="message" value="">
    <input type="button" name="buttonMsg" value="send message">
    <input type="button" name="buttonDiscon" value="disconnect">
  </body>
</html>

このクライアントをraspiに置いておいて、apacheとかで見られるようにしておけばOK

f:id:katakanan:20181129000745p:plain
OK