子供が産まれました -1000人に一人の逸材-
はじめに
令和元年に子供が産まれました。元気な男の子です。
3人目の子供なので慣れたもんですが、久しぶりに見る新生児はちっこくてかわいい。
上の子がちょっと生意気になりつつある年齢なので、尚更かわいいです。
ちょっとした問題
しかし産まれてすぐに"先天性内反足"であることがわかりました。
足首から先が内側に曲がっているのです。
調べると1000人に一人の割合で存在し、原因は不明とのこと。
幸い治療方法はある程度確立しており、
矯正器具を付け時間をかけて足の曲がり具合を矯正する必要があるらしい。
患者数が少ないせいか近場の大学病院ですら対応できず、
車で1.5時間の病院に通うことになりました。
新生児には結構な苦痛だと思う。
この記事の趣旨
家族とはいえ自分以外のことをブログに書くのは気が引けますが、
自分の今の不安感を将来抱くかも知れない親御さんの励みになればと思い、
本記事を書き残すことにしました。
経過
通院1回目(出生後15日):
- 症状確認のため触診してもらう
- レントゲン撮影
- 予想通り内反足との結果
- 今後の説明を受ける
- ギプスによる矯正で様子を見るが、場合によってはアキレス腱を切ったりもする
- 毎週一回・合計10週、ギプスを巻くために通院する
- ギプスを巻いてもらう
- ギプスに関する注意事項を受講する
- ギプスは通院前日の夜か当日の午前に家で取り外してから通院する
- ギプスを巻いてから三日間はキッチンペーパーをギプスに巻き頻繁に取り換える(ギプスから水が滲み出るので)
診察だけのつもりだったのですが、まさか当日ギプスを巻いてもらうことになるとは驚きました。
7時に家を出て、家に着いたのが17時。新生児にはなかなかハードな一日だったと思います。
施術中は赤ん坊は違和感に耐えられず喚いてましたが、夜にはギプスを気にせず熟睡してました。ちょっと安心。
毎週平日の14時に通院する事になり、嫁一人に行ってもらうのも不安なので仕事をどうすべきか悩み中。
通院2回目
続く
今更ですが、USB3.0を使いこなしたい
EZ-USB FX3の使い方
EZ-USB FX3とは:
EZ-USB FX3とはUSB3.0を容易に使えるようにするためのIC。一般的なペリフェラル用IFに加えて柔軟に仕様を変更できる汎用のIFも備える。
IF:
・I2C:マスタとして動作、100kHz/200kHz/1MHz
・I2S:トランスミッタorレシーバとして動作、100kHz/400kHz/1MHz
・UART:フロー制御に対応、300bps ~ 4608Kbps
・SPI:トランザクションサイズは4bit~32bit、最大33MHz、4モードに対応
・GPIF Ⅱ:最大100MHz、8/16/32bit、プログラマブル、マスタorスレーブどちらも可能
外部クロックは19.2MHz/26MHz/38.4MHz/52MHzに対応。内部で19.2MHzが生成される?
電源は、各IF毎に異なる電圧を供給可能。
ブート方法:
ブート方法はPMODEのピン設定で選択可能。通常は次のいずれかで行う。
・PMODE[2:0] = F11:USBでファームウェアを読み込んで起動する
・PMODE[2:0] = 0F1:SPI ROMで起動
EZ-USB FX3とFPGAとの接続:
EZ-USB FX3はGPIF Ⅱを介してFPGAと接続可能。
FPGAのコンフィギュレーションはEZ-USB FX3を介して行うことも可能。外部メモリを削減できる。
EZ-USB FX3とイメージセンサの接続:
EZ-USB FX3はGPIF Ⅱを介してイメージセンサと接続できる。
外部デバイスとのデータ通信:
EZ-USB EX3と外部デバイスはソケットを介して接続される。各ソケットはペリフェラル用IF毎に存在する。ただしGPIF はソケット4つあり?対応するソケットを介して接続される。スレッドとソケットは1:1対応。
自動DMAチャネル:
GPIFソケットはDMAバッファが一杯になったことをUSBソケットに通知できる。
USBソケットはDMAバッファが空になったことをGPIFソケットに通知できる。
外部データを加工しない場合は上記の手法を用いる。
手動DMAチャネル:
GPIFソケットはDMAバッファが一杯になったことをCPUに通知し、CPUはUSBソケットに伝達する。
USBソケットはDMAバッファが空になったことをCPUに通知し、CPUはGPIFソケットに伝達する。
外部データを加工する場合は上記の手法を用いる。
ソケットはデータ管理のため、DMAバッファアドレス、バッファサイズ、ディスクリプタチェーンを仕様する。つまり、アドレスとバッファサイズと次のアドレスのポインタを用いて順次データを転送する。
DMAディスクリプタの切り替えには数usの時間を要する。通常のデータ転送では非常に大きな時間である。DMAディスクリプタ変更の際に、アクティブなGPIFスレッド(ソケット)を切り替えることで待ち時間0で転送用DMAバッファを切り替えられる。
参考:
EZ-USB FX3 入門 https://www.cypress.com/file/140781/download
課題解決マトリクス(Yマトリクス)の考案
背景
前職のベンチャー企業に勤めているときに(現職もベンチャーだけど)、人手が足りず効率よく課題解決する必要性がありました。
課題の真因を把握するため「Whyを5回繰り返す」トヨタ方式にひと手間加える事で、
対策案も効率的に決められる手法を考案した(というほどでもないですが)周知・宣伝したいと思います。
*既にフレームワークとして世の中に知られている方法があるなら教えてください。悲しいですが車輪の再発明はしたくないので、今後はそれを参考にします。
Yマトリクス
Yの意味は、
- Why(ワイ= Y )を5回繰り返す手法を元にしていることから
- 複数の課題を一つの対策方法で対策するイメージ
- 課題解決して問題を白紙(White)にしましょうという意味を込めて
- 自分の名前の頭文字
手法
- 複数の課題を挙げる(縦軸に記載)
- 各課題についてWhyを繰り返す(縦軸に記載)
- 各Whyに対する解決法を考える(横軸に記載)
- 各々の解決方法が他のwhyを解決しうるか検討する(縦横の交叉)
- 実施する解決法を決める(横軸からピックアップ)
例
かなり私的な内容ですが、私個人の家庭事情を例にします。
家族構成:
- 父親( 自分):サラリーマン
- 母親(嫁):専業主婦、子供3人目を妊娠中
- 子供1:4歳
- 子供2:3歳
現場の状況と課題:
- 住居は4LDK
- 父親の職場が家から遠いため、平日は家事ができない
- 母親が家事と子育てと妊娠で疲弊している
- 子供がリビングでおもちゃを散らかす
- 1部屋は洗濯物を部屋干ししている
- 子供3人それぞれに部屋を提供できない
Yマトリクス
まだまだブラシュアップが必要だが、例としては以です。
繰り返しになりますが手順を再掲します。
- 複数の課題を挙げる(縦軸に記載)
- 各課題についてWhyを繰り返す(縦軸に記載)
- 各Whyに対する解決法を考える(横軸に記載)
- 各々の解決方法が他のwhyを解決しうるか検討する(縦横の交叉)
- 実施する解決法を決める(横軸からピックアップ)
加えて、全課題のWhyを眺めながら、複数の課題を網羅的に解決できる案を追加して、再検討すると良いです。
この作業に終わりはありません。納得するか時間の許す限り続けましょう。
宮本茂氏曰く「アイデアとは複数の課題をいっぺんに解決すること」。
解決策の捻出作業はクリエイティブであり、個性的を発揮できる場だと思っています。
今後の検討事項
上記の例では考慮していませんが、各課題は複数の真因のAND又はORで構成されていることがほとんどです。
また解決策によっては時間やお金がかかったり、リスクがあったり、何かを犠牲にしたりとデメリットは少なからずあります。
従って以下を考慮して解決策を検討する必要があります。
- 課題の真因のAND/ORの考慮
- 解決策のデメリット
- 解決策間の関連性
MERNことはじめ
背景
MERN 開発の流れを知りたくてyotuube(https://www.youtube.com/watch?v=7CqJlxBYj-M)を見た。
動画は情報量が多くて捗るけど、その分繰り返し見るには時間がかかるので文字に起こした。
MongoDBの説明
- Database
- Collection
- Document
- Index
- $lookup
- Reference
Example
Mongo DBの例
{ name:" ", title:" ", address:{ address1:" ", city:" ", state: " ", }, topics:[" ", " ", " ",], number: }
MogoDB Atlasの紹介
512MBまで無料、Cluster使えるとか
作成するアプリの説明
Appは以下を含む
- Exercises
- Users
全てのエクササイズは一人のユーザーのみ持つ
ディレクトリの作成と環境の整備
特定のディレクトリで、
create-react-app mern-exercise-tracker
数分待って完了したらディレクトリ変更
cd mern-exercise-tracker
バックエンド用のディレクトリを作成し環境もろもろを整備する
mkdir backend cd backend npm install express cors mongoose dotenv npm install -g nodemon
バックエンドとMongoDBの接続
backendディレクトリにserver.jsファイルを新規作成する。
const express = require('express'); const cors = require('cors'); const mongoose = require('mongoose'); require('dotenv').config(); const app = express(); const port = process.env.PORT || 5000; app.use(cors()); app.use(express.json()); const uri = process.env.ATLAS_URI; mongoose.connect(uri, {userNewUrlParser: true, userCreateIndex: true }); const connection = mongoose.connection; connection.once('open', () => { console.log("MongoDB database connection established successfully"); }) const exercisesRouter = require('./routes/exercises'); const usersRouter = require('./routes/users'); app.use('/exercises', exercisesRouter); app.use('/users', usersRouter); app.listen(port,() => { console.log(`Server is runnning on port: ${port}`); });
backendディレクトリに.envファイルを新規作成する。
MongoDB Atlas clusterのconnection clusterのconnection String OnlyのCopyをクリック
.envに以下を記載。
ATLAS_URI=ペースト(先ほどコピーしたもの)
passwordの箇所にパスワードを記載する。
backendディレクトリでnodemon server
以上でMongoDBにアクセスできるようになる。
modelの作成
backendにmodelsフォルダを作成。
modelsフォルダに
- exercise.model.js
- user.model.js
を新規作成する。
exercise.model.js
const mongoose = require('monngoose'); const Schema = mongoose.Schema; const exerciseSchema = new Schema({ username: { type: String, required: true}, description: { type: String, required: true}, duration: { type: Number, required: true}, date: { type: Date, required: true}, }, { timestamps: true, }); const Exercise = mongoose.model('Exercise', exerciseSchema); module.exports = Exercise;
user.mode.js
const mongoose = require('monngoose'); const Schema = mongoose.Schema; const userSchema = new Schema({ username:{ type: String, required: true, unique: true, trim: true, minlength: 3 }, }, { timestamps: true, }); const User = mongoose.model('User', userSchema); module.exports = User;
Routeの作成
backendディレクトリ内にroutesディレクトリを作成する。
routesディレクトリ内に
- exercises.js
- users.js
を新規作成する。
exercises.js
const router = require('express').Router(); let Exercise = require('../models/exrecise.model'); router.route('/').get((req, res) => { Exercise.find() .then(exercises => res.json(exercises)) .catch(err => res.status(400).json('Error: ' + err)); }); router.route('/add').post((req, res) => { const username = req.body.username; const description = req.body.description; const duration = Number(req.body.duration); const date = Date.parse(req.body.date); const newExercise = new Exercise({ username, description, duration, date, }); newExercise.save() .then(() => res.json('Exercise added!')) .catch(err => res.status(400).json('Error: ' + err)); }); module.exports = router;
user.js
const router = require('express').Router(); let User = require('../models/user.model'); router.route('/').get((req, res) => { User.find() .then(users => res.json(users)) .catch(err => res.status(400).json('Error: ' + err)); }); router.route('/add').post((req, res) => { const username = req.body.username; const newUser = new User({username}); newUser.save() .then(() => res.json('User added!')) .catch(err => res.status(400).json('Error: ' + err)); }); module.exports = router;
server.jsにルートを記載する(上述)。
---ここまで動画開始から30分---
データベースの確認
Insomniaでサーバーの動作を確認する。
exercises.jsにIDのルートの処理を追加する(上述)。
get,delete,postなど
---ここまで動画開始から43分。ここからReactの説明開始---
ReactでHello Worldの表示
publicのindex.htmlを確認する
index.jsを確認する
App.jsに移動。
exercise-trackerフォルダで
- npm install bootstrap
- npm install reat-router-dom
使用するコンポーネントをあらかじめimportする。
srcディレクトリ下にcomponentディレクトリを作成する。
その後
これ以降のReactの説明に関する情報は少し古い。
Hooksを使用するのが今後のトレンドになるはず。
従ってこれ以降は動画をまとめる必要はないような気がするので
代わりにReact Hooksについて読みかじったことを記載しておく。
参考文献
りあクト!
りあクト! TypeScriptで始めるつらくないReact開発 第2版 - くるみ割り書房 - BOOTH
react training公式ページ
React Training: React Router v5.1
Qiitaの記事
useStateの使い方
import React, {FC, useState } from 'react'; import { Button, Card, Statistic } from 'semantic-ui-react'; import './App.css'; const App:FC = () => { const [count, setCount] = usetState(0); const increment = () => { setCount(count + 1); }; const decremet = () => { setCount(count -1); }; return( <div className="container"> <header> <h1>カウンター</h1> </header> <Card> <Statistic className="number-board"> <Statistic.Label>count</Statistic.Label> <Statistic.value>{count}</Statistic.value> </Statistic> <Card.Content> <div className="ui two buttons"> <Button color="red" onClick={decrement}>-1</Button> <Button color="green" onClick={increment}>+1</Button> </div> </Card.Content> </Card> </div> ); }; export default App;
useEffectの使い方
import React, {FC, useEffect, useState} from 'react'; import { Button, Card, Icon, Statistics } from 'semantic-ui-react'; import './App.css'; const LIMIT = 60; const App:FC = () => { const [timeLeft, setTimeLeft] = useState(LIMIT); const reset = () => { setTimeLeft(LIMIT); }; const tick = () => { setTimeLeft(prevTime => (prevTime === 0? LIMIT: prevTime -1)); }; useEffect(() => { const timerId = setInterval(tick, 1000); return () => clearInterval(timerId); },[]); return ( <div className="container"> <header> <h1>タイマー</h1> </header> <Card> <Statistic className="number-board"> <Statistics.Label>time</Statistics.Label> <Statistics.value>{timeLeft}</Statistics.value> </Statistic> <Card.content> <Button color="red" fluid on Click={reset}> <Icon name="redo" /> Reset </Button> </Card.content> </Card> </div> ); }; export default App;
Custom Hooksの例
import React, { FC, useEffect, useState } from 'react'; import AppComponent from ' ../components/App'; //Custom hook "useTimer" const useTimer = (limitSec: number):[number, () => void] => { const [timeLeft, setTimeLeft] = useState(limitSec); const reset = () => { setTimeLeft(limitSec); }; const tick = () => { setTimeLeft(prev => ( prevTime === 0? limitSec : prevTime -1)); }; useEffect(() => { const timerId = setInterval(tick, 1000); return () => clearInterval(timerId); },[]); return [timeLeft, reset]; } const AppContainer: FC= () => { const LIMIT = 60; const [timeLeft, reset] = useTimer(LIMIT); return <AppComponent timeLeft={timeLeft} reset={reset} />; }; export default AppContainer;
react-routerの例
import React from 'react'; import ReactDom from 'react-dom'; import { Browsewrrouter as router, Route, Switch, useParams, useHistory, useLocation, } from 'react-router-dom'; function Hello(){ const history = useHistory(); return( <div> <h1>Hello</h1> <button onClick={() => history.push('/hello/react-router?message=hooks#test')}>Next</button> </div> ); } function HelloSomeone(){ const history = useHistory(); const location = useLocation(); const {name} = useParams(); return( <div> <h1>Hello {name}</h1> <p>pathname: {location.pathname}</p> <p>search: {location.search} </p> <p>hash: {location.hash}</p> <button onClick={() => history.goBack()}>Go Back</button> </div> ); } function App(){ return ( <Router> <Switch> <Route path="/" exact> <Hello /> </Route> <Route path="/hello/:name" exact> <HelloSomeone/> </Route> </Switch> </Router> ); }
react-reduxの例
Yocto Projectの勉強まとめ(途中)
背景
SoC FPGAを搭載したオリジナル基板を開発できるようになりたい。
Linux使えれば色々便利。
基板毎に最適化された組込みLinux OSを作成できるYocto Projectなるものを知ったので勉強したい。
参考文献
Linuxディストリビューション
Linuxカーネル + 各種ライブラリ = Linux OS
各種ライブラリにはOSSプロジェクトも含まれる。
頒布方法
一連の流れ:
ソースコード => ダウンロード => コンパイル => バイナリ => インストール
バイナリーベース:
ディストリビューターがコンパイル済のソフトウェアをパッケージとして頒布。
パッケージにはバイナリとインストール方法をまとめられている。
ユーザーはそのパッケージをインストールする。
ソースベース:
ディストリビューターがコンパイル方法を頒布する。
ユーザーがコンパイルしインストールする。
Yocto Projectとは
Yocto Projectは組み込み向けOS開発を構築する仕組みを提供するプロジェクト。
ソースコードベース。
プロジェクト体制:
- Poky
- OpenEmbedded
- レシピとbitbakeを開発
- matchbox
- GUIライブラリ
- Eclipse IDE Plug-in
- opkg
- パッケージングシステム
- Toaster
- ビルドサポート用GUI
Poky
Pokyとは
- リファレンスビルドシステム
- ディストリビューション作成をサポートする
- bitbakeとメタデータ(レシピと設定ファイル)から構成される
- Linuxカーネル、ブートローダー、ユーザーランド、クロスツールチェインを生成する
レシピとは
- 拡張子は.bb又は.bbappend
- ソースコードの取得、ソフトウェアのコンパイル、パッケージングまでの動作を定義
- シェルスクリプトとPythonで記述
- レシピ同士の依存関係を設定
- bbppanedファイルは既存のbbファイルを修正する際に使用
設定ファイルとは
- 拡張子は.conf
- CPUアーキテクチャなどのターゲットマシン毎の定義
- ビルド環境などの独自設定
bitbakeとは
- Pythonで書かれたビルドツール
- レシピを解析し、定義された動作を実行する
bitbakeの動作
- レシピを解析
- ソースコードのダウンロード
- どこからダウンロードするか
- do_fetch
- ソースコードの展開
- どのように展開するか
- do_unpack
- パッチの適用
- どのようなパッチを適用するか
- do_patch
- ソフトウェアのコンパイル
- コンパイル方法の指定
- 依存関係の記述
- do_configure
- do_compile
- 生成物をパッケージ化
- インストール先
- どのファイルを含むか
- パッケージング方式の指定
- do_install
- do_package
レイヤー機能
まだ。
MAX10で画像処理
背景
FPGAで画像処理をしたい。
SoC FPGAでやろうと思ったけど、学習コストが高く、途中で挫折してしまった。
一旦、FPGAとマイコンをハード的に分けることで何かしらの進捗を出し、モチベーションを高める。
やりたいこと
各モジュールの簡単な説明
マイコン
言わずと知れたArduino Uno。
カメラモジュール
OV7675のモジュール品を使用する。
秋月で購入。550円。安い。
OV7675使用30万画素カメラ B0070: カメラ 秋月電子通商-電子部品・ネット通販
供給電源は3.3V、出力形式は選択可能。
画像データはパラレル8出力。
1~4ピン(電源、GND、I2C)をArduinoに接続する。
MAX10 EVAL Kit
Intelから販売されているMAX10の安価な評価ボード。
FPGAへのデータ書き込みには専用のツールが必要。
https://www.intel.co.jp/content/www/jp/ja/programmable/products/boards_and_kits/dev-kits/altera/kit-max-10-evaluation.html
カメラモジュールをマイコンのI2Cで制御
OV7675カメラモジュールのデータは以下。
細かい点は色々あるが、まずはデータを出力できればよい。
真っ黒だとデータが出力されているかどうかが不明なのでつらい。
http://akizukidenshi.com/download/ds/omnivision/ov7675.pdf
データシートから、何かしらの画像データを出力するために以下の設定が必要とわかる。
ENとPWDNは以下の設定が必要。
Pin | Level |
---|---|
PWDN | L |
PEN | H |
初期化時に各アドレスへ送信するデータは以下。
address | data | description |
---|---|---|
0xB8 | 4'h1 | 1.8V requirement |
0xB8 | 4'h2 | 1.8V requirement |
0x71 | 0x01 | Test pattern Enable |
0x17 | Horizontal start | |
0x18 | Horizontal stop | |
0x32 | Horizontal start[2:0] and stop[5:3] | |
0x19 | Vertical start | |
0x1A | Vertical stop | |
0x03 | Vertical start[2:0] and stop[5:3] |
スレーブアドレスは、Write0x42、Read0x43。
Write/Readで末尾に1/0を付加されている。
一般的にI2Cで使用される7bitのアドレスは0x21。
Direction | b6 | b5 | b4 | b3 | b2 | b1 | b0 | W/R |
---|---|---|---|---|---|---|---|---|
Write | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 1 |
Read | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 |
OV7675カメラモジュールとArduinoを接続する。
SCCB(I2C)でデータの送受信を行う。
ArduinoはI2Cのポートを有するが、Digital IOポートを使ってSCCBの制御を行っているコードをgithubで見つけた。ただしOV7670。
https://gist.github.com/muhammadyaseen/75490348a4644dcbc70f
これを修正すればよさそう。
Arduino一つで複数カメラの制御もできそうなので、
今後の拡張性を考慮してありがたく拝借して使用する。
OV7675の画素はベイヤパターン。
しかしレジスタの設定を変えることで、出力Formatは変更可能。
今回はRGB565でやってみる。
RGB565は、R:5bit、G:6bit、B:5bitの合計16bitを1画素のデータとするFormat。
OV7675は画像データの表示領域を選択できる。
0x17~0x1A、0x03、0x32で設定する。
VGAのデータ出威力ダイアグラムは以下。
データをディスプレイ上に表示するためには、VGAを使ったアナログ信号だとDAコンバータが必要。
今回はDAコンバーターがないので、デジタルデータを閾値で0/1切り替えて表示する。
とりあえず画像だし
FPGAにデータを書き込み、OV7675を初期化すると画像が出るようになった。
ただし、FPGAによるVGA出力とOV7675のデータ入力は同期をとっていないので、
表示される画像はひどい有様だった。
そこで、OV7675から入力されるPCLK信号(画素データのクロック)を使ってFPGAからVGAデータを出力したところ、
画像が表示されなかった(入力データがない状態)。
波形を観測すると、PCLKは鈍っており十分な信号レベルが出力されていないことがわかった。
コンパレーターかアンプが必要とわかったが、そこまで改修するのも手間なので、今回はここまでとする。
pyxelで遊ぶ
背景
Pythonで簡単にドット絵ゲームが作成できるpyxelなるものを知ったので、
Pythonの復習がてら使ってみる。
pyxle
https://github.com/kitao/pyxel/blob/master/README.ja.md
関数を削減して、覚えるよりも作ることに注力できる。学習コストが極めて低い。
ドット絵やサウンドエフェクトの開発ツールも同梱されている。
なんか作ってみる
とりあえずカラフルなエフェクトを作ってみた。
from pyxel import init, run, circ, cls from math import sin, cos class App: def __init__(self): init(160,120) self.i = 0 run(self.update, self.draw) def update(self): self.i += 1 self.i %= 1000 def draw(self): cls(1) for j in range(1500): circ(80+j/(50.1-2*self.i/4)*sin(j/2),60+j/(50.1-2*self.i/4)*cos(j/2),1,(j+self.i)%15) App()
何でもない画像だけど、これだけでも楽しい。ドット絵だからなのか。
これがドット絵の魔力・・・
ゲームでも作ってみる
せっかくなのでゲームでも作ってみる。
企画
ざっくりとした仕様
- 横スクロールアクション
- 自キャラのアクション
- 左右への移動
- ジャンプ
- 攻撃
- 敵キャラのアクション
- 左右への移動
絶賛作成中!!
途中経過
左右に移動+ジャンプ+攻撃(火の玉を出す)
移動時に画像を変えたいけど、画像を作るのがつらい・・・
昔からゲーム作成の肝は画像作成だと思っています。