tag:blogger.com,1999:blog-14710724468557881662024-03-14T03:24:05.235+09:00柴田(ひ)食堂柴田 ひ 食堂
luky.org
linux
趣味
日常luky.orghttp://www.blogger.com/profile/17273806834102337860noreply@blogger.comBlogger3199125tag:blogger.com,1999:blog-1471072446855788166.post-53730849798649149942020-11-03T17:58:00.001+09:002020-11-04T18:00:56.849+09:00散髪<p>いつの間にかまた伸び放題になっていたので自宅で散髪。</p><p>バリカンだけで仕上げてもらったが今一つ髪がまとまらない(^^;</p><p>ちょっとおかしな気がするが、まぁ素人仕事なので仕方がない。</p><p>これで会社に出るか(^^;;; <br /></p>luky.orghttp://www.blogger.com/profile/17273806834102337860noreply@blogger.com0tag:blogger.com,1999:blog-1471072446855788166.post-23056111261424700662020-10-03T23:19:00.004+09:002020-10-03T23:21:26.672+09:00macos CatalinaでNFSサーバを動かし、RP4Bから/マウントする<p>macos側の設定は、下記を参考にした。</p><p><a href="http://profaim.jp/tools/soft/macx/nfs/start_nfsd.php" target="_blank">MacOS X で NFSサーバーを構築する</a> <a href="http://www.maruko2.com/mw/Mac_OS_X_%E3%81%A7_NFS_%E3%82%92%E4%BD%BF%E3%81%86"><br />Mac OS X で NFS を使う</a> </p><p>その結果のサーバ側の/etc/exportsの設定は下記。
</p><blockquote>/Users/shibata/RP4Bnfs/root -maproot=root -alldirs -network 192.168.0.0 -mask 255.255.255.0
</blockquote><p>
RP4B側は、ubuntu20.04を動かしているが、microSDでブートだけさせる。<br /> /boot/firmware/cmdline.txtの設定は下記。
</p><blockquote>net.ifnames=0 dwc_otg.lpm_enable=0 console=tty1 root=/dev/nfs nfsroot=192.168.0.102:/Users/shibata/RP4Bnfs/root,tcp,rw ip=dhcp rootfstype=nfs elevator=deadline rootwait fixrtc</blockquote>luky.orghttp://www.blogger.com/profile/17273806834102337860noreply@blogger.com0tag:blogger.com,1999:blog-1471072446855788166.post-82974499917494086212020-09-26T10:30:00.012+09:002020-09-28T23:24:55.959+09:00散髪久々に出張先で散髪。
午後から披露宴出席があるので、ご両家に失礼が無いように
素人散髪を隠してもらうつもり。
あれこれ調べて、昔の職場の近くの「ミヤモリ」さんに行くことにした。
実は初めて。
いわゆるフルコースで税込4950円だったが、さすがにプロ。
耳かき、爪磨き、ヘッドマッサージもありで大満足だった。
やはりたまには良い床屋さんでやってもらうのは良いな(^^)luky.orghttp://www.blogger.com/profile/17273806834102337860noreply@blogger.com0tag:blogger.com,1999:blog-1471072446855788166.post-76025616780029618222020-09-08T09:32:00.001+09:002020-09-12T09:36:13.457+09:00散髪今回も自宅で散髪。
床屋さんに行きたいのは山々なんだが、
雨だったり暑かったり気が乗らんかったり。
カミサンにバリカン6mmで上まで刈り上げてもらい
トップは適当にハサミで。
まぁ、在宅が多いのでこれでなんとかなるか(^^;luky.orghttp://www.blogger.com/profile/17273806834102337860noreply@blogger.com0tag:blogger.com,1999:blog-1471072446855788166.post-66233335132680134752020-08-14T13:21:00.005+09:002020-08-14T13:59:32.514+09:00散髪<p> クソ暑いのと感染リスク低減を踏まえ、自宅で散髪する事に(^^;</p><p> 通販でバリカンを購入。</p><p> #折角、国内家電メーカ製を選んだのに、届いたらMade in Chinaだった(--;<br /> #もう少し高いのにしたら、国内製だったのかな?</p><p> ま、ともあれ、説明書通りに一晩充電してから、注油して初使用。</p><p>下の方は6mmで刈上げ、上の方は12mm。トップはハサミで切ってもらった。<br />初めてにしてはなかなかいい感じです。 </p><p>当分、これでしのぐかなぁ。</p><p> </p>luky.orghttp://www.blogger.com/profile/17273806834102337860noreply@blogger.com0tag:blogger.com,1999:blog-1471072446855788166.post-80039112330534076872020-08-13T07:55:00.004+09:002020-08-13T20:08:34.489+09:00macosでの/etc/fstabの編集<p>$ sudo su</p><p># vifs</p><p>#<br /># Warning - this file should only be modified with vifs(8)<br />#<br /># Failure to do so is unsupported and may be destructive.<br />#<br />UUID=BA80B0B6-B49B-47A4-8C9F-XXXXXXXXXXXX /Users/shibata apfs rw,auto<br /></p>luky.orghttp://www.blogger.com/profile/17273806834102337860noreply@blogger.com0tag:blogger.com,1999:blog-1471072446855788166.post-18922717960468281222020-08-09T21:03:00.002+09:002020-08-09T21:04:22.460+09:00MacBook Pro(late 2008)でCatalinaのIMEを動かす<h1 class="main-header"><span style="font-weight: normal;"><span style="font-size: medium;">ずっとmacos patcherのお世話になりながらHigh Sierraで動かしていたMacBook Pro(late 2008)だが、Xcodeなどのapple謹製ソフトがインストール出来なくなり困ってきた。</span></span></h1><h1 class="main-header" style="margin-left: 40px; text-align: left;"><span style="color: #999999;"><span style="font-weight: normal;"><span style="font-size: medium;">#実は以前、Mojaveにしてみたのだが不安定でどうにもならなかったので、<br />#High Sierraに戻していた。 </span></span></span><br /></h1><p> 駄目元でCatalinaにしてみた(^^;</p><h1 style="text-align: left;"><span style="font-size: x-large;"><b> </b></span></h1><h1 style="text-align: left;"><span style="font-size: x-large;"><b>【全体の手順】</b></span></h1><p><b>1.まずはTime Machineでバックアップをとる。</b><br /> 事前にできるだけ不要なファイルは消しておく。<br /></p><p><b>2.<a href="http://dosdude1.com/catalina/" target="_blank">macOS Catalina Patcher</a>をダウンロードし、<br /> 手持ちのUSBメモリをインストールメディアにする。</b></p><p><b>3.手順通りにmacos Patcherで作成したインストールメディアで起動させ、<br /> 内蔵HDDにCatalinaをインストールする。</b></p><p style="margin-left: 40px; text-align: left;"><span style="color: #999999;">#と、スンナリいっているいるように書いているが、postinstallのpatchが失敗して<br />#駄目元で内蔵HDDからCatalinaを起動させた後にpostinstallを行なった。<br />#Catalinaの起動も30分ぐらいかかり、けっこう待たされた。</span></p><p><b>4.内蔵HDDからCatalina起動後、もう一度インストールメディアで起動して<br /> postinstall patchを実行する。</b></p><p><b>5.日本語入力がおかしくなるので、<span style="color: red;">MojaveのIMEを移植</span>する。</b></p><p><b>6.再起動すれば、出来上がり。</b></p><p> <span style="color: red;">肝は上記の5である。</span></p><p>ネットを探すと、<a href="https://www.taikun-room.com/2020/01/catalina-patcher-bugs.html" target="_blank">macOS Catalina Patcher 不具合情報と解決策</a>という、ありがたいサイトがあった。 </p><p>もう一台のmacをたまたまMojaveで動かしていたので、そちらから関係するファイルを持ってきた。</p><div style="margin-left: 40px; text-align: left;"><span style="color: #999999;">#移植先はMacintosh HD - Dataではなく、Macintosh HDの方なのだが、</span><br /><span style="color: #999999;">#これで良かったんだろうな(^^; </span></div><p style="text-align: left;"><span style="font-size: x-large;"><b> </b></span></p><h1 style="text-align: left;"><span style="font-size: x-large;"><b>【移植したファイル】</b></span></h1><p>下記の<span style="color: #2b00fe;">青文字がMojaveから移植したファイル</span>。<br />同じく<span style="color: red;">赤文字はCatalinaにあったファイルのバックアップ</span>。<br /></p><p></p><blockquote>sh-3.2# pwd<br /><span style="background-color: #fcff01;">/usr/lib</span><br />sh-3.2# ls -l libmecab*<br />-rwxr-xr-x@ 1 root wheel 1596512 8 9 18:07 <span style="color: #2b00fe;">libmecab.1.0.0.dylib</span><br />-rwxr-xr-x@ 1 root wheel 1596512 8 9 18:07 <span style="color: #2b00fe;">libmecab.dylib</span><br />-rwxr-xr-x 1 root wheel 812464 8 6 09:49 <span style="color: red;">libmecab.dylib.bak</span><br />-rwxr-xr-x@ 1 root wheel 4820080 8 9 18:07 <span style="color: #2b00fe;">libmecabra.dylib</span><br />-rwxr-xr-x 1 root wheel 2881600 8 6 09:50 <span style="color: red;">libmecabra.dylib.bak</span></blockquote><span style="color: red;"></span><p></p><p> <br /></p><blockquote>sh-3.2# pwd<br /><span style="background-color: #fcff01;">/System/Library/Input Methods</span><br />sh-3.2# ls -l JapaneseIM.*<br /><span style="color: #2b00fe;">JapaneseIM.app</span>:<br />total 0<br />drwxr-xr-x@ 9 root wheel 288 2 23 2019 Contents<br /><br /><span style="color: red;">JapaneseIM.bak</span>:<br />total 0<br />drwxr-xr-x 9 root wheel 288 6 6 15:27 Contents </blockquote><p></p><p><br /></p><p></p><blockquote>sh-3.2# pwd<br /><span style="background-color: #fcff01;">/System/Library/PrivateFrameworks</span><br />sh-3.2# ls TextInput*<br /><span style="color: #2b00fe;">TextInput.framework</span>:<br />Resources TextInput Versions<br /><br /><span style="color: red;">TextInput.framework.bak<span style="color: black;">:</span></span><br />LanguageIntelligenceTrialDefaults.pb TextInput<br />Resources Versions<br /><br /><span style="color: #2b00fe;">TextInputCore.framework</span>:<br />Resources TextInputCore Versions<br /><br /><span style="color: red;">TextInputCore.framework.bak</span>:<br />Resources TextInputCore Versions<br /><br />TextInputMenuUI.framework:<br />Resources TextInputMenuUI Versions</blockquote><p> </p><h1 style="text-align: left;"><span style="font-size: x-large;"> 【移植のちょっと詳細】</span></h1><h3 style="margin-left: 40px; text-align: left;"><span style="font-size: x-large;"><span style="font-size: medium;">【移植元作業】Mojave側</span> <br /></span></h3><p></p><ol style="margin-left: 40px; text-align: left;"><li>ターミナルを開き、suでrootになる</li><li>上記の青文字のファイルを、cp -a でどこかのフォルダにまとめる</li><li>zipで固めて、移植先マシンにコピーする <br /></li></ol><h3 style="margin-left: 40px; text-align: left;"><span style="font-size: medium;">【移植先作業】Catalina側</span></h3><ol style="margin-left: 40px; text-align: left;"><li>コピーされたzipを解凍し「何処かのフォルダ」に置く</li><li>移植先をインストールメディアで立ち上げる</li><li>移植先のフォルダで、mv hoge hoge.bakする</li><li>移植先フォルダに 「何処かのフォルダ」からcp -aする</li><li>コピーしたファイルに対してchown -R root:whell hogeする</li><li>上記3.〜5.を対照ファイル分、繰り返す</li></ol><p></p><p style="text-align: left;"> </p><h2 style="text-align: left;">【ご参考情報】</h2><p> <a href="https://qiita.com/reo/items/d68b41c807770b6ebb10" target="_blank">macOS でよく見かける拡張属性や ACL</a></p><p></p>luky.orghttp://www.blogger.com/profile/17273806834102337860noreply@blogger.com0tag:blogger.com,1999:blog-1471072446855788166.post-89534282507768142822020-08-08T22:36:00.003+09:002020-08-08T22:36:50.180+09:00mongodb connector for business intelligence<p> mongodb connector for business intelligence<br />って、mongodbをODBCぽいSQL-DBに見せかけるラッパーかな。 </p><p>https://www.mongodb.com/products/bi-connector</p><p>https://docs.mongodb.com/bi-connector/master/ <br /></p><p><br /></p>luky.orghttp://www.blogger.com/profile/17273806834102337860noreply@blogger.com0tag:blogger.com,1999:blog-1471072446855788166.post-75869807751851002522020-08-07T20:57:00.011+09:002020-08-07T22:16:44.450+09:00RP3B+のルートパーティションをnfsでマウント<p>絶不調のでお蔵入りにしていたRaspberry Pi 3B+だが、捨てるには惜しいので、不安定なμSDカードをできるだけ使わない方法で安定するかどうかを検証すべく、以下を行なった。</p><p><span style="font-size: x-large;">【USB経由でSDカードを使う】 </span><br /></p><ul style="text-align: left;"><li> USB経由でSDカードを使うようにする<br />/も/bootもSDカードのまま。ただし、sd→USBアダプタを使って起動させる。</li></ul><p style="margin-left: 40px; text-align: left;">何も設定しなくても、RP3B+は標準でUSBブートするようで、上記はあっさり動いた。</p><p style="text-align: left;"> </p><p style="text-align: left;">上記でも以前より安定して動いたような気がする。</p><p>しかし、もう一歩進めて、下記のようにした。 <br /></p><p> </p><p><span style="font-size: x-large;">【USB経由で/bootさせ、/パーティションはnfsでマウントする】</span><br /></p><ul style="text-align: left;"><li>USB経由のSDカードは、/bootだけにする(ほぼread onlyになる)</li><li>/ファイルシステムは、隣に並んでいるRaspberry Pi 4Bをnfsサーバにして、<br />そこからのマウントにする<br />(RP4Bのストレージは、USB3経由でマウントしているSSDなので<br /> SDカードよりは性能も耐久性も良いだろうと)</li><li> 具体的な方法は<a href="NFS Root on Raspberry Pi 4" target="_blank">NFS Root on Raspberry Pi 4</a> そのままでいけた。<br />(上記ページはraspbianの例もubuntuの例もあり、非常に助かる)</li></ul><p>次にやるかもしれないのは、下記。</p><p><span style="font-size: x-large;">【PXEブートを使い、tftpで/bootをマウントさせ、/はnfsでマウント】</span></p><p style="margin-left: 40px; text-align: left;">これができたら、不安定なSDから完全におさらばできる。</p><p style="margin-left: 40px; text-align: left;">それらしい情報は下記にあるので、不安定さが解決しな時には試してみよう。</p><p style="margin-left: 40px; text-align: left;"><a href="https://qiita.com/ysugi/items/73855f966bac7634d831" target="_blank">Raspberry Pi 3 でSDカードなしのネットワークブートをする</a></p><p style="margin-left: 40px; text-align: left;"><a href="https://www.raspberrypi.org/documentation/hardware/raspberrypi/bootmodes/net.md" target="_blank">Network booting</a><br /></p><p>以上(^^; <br /></p><div><div><p> <br /></p><br /></div></div>luky.orghttp://www.blogger.com/profile/17273806834102337860noreply@blogger.com0tag:blogger.com,1999:blog-1471072446855788166.post-70145839778934217282020-08-03T01:53:00.002+09:002020-08-03T16:06:20.117+09:00JSON形式のファイルと名乗るには<div><a href="https://www.json.org/json-en.html">https://www.json.org/json-en.html</a>(日本語版は<a href="https://www.json.org/json-ja.html" target="_blank">https://www.json.org/json-ja.html</a>)によると、</div><div><blockquote>{ key: value }</blockquote></div><div>というのが一つのObjectであり</div><div></div><blockquote><div>{ key: value }<br /></div><div><div>{ key: value }</div></div></blockquote><div><div><br /></div><div>というのは、複数のObjectを列記してあるに過ぎず、厳密にはJSONのObjectではない。</div><div><br /></div><div>よって、上記のような形式のファイルは「JSONのようなもの」であるということになる。<br /></div><div><br /></div><div>厳密にJSON形式のファイルフォーマットというなら、<br /></div></div><div></div><blockquote><div>[</div><div> { key: value }<br /><div> { key: value }</div><div>]</div></div></blockquote><div><div></div><div>という配列(arrey)にする必要がありそうだ。</div><div><br /></div><div>各種センサーのログを厳密にJSON形式のファイルフォーマットにするのは大変なので</div><div>「JSONのようなもの」のファイルにしておこう(^^;<br /></div></div>luky.orghttp://www.blogger.com/profile/17273806834102337860noreply@blogger.com0tag:blogger.com,1999:blog-1471072446855788166.post-52100922658704202232020-08-02T21:36:00.005+09:002020-08-04T22:34:59.635+09:00Raspberry Pi 4B + BME280使用 温湿度・気圧センサモジュールキット<p class="post-title entry-title" style="text-align: left;"><a href="https://blog.luky.org/2020/08/raspberry-pi-4b-apds9660.html">Raspberry Pi 4B + APDS9660使用光学式ジェスチャーセンサモジュールキット </a>の続き。</p><p class="post-title entry-title" style="text-align: left;">【お品書き】</p><p class="post-title entry-title" style="margin-left: 40px; text-align: left;">温度、湿度、大気圧のセンサが一つに入っているBME280のモジュールである<a href="http://akizukidenshi.com/catalog/g/gK-09421/" target="_blank">BME280使用 温湿度・気圧センサモジュールキット</a>をi2cでラズパイに接続し、ログ取得するもの。</p><p class="post-title entry-title" style="margin-left: 40px; text-align: left;">【準備】</p><p class="post-title entry-title" style="margin-left: 40px; text-align: left;"><a href="https://www.switch-science.com/catalog/2236/" target="_blank">スイッチサイエンスの販売サイト</a>に<a href="https://github.com/SWITCHSCIENCE/BME280" target="_blank">Githubの公開リポジトリ(Pythonスクリプトなど)</a>へのリンクがあったので、それを利用することにした。</p><p class="post-title entry-title" style="margin-left: 80px; text-align: left;">#python2向けだったので、少し手直しが必要だったけど。</p><p class="post-title entry-title" style="text-align: left;">【スクリプト】<a href="https://drive.google.com/file/d/1DpT9oQAUcKhTXw5ex5ggCak4u_wrxtcd/view?usp=sharing" target="_blank">his.env2.py</a><br /></p><p class="post-title entry-title" style="text-align: left;"></p><p class="post-title entry-title" style="text-align: left;"></p><blockquote><p class="post-title entry-title" style="text-align: left;">[code]<br />#!/usr/bin/python3<br /><br />#coding: utf-8<br /><br />from smbus import SMBus<br />import datetime<br />import time<br /><br />bus_number = 1<br />i2c_address = 0x76<br /><br />bus = SMBus(bus_number)<br />path = '/sys/class/thermal/thermal_zone0/temp'<br /><br />digT = []<br />digH = []<br />digP = []<br /><br />t_fine = 0.0<br /><br /><br />def writeReg(reg_address, data):<br /> bus.write_byte_data(i2c_address, reg_address, data)<br /><br /><br />def get_calib_param():<br /> calib = []<br /><br /> for i in range(0x88, 0x88 + 24):<br /> calib.append(bus.read_byte_data(i2c_address, i))<br /> calib.append(bus.read_byte_data(i2c_address, 0xA1))<br /> for i in range(0xE1, 0xE1 + 7):<br /> calib.append(bus.read_byte_data(i2c_address, i))<br /><br /> digT.append((calib[1] << 8) | calib[0])<br /> digT.append((calib[3] << 8) | calib[2])<br /> digT.append((calib[5] << 8) | calib[4])<br /> digP.append((calib[7] << 8) | calib[6])<br /> digP.append((calib[9] << 8) | calib[8])<br /> digP.append((calib[11] << 8) | calib[10])<br /> digP.append((calib[13] << 8) | calib[12])<br /> digP.append((calib[15] << 8) | calib[14])<br /> digP.append((calib[17] << 8) | calib[16])<br /> digP.append((calib[19] << 8) | calib[18])<br /> digP.append((calib[21] << 8) | calib[20])<br /> digP.append((calib[23] << 8) | calib[22])<br /> digH.append(calib[24])<br /> digH.append((calib[26] << 8) | calib[25])<br /> digH.append(calib[27])<br /> digH.append((calib[28] << 4) | (0x0F & calib[29]))<br /> digH.append((calib[30] << 4) | ((calib[29] >> 4) & 0x0F))<br /> digH.append(calib[31])<br /><br /> for i in range(1, 2):<br /> if digT[i] & 0x8000:<br /> digT[i] = (-digT[i] ^ 0xFFFF) + 1<br /><br /> for i in range(1, 8):<br /> if digP[i] & 0x8000:<br /> digP[i] = (-digP[i] ^ 0xFFFF) + 1<br /><br /> for i in range(0, 6):<br /> if digH[i] & 0x8000:<br /> digH[i] = (-digH[i] ^ 0xFFFF) + 1<br /><br /><br />def readData():<br /> data = []<br /> for i in range(0xF7, 0xF7 + 8):<br /> data.append(bus.read_byte_data(i2c_address, i))<br /> pres_raw = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4)<br /> temp_raw = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4)<br /> hum_raw = (data[6] << 8) | data[7]<br /> outstring = "{ \"place\": \"home\" ,"<br /> outstring += " \"time\": \"{}\" , ".format(<br /> datetime.datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ"))<br /> print(outstring, end="")<br /> with open(path) as f:<br /> tcpu = float(f.read()) / 1000.0<br /> print("\"cpu\": {:.1f} ,".format(tcpu), end='')<br /> compensate_T(temp_raw)<br /> compensate_H(hum_raw)<br /> compensate_P(pres_raw)<br /><br /><br />def compensate_P(adc_P):<br /> global t_fine<br /><br /> v1 = (t_fine / 2.0) - 64000.0<br /> v2 = (((v1 / 4.0) * (v1 / 4.0)) / 2048) * digP[5]<br /> v2 = v2 + ((v1 * digP[4]) * 2.0)<br /> v2 = (v2 / 4.0) + (digP[3] * 65536.0)<br /> v1 = (((digP[2] * (((v1 / 4.0) * (v1 / 4.0)) / 8192)) / 8) +<br /> ((digP[1] * v1) / 2.0)) / 262144<br /> v1 = ((32768 + v1) * digP[0]) / 32768<br /><br /> if v1 == 0:<br /> return 0<br /> pressure = ((1048576 - adc_P) - (v2 / 4096)) * 3125<br /> if pressure < 0x80000000:<br /> pressure = (pressure * 2.0) / v1<br /> else:<br /> pressure = (pressure / v1) * 2<br /> v1 = (digP[8] * (((pressure / 8.0) * (pressure / 8.0)) / 8192.0)) / 4096<br /> v2 = ((pressure / 4.0) * digP[7]) / 8192.0<br /> pressure = pressure + ((v1 + v2 + digP[6]) / 16.0)<br /><br /> print(" \"pressure\": {:.1f} ".format(pressure / 100) + "}")<br /><br />def compensate_T(adc_T):<br /> global t_fine<br /> v1 = (adc_T / 16384.0 - digT[0] / 1024.0) * digT[1]<br /> v2 = (adc_T / 131072.0 - digT[0] / 8192.0) * \<br /> (adc_T / 131072.0 - digT[0] / 8192.0) * digT[2]<br /> t_fine = v1 + v2<br /> temperature = t_fine / 5120.0<br /> print("\"temp\": {:.1f} ,".format(temperature), end='')<br /><br /><br />def compensate_H(adc_H):<br /> global t_fine<br /> var_h = t_fine - 76800.0<br /> if var_h != 0:<br /> var_h = (adc_H - (digH[3] * 64.0 + digH[4] / 16384.0 * var_h)) * (digH[1] / 65536.0 * (<br /> 1.0 + digH[5] / 67108864.0 * var_h * (1.0 + digH[2] / 67108864.0 * var_h)))<br /> else:<br /> return 0<br /> var_h = var_h * (1.0 - digH[0] * var_h / 524288.0)<br /> if var_h > 100.0:<br /> var_h = 100.0<br /> elif var_h < 0.0:<br /> var_h = 0.0<br /> print(" \"humid\": {:.1f} ,".format(var_h), end='')<br /><br /><br />def setup():<br /> osrs_t = 1 # Temperature oversampling x 1<br /> osrs_p = 1 # Pressure oversampling x 1<br /> osrs_h = 1 # Humidity oversampling x 1<br /> mode = 3 # Normal mode<br /> t_sb = 5 # Tstandby 1000ms<br /> filter = 0 # Filter off<br /> spi3w_en = 0 # 3-wire SPI Disable<br /><br /> ctrl_meas_reg = (osrs_t << 5) | (osrs_p << 2) | mode<br /> config_reg = (t_sb << 5) | (filter << 2) | spi3w_en<br /> ctrl_hum_reg = osrs_h<br /><br /> writeReg(0xF2, ctrl_hum_reg)<br /> writeReg(0xF4, ctrl_meas_reg)<br /> writeReg(0xF5, config_reg)<br /><br /><br />setup()<br />get_calib_param()<br /><br /><br />if __name__ == '__main__':<br /> try:<br /> readData()<br /> except KeyboardInterrupt:<br /> pass</p><p class="post-title entry-title" style="text-align: left;">[/code]</p></blockquote><p class="post-title entry-title" style="text-align: left;"></p><div><br /></div><div>【実行結果】</div><div style="margin-left: 40px; text-align: left;">下記1行を標準出力に出して終わる。</div><blockquote>{ place: "home" , time: "2020-08-02T12:33:42Z" , "cpu": 42.4 ,"temp": 33.2 , "humid": 56.7 , "pressure": 1013.9 }</blockquote><div> </div><div>【今後の予定】</div><ul><li>crontabで10分ごとに動作させて、ファイルにためておく。</li><li>node.jsとmongoDBで作ったサービスに結果を登録し、Chart.jsなどでグラフ化する。</li></ul><div><br /></div>luky.orghttp://www.blogger.com/profile/17273806834102337860noreply@blogger.com0tag:blogger.com,1999:blog-1471072446855788166.post-83191028985992285812020-08-02T21:04:00.002+09:002020-08-04T22:35:39.037+09:00Raspberry Pi 4B + APDS9660使用光学式ジェスチャーセンサモジュールキット<div><a href="https://blog.luky.org/2020/08/raspberry-pi-4b-i2c.html" target="_blank">Raspberry Pi 4B のi2cバスにセンサーを接続</a>の続き</div><div><br /></div><div>【余談】</div><div style="margin-left: 40px; text-align: left;">APDS9660をラズパイ上で動作させるので、スクリプトの方が何かと都合が良さそう。</div><div style="margin-left: 40px; text-align: left;">Arduino用は秋月のサイトの<a href="http://akizukidenshi.com/download/ds/akizuki/apds9960_sample.zip">サンプルプログラム</a>はArduino用。</div><div style="margin-left: 40px; text-align: left;"><br /></div><div style="margin-left: 40px; text-align: left;">あちこち探して見つかったのは、Python用のライブラリである<a href="https://github.com/liske/python-apds9960">https://github.com/liske/python-apds9960</a>だった。</div><div style="margin-left: 40px; text-align: left;">Pythonは書いたことがないのだが、まぁ仕方ない。<br /></div><div><br /></div><div>【ソフトウエアの準備】</div><div></div><blockquote><div># apt install python3-smbus python3-pip</div><div># python3 -m pip install apds9960</div><div># python3 -m pip install RPi.GPIO</div><div><br /></div></blockquote><div style="margin-left: 40px; text-align: left;">pipというパッケージマネージャで、ライブラリをインストールしてくれるのね。</div><div style="margin-left: 40px; text-align: left;">便利だな。</div><div style="margin-left: 40px; text-align: left;">jsのnpmと言い、pythonのpipと言い、あえてOSのパッケージマネージャと</div><div style="margin-left: 40px; text-align: left;">別に用意するのは、今の流行というか、OS非依存にしてポータビリティを</div><div style="margin-left: 40px; text-align: left;">上げる方針なんだろうな。</div><div><br /></div><div>【スクリプト】<a href="https://drive.google.com/file/d/1huIGmItJf4OsbhZeYPo5a7eVq33ZhSEN/view?usp=sharing" target="_blank">his.ambient.py</a></div><div style="margin-left: 40px; text-align: left;"><a href="https://github.com/liske/python-apds9960">https://github.com/liske/python-apds9960</a>の中のテストスクリプトを元に、下記をでっち上げた。</div><blockquote><div>[code]</div><div>#!/usr/bin/python3<br /><br />from apds9960.const import *<br />from apds9960 import APDS9960<br />import RPi.GPIO as GPIO<br />import smbus<br />import datetime, time<br />from time import sleep<br /><br />port = 1<br />bus = smbus.SMBus(port)<br /><br />apds = APDS9960(bus)<br /><br />def intH(channel):<br /> print()<br /><br />GPIO.setmode(GPIO.BOARD)<br />GPIO.setup(7, GPIO.IN)<br />try:<br /> # Interrupt-Event hinzufuegen, steigende Flanke<br /> GPIO.add_event_detect(7, GPIO.FALLING, callback = intH)<br /> apds.enableLightSensor()</div><div> sleep(1)<br /> outstring = "{ place : \"home\" ,"<br /> outstring += " time : \"{}\" ,".format(datetime.datetime.utcnow().strftime(<br />"%Y-%m-%dT%H:%M:%SZ"))<br /> outstring += " AmbientLight : {} ,".format(apds.readAmbientLight())<br /> outstring += " red :{} ,".format(apds.readRedLight())<br /> outstring += " green :{} ,".format(apds.readGreenLight())<br /> outstring += " blue :{} ".format(apds.readBlueLight()) + "}"<br /> print(outstring)<br /><br />finally:<br /> GPIO.cleanup()</div><div><br /></div><div>[/code]</div></blockquote><div></div><div>【実行結果】</div><div style="margin-left: 40px; text-align: left;">下記1行を標準出力に出して終わる。</div><div style="text-align: left;"><blockquote>{ place : "home" , time : "2020-08-02T11:58:17Z" , "AmbientLight" : 151 , "red" :33 , "green" :28 , "blue" :26 }</blockquote><div>【今後の予定】</div><ul><li>crontabで10分ごとに動作させて、ファイルにためておく。</li><li>node.jsとmongoDBで作ったサービスに結果を登録し、Chart.jsなどでグラフ化する。</li><li>もともとAPDS9660はジェスチャーセンサーなんだが、その機能は使う予定なし。</li></ul><div><br /></div><br /></div><div><br /></div>luky.orghttp://www.blogger.com/profile/17273806834102337860noreply@blogger.com0tag:blogger.com,1999:blog-1471072446855788166.post-54893103313723028402020-08-02T20:37:00.006+09:002020-08-02T20:40:18.740+09:00Raspberry Pi 4B のi2cバスにセンサーを接続<div>【お品書き】</div><div style="margin-left: 40px; text-align: left;">ずっと工作箱の中にしまっていた<br /><a href="http://akizukidenshi.com/catalog/g/gK-09754/" target="_blank">APDS9660使用 光学式ジェスチャーセンサモジュールキット</a>と</div><div style="margin-left: 40px; text-align: left;"><a href="http://akizukidenshi.com/catalog/g/gK-09421/" target="_blank">BME280使用 温湿度・気圧センサモジュールキット</a>を</div><div style="margin-left: 40px; text-align: left;">Rapberry pi 4Bのi2cにバス繋いでみた。</div><div style="margin-left: 40px; text-align: left;"></div><blockquote style="margin-left: 40px; text-align: left;"><div>#正確には、APDS9660モジュールは秋月のものではなく、同等品。</div><div></div></blockquote><div>【接続】</div><div style="margin-left: 40px; text-align: left;">ラズパイ4Bは、放熱のためにアルミ合金ケースに入れているが、GPIO(40pin)はフラットケーブルでケース外に引き出すことができる。</div><div style="margin-left: 40px; text-align: left;">そこからブレッドボードに繋いでセンサーモジュールを接続してみた。</div><div class="separator" style="clear: both; margin-left: 40px; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7jVO0TnPCJUlL1omthidV406KbwTlcioAm7x3VvMBsYDA-Dvq_yTq7Px-ZfXTUTHTuMUVhlckKCDf8_XJCNe79pIDCQqGJpCHkJTVpetaszAeHGi9xxnkdZpQ0hG_UKUFflDa3QzMIPs/s1741/BME280%252BAPDS9660-1.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1741" data-original-width="1127" height="673" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7jVO0TnPCJUlL1omthidV406KbwTlcioAm7x3VvMBsYDA-Dvq_yTq7Px-ZfXTUTHTuMUVhlckKCDf8_XJCNe79pIDCQqGJpCHkJTVpetaszAeHGi9xxnkdZpQ0hG_UKUFflDa3QzMIPs/s640/BME280%252BAPDS9660-1.jpg" width="498" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfaH3UY0JbgrvMdWctnO7W1-5684t9S7HyI52qGtHDbO07jSAK0flumDihfVXOx5iB0nTVlIdT3seNohyphenhypheng9aFCUJYqwPQrK0B6-FF3-Otsn6Iapjc1gv6Ax4nhUQS-usFPzSzlHP3Fw2o/s1605/APDS9960%252BBME280-2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1086" data-original-width="1605" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfaH3UY0JbgrvMdWctnO7W1-5684t9S7HyI52qGtHDbO07jSAK0flumDihfVXOx5iB0nTVlIdT3seNohyphenhypheng9aFCUJYqwPQrK0B6-FF3-Otsn6Iapjc1gv6Ax4nhUQS-usFPzSzlHP3Fw2o/s640/APDS9960%252BBME280-2.jpg" width="640" /></a></div><div><br /></div><div><br /></div><div>【接続確認】</div><div><div style="margin-left: 40px; text-align: left;"># apt install i2c-tools<br /></div><div style="margin-left: 40px; text-align: left;"># i2cdetect -y 1<br /></div></div><div></div><blockquote><div> 0 1 2 3 4 5 6 7 8 9 a b c d e f<br />00: -- -- -- -- -- -- -- -- -- -- -- -- -- <br />10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- <br />20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- <br />30: -- -- -- -- -- -- -- -- -- 39 -- -- -- -- -- -- <br />40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- <br />50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- <br />60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- <br />70: -- -- -- -- -- -- 76 -- <br /></div><div></div></blockquote><ul><li>0x39がAPDS9660</li><li>0x76がBME280</li></ul><div style="margin-left: 40px; text-align: left;">とりあえず、認識されているようだ。</div><div style="text-align: left;"><br /></div><div style="text-align: left;">ソフトウエアの設定については、別途。</div><div style="text-align: left;"><br /></div><div><br /></div>luky.orghttp://www.blogger.com/profile/17273806834102337860noreply@blogger.com0tag:blogger.com,1999:blog-1471072446855788166.post-16265849245820120092020-08-01T00:40:00.004+09:002020-08-01T07:08:11.499+09:00サーバサイドの準備 その1<div>【準備段階のメモ】<br /></div><ol><li>raspberry Pi 4B(8GB)にSSD(500GB)をUSB3.0で接続し、</li><li>そこにubuntu 20.04 LTSをインストール。</li><li>node.js、express、nodemon、vue.js、chart.jsをインストール。</li><li>さらに、npm install -g d3でd3をインストール。</li><li>ubuntuのパッケージからではなく、mongodb-orgをインストール。</li><li>追加でnpm install -g mongoose<br /></li></ol><div>vue.jsはスマホなどからアクセスする時のGUI用。</div><div>chart.jsはグラフ表示用。</div><div>d3.jsもグラフ表示だけど、先は長そう。<br /></div><div><div><br /></div><div><br /></div></div>luky.orghttp://www.blogger.com/profile/17273806834102337860noreply@blogger.com0tag:blogger.com,1999:blog-1471072446855788166.post-48381331598951759992020-07-30T23:17:00.002+09:002020-08-03T15:29:21.019+09:00M5Stack COCOA Counter + ENV.2 Sensor + GPS Unit のログファイルをHTTP POSTするスケッチ その1【主な機能】<div><div><ul style="text-align: left;"><li><div><a href="https://blog.luky.org/2020/07/m5stack-cocoa-counter-env2-sensor-gps_30.html">M5Stack COCOA Counter + ENV.2 Sensor + GPS Unit その4</a>で出力した</div><div>M5StackのマイクロSDカード内のログを、M5StackからWiFi経由でhttp POSTするもの。</div></li><li>POST先は、node.js+mongoDBで動いているものなどを想定している。<br /></li></ul><br /></div><div>【付加機能】</div><div><ul style="text-align: left;"><li>ボタンA(左)を押すと、M5Stack-SD-Updaterに遷移する。</li><li>読み出すログファイル名、接続するWiFiのSSID/pass、http POSTするURLを<br />マイクロSD内の"/GPSlog.conf"という名の初期設定ファイルから読み出すようにした。<br />(使用環境に合わせるためのスケッチの修正やリコンパイルを不要にした。)</li></ul><br /></div><div>【かっこ悪いところ】</div><div><ul style="text-align: left;"><li>ログファイル内のJSONのフォーマットチェックを一切おこなっていない。</li><li>http POSTが失敗した時のエラー処理を一切おこなっていない。</li><li>何レコードをPOSTしたのかもカウントしていない。</li></ul></div><div style="text-align: left;"><br /></div><div style="text-align: left;">【初期設定ファイル例】</div><div style="text-align: left;"></div><blockquote><div style="text-align: left;"><span style="color: #2b00fe;">{<br /> logfile: "/GPSlog.jsn",<br /> buf: 2048,<br /> ssid: "secret-SSID-home2.4",<br /> pass: "secret-password-home",<br /> url: "http://192.168.0.112:3000/log"<br />}</span></div><div style="text-align: left;"></div></blockquote><div style="text-align: left;"><br /></div><div style="text-align: left;">【初期設定ファイルの説明】</div><div style="text-align: left;"></div><blockquote><div style="text-align: left;">logfile: ログファイル名</div><div style="text-align: left;">buf: 1レコードのJSON文字列用のバッファ長</div><div style="text-align: left;">ssid: 接続するWiFiのSSID</div><div style="text-align: left;">pass: WiFiのパスワード</div><div style="text-align: left;">url: httpでPOSTするURL <br /></div><div style="text-align: left;"></div></blockquote><div style="text-align: left;">【スケッチ・ソース】<a href="https://drive.google.com/file/d/1agZlQFWbrgczgcEf-MBDefEyhSP1ZqNX/view?usp=sharing" target="_blank">his.GPS.LOG.POST.ino</a><br /></div><div style="text-align: left;"><blockquote>[code]<br />// M5Stack ----------------------------------------------------------------<br />#include <M5Stack.h><br />#include "M5StackUpdater.h"<br />// HTTP -------------------------------------------------------------------<br />#include <HTTPClient.h><br />// JSON -------------------------------------------------------------------<br />#include <ArduinoJson.h><br />// SD ---------------------------------------------------------------------<br />#include <SPI.h><br />#include <SD.h><br />// WiFi -------------------------------------------------------------------<br />#include <WiFi.h><br /><br />// CONFIG -----------------------------------------------------------------<br />struct Config {<br /> char logfile[12];<br /> int buf;<br /> char ssid[64];<br /> char pass[64];<br /> char url[256];<br />};<br /><br />Config config;<br /><br />const char *cnfFileName = "/GPSlog.cnf"; //環境毎に設定<br /><br />File logFile;<br /><br />void loadConfiguration(const char *filename, Config &config) {<br /> File file = SD.open(cnfFileName);<br /> StaticJsonDocument<512> doc;<br /><br /> // Deserialize the JSON document<br /> DeserializationError error = deserializeJson(doc, file);<br /> if (error)<br /> Serial.println(F("ERROR while reading config file. using default conf"));<br /><br /> // Copy values from the JsonDocument to the Config<br /> strlcpy(config.logfile,<br /> doc["logfile"] | "/GPSlog.jsn", //環境毎に設定<br /> sizeof(config.logfile));<br /> Serial.println("log file name: " + String(config.logfile));<br /> config.buf = doc["buf"] | 1024; //環境毎に設定<br /> Serial.println("JSON line buffer size: " + String(config.buf));<br /> strlcpy(config.ssid,<br /> doc["ssid"] | "SSID-open", //環境毎に設定<br /> sizeof(config.ssid));<br /> Serial.println("SSID: " + String(config.ssid));<br /> strlcpy(config.pass,<br /> doc["pass"] | "passowrd", //環境毎に設定<br /> sizeof(config.pass));<br /> Serial.println("pass: " + String(config.pass));<br /> strlcpy(config.url,<br /> doc["url"] | "http://example.com:3000/postjson", //環境毎に設定<br /> sizeof(config.url));<br /> Serial.println("http POST url: " + String(config.url));<br /><br /> // Close the file (Curiously, File's destructor doesn't close the file)<br /> file.close();<br />}<br />// HTTP -------------------------------------------------------------------<br />bool dohttpPOST(String logstring)<br />{<br /> bool b = false;<br /> HTTPClient http;<br /> http.begin(config.url);<br /> http.addHeader("Content-Type", "application/json");<br /> int status_code = http.POST(logstring);<br /> Serial.printf("status_code=%d\r\n", status_code);<br /> if (status_code == 200) {<br /> String json_response = http.getString();<br /> Serial.println("respose->"); Serial.println(json_response);<br /> b = true;<br /> }<br /> http.end();<br /> return b;<br />}<br />// WiFi -------------------------------------------------------------------<br />void connectWiFi() {<br /> WiFi.mode(WIFI_STA); //STAモード(子機)として使用<br /> WiFi.disconnect(); //Wi-Fi切断<br /><br /> WiFi.begin(config.ssid , config.pass); //環境毎に設定<br /> while (WiFi.status() != WL_CONNECTED) {<br /> Serial.println("trying WiFi Connection...");<br /> delay(1000);<br /> }<br /> Serial.println("WiFi Connected.");<br />}<br /><br />// Inside -----------------------------------------------------------------<br />void setup() {<br /> M5.begin();<br /> M5.Power.begin();<br /> M5.Lcd.println("Hello!, JSON http.post");<br /><br /> Serial.begin(115200);<br /> loadConfiguration(cnfFileName, config);<br /><br /> //SD -------------------------------------------<br /> logFile = SD.open(String(config.logfile));<br /> if (logFile) {<br /> Serial.println("log file found");<br /> } else {<br /> Serial.println("error: opening " + String(config.logfile));<br /> }<br /><br /> //WiFI -------------------------------------------<br /> connectWiFi();<br /><br /> //HTTP -------------------------------------------<br /> int pt = 0;<br /> char readbuf[config.buf] = "";<br /> while (logFile.available()) {<br /> readbuf[pt] = logFile.read();<br /> if (readbuf[pt] == 0x0A) {<br /> readbuf[pt + 1] = 0;<br /> String s = readbuf;<br /> Serial.println("String length=" + String(s.length()));<br /> Serial.println(s);<br /> if (dohttpPOST(s)) {<br /> Serial.println("post OK");<br /> } else {<br /> Serial.println("post ERROR");<br /> }<br /> pt = 0;<br /> char readbuf[config.buf] = "";<br /> delay(50);<br /> } else {<br /> pt++;<br /> }<br /> }<br />}<br /><br />void loop() {<br /> M5.update();<br /> M5.Lcd.setTextSize(3);<br /> M5.Lcd.println();<br /> M5.Lcd.setTextColor(BLUE, WHITE);<br /> M5.Lcd.println("log file http.POST done.");<br /> M5.Lcd.println("A: SDUpdater");<br /> while (1) {<br /> if (M5.BtnA.wasReleased()) { //AボタンでSDUpdater<br /> updateFromFS(SD);<br /> ESP.restart();<br /> }<br /> delay(100);<br /> M5.update(); // update button state<br /> }<br />}<br />// Arranged and written by 柴田(ひ)<br />[/code]</blockquote><br /></div><br /></div>luky.orghttp://www.blogger.com/profile/17273806834102337860noreply@blogger.com0tag:blogger.com,1999:blog-1471072446855788166.post-73334322493562647152020-07-30T22:50:00.002+09:002020-08-03T15:32:26.011+09:00M5Stack COCOA Counter + ENV.2 Sensor + GPS Unit その4<div><a href="https://blog.luky.org/2020/07/m5stack-cocoa-counter-env2-sensor-gps_26.html">M5Stack COCOA Counter + ENV.2 Sensor + GPS Unit その3</a>から、ごくわずか変更。</div><div><br /></div><div><div>【変更内容】<br /></div><div><ul style="text-align: left;"><li>出力ファイル名の変更<br /><b><span style="color: #cc0000;">→マイクロSDカードに"GPSlog.jsn"というファイル名で<br /> JSONフォーマットのログを出力する。</span></b><br /></li></ul><br /></div><div>【既知のバグ】</div><div style="text-align: left;"><ul style="text-align: left;"><li>GPSからの取得データ値がおかしなことがある。<br /><span style="color: #cc0000;"><b>→あれこれ調べたけど、断念(^^;</b></span></li></ul></div><div style="text-align: left;"><br /></div><div style="text-align: left;">【今後の予定】</div><div style="text-align: left;"><ul style="text-align: left;"><li>JSON形式のログをhttp POSTで<br />node.js+express+mongoDBで構築している<br />ログ収集サーバにuploadするスケッチを作成する。<br /><b><span style="color: #cc0000;">→一応できたので、別に書いときます。</span></b><br /><br /></li><li>コテコテコーディングから<a href="https://github.com/arduino-libraries/Arduino_JSON">Arduino_JSON</a>を利用するように書き直し。<br /><b><span style="color: #cc0000;">→変更してない。<br /> http POSTするスケッチの中でちょっとだけ使用。</span></b><br /><br /></li><li>ログ収集サーバ側では、JSON→GPX変換して、<br />googleMap等に表示できるようにする。<br /><span style="color: #cc0000;"><b>→まだ未着手。</b></span><br /><br /></li><li>同じくサーバサイドで、グラフ表示などの機能を作る。<br />生成したグラフは、Blogger上の<a href="https://blog.luky.org/">このブログ</a>に自動投稿させる。<br /><b><span style="color: #cc0000;">→同じく未着手。</span></b><br /></li></ul></div><div style="text-align: left;"><br /></div><div style="text-align: left;">【出力ファイル内の例】<br /></div><div style="text-align: left;"></div><blockquote><div style="text-align: left;"><span style="color: #666666;">{ "class": "TPV" ,"mode": 3 ,"time": "2020-07-30T06:41:13Z" ,"lat": 35.123456 ,"lon": 139.123456 ,"alt": 26.5 ,"track": 185.950000 ,"speed": 0.0 ,"ble": 15 ,"cocoa": 4 ,"temp": 27.4 ,"humidity": 70.0 ,"pressure": 1015.5 }<br />{ "class": "TPV" ,"mode": 3 ,"time": "2020-07-30T06:41:24Z" ,"lat": 35.123456 ,"lon": 139.123456 ,"alt": 25.2 ,"track": 185.950000 ,"speed": 0.0 ,"ble": 16 ,"cocoa": 5 ,"temp": 27.4 ,"humidity": 70.0 ,"pressure": 1015.5 }<br />{ "class": "TPV" ,"mode": 3 ,"time": "2020-07-30T06:41:34Z" ,"lat": 35.123456 ,"lon": 139.123456 ,"alt": 25.3 ,"track": 185.950000 ,"speed": 0.0 ,"ble": 15 ,"cocoa": 6 ,"temp": 27.4 ,"humidity": 70.0 ,"pressure": 1015.5 }</span><br /></div></blockquote><div style="text-align: left;"><br /></div><div style="text-align: left;">【スケッチ・ソース】<a href="https://drive.google.com/file/d/1_xV1R8nWv9erLn9i9sGWuJ-4Mr3QvVhr/view?usp=sharing" target="_blank">his.GPS.LOG.SAVE.ino</a></div><div style="text-align: left;"></div><div style="text-align: left;"><blockquote>[code]<br />// M5Stack ----------------------------------------------------------------<br />#include <M5Stack.h><br />#include "M5StackUpdater.h"<br />// BLE & Cocoa ------------------------------------------------------------<br />#include <BLEDevice.h><br />// ENV2 -------------------------------------------------------------------<br />/* add library Adafruit_BMP280 & Adafruit_SHT31 from library manage */<br />#include <Adafruit_Sensor.h><br />#include <Adafruit_SHT31.h><br />#include <Wire.h> //The SHT31 uses I2C comunication.<br />#include <Adafruit_BMP280.h><br />// GPS --------------------------------------------------------------------<br />#include <TinyGPS++.h><br />// SD ---------------------------------------------------------------------<br />#include <SPI.h><br />#include <SD.h><br />// BLE & Cocoa ------------------------------------------------------------<br />int scanTime = 5;<br />BLEScan* pBLEScan;<br />const int chipSelect = 4;<br />bool onBeep = true;<br /><br />//接触確認アプリのUUID<br />const char* cocoaUUID = "0000fd6f-0000-1000-8000-00805f9b34fb";<br />int cocoaCnt = 0; //time out in seconds<br /><br />class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {<br /> void onResult(BLEAdvertisedDevice advertisedDevice) {<br /> if (advertisedDevice.haveServiceUUID()) {<br /> if (strncmp(advertisedDevice.getServiceUUID().toString().c_str(), cocoaUUID, 36) == 0) {<br /> cocoaCnt++;<br /> if (onBeep) {<br /> M5.Speaker.beep();<br /> delay(10);<br /> M5.Speaker.mute();<br /> }<br /> M5.Lcd.setCursor(0, 110);<br /> M5.Lcd.setTextSize(2);<br /> M5.Lcd.setTextColor(GREEN, BLACK);<br /> M5.Lcd.printf("%d ", cocoaCnt);<br /> M5.Lcd.setTextSize(1);<br /> }<br /> }<br /> M5.Lcd.println(advertisedDevice.toString().c_str());<br /> M5.Lcd.setTextSize(1);<br /> M5.Lcd.setTextColor(WHITE, BLACK);<br /> }<br />};<br /><br />void setupBLE() {<br /> BLEDevice::init("");<br /> pBLEScan = BLEDevice::getScan(); //create new scan<br /> pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());<br /> pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster<br /> pBLEScan->setInterval(100);<br /> pBLEScan->setWindow(99); // less or equal setInterval value<br />}<br />// ENV2 -------------------------------------------------------------------<br />Adafruit_SHT31 sht31 = Adafruit_SHT31();<br />Adafruit_BMP280 bme;<br /><br />bool hasSHT31 = false;<br />bool hasBMP280 = false;<br />float tmp = 100;<br />float hum = 0;<br />float pressure = 0;<br /><br />void setupENV2() {<br /> //ENV2 sensor on I2C setup<br /> Wire.begin();<br /> Serial.println(F("ENV.2 Chk"));<br /><br /> if (sht31.begin(0x44)) { // Set to 0x45 for alternate i2c addr<br /> hasSHT31 = true;<br /> Serial.println("SHT31 Ok");<br /><br /> Serial.print("Heater: ");<br /> if (sht31.isHeaterEnabled())<br /> Serial.println("Ena");<br /> else<br /> Serial.println("Dis");<br /> }<br /><br /> if (bme.begin(0x76)) {<br /> hasBMP280 = true;<br /> Serial.println("BMP280 Ok");<br /> }<br />}<br />// GPS --------------------------------------------------------------------<br />//bool hasRTC = false;<br />bool hasGPS = false;<br />TinyGPSPlus gps; // The TinyGPS++ object<br />HardwareSerial hsGps(2);// The serial connection to the GPS device<br />static const uint32_t GPSBaud = 9600;<br /><br />void setupGPS() {<br /> hsGps.begin(GPSBaud);<br /> delay(500);<br /><br /> if (hsGps.available() > 0) {<br /> hasGPS = true;<br /> Serial.println("GPS Ok");<br /> }<br />}<br />// SD ---------------------------------------------------------------------<br />// log file name<br />const char* logfile = "<span style="color: #cc0000;">/GPSlog.jsn</span>";<br />// Inside -----------------------------------------------------------------<br />unsigned char bright = 0x03;<br />unsigned char brightPitch = 0x10;<br />//文字列<br /><a href="#" id="JSON" name="JSON"></a>const char* log<a href="#" id="JSON" name="JSON">JSON</a> = "<span style="color: #38761d;">{ \"class\": \"TPV\" ,\<br />\"mode\": 3 ,\<br />\"time\": \"%d-%02d-%02dT%02d:%02d:%02dZ\" ,\<br />\"lat\": %lf ,\<br />\"lon\": %lf ,\<br />\"alt\": %.1f ,\<br />\"track\": %lf ,\<br />\"speed\": %.1f ,\<br />\"ble\": %d ,\<br />\"cocoa\": %d ,\<br />\"temp\": %.1f ,\<br />\"humidity\": %.1f ,\<br />\"pressure\": %.1f }</span>";<br /><br />// ------------------------------------------------------------------------<br />void setup() {<br /><br /> // Initialize the M5Stack<br /> M5.begin();<br /> M5.Power.begin();<br /> M5.Lcd.setBrightness(bright);<br /> M5.Lcd.setTextSize(1);<br /> M5.Lcd.println("Hello!, COCOA Scan");<br /><br /> Serial.begin(115200);<br /><br /> setupBLE();<br /> setupENV2();<br /> setupGPS();<br /><br /> if (digitalRead(BUTTON_A_PIN) == 0) {<br /> Serial.println("Will Load menu binary");<br /> updateFromFS(SD);<br /> ESP.restart();<br /> }<br /><br />}<br /><br />void loop() {<br /> // print all found BLE devices<br /> M5.Lcd.setTextSize(1);<br /><br /> BLEScanResults foundDevices = pBLEScan->start(scanTime, false);<br /><br /> // print counts of BLE devices<br /> int sumdev = foundDevices.getCount();<br /><br /> // print env2 data<br /> if (hasSHT31) {<br /> tmp = sht31.readTemperature();<br /> hum = sht31.readHumidity();<br /> }<br /> if (hasBMP280) {<br /> pressure = bme.readPressure() / 100;<br /> // hPa = Pa / 100;<br /> }<br /><br /> while (hsGps.available() > 0) {<br /> gps.encode(hsGps.read());<br /> }<br /><br /> Serial.printf(logJSON, gps.date.year(), gps.date.month(), gps.date.day(),<br /> gps.time.hour(), gps.time.minute(), gps.time.second(),<br /> gps.location.lat(), gps.location.lng(), gps.altitude.meters(), gps.course.deg(),<br /> gps.speed.mps(), sumdev, cocoaCnt, tmp, hum, pressure);<br /> Serial.println();<br /><br /> // SDカードへの書き込み処理(ファイル追加モード)<br /> // SD.beginはM5.begin内で処理されているので不要<br /> // open the file. note that only one file can be open at a time,<br /> // so you have to close this one before opening another.<br /> File dfile = SD.open(logfile, FILE_APPEND);<br /><br /> // if the file is available, write to it:<br /> if (dfile) {<br /> dfile.printf(logJSON, gps.date.year(), gps.date.month(), gps.date.day(),<br /> gps.time.hour(), gps.time.minute(), gps.time.second(),<br /> gps.location.lat(), gps.location.lng(), gps.altitude.meters(), gps.course.deg(),<br /> gps.speed.mps(), sumdev, cocoaCnt, tmp, hum, pressure);<br /> dfile.println();<br /> }<br /><br /> // clear screen and set cursor to the top<br /> M5.Lcd.fillScreen(BLACK);<br /> M5.Lcd.setCursor(0, 0);<br /> M5.Lcd.setTextSize(2);<br /> M5.Lcd.setTextColor(WHITE, BLACK);<br /> M5.Lcd.printf(logJSON, gps.date.year(), gps.date.month(), gps.date.day(),<br /> gps.time.hour(), gps.time.minute(), gps.time.second(),<br /> gps.location.lat(), gps.location.lng(), gps.altitude.meters(), gps.course.deg(),<br /> gps.speed.mps(), sumdev, cocoaCnt, tmp, hum, pressure);<br /> M5.Lcd.println();<br /><br /> //Button controll<br /> M5.Lcd.setTextSize(3);<br /> M5.Lcd.println();<br /> M5.Lcd.setTextColor(BLUE, WHITE);<br /> M5.Lcd.println("A: SDUpdater");<br /> M5.Lcd.println("B: Beep on/off");<br /> M5.Lcd.println("C: Brightness");<br /><br /> int timer = 100;<br /> while (timer--) {<br /> if (M5.BtnA.wasReleased()) { //AボタンでSDUpdater<br /> updateFromFS(SD);<br /> ESP.restart();<br /> } else if (M5.BtnB.wasReleased()) { //Bボタンでbeepをon/off切り替える<br /> onBeep = !onBeep;<br /> } else if (M5.BtnC.wasReleased()) { //Cボタンで輝度を変更<br /> bright += brightPitch;<br /> M5.Lcd.setBrightness(bright);<br /> }<br /> delay(50);<br /> M5.update(); // update button state<br /> }<br /><br /> //init for next loop<br /> dfile.close();<br /> pBLEScan->clearResults(); // delete results fromBLEScan buffer to release memory<br /> cocoaCnt = 0;<br /><br /> M5.Lcd.setTextColor(WHITE, BLACK);<br /> M5.Lcd.setCursor(0, 110);<br /> M5.Lcd.setTextSize(1);<br />}<br /><br />// Arranged and written by 柴田(ひ)<br />/* BLE<br /> Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleScan.cpp<br /> Ported to Arduino ESP32 by Evandro Copercini<br />*/<br />/* Cocoa<br /> Thanks to https://gist.github.com/ksasao/0da6437d3eac9b2dbd675b6fee5d1117<br /> by https://gist.github.com/ksasao<br />*/<br />/* GPS<br /> This sample sketch demonstrates the normal use of a TinyGPS++ (TinyGPSPlus) object.<br /> by Mikal Hart<br />*/<br />/* SD<br /> SD card wrie routine<br /> https://raspberrypi.mongonta.com/howto-write-csv-to-sdcard-on-m5stack/<br />*/<br />[/code]</blockquote><br /></div></div>luky.orghttp://www.blogger.com/profile/17273806834102337860noreply@blogger.com0tag:blogger.com,1999:blog-1471072446855788166.post-43417982281198118782020-07-26T13:49:00.001+09:002020-07-26T13:49:52.173+09:00gpsd_jsonをもとにnode.js+mongoose用のスキーマ<div>【メモ】</div><div style="margin-left: 40px; text-align: left;">M5StackにGPS Unitをつけて、各種ログをJSON形式で保存・データ連携することを試作中だが、「はて、どんなKeyにするのが適切かな?」と思ったのであちこち調べて見た。</div><div style="margin-left: 40px; text-align: left;"><br /></div><div style="margin-left: 40px; text-align: left;">なかなか良い情報が見つからなかったが、ここ↓の情報を元にすることにした。</div><div style="margin-left: 40px; text-align: left;"><a href="https://gpsd.gitlab.io/gpsd/gpsd_json.html">https://gpsd.gitlab.io/gpsd/gpsd_json.html</a></div><div style="margin-left: 40px; text-align: left;"><br /></div><div style="margin-left: 40px; text-align: left;">上記に加えて、</div><div style="margin-left: 40px; text-align: left;"><ul style="text-align: left;"><li>温度</li><li>湿度</li><li>気圧</li></ul></div><div style="margin-left: 40px; text-align: left;">などの情報を表すJSONのスキーマを自分のために記録しておく。</div><div style="text-align: left;"><br /></div><div style="text-align: left;">【コード】</div><div style="text-align: left;"></div><blockquote><div style="text-align: left;">[code]</div><div style="text-align: left;">//<br />// https://gpsd.gitlab.io/gpsd/gpsd_json.html<br />//<br /><br />const mongoose = require('mongoose');<br /><br />// gpsd TPV format<br />const GpsSchema = mongoose.Schema({<br /> class: String,<br /> tag: String,<br /> device: String,<br /> mode: Number,<br /> time: String,<br /> ept: Number,<br /> lat: Number,<br /> lon: Number,<br /> alt: Number,<br /> epx: Number,<br /> epy: Number,<br /> epv: Number,<br /> track: Number,<br /> speed: Number,<br /> climb: Number,</div><div style="text-align: left;"> epd: Number,<br /> eps: Number,<br /> epc: Number,<br /> ble: Number,<br /> cocoa: Number,<br /> temp: Number,<br /> humid: Number,<br /> press: Number<br /><br />});<br /><br />module.exports = mongoose.model('Gps',GpsSchema);</div><div style="text-align: left;">[/code]</div><div style="text-align: left;"><br /></div><div style="text-align: left;"><br /></div><div style="text-align: left;"></div></blockquote><div style="text-align: left;"><br /></div>luky.orghttp://www.blogger.com/profile/17273806834102337860noreply@blogger.com0tag:blogger.com,1999:blog-1471072446855788166.post-36943679028052812692020-07-26T12:54:00.003+09:002020-07-26T13:14:58.238+09:00M5Stack COCOA Counter + ENV.2 Sensor + GPS Unit その3<div><a href="https://blog.luky.org/2020/07/m5stack-cocoa-counter-env2-sensor-gps_19.html">M5Stack COCOA Counter + ENV.2 Sensor + GPS Unit その2</a>から、ちょいと変更</div><div><br /></div><div>【変更内容】<br /></div><div><ul style="text-align: left;"><li>出力ファイルをJSON形式に変更</li><li>M5Stack-SD-Updaterに適当に対応(^^;</li><li>上記に伴いボタン割り当て変更</li><li>setup()内の各初期化処理をサブルーチン化<br /></li></ul></div><div style="text-align: left;">【既知のバグ】</div><div style="text-align: left;"><ul style="text-align: left;"><li>GPSからの取得データ値がおかしなことがある。<br />具体的には、timeが更新されないことがある。<br />シリアル経由での読み込みルーチンの見直しが必要のようだが、<br />後回しにしている(^^;</li></ul></div><div style="text-align: left;">【今後の予定】</div><div style="text-align: left;"><ul style="text-align: left;"><li>現在決めうちにしているログファイル名を<br />log-YYYYMMDD.txtに変更する。<br /><br /></li><li>JSON形式のログをhttp POSTで<br />node.js+express+mongoDBで構築している<br />ログ収集サーバにuploadするスケッチを作成する。<br /><br />#そのために、M5Stack-SD-Updaterに対応したようなもの。<br />#尚、一つのスケッチでやろうとしたが、サイズオーバで入らなかった(^^;<br /><br /></li><li>コテコテコーディングから<a href="https://github.com/arduino-libraries/Arduino_JSON">Arduino_JSON</a>を利用するように書き直し。<br /><br /></li><li>ログ収集サーバ側では、JSON→GPX変換して、<br />googleMap等に表示できるようにする。<br /><br /></li><li>同じくサーバサイドで、グラフ表示などの機能を作る。<br />生成したグラフは、Blogger上の<a href="https://blog.luky.org/">このブログ</a>に自動投稿させる。<br /><br /></li></ul></div><div style="text-align: left;">【ソース】</div><div style="text-align: left;"><br /></div><div style="margin-left: 40px; text-align: left;">[code]<br />// M5Stack ----------------------------------------------------------------<br />#include <M5Stack.h><br />#include "M5StackUpdater.h"<br />// BLE & Cocoa ------------------------------------------------------------<br />#include <BLEDevice.h><br />// ENV2 -------------------------------------------------------------------<br />/* add library Adafruit_BMP280 & Adafruit_SHT31 from library manage */<br />#include <Adafruit_Sensor.h><br />#include <Adafruit_SHT31.h><br />#include <Wire.h> //The SHT31 uses I2C comunication.<br />#include <Adafruit_BMP280.h><br />// GPS --------------------------------------------------------------------<br />#include <TinyGPS++.h><br />// SD ---------------------------------------------------------------------<br />#include <SPI.h><br />#include <SD.h><br />// BLE & Cocoa ------------------------------------------------------------<br />int scanTime = 5;<br />BLEScan* pBLEScan;<br />const int chipSelect = 4;<br />bool onBeep = true;<br /><br />//接触確認アプリのUUID<br />const char* cocoaUUID = "0000fd6f-0000-1000-8000-00805f9b34fb";<br />int cocoaCnt = 0; //time out in seconds<br /><br />class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {<br /> void onResult(BLEAdvertisedDevice advertisedDevice) {<br /> if (advertisedDevice.haveServiceUUID()) {<br /> if (strncmp(advertisedDevice.getServiceUUID().toString().c_str(), cocoaUUID, 36) == 0) {<br /> cocoaCnt++;<br /> if (onBeep) {<br /> M5.Speaker.beep();<br /> delay(10);<br /> M5.Speaker.mute();<br /> }<br /> M5.Lcd.setCursor(0, 110);<br /> M5.Lcd.setTextSize(2);<br /> M5.Lcd.setTextColor(GREEN, BLACK);<br /> M5.Lcd.printf("%d ", cocoaCnt);<br /> M5.Lcd.setTextSize(1);<br /> }<br /> }<br /> M5.Lcd.println(advertisedDevice.toString().c_str());<br /> M5.Lcd.setTextSize(1);<br /> M5.Lcd.setTextColor(WHITE, BLACK);<br /> }<br />};<br /><br />void setupBLE() {<br /> BLEDevice::init("");<br /> pBLEScan = BLEDevice::getScan(); //create new scan<br /> pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());<br /> pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster<br /> pBLEScan->setInterval(100);<br /> pBLEScan->setWindow(99); // less or equal setInterval value<br />}<br />// ENV2 -------------------------------------------------------------------<br />Adafruit_SHT31 sht31 = Adafruit_SHT31();<br />Adafruit_BMP280 bme;<br /><br />bool hasSHT31 = false;<br />bool hasBMP280 = false;<br />float tmp = 100;<br />float hum = 0;<br />float pressure = 0;<br /><br />void setupENV2() {<br /> //ENV2 sensor on I2C setup<br /> Wire.begin();<br /> Serial.println(F("ENV.2 Chk"));<br /><br /> if (sht31.begin(0x44)) { // Set to 0x45 for alternate i2c addr<br /> hasSHT31 = true;<br /> Serial.println("SHT31 Ok");<br /><br /> Serial.print("Heater: ");<br /> if (sht31.isHeaterEnabled())<br /> Serial.println("Ena");<br /> else<br /> Serial.println("Dis");<br /> }<br /><br /> if (bme.begin(0x76)) {<br /> hasBMP280 = true;<br /> Serial.println("BMP280 Ok");<br /> }<br />}<br />// GPS --------------------------------------------------------------------<br />//bool hasRTC = false;<br />bool hasGPS = false;<br />TinyGPSPlus gps; // The TinyGPS++ object<br />HardwareSerial hsGps(2);// The serial connection to the GPS device<br />static const uint32_t GPSBaud = 9600;<br /><br />void setupGPS() {<br /> hsGps.begin(GPSBaud);<br /> delay(500);<br /><br /> if (hsGps.available() > 0) {<br /> hasGPS = true;<br /> Serial.println("GPS Ok");<br /> }<br />}<br />// SD ---------------------------------------------------------------------<br />// log file name<br />const char* logfile = "/logJSON.txt";<br />// Inside -----------------------------------------------------------------<br />unsigned char bright = 0x03;<br />unsigned char brightPitch = 0x10;<br />//文字列<br />const char* logJSON = "{ \"class\": \"TPV\" ,\<br />\"mode\": 3 ,\<br />\"time\": \"%d-%02d-%02dT%02d:%02d:%02dZ\" ,\<br />\"lat\": %lf ,\<br />\"lon\": %lf ,\<br />\"alt\": %.1f ,\<br />\"track\": %lf ,\<br />\"speed\": %.1f ,\<br />\"ble\": %d ,\<br />\"cocoa\": %d ,\<br />\"temp\": %.1f ,\<br />\"humidity\": %.1f ,\<br />\"pressure\": %.1f }";<br /><br />// ------------------------------------------------------------------------<br />void setup() {<br /><br /> // Initialize the M5Stack<br /> M5.begin();<br /> M5.Power.begin();<br /> M5.Lcd.setBrightness(bright);<br /> M5.Lcd.setTextSize(1);<br /> M5.Lcd.println("Hello!, COCOA Scan");<br /><br /> Serial.begin(115200);<br /><br /> setupBLE();<br /> setupENV2();<br /> setupGPS();<br /><br /> if (digitalRead(BUTTON_A_PIN) == 0) {<br /> Serial.println("Will Load menu binary");<br /> updateFromFS(SD);<br /> ESP.restart();<br /> }<br /><br />}<br /><br />void loop() {<br /> // print all found BLE devices<br /> M5.Lcd.setTextSize(1);<br /><br /> BLEScanResults foundDevices = pBLEScan->start(scanTime, false);<br /><br /> // print counts of BLE devices<br /> int sumdev = foundDevices.getCount();<br /><br /> // print env2 data<br /> if (hasSHT31) {<br /> tmp = sht31.readTemperature();<br /> hum = sht31.readHumidity();<br /> }<br /> if (hasBMP280) {<br /> pressure = bme.readPressure() / 100;<br /> // hPa = Pa / 100;<br /> }<br /><br /> while (hsGps.available() > 0) {<br /> gps.encode(hsGps.read());<br /> }<br /><br /> Serial.printf(logJSON, gps.date.year(), gps.date.month(), gps.date.day(),<br /> gps.time.hour(), gps.time.minute(), gps.time.second(),<br /> gps.location.lat(), gps.location.lng(), gps.altitude.meters(), gps.course.deg(),<br /> gps.speed.mps(), sumdev, cocoaCnt, tmp, hum, pressure);<br /> Serial.println();<br /><br /> // SDカードへの書き込み処理(ファイル追加モード)<br /> // SD.beginはM5.begin内で処理されているので不要<br /> // open the file. note that only one file can be open at a time,<br /> // so you have to close this one before opening another.<br /> File dfile = SD.open(logfile, FILE_APPEND);<br /><br /> // if the file is available, write to it:<br /> if (dfile) {<br /> dfile.printf(logJSON, gps.date.year(), gps.date.month(), gps.date.day(),<br /> gps.time.hour(), gps.time.minute(), gps.time.second(),<br /> gps.location.lat(), gps.location.lng(), gps.altitude.meters(), gps.course.deg(),<br /> gps.speed.mps(), sumdev, cocoaCnt, tmp, hum, pressure);<br /> dfile.println();<br /> }<br /><br /> // clear screen and set cursor to the top<br /> M5.Lcd.fillScreen(BLACK);<br /> M5.Lcd.setCursor(0, 0);<br /> M5.Lcd.setTextSize(2);<br /> M5.Lcd.setTextColor(WHITE, BLACK);<br /> M5.Lcd.printf(logJSON, gps.date.year(), gps.date.month(), gps.date.day(),<br /> gps.time.hour(), gps.time.minute(), gps.time.second(),<br /> gps.location.lat(), gps.location.lng(), gps.altitude.meters(), gps.course.deg(),<br /> gps.speed.mps(), sumdev, cocoaCnt, tmp, hum, pressure);<br /> M5.Lcd.println();<br /><br /> //Button controll<br /> M5.Lcd.setTextSize(3);<br /> M5.Lcd.println();<br /> M5.Lcd.setTextColor(BLUE, WHITE);<br /> M5.Lcd.println("A: SDUpdater");<br /> M5.Lcd.println("B: Beep on/off");<br /> M5.Lcd.println("C: Brightness");<br /><br /> int timer = 100;<br /> while (timer--) {<br /> if (M5.BtnA.wasReleased()) { //AボタンでSDUpdater<br /> updateFromFS(SD);<br /> ESP.restart();<br /> } else if (M5.BtnB.wasReleased()) { //Bボタンでbeepをon/off切り替える<br /> onBeep = !onBeep;<br /> } else if (M5.BtnC.wasReleased()) { //Cボタンで輝度を変更<br /> bright += brightPitch;<br /> M5.Lcd.setBrightness(bright);<br /> }<br /> delay(50);<br /> M5.update(); // update button state<br /> }<br /><br /> //init for next loop<br /> dfile.close();<br /> pBLEScan->clearResults(); // delete results fromBLEScan buffer to release memory<br /> cocoaCnt = 0;<br /><br /> M5.Lcd.setTextColor(WHITE, BLACK);<br /> M5.Lcd.setCursor(0, 110);<br /> M5.Lcd.setTextSize(1);<br />}<br /><br />// Arranged and written by 柴田(ひ)<br />/* BLE<br /> Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleScan.cpp<br /> Ported to Arduino ESP32 by Evandro Copercini<br />*/<br />/* Cocoa<br /> Thanks to https://gist.github.com/ksasao/0da6437d3eac9b2dbd675b6fee5d1117<br /> by https://gist.github.com/ksasao<br />*/<br />/* GPS<br /> This sample sketch demonstrates the normal use of a TinyGPS++ (TinyGPSPlus) object.<br /> by Mikal Hart<br />*/<br />/* SD<br /> SD card wrie routine<br /> https://raspberrypi.mongonta.com/howto-write-csv-to-sdcard-on-m5stack/<br />*/<br />[/code]<br /></div>luky.orghttp://www.blogger.com/profile/17273806834102337860noreply@blogger.com0tag:blogger.com,1999:blog-1471072446855788166.post-70095200253727606642020-07-25T01:12:00.001+09:002020-07-25T01:31:54.445+09:00node.jp + express + mongoDB関連のインストール<div style="text-align: left;"><span style="color: #2b00fe;"><b><font size="5">node.jp と express のインストール</font><br /><br /></b></span></div><div style="margin-left: 40px; text-align: left;">下記ページがかなり参考になったけど、肝心の「最終結果のjsソース」が書かれてないので、やっぱりハマった。</div><div><br /></div><div style="margin-left: 40px; text-align: left;"><a href="https://reffect.co.jp/node-js/express-jsnode-js-mongodb" target="_blank">https://reffect.co.jp/node-js/express-jsnode-js-mongodb</a></div><div style="margin-left: 40px; text-align: left;"><br /></div><div style="text-align: left;"><font size="5"><span style="color: #2b00fe;"><b>mongoDBをubuntuにインストール</b></span></font></div><div style="text-align: left;"><br /></div><div style="margin-left: 40px; text-align: left;">ここが本家なのか?ということも知らないが(^^;</div><div style="margin-left: 40px; text-align: left;"><a href="https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/" target="_blank">https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/</a><br /></div><div><br /></div><div><font size="5"><span style="color: #2b00fe;"><b>n コマンドの出力結果</b></span></font></div><div style="text-align: left;"><div style="margin-left: 40px;"> ο node/12.18.3<br /><br />Use up/down arrow keys to select a version, return key to install, d to delete, q to quit<br /></div></div><div style="text-align: left;"><br /></div><div style="text-align: left;"><span style="color: #2b00fe;"><font size="5"><b>npm list -g コマンドの出力結果</b></font></span></div><div style="margin-left: 40px; text-align: left;">ちょっと多すぎるので省略</div><div style="margin-left: 40px; text-align: left;">とりあえず、expressを入れとけば、body-parserは入れなくて良いようだ。</div><div style="margin-left: 40px; text-align: left;"><br /></div><div style="text-align: left;"><br /></div>luky.orghttp://www.blogger.com/profile/17273806834102337860noreply@blogger.com0tag:blogger.com,1999:blog-1471072446855788166.post-72474458768017919052020-07-25T00:57:00.002+09:002020-07-25T01:06:37.458+09:00node.jp + express + mongoDB 作業メモ<div><ol style="text-align: left;"><li><span style="color: #2b00fe;"><b>インストールしたPATH</b></span><br />/var/www/node/express_mongodb<br /><br /></li><li><span style="color: #2b00fe;"><b>起動コマンド</b></span><br />npx nodemon app.js<br /><br /></li><li><span style="color: #2b00fe;"><b>app.js</b></span></li></ol></div><blockquote><div style="text-align: left;"><blockquote><div style="text-align: left;">const express = require('express');<br /></div></blockquote></div></blockquote><blockquote><div style="text-align: left;"><blockquote><div><div style="text-align: left;">const app = express();<br /></div><div>const mongoose = require('mongoose');<br />const userRouter = require('./routes/user');<br /><br />app.use('/user', userRouter);<br />//app.use(express.json());<br /><br />const port = 3000;<br /><br />const options = {<br /> useUnifiedTopology : true,<br /> useNewUrlParser : true<br />}<br /><br />mongoose.connect('mongodb://127.0.0.1/test_db',options);<br /><br />const db = mongoose.connection;<br /><br />db.on('error', console.error.bind(console, 'connection error:'));<br />db.once('open', () => console.log('Database connection successful')); <br /></div></div></blockquote></div></blockquote><blockquote><div style="text-align: left;"><blockquote><div><div style="text-align: left;">app.get('/', (req, res) => <br /> res.sendFile('/var/www/node/express_mongodb/test.html'))<br /><br />app.listen(port, <br /> () => console.log(`Example app listening on port ${port}!`)); </div></div></blockquote></div></blockquote><div> </div><div><ol style="text-align: left;"><li><span style="color: #2b00fe;"><b>models/User.js</b></span><br /><blockquote>const mongoose = require('mongoose');<br /><br />const UserSchema = mongoose.Schema({<br /> name: String,<br /> age: Number<br />});<br /><br />module.exports = mongoose.model('User',UserSchema);</blockquote> </li><li><span style="color: #2b00fe;"><b>routes/user.js</b></span><br />const express = require('express');<br /><br />const router = express.Router();<br />const User = require('../models/User');<br /><br />router.use(express.json());<br />router.use(express.urlencoded({ extended: false }));<br /><br />router.get('/', async (req, res) => {<br /> const users = await User.find({});<br /> res.json(users);<br />});<br /><br />router.get('/:userID',(req, res)=>{<br /> User.findById(req.params.userID,(err,user)=>{<br /> if (err) console.log('error');<br /> res.send(user);<br /> });<br />});<br /><br />router.post('/', async (req,res)=>{<br /> console.log(req.body);<br /><br /> const user = new User({<br /> name: req.body.name,<br /> age: req.body.age<br /> });<br /><br /> const savedUser = await user.save();<br /> res.json(savedUser);<br /><br />});<br /><br />router.delete('/:userID',async (req,res)=>{<br /> const user = await User.remove({_id: req.params.userID});<br /> res.send(user);<br />});<br /><br />router.patch('/:userID',async (req,res)=>{<br /> console.log(req.body.age);<br /> const user = await User.updateOne({_id: req.params.userID},{$set:{age:re<br />q.body.age}});<br /> res.send(user);<br />});<br /><br />module.exports = router;<br /><br /></li><li><span style="color: #2b00fe;"><b>test.html</b></span><br /><!DOCTYPE html><br /><html lang="ja"><br /><head><br /> <meta charset="UTF-8"><br /> <title>入力フォーム</title><br /></head><br /><body><br /><h1>入力フォーム</h1><br /><form action="/user" method="POST"><br /> name <input type="text" name="name"><br><br /> age <input type="text" name="age"><br><br /> <button type="submit">送信</button><br /></form><br /></body><br /></html><br /><br /></li><li><span style="color: #2b00fe;"><b>確認方法</b></span></li></ol><ul style="text-align: left;"><li>http://server:3000/<br />POSTする入力フォームが表示される</li><li>http://server:3000/user<br />GETで登録一覧がJSON形式で出力される</li></ul></div><div style="text-align: left;">以上、作業途中メモ。<br /></div>luky.orghttp://www.blogger.com/profile/17273806834102337860noreply@blogger.com0tag:blogger.com,1999:blog-1471072446855788166.post-27963785696809604952020-07-19T10:14:00.000+09:002020-07-19T10:14:04.662+09:00M5Stack COCOA Counter + ENV.2 Sensor + GPS Unit その2<div>主に「<a href="https://blog.luky.org/2020/07/m5stack-cocoa-counter-env2-sensor-gps.html">M5Stack COCOA Counter + ENV.2 Sensor + GPS Unit</a>」の補足情報です。</div><div><br /></div><div>【今回のハード構成】</div><div><ul style="text-align: left;"><li><a href="https://www.switch-science.com/catalog/3647/">M5Stack Basic<br /></a></li><li><a href="https://www.switch-science.com/catalog/5694/">M5Stack用GPSユニット</a></li><li><a href="https://www.switch-science.com/catalog/6344/">M5Stack用環境センサユニット ver.2(ENV II)</a></li><li><a href="https://www.switch-science.com/catalog/3653/">M5Stack用電池モジュール</a></li></ul></div><div>【各ユニットの接続】</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh45U8H1X2T4bgFuBRfeIvRWtg5CaCOEz1_Z1w3LiTZELxEJ_ibBU-B8VWdCXRu0DPgYuuHKAm3bA2QmChSomTlfbTwIzL7tF_oqrxz4xJ-BQSeIvxKu-tlppz7SvjiFEbtYJopVQvfIf4/s2048/M5Stack-cabling.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1149" data-original-width="2048" height="351" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh45U8H1X2T4bgFuBRfeIvRWtg5CaCOEz1_Z1w3LiTZELxEJ_ibBU-B8VWdCXRu0DPgYuuHKAm3bA2QmChSomTlfbTwIzL7tF_oqrxz4xJ-BQSeIvxKu-tlppz7SvjiFEbtYJopVQvfIf4/w625-h351/M5Stack-cabling.png" width="625" /></a></div><div><br /></div><div><br /></div><div>【SDカードのログ出力例】</div><div style="margin-left: 40px; text-align: left;">以下のようなログをファイルとして出力される。<br />緯度経度は一部数値をnで置き換えてます。</div><blockquote><div style="margin-left: 40px; text-align: left;">Loc: 35.nnnnnn 139.nnnnnn<br />2020/07/18 13:57:34.00 UTC<br />Sum5 Cocoa1<br />Tmp: 28.9C<br />Hum: 69.3%<br />Prs: 1013hPa<br /></div></blockquote><div><br /></div><div>【バッテリーでの動作時間】</div><div style="margin-left: 40px; text-align: left;">上記の【今回のハード構成】で、一晩窓際に置いてどのぐらいバッテリーが持つか、<br />位置情報の精度はどの程度か、確認してみた。</div><div style="margin-left: 40px; text-align: left;">尚、増設の<a href="https://www.switch-science.com/catalog/3653/">M5Stack用電池モジュール</a>の他に、<a href="https://www.switch-science.com/catalog/3647/">M5Stack Basic</a>の底モジュールにも<br />小さいながらバッテリーが搭載されている。<br />あちこちのサイトに「2つのバッテリーを同時に搭載してはダメ」と書いてあるが、<br />まぁ実験なので、承知の上でやってみた(^^;<br /></div><div style="margin-left: 40px; text-align: left;"><ol style="text-align: left;"><li>バッテリー動作開始時刻<br />上記のログが、バッテリーで動作させた際の最初の記録である。<br />UTCとJSTは9時間の時差があるので、日本時間では2020/07/18の<br />23時ちょっと前というところ。<br /><br /></li><li>最終ログ<br />朝起きて、M5Stackを見て見たら、動作が止まっていた。<br />microSDを取り外して、ログの最終データを見たところが、下記。<br />ざっくり6時間動いている。<br /></li></ol></div><blockquote><div style="margin-left: 40px; text-align: left;">Loc: 35.nnnnnn 139.nnnnnn<br />2020/07/18 19:47:27.00 UTC<br />Sum4 Cocoa1<br />Tmp: 23.9C<br />Hum: 84.2%<br />Prs: 1012hPa </div></blockquote><div>【GPSの位置精度】</div><div style="margin-left: 40px; text-align: left;">最終ログに出力されている緯度経度を<a href="https://fukuno.jig.jp/app/printmap/latlngmap.html#15/35.000000/139.000000/&base=std&ls=std&disp=1&vs=c1j0l0u0f1" target="_blank">緯度経度地図</a>で確認してみた。</div><div style="margin-left: 40px; text-align: left;">窓際に置いておいただけだけど、数m程度の誤差しかなかった。<br />結構優秀(^^)<br /></div><div><div> <div style="text-align: left;">【買っとけばよかったハード】</div><div style="text-align: left;"><ul style="text-align: left;"><li><a href="https://www.switch-science.com/catalog/5206/">M5Stack PLUSエンコーダモジュール<br /></a>GPSユニットが、ジャンパ線なしで接続可能になる。<br /><a href="https://www.switch-science.com/catalog/3653/">M5Stack用電池モジュール</a>よりも容量が少ないものの、バッテリーもある。<br />価格もそれほど変わらない。<br /></li><li><a href="https://www.switch-science.com/catalog/3861/">M5Stack用GPSモジュール V2<br /></a>M5Stack本体と一体になるため、ちょっとかっこいい。<br />でも、少し高い(^^;<br /></li></ul></div></div></div>luky.orghttp://www.blogger.com/profile/17273806834102337860noreply@blogger.com0tag:blogger.com,1999:blog-1471072446855788166.post-78316094046841921282020-07-19T00:49:00.007+09:002020-07-19T10:20:00.281+09:00M5Stack COCOA Counter + ENV.2 Sensor + GPS Unit<div>【主な機能】</div><div><ul style="text-align: left;"><li>M5Stackの内蔵BLEを使って、厚労省の接触確認アプリCocoaを検出するもの。</li><li>BLE全体で検出した台数と内数としてのCoCoa台数を表示する。</li><li>検出した情報は、microSDにログファイルとして記録する。</li><li>M5Stack Basicに温度湿度気圧センサであるENV.2 UnitをGROVE経由で接続し、<br />それらの情報もついでに表示・記録する。</li><li>GPS Unitを接続し、検出した時の位置情報と日時を記録する。</li></ul></div><div>【付加機能】</div><div><ul style="text-align: left;"><li>ボタンA(左)を押すと、Cocoa検出時のBeep音をon/offさせる。</li><li>ボタンB(中)を押すと、LCDのサイクリックに変わる。</li><li>ボタンC(右)を押すと、画面とログファイルに「memo」と出力する。<br />何か気付いたことがあった時のイベント記録用。<br /></li></ul></div><div>【余談】<br /></div><div> 追加で購入したGPS UnitのGROVEコネクタはUARTだった。</div><div> M5StackのGROVEコネクタはENV.2 Sensorで埋まっているし、</div><div> そもそもI2Cしか使えないようだし。</div><div><br /></div><div> ということで、UART2ポートに無理やり接続。</div><div> 最初は動かなくて悩んだが、M5Stack側TX2にGPS側RX、</div><div> M5Stack側RX2にGPS側TXを繋ぐと動いた(^^;</div><div><br /></div><div><span> </span>#UART(シリアル通信)なんで、考えてみれば当たり前なんだが、</div><div><span> </span>#こんなこともパッと思い出せないほどオッサン化が...。</div><div><br /></div><div> 電池が届いたら、RTCも接続するかな。</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3_mi_HxpaKx4K9qusKvxbqgZVTGvcfiTmTSeGmslLRvA_hyphenhyphenM4vCTV2MpA0KvWHftJqt971nSE4s5YqyorYYjk7GG8F_IHsuDNg0pdkOPIiIGnfTqGokpoiGdB4crHa2U2koQjIdRPCwE/s1869/M5Stack-GPS-ENV.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1165" data-original-width="1869" height="389" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3_mi_HxpaKx4K9qusKvxbqgZVTGvcfiTmTSeGmslLRvA_hyphenhyphenM4vCTV2MpA0KvWHftJqt971nSE4s5YqyorYYjk7GG8F_IHsuDNg0pdkOPIiIGnfTqGokpoiGdB4crHa2U2koQjIdRPCwE/w625-h389/M5Stack-GPS-ENV.jpg" width="625" /></a></div><div><br /></div><div>[code]<br />/*<br /> Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleScan.cpp<br /> Ported to Arduino ESP32 by Evandro Copercini<br />*/<br />/*<br /> Thanks to https://gist.github.com/ksasao/0da6437d3eac9b2dbd675b6fee5d1117<br /> by https://gist.github.com/ksasao<br />*/<br />/*<br /> This sample sketch demonstrates the normal use of a TinyGPS++ (TinyGPSPlus) object.<br /> by Mikal Hart<br />*/<br />/*<br /> SD card wrie routine<br /> https://raspberrypi.mongonta.com/howto-write-csv-to-sdcard-on-m5stack/<br />*/<br /><br />//////////////////////////////////////////////////////////////////////////////////<br />#include <M5Stack.h><br />#include <TinyGPS++.h><br />#include <BLEDevice.h><br /><br />//////////////////////////////////////////////////////////////////////////////////<br />/*<br /> note: need add library Adafruit_BMP280 & Adafruit_SHT31 from library manage<br />*/<br />#include <Adafruit_SHT31.h><br />#include <Wire.h> //The SHT31 uses I2C comunication.<br />#include <Adafruit_Sensor.h><br />#include <Adafruit_BMP280.h><br /><br />//////////////////////////////////////////////////////////////////////////////////<br />#include <SPI.h><br />#include <SD.h><br /><br />//////////////////////////////////////////////////////////////////////////////////<br />Adafruit_SHT31 sht31 = Adafruit_SHT31();<br />Adafruit_BMP280 bme;<br /><br />//time out in seconds<br />int scanTime = 5;<br />BLEScan* pBLEScan;<br /><br />const int chipSelect = 4;<br /><br />TinyGPSPlus gps; // The TinyGPS++ object<br />HardwareSerial hsGps(2);// The serial connection to the GPS device<br /><br />//接触確認アプリのUUID<br />const char* uuid = "0000fd6f-0000-1000-8000-00805f9b34fb";<br />int cocoaCnt = 0;<br /><br />//log file name<br />const char* logfile = "/log.txt";<br /><br />//文字列<br />const char* sumdevStr = "Sum";<br />const char* cocoaStr = " Cocoa";<br />const char* envStr = "Tmp: %3.1fC\r\nHum: %3.1f%%\r\nPrs: %3.0fhPa\r\n";<br />const char* locStr = "Loc: %lf %lf\r\n";<br />const char* dateStr = "%d/%02d/%02d ";<br />const char* timeStr = "%02d:%02d:%02d.%02d UTC\r\n";<br /><br />//RTCまたはGPS<br />//bool hasRTC = false;<br />bool hasGPS = false;<br /><br />//Sensor flag<br />bool hasSHT31 = false;<br />bool hasBMP280 = false;<br />float tmp = 100;<br />float hum = 0;<br />float pressure = 0;<br /><br />//Other flags,Params<br />bool onBeep = true;<br />unsigned char bright = 0x03;<br />unsigned char brightPitch = 0x10;<br />static const uint32_t GPSBaud = 9600;<br />//////////////////////////////////////////////////////////////////////////////////<br />class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {<br /> void onResult(BLEAdvertisedDevice advertisedDevice) {<br /> if (advertisedDevice.haveServiceUUID()) {<br /> if (strncmp(advertisedDevice.getServiceUUID().toString().c_str(), uuid, 36) == 0) {<br /> cocoaCnt++;<br /> if (onBeep) {<br /> M5.Speaker.beep();<br /> delay(10);<br /> M5.Speaker.mute();<br /> }<br /> M5.Lcd.setCursor(0, 110);<br /> M5.Lcd.setTextSize(2);<br /> M5.Lcd.setTextColor(GREEN, BLACK);<br /> M5.Lcd.printf("%d ", cocoaCnt);<br /> M5.Lcd.setTextSize(1);<br /> }<br /> }<br /> M5.Lcd.println(advertisedDevice.toString().c_str());<br /> M5.Lcd.setTextSize(1);<br /> M5.Lcd.setTextColor(WHITE, BLACK);<br /> }<br />};<br /><br />//////////////////////////////////////////////////////////////////////////////////<br />void setup() {<br /><br /> // Initialize the M5Stack<br /> M5.begin();<br /> M5.Power.begin();<br /> M5.Lcd.setBrightness(bright);<br /> M5.Lcd.setTextSize(1);<br /> M5.Lcd.println("Hello!, COCOA Scan");<br /><br /> Serial.begin(115200);<br /><br /> //BLE setup<br /> BLEDevice::init("");<br /> pBLEScan = BLEDevice::getScan(); //create new scan<br /> pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());<br /> pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster<br /> pBLEScan->setInterval(100);<br /> pBLEScan->setWindow(99); // less or equal setInterval value<br /><br /> //ENV sensor on I2C setup<br /> Wire.begin();<br /> Serial.println(F("ENV.2 Chk"));<br /><br /> if (sht31.begin(0x44)) { // Set to 0x45 for alternate i2c addr<br /> hasSHT31 = true;<br /> Serial.println("SHT31 Ok");<br /><br /> Serial.print("Heater: ");<br /> if (sht31.isHeaterEnabled())<br /> Serial.println("Enable");<br /> else<br /> Serial.println("Disable");<br /> }<br /><br /> if (bme.begin(0x76)) {<br /> hasBMP280 = true;<br /> Serial.println("BMP280 Ok");<br /> }<br /><br /> //GPS setup<br /> hsGps.begin(GPSBaud);<br /> delay(500);<br /><br /> if (hsGps.available() > 0) {<br /> hasGPS = true;<br /> Serial.println("GPS Ok");<br /> }<br />}<br /><br />void loop() {<br /> // print all found BLE devices<br /> M5.Lcd.setTextSize(1);<br /><br /> if (hasGPS) {<br /> while (hsGps.available() > 0) {<br /> gps.encode(hsGps.read());<br /> }<br /> Serial.printf(locStr, gps.location.lat(), gps.location.lng());<br /> Serial.printf(dateStr, gps.date.year(), gps.date.month(), gps.date.day() );<br /> Serial.printf(timeStr, gps.time.hour(), gps.time.minute(), gps.time.second(), gps.time.centisecond());<br /> }<br /><br /> BLEScanResults foundDevices = pBLEScan->start(scanTime, false);<br /><br /> // clear screen and set cursor to the top<br /> M5.Lcd.fillScreen(BLACK);<br /> M5.Lcd.setCursor(0, 0);<br /> M5.Lcd.setTextSize(2);<br /> M5.Lcd.setTextColor(WHITE, BLACK);<br /> M5.Lcd.printf(dateStr, gps.date.year(), gps.date.month(), gps.date.day() );<br /> M5.Lcd.printf(timeStr, gps.time.hour(), gps.time.minute(), gps.time.second(), gps.time.centisecond());<br /><br /> // print counts of BLE devices<br /> int sumdev = foundDevices.getCount();<br /><br /> M5.Lcd.setTextSize(3);<br /> M5.Lcd.print(sumdevStr);<br /> M5.Lcd.setTextColor(RED, BLACK);<br /> M5.Lcd.print(sumdev);<br /><br /> // print count of cocoa APPs<br /> M5.Lcd.setTextColor(WHITE, BLACK);<br /> M5.Lcd.print(cocoaStr);<br /> M5.Lcd.setTextColor(GREEN, BLACK);<br /> M5.Lcd.println(cocoaCnt);<br /><br /> // print env2 data<br /> if (hasSHT31) {<br /> tmp = sht31.readTemperature();<br /> hum = sht31.readHumidity();<br /> }<br /> if (hasBMP280) {<br /> pressure = bme.readPressure() / 100;<br /> // hPa = Pa / 100;<br /> }<br /><br /> M5.Lcd.setTextColor(WHITE, BLACK);<br /> M5.Lcd.printf(envStr, tmp, hum, pressure);<br /><br /> // print to the serial port too<br /> Serial.print(sumdevStr);<br /> Serial.print(sumdev);<br /> Serial.print(cocoaStr);<br /> Serial.println(cocoaCnt);<br /> Serial.printf(envStr, tmp, hum, pressure);<br /> Serial.println();<br /><br /> // SDカードへの書き込み処理(ファイル追加モード)<br /> // SD.beginはM5.begin内で処理されているので不要<br /> // open the file. note that only one file can be open at a time,<br /> // so you have to close this one before opening another.<br /> File dfile = SD.open(logfile, FILE_APPEND);<br /><br /> // if the file is available, write to it:<br /> if (dfile) {<br /> dfile.printf(locStr, gps.location.lat(), gps.location.lng());<br /> dfile.printf(dateStr, gps.date.year(), gps.date.month(), gps.date.day() );<br /> dfile.printf(timeStr, gps.time.hour(), gps.time.minute(), gps.time.second(), gps.time.centisecond());<br /> dfile.print(sumdevStr);<br /> dfile.print(sumdev);<br /> dfile.print(cocoaStr);<br /> dfile.println(cocoaCnt);<br /> dfile.printf(envStr, tmp, hum, pressure);<br /> dfile.println();<br /><br /> }<br /><br /> //Button controll<br /> M5.Lcd.setTextSize(3);<br /> M5.Lcd.println();<br /> M5.Lcd.setTextColor(BLUE, WHITE);<br /> M5.Lcd.println("A: Beep on/off");<br /> M5.Lcd.println("B: Brightness");<br /> M5.Lcd.println("C: Memo");<br /><br /> int timer = 100;<br /> while (timer--) {<br /> if (M5.BtnA.wasReleased()) { //Aボタンでbeepをon/off切り替える<br /> onBeep = !onBeep;<br /> } else if (M5.BtnB.wasReleased()) { //Bボタンで輝度を変更<br /> bright += brightPitch;<br /> M5.Lcd.setBrightness(bright);<br /> } else if (M5.BtnC.wasReleased()) { //Cボタンでevent記録<br /> dfile.println("Memo");<br /> M5.Lcd.setTextColor(YELLOW, BLACK);<br /> M5.Lcd.println("Wrote");<br /> }<br /> delay(70);<br /> M5.update(); // update button state<br /> }<br /><br /> //init for next loop<br /> dfile.close();<br /> pBLEScan->clearResults(); // delete results fromBLEScan buffer to release memory<br /> cocoaCnt = 0;<br /><br /> M5.Lcd.setTextColor(WHITE, BLACK);<br /> M5.Lcd.setCursor(0, 110);<br /> M5.Lcd.setTextSize(1);<br /><br />}<br />// Arranged and written by 柴田(ひ)<br />[/code]<br /></div>luky.orghttp://www.blogger.com/profile/17273806834102337860noreply@blogger.com0tag:blogger.com,1999:blog-1471072446855788166.post-65195252079628502992020-07-16T17:43:00.000+09:002020-07-16T17:43:00.172+09:00M5Stack COCOA Counter & ENV.2 Sensor<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1wL0BxdtMDkeoabiUJo9j-4IUiJUUHGslLPNaH4P4djWGDiUy2ZzTVlw0ixdFm3Yq7PAEpdR5LlQInD6bWV84BH0shSWO6lPTrm7rZx39gjAGtuPb6l-T1FEr-ZO1c6TfNtcy-6jdI0I/s1293/M5Stack%252BCOCOA%252BENV2.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1188" data-original-width="1293" height="368" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1wL0BxdtMDkeoabiUJo9j-4IUiJUUHGslLPNaH4P4djWGDiUy2ZzTVlw0ixdFm3Yq7PAEpdR5LlQInD6bWV84BH0shSWO6lPTrm7rZx39gjAGtuPb6l-T1FEr-ZO1c6TfNtcy-6jdI0I/w400-h368/M5Stack%252BCOCOA%252BENV2.jpg" width="400" /></a></div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dzx7L7Hm1llPbLEdQ5C6HO1UjnN07PyzhLFho3ti4FEFCsJgMOzbZrccqTTtGd2i1FFZ6L8cSebzyjankO5Iw' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div><div><br /></div><div><br /></div><div>[code]</div>/*<br /> Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleScan.cpp<br /> Ported to Arduino ESP32 by Evandro Copercini<br />*/<br />/*<br /> Thanks to https://gist.github.com/ksasao/0da6437d3eac9b2dbd675b6fee5d1117<br /> by https://gist.github.com/ksasao<br />*/<br />/*<br /> SD card wrie routine<br /> https://raspberrypi.mongonta.com/howto-write-csv-to-sdcard-on-m5stack/<br />*/<br /><br />//////////////////////////////////////////////////////////////////////////////////<br />#include <M5Stack.h><br /><br />#include <BLEDevice.h><br />//#include <BLEUtils.h><br />//#include <BLEScan.h><br />//#include <BLEAdvertisedDevice.h><br /><br />//////////////////////////////////////////////////////////////////////////////////<br />/*<br /> note: need add library Adafruit_BMP280 & Adafruit_SHT31 from library manage<br />*/<br />#include <Adafruit_SHT31.h><br />#include <Wire.h> //The SHT31 uses I2C comunication.<br />#include <Adafruit_Sensor.h><br />#include <Adafruit_BMP280.h><br /><br />//////////////////////////////////////////////////////////////////////////////////<br />#include <SPI.h><br />#include <SD.h><br /><br />//////////////////////////////////////////////////////////////////////////////////<br />Adafruit_SHT31 sht31 = Adafruit_SHT31();<br />Adafruit_BMP280 bme;<br /><br />//time out in seconds<br />int scanTime = 5;<br />BLEScan* pBLEScan;<br /><br />const int chipSelect = 4;<br /><br />//接触確認アプリのUUID<br />const char* uuid = "0000fd6f-0000-1000-8000-00805f9b34fb";<br />int cocoaCnt = 0;<br /><br />//log file name<br />const char* logfile = "/datalog.txt";<br /><br />//文字列<br />const char* sumdevStr = "Sum";<br />const char* cocoaStr = " Cocoa";<br />const char* envStr = "Temp: %3.1fC\r\nHumid: %3.1f%%\r\nPress: %3.0fhPa\r\n";<br />//RTC買うまで固定<br />const char* dateStr = "2020.07.15 10:10:00 ";<br /><br />//Sensor flag<br />bool hasSHT31 = false;<br />bool hasBMP280 = false;<br />float tmp = 100;<br />float hum = 0;<br />float pressure = 0;<br /><br />//Other flags,Params<br />bool onBeep = true;<br />int bright = 20;<br />int brightPitch = 10;<br />//////////////////////////////////////////////////////////////////////////////////<br />class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {<br /> void onResult(BLEAdvertisedDevice advertisedDevice) {<br /> if (advertisedDevice.haveServiceUUID()) {<br /> if (strncmp(advertisedDevice.getServiceUUID().toString().c_str(), uuid, 36) == 0) {<br /> cocoaCnt++;<br /> if (onBeep) {<br /> M5.Speaker.beep();<br /> delay(10);<br /> M5.Speaker.mute();<br /> }<br /> M5.Lcd.setCursor(0, 110);<br /> M5.Lcd.setTextSize(2);<br /> M5.Lcd.setTextColor(GREEN, BLACK);<br /> M5.Lcd.printf("%d ", cocoaCnt);<br /> M5.Lcd.setTextSize(1);<br /> }<br /> }<br /> M5.Lcd.println(advertisedDevice.toString().c_str());<br /> M5.Lcd.setTextSize(1);<br /> M5.Lcd.setTextColor(WHITE, BLACK);<br /> }<br />};<br /><br />//////////////////////////////////////////////////////////////////////////////////<br /><br />void setup() {<br /><br /> // Initialize the M5Stack<br /> M5.begin();<br /> M5.Power.begin();<br /> M5.Lcd.setBrightness(bright);<br /> M5.Lcd.setTextSize(1);<br /> M5.Lcd.println("Hello!, cacoa BLE Scan");<br /><br /> BLEDevice::init("");<br /> pBLEScan = BLEDevice::getScan(); //create new scan<br /> pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());<br /> pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster<br /> pBLEScan->setInterval(100);<br /> pBLEScan->setWindow(99); // less or equal setInterval value<br /><br /> Wire.begin();<br /> Serial.println(F("ENV2 Unit(SHT31 and BMP280) test..."));<br /><br /> if (sht31.begin(0x44)) { // Set to 0x45 for alternate i2c addr<br /> hasSHT31 = true;<br /> Serial.println("Found SHT31");<br /><br /> Serial.print("Heater Enabled State: ");<br /> if (sht31.isHeaterEnabled())<br /> Serial.println("ENABLED");<br /> else<br /> Serial.println("DISABLED");<br /> }<br /><br /> if (bme.begin(0x76)) {<br /> hasBMP280 = true;<br /> Serial.println("Found a valid BMP280 sensor");<br /> }<br /><br />}<br /><br />void loop() {<br /> // print all found BLE devices<br /> M5.Lcd.setTextSize(1);<br /> BLEScanResults foundDevices = pBLEScan->start(scanTime, false);<br /><br /> // clear screen and set cursor to the top<br /> M5.Lcd.fillScreen(BLACK);<br /> M5.Lcd.setCursor(0, 0);<br /> M5.Lcd.setTextSize(2);<br /> M5.Lcd.setTextColor(WHITE, BLACK);<br /> M5.Lcd.println(dateStr);<br /><br /> // print counts of BLE devices<br /> int sumdev = foundDevices.getCount();<br /><br /> M5.Lcd.setTextSize(3);<br /> M5.Lcd.print(sumdevStr);<br /> M5.Lcd.setTextColor(RED, BLACK);<br /> M5.Lcd.print(sumdev);<br /><br /> // print count of cocoa APPs<br /> M5.Lcd.setTextColor(WHITE, BLACK);<br /> M5.Lcd.print(cocoaStr);<br /> M5.Lcd.setTextColor(GREEN, BLACK);<br /> M5.Lcd.println(cocoaCnt);<br /><br /> // print env2 data<br /> if (hasSHT31) {<br /> tmp = sht31.readTemperature();<br /> hum = sht31.readHumidity();<br /> }<br /> if (hasBMP280) {<br /> pressure = bme.readPressure() / 100;<br /> // hPa = Pa / 100;<br /> }<br /><br /> M5.Lcd.setTextColor(WHITE, BLACK);<br /> M5.Lcd.printf(envStr, tmp, hum, pressure);<br /><br /> // print to the serial port too<br /> Serial.println(dateStr);<br /> Serial.print(sumdevStr);<br /> Serial.println(sumdev);<br /> Serial.print(cocoaStr);<br /> Serial.println(cocoaCnt);<br /> Serial.printf(envStr, tmp, hum, pressure);<br /><br /> // SDカードへの書き込み処理(ファイル追加モード)<br /> // SD.beginはM5.begin内で処理されているので不要<br /> // open the file. note that only one file can be open at a time,<br /> // so you have to close this one before opening another.<br /> File dfile = SD.open(logfile, FILE_APPEND);<br /><br /> // if the file is available, write to it:<br /> if (dfile) {<br /> dfile.println(dateStr);<br /> dfile.print(sumdevStr);<br /> dfile.print(sumdev);<br /> dfile.print(cocoaStr);<br /> dfile.println(cocoaCnt);<br /> dfile.printf(envStr, tmp, hum, pressure);<br /><br /> dfile.close();<br /> }<br /><br /> //Button controll<br /> M5.Lcd.setTextSize(3);<br /> M5.Lcd.println("");<br /> M5.Lcd.setTextColor(BLUE, WHITE);<br /> M5.Lcd.println("A: Beep on/off");<br /> M5.Lcd.println("B: DOWN bright");<br /> M5.Lcd.println("C: UP bright");<br /><br /> int timer = 100;<br /> while (timer--) {<br /> if (M5.BtnA.wasReleased()) { //Aボタンでbeepをon/off切り替える<br /> onBeep = !onBeep;<br /> } else if (M5.BtnB.wasReleased()) { //Bボタンで輝度を下げる<br /> bright -= brightPitch;<br /> } else if (M5.BtnC.wasReleased()) { //Cボタンで輝度を上げる<br /> bright += brightPitch;<br /> }<br /> M5.Lcd.setBrightness(bright);<br /> delay(70);<br /> M5.update(); // update button state<br /> }<br /><br /> //init for next loop<br /> M5.Lcd.setTextColor(WHITE, BLACK);<br /> M5.Lcd.setCursor(0, 110);<br /> M5.Lcd.setTextSize(1);<br /><br /><br /> pBLEScan->clearResults(); // delete results fromBLEScan buffer to release memory<br /> cocoaCnt = 0;<br /><br />}<br />// Arranged and written by 柴田(ひ)<br />[/code]<br />luky.orghttp://www.blogger.com/profile/17273806834102337860noreply@blogger.com0tag:blogger.com,1999:blog-1471072446855788166.post-55717137155172985392020-07-14T20:56:00.003+09:002020-07-14T21:08:59.150+09:00M5Stack用環境センサユニット ver.2(ENV II)の動作テスト<div>とりあえず、動いた。 <br /></div><div><br /></div><div><span style="color: black;"><a href="https://www.switch-science.com/catalog/3647/">https://www.switch-science.com/catalog/3647/</a><br /></span></div><div><span style="color: black;"><a href="https://www.switch-science.com/catalog/6344/">https://www.switch-science.com/catalog/6344/</a><br /></span></div><code><pre><font color="#95a5a6"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDH9w0JjuJVyecF-9GQ1g0tZqj6JIy4jO8je8657P0ZGam6Pn981OlfKCEirWOfDgnJbx6RnxXLXOUwQNHr2oDo23E2YGXsmEz_DseXYXTrzmb-jOkI2tShXCGeQlHpm9omXZrYx972Ds/s1280/20200714_205916.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1280" data-original-width="1221" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDH9w0JjuJVyecF-9GQ1g0tZqj6JIy4jO8je8657P0ZGam6Pn981OlfKCEirWOfDgnJbx6RnxXLXOUwQNHr2oDo23E2YGXsmEz_DseXYXTrzmb-jOkI2tShXCGeQlHpm9omXZrYx972Ds/s320/20200714_205916.jpg" /></a></div><span style="color: black;"><br /><br />M5StackのサンプルコードがENV. IIではなく、旧版のENVのものしかなく、<br />センサーの種類が違ったので、ちょいと手間取った。<br /><br /></span><br />/*</font>
<font color="#95a5a6"> note: need add library Adafruit_BMP280 & Adafruit_SHT31 from library manage</font>
<font color="#95a5a6">*/</font>
<font color="#5e6d03">#include</font> <font color="#434f54"><</font><font color="#d35400">M5Stack</font><font color="#434f54">.</font><font color="#000000">h</font><font color="#434f54">></font>
<font color="#5e6d03">#include</font> <font color="#434f54"><</font><font color="#000000">Adafruit_SHT31</font><font color="#434f54">.</font><font color="#000000">h</font><font color="#434f54">></font>
<font color="#5e6d03">#include</font> <font color="#434f54"><</font><font color="#d35400">Wire</font><font color="#434f54">.</font><font color="#000000">h</font><font color="#434f54">></font> <font color="#434f54">//The SHT31 uses I2C comunication.</font>
<font color="#5e6d03">#include</font> <font color="#434f54"><</font><font color="#000000">Adafruit_Sensor</font><font color="#434f54">.</font><font color="#000000">h</font><font color="#434f54">></font>
<font color="#5e6d03">#include</font> <font color="#434f54"><</font><font color="#000000">Adafruit_BMP280</font><font color="#434f54">.</font><font color="#000000">h</font><font color="#434f54">></font>
<font color="#000000">Adafruit_SHT31</font> <font color="#000000">sht31</font> <font color="#434f54">=</font> <font color="#000000">Adafruit_SHT31</font><font color="#000000">(</font><font color="#000000">)</font><font color="#000000">;</font>
<font color="#434f54">//DHT12 dht12; //Preset scale CELSIUS and ID 0x5c.</font>
<font color="#000000">Adafruit_BMP280</font> <font color="#000000">bme</font><font color="#000000">;</font>
<font color="#00979c">void</font> <font color="#5e6d03">setup</font><font color="#000000">(</font><font color="#000000">)</font> <font color="#000000">{</font>
<font color="#d35400">M5</font><font color="#434f54">.</font><font color="#d35400">begin</font><font color="#000000">(</font><font color="#000000">)</font><font color="#000000">;</font>
<font color="#d35400">M5</font><font color="#434f54">.</font><font color="#d35400">Power</font><font color="#434f54">.</font><font color="#d35400">begin</font><font color="#000000">(</font><font color="#000000">)</font><font color="#000000">;</font>
<font color="#d35400">Wire</font><font color="#434f54">.</font><font color="#d35400">begin</font><font color="#000000">(</font><font color="#000000">)</font><font color="#000000">;</font>
<font color="#d35400">M5</font><font color="#434f54">.</font><b><font color="#d35400">Lcd</font></b><font color="#434f54">.</font><font color="#000000">setBrightness</font><font color="#000000">(</font><font color="#000000">10</font><font color="#000000">)</font><font color="#000000">;</font>
<b><font color="#d35400">Serial</font></b><font color="#434f54">.</font><font color="#d35400">println</font><font color="#000000">(</font><font color="#000000">F</font><font color="#000000">(</font><font color="#005c5f">"ENV2 Unit(SHT12 and BMP280) test..."</font><font color="#000000">)</font><font color="#000000">)</font><font color="#000000">;</font>
<font color="#5e6d03">if</font> <font color="#000000">(</font><font color="#434f54">!</font> <font color="#000000">sht31</font><font color="#434f54">.</font><font color="#d35400">begin</font><font color="#000000">(</font><font color="#000000">0x44</font><font color="#000000">)</font><font color="#000000">)</font> <font color="#000000">{</font> <font color="#434f54">// Set to 0x45 for alternate i2c addr</font>
<b><font color="#d35400">Serial</font></b><font color="#434f54">.</font><font color="#d35400">println</font><font color="#000000">(</font><font color="#005c5f">"Couldn't find SHT31"</font><font color="#000000">)</font><font color="#000000">;</font>
<font color="#5e6d03">while</font> <font color="#000000">(</font><font color="#000000">1</font><font color="#000000">)</font> <font color="#d35400">delay</font><font color="#000000">(</font><font color="#000000">1</font><font color="#000000">)</font><font color="#000000">;</font>
<font color="#000000">}</font>
<b><font color="#d35400">Serial</font></b><font color="#434f54">.</font><font color="#d35400">print</font><font color="#000000">(</font><font color="#005c5f">"Heater Enabled State: "</font><font color="#000000">)</font><font color="#000000">;</font>
<font color="#5e6d03">if</font> <font color="#000000">(</font><font color="#000000">sht31</font><font color="#434f54">.</font><font color="#000000">isHeaterEnabled</font><font color="#000000">(</font><font color="#000000">)</font><font color="#000000">)</font>
<b><font color="#d35400">Serial</font></b><font color="#434f54">.</font><font color="#d35400">println</font><font color="#000000">(</font><font color="#005c5f">"ENABLED"</font><font color="#000000">)</font><font color="#000000">;</font>
<font color="#5e6d03">else</font>
<b><font color="#d35400">Serial</font></b><font color="#434f54">.</font><font color="#d35400">println</font><font color="#000000">(</font><font color="#005c5f">"DISABLED"</font><font color="#000000">)</font><font color="#000000">;</font>
<font color="#5e6d03">if</font> <font color="#000000">(</font><font color="#434f54">!</font> <font color="#000000">bme</font><font color="#434f54">.</font><font color="#d35400">begin</font><font color="#000000">(</font><font color="#000000">0x76</font><font color="#000000">)</font><font color="#000000">)</font> <font color="#000000">{</font>
<b><font color="#d35400">Serial</font></b><font color="#434f54">.</font><font color="#d35400">println</font><font color="#000000">(</font><font color="#005c5f">"Could not find a valid BMP280 sensor, check wiring!"</font><font color="#000000">)</font><font color="#000000">;</font>
<font color="#d35400">M5</font><font color="#434f54">.</font><b><font color="#d35400">Lcd</font></b><font color="#434f54">.</font><font color="#d35400">println</font><font color="#000000">(</font><font color="#005c5f">"Could not find a valid BMP280 sensor, check wiring!"</font><font color="#000000">)</font><font color="#000000">;</font>
<font color="#5e6d03">while</font> <font color="#000000">(</font><font color="#000000">1</font><font color="#000000">)</font> <font color="#d35400">delay</font><font color="#000000">(</font><font color="#000000">1</font><font color="#000000">)</font><font color="#000000">;</font>
<font color="#000000">}</font>
<font color="#d35400">M5</font><font color="#434f54">.</font><b><font color="#d35400">Lcd</font></b><font color="#434f54">.</font><font color="#d35400">clear</font><font color="#000000">(</font><font color="#00979c">BLACK</font><font color="#000000">)</font><font color="#000000">;</font>
<font color="#d35400">M5</font><font color="#434f54">.</font><b><font color="#d35400">Lcd</font></b><font color="#434f54">.</font><font color="#d35400">println</font><font color="#000000">(</font><font color="#005c5f">"ENV Unit test..."</font><font color="#000000">)</font><font color="#000000">;</font>
<font color="#000000">}</font>
<font color="#00979c">void</font> <font color="#5e6d03">loop</font><font color="#000000">(</font><font color="#000000">)</font> <font color="#000000">{</font>
<font color="#00979c">float</font> <font color="#000000">tmp</font> <font color="#434f54">=</font> <font color="#000000">sht31</font><font color="#434f54">.</font><font color="#d35400">readTemperature</font><font color="#000000">(</font><font color="#000000">)</font><font color="#000000">;</font>
<font color="#00979c">float</font> <font color="#000000">hum</font> <font color="#434f54">=</font> <font color="#000000">sht31</font><font color="#434f54">.</font><font color="#000000">readHumidity</font><font color="#000000">(</font><font color="#000000">)</font><font color="#000000">;</font>
<font color="#00979c">float</font> <font color="#000000">pressure</font> <font color="#434f54">=</font> <font color="#000000">bme</font><font color="#434f54">.</font><font color="#000000">readPressure</font><font color="#000000">(</font><font color="#000000">)</font> <font color="#434f54">/</font><font color="#000000">100</font> <font color="#000000">;</font>
<b><font color="#d35400">Serial</font></b><font color="#434f54">.</font><font color="#d35400">printf</font><font color="#000000">(</font><font color="#005c5f">"Temperatura: %2.2f*C Humedad: %0.2f%% Pressure: %0.2fhPa\r\n"</font><font color="#434f54">,</font> <font color="#000000">tmp</font><font color="#434f54">,</font> <font color="#000000">hum</font><font color="#434f54">,</font> <font color="#000000">pressure</font><font color="#000000">)</font><font color="#000000">;</font>
<font color="#d35400">M5</font><font color="#434f54">.</font><b><font color="#d35400">Lcd</font></b><font color="#434f54">.</font><font color="#d35400">setCursor</font><font color="#000000">(</font><font color="#000000">0</font><font color="#434f54">,</font> <font color="#000000">0</font><font color="#000000">)</font><font color="#000000">;</font>
<font color="#d35400">M5</font><font color="#434f54">.</font><b><font color="#d35400">Lcd</font></b><font color="#434f54">.</font><font color="#d35400">setTextColor</font><font color="#000000">(</font><font color="#00979c">WHITE</font><font color="#434f54">,</font> <font color="#00979c">BLACK</font><font color="#000000">)</font><font color="#000000">;</font>
<font color="#d35400">M5</font><font color="#434f54">.</font><b><font color="#d35400">Lcd</font></b><font color="#434f54">.</font><font color="#d35400">setTextSize</font><font color="#000000">(</font><font color="#000000">3</font><font color="#000000">)</font><font color="#000000">;</font>
<font color="#d35400">M5</font><font color="#434f54">.</font><b><font color="#d35400">Lcd</font></b><font color="#434f54">.</font><font color="#d35400">printf</font><font color="#000000">(</font><font color="#005c5f">"Temp: %2.1fC \r\nHumi: %2.0f%% \r\nPressure:%2.0fhPa\r\n"</font><font color="#434f54">,</font> <font color="#000000">tmp</font><font color="#434f54">,</font> <font color="#000000">hum</font><font color="#434f54">,</font> <font color="#000000">pressure</font><font color="#000000">)</font><font color="#000000">;</font>
<font color="#d35400">delay</font><font color="#000000">(</font><font color="#000000">1000</font><font color="#000000">)</font><font color="#000000">;</font>
<font color="#000000">}</font>
</pre>
</code>luky.orghttp://www.blogger.com/profile/17273806834102337860noreply@blogger.com0tag:blogger.com,1999:blog-1471072446855788166.post-31608803546207128972020-05-28T16:23:00.001+09:002020-05-28T23:24:14.797+09:00散髪<div>リスク回避で控えていたが、超ボサボサ状態に耐えられずに<div>約2ヶ月ぶりに散髪。</div><div><br />混まない時間を狙い、会社を早引けして(^^;</div><div>いつもの床屋さん。</div><div><br /></div></div><div>私の他には一人だった。</div><div>理容師さんも手持ち無沙汰な感じ。</div><div><br /></div><div>いつものように刈り上げて、上も髪がたつぐらいに短めで。</div><div>少しでもリスク低減のため、顔そり・ひげ剃りはせず。</div><div><br /></div><div>それでもスッキリしました(^^)</div><div><br /></div>luky.orghttp://www.blogger.com/profile/17273806834102337860noreply@blogger.com0