お知らせ

  • らずぱいでIoT

らずぱいでIoT 第14回(ラズパイ4B登場)

noimage

らずぱいでIoT 第14回(ラズパイ4B登場)

かわせです。 久しぶりにらずぱいでIoTを更新します。 いよいよ日本でもRaspberry 4Bが発売されました。 ということでスイッチサイエンスさんで購入してDebian10ベースのOSを入れてみました。 やはり前にも書いた通りlibgpio仕様となっているためgpioコマンドを起動するとエラーが発生します。 Oops - unable to determine board type... model: 17 というメッセージでボードタイプが特定できないというメッセージが出て終了します。 でこれに対応するためにはどうするかというと答えはここにありました。 http://wiringpi.com/wiringpi-updated-to-2-52-for-the-raspberry-pi-4b/ sudo su - で管理ユーザーになり wget https://project-downloads.drogon.net/wiringpi-latest.deb sudo dpkg -i wiringpi-latest.deb で解決いたしました。

  • らずぱいでIoT

らずぱいでIoT 第13回(C言語で制御するために、その4)

noimage

らずぱいでIoT 第13回(C言語で制御するために、その4)

かわせです。相変わらずラズパイをC言語で使う方法について調べています。 そんな中、前回GPIOにアクセスるために/sys/class/gpioによるアクセス方法をご紹介しましたが、そのドキュメントの中に重大なことが書かれておりました。 /sys/class/gpioでのアクセスは現在推奨されておらず、libgpiodというライブラリを使うように勧めています。 2020年には/sys/class/gpioは廃止されlibgpiodに変更されるようです。 libgpiodでは /dev/gpiochipN にアクセスるライブラリでNは0から始まる数字になるようです。 現在は/dev/gpiochip0しか存在しておらず1や2はありませんがひょっとすると複数のデバイスを想定しているのかもしれません。 ちなみにすでに、libgpiodはGIT HUBで公開されています。 https://github.com/brgl/libgpiod ただいま解析中のためこれ以上詳しいことは書けませんが、現在作成しているプログラムは変更しないと新しいシステムでは動作しなくなる可能性が出てくるため、ラッピング関数で同じインターフェイスから使えるような工夫をしておかないと対応に苦慮するものと思われます。 それから、SPI通信やI2C通信用のデバイスファイルは変更なく使えるようです。 また、解析できたらブログ上でご報告したいと思います。

  • らずぱいでIoT

らずぱいでIoT 第12回(C言語で制御するために、その3)

noimage

らずぱいでIoT 第12回(C言語で制御するために、その3)

前回は、メモリのアドレスと意味についてマニュアルから読み取れるというお話をしました。 C言語を使うと、ポインターに仮想メモリのアドレスを与えてあげればメモリにアクセスすることも可能でしょう。 しかし、ラズベリーパイは基本的にRasbian LinuxというOSが乗っているのでメモリーにアクセスるるためにはメモリデバイス/dev/memを介してアクセスるようにします。 ただ、/dev/mem はrootユーザにしか書込み権が与えられておらず、このデバイスに書込みアクセスるためにroot権限が必要になります。 なので、実際には/dev/gpiomem というデバイスにアクセスします。 (/dev/gpiomem にはrootグループユーザまでに書込み権が与えられています。) このデバイスファイルにCでアクセスるためにはfopenサブルーチンではなくopen システムコールを使います。 open通常のファイルアクセスではなくデバイスファイルにアクセスる場合に使い、ドライバの機能にアクセスるためのファイルディスクリプタを得ることが出来ます。 実際にメモリにアクセスするためにはmmap()関数でGPIOメモリをマッピングし、終了時にはmunmap()関数でアンマップします。 また、Rasbian Linuxでは一般ファイルとしてGPIOにアクセスることも可能で、 /sys/class/gpio 以下の export ファイルにコントロールするGPIOのピン番号を指定するとコントロール用の /sys/class/gpio/gpioxx というディレクトリが出来上がりその下にdevice,value,edge,active_low等の制御用ファイルが出来上がりこれらのファイルにアクセスすることでGPIOピンをコントロールすることが出来ます。 参考 https://www.kernel.org/doc/Documentation/gpio/sysfs.txt   この制御ファイルはC言語からだけではなく、ファイルにアクセスできればどんな言語からもアクセス可能です。

  • らずぱいでIoT

らずぱいでIoT 第11回(C言語で制御するために、その2)

noimage

らずぱいでIoT 第11回(C言語で制御するために、その2)

こんばんわ、かわせです。 ラズパイでIoT前回は現在乗っている、BROADCOMのチップによって制御する方法が変わってくるのでチップセットを知る方法について書いてみました。 RaspberryPi ZeroではBCM2835というチップでこの説明書を読んでみるとラズパイのメモリ配置やペリフェラルデバイスIOマップや各種レジスタの意味が書かれており これを読むことでUARTシリアル通信にかかわるレジスタやGPIOの操作にかかわるレジスタ群の説明が書かれています。 このような説明書をもとにして、C言語で直接ハードウエアを制御することも可能になります。 また、ラズパイでは標準でRasbianというDebian LinuxをベースにしたOSが配布されておりこのOSを使うことが一般的です。 OSでは各種ペリフェラルデバイスをコントロールするためのドライバが用意されておりこれをC言語から制御することで操作する方法もあります。 各種デバイスドライバをRasbian Linuxに組み込むためには raspi-config というコマンドを使います。 raspy-configではそのほかにsshの起動や起動時にGUIを使うかCUIを使うかの設定やlocal設定なども可能で、ラズパイは最も小さいLinuxPCとも言えます。 そこで手前みそではありますが、UNIX Like OSの勉強会を今後開いていこうと考えており下記のアドレスでメンバーを募集しております。 https://bashw.connpass.com/   ご興味のある方はこのURLからメンバー登録お待ちしております。  

  • らずぱいでIoT

らずぱいでIoT 第10回(C言語で制御するために、その1)

noimage

らずぱいでIoT 第10回(C言語で制御するために、その1)

こんばんわ川瀬です。 すみません、最近更新をさぼってました。 らずぱいでIoTを書き始めてはや10回を迎えました。 今回から数回はC言語で使って温度、気圧、湿度センサーを使ってみたいと考えています。 その前に! C言語でラズパイを使うにあたっては様々なライブラリが用意されています。 なかでも、ライブラリを使わずにメモリーマップドIOで配置されているレジスタへのアクセスする方法は最もハードウエアを直接制御する方法ということができます。 そのためには、ラズパイで使用されているチップセットの情報が必要となります。 調べ方は以下の通り root@raspberrypi:~# cat /proc/cpuinfo processor : 0 model name : ARMv6-compatible processor rev 7 (v6l) BogoMIPS : 697.95 Features : half thumb fastmult vfp edsp java tls CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x0 CPU part : 0xb76 CPU revision : 7 Hardware : BCM2835 Revision : 9000c1 Serial : 000000003b4523d6 catで/proc/cpuinfoを読んでみると上のような情報が得られチップセットは、BCM2835というタイプであることがわかります。 で、BCM2835をネットで検索してみると https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2835/README.md が先頭に出てきて、内容を読んでみるとBCM2835がModel A、A+、B および Zeroで使われていることがわかります。 更に、このページからチップセットの細かい内容が解説されたPDFを得ることも可能です。 ただし、文章はすべて英語です。

  • らずぱいでIoT

らずぱいでIoT 第9回(python版 気温・気圧・湿度計算)

noimage

らずぱいでIoT 第9回(python版 気温・気圧・湿度計算)

今回は、いよいよpython版のレジスタの読取り・計算・表示の全プログラムです。 このプログラムでは、Dict(連想配列)を使う事でチップ説明書にあるレジスタアドレスと一致するように工夫してあります。 プログラムの内容自体は、前回のチップ説明書の中にある保障式を今まで書いてきたプログラムに合うように書き直したものです。 ------------------------------------- 以下ソース #!/usr/bin/python import smbus import time SMBUS_NUMBER = 1 SMBUS_ADDR = 0x77 SMBUS_REG_CONF = 0xF5 SMBUS_REG_CTRL_MEAS = 0xF4 SMBUS_REG_CTRL_HUM = 0xF2 dig_T = {} dig_P = {} dig_H = {} calib = {} n = 0x88 while n <= 0xA1: __ calib[n] = 0 __ n = n + 1 n = 0xE1 while n <= 0xF0: __ calib[n] = 0 __ n = n + 1 n = 0xF7 while n <= 0xFE: __ calib[n] = 0 __ n = n + 1 bus = smbus.SMBus(SMBUS_NUMBER) bus.write_byte_data(SMBUS_ADDR,SMBUS_REG_CONF,0xA0) bus.write_byte_data(SMBUS_ADDR,SMBUS_REG_CTRL_HUM,0x01) bus.write_byte_data(SMBUS_ADDR,SMBUS_REG_CTRL_MEAS,0x25) time.sleep(0.1) for k in calib.keys(): __ calib[k] = bus.read_byte_data(SMBUS_ADDR, k) dig_T[1] = (calib[0x89] << 8 | calib[0x88]) dig_T[2] = (calib[0x8B] << 8 | calib[0x8A]) dig_T[3] = (calib[0x8D] << 8 | calib[0x8C]) dig_P[1] = (calib[0x8F] << 8 | calib[0x8E]) dig_P[2] = (calib[0x91] << 8 | calib[0x90]) dig_P[3] = (calib[0x93] << 8 | calib[0x92]) dig_P[4] = (calib[0x95] << 8 | calib[0x94]) dig_P[5] = (calib[0x97] << 8 | calib[0x96]) dig_P[6] = (calib[0x99] << 8 | calib[0x98]) dig_P[7] = (calib[0x9B] << 8 | calib[0x9A]) dig_P[8] = (calib[0x9D] << 8 | calib[0x9C]) dig_P[9] = (calib[0x9F] << 8 | calib[0x9E]) dig_H[1] = calib[0xA1] dig_H[2] = (calib[0xE2] << 8 | calib[0xE1]) dig_H[3] = (calib[0xE3]) dig_H[4] = (calib[0xE4] << 4 | calib[0xE5] & 0xf) dig_H[5] = (calib[0xE6] << 4 | calib[0xE5] >> 4) dig_H[6] = (calib[0xE7]) for i in [2,3]: __ if (dig_T[i] & 0x8000): ____ dig_T[i] = (-dig_T[i] ^ 0xffff)+1 for i in [2,3,4,5,6,7,8,9]: __ if (dig_P[i] & 0x8000): ____ dig_P[i] = (-dig_P[i] ^ 0xffff)+1 for i in [2,4,5]: __ if (dig_H[i] & 0x8000): ____ dig_H[i] = (-dig_H[i] ^ 0xffff)+1 if (dig_H[6] & 0x80): __ dig_H[6] = (-dig_H[6] ^ 0xff)+1 raw_T = calib[0xFA] << 12 | calib[0xFB] << 4 | calib[0xFC] >> 4 raw_P = calib[0xF7] << 12 | calib[0xF8] << 4 | calib[0xF9] >> 4 raw_H = calib[0xFD] << 8 | calib[0xFE] tv1 = ((raw_T >> 3) - (dig_T[1] << 1)) * (dig_T[2] >> 11) tv2 = (((raw_T >> 4) - dig_T[1]) * ((raw_T >> 4) - dig_T[1])) >> 12 tv2 = (tv2 * dig_T[3]) >> 14 t_fine = tv1 + tv2 Temp = ((t_fine * 5 + 128) >> 8) / 100.0 pv1 = (t_fine / 2.0) - 64000 pv2 = ((pv1 / 4.0) * (pv1 / 4.0) / 2048) * dig_P[6] pv2 = pv2 + ((pv1 * dig_P[5]) * 2.0) pv2 = (pv2 / 4.0) + (dig_P[4] * 65536.0) pv1 = (((dig_P[3] * (((pv1 /4.0) * (pv1 * 4.0)) /8192)) / 8) + ((dig_P[2] * pv1) / 2.0)) / 262144 pv1 = ((32768 + pv1) * dig_P[1]) / 32768 if pv1 != 0: __ p = ((1048576 - raw_P) - (pv2 / 4096)) * 3125 __ if p < 0x80000000: ____ p = (p * 2.0) / pv1 __ else: ____ p = (p / pv1) * 2 __ pv1 = (dig_P[9] * (((p / 8.0) * (p / 8.0)) / 8192.0)) / 4096 __ pv2 = ((p / 4.0) * dig_P[8]) / 8192.0 __ p = p + ((pv1+ pv2 + dig_P[7]) /16.0) else: __ p = 0 Pres = p / 100.0 hv = t_fine - 76800.0 if hv != 0: __ hv = (raw_H - (dig_H[4] * 64.0 + dig_H[5]/16384.0 * hv)) * (dig_H[2] / 65536.0 * (1.0 + dig_H[6] / 67108864.0 * hv * (1.0 + dig_H[3] / 67108864.0 * hv))) __ hv = hv * (1.0 - dig_H[1] * hv / 524288.0) __ if hv > 100.0: ____ hv = 100.0 __ elif hv < 0.0: ____ hv = 0.0 else: __ hv=0.0 Hum = hv print "T=%2.1f P=%4.1f H=%1.2f" % (Temp,Pres,Hum) ------------------------------------- ここまで 尚、_はスペースです。 ソースはこちらからダウンロードできます。  

  • らずぱいでIoT

らずぱいでIoT 第8回(16Bit幅の補数計算検証)

noimage

らずぱいでIoT 第8回(16Bit幅の補数計算検証)

pythonのint型変数の扱いには少し注意が必要です。 python3のint型は最大のBit幅に制限なくShortやLongといった区別がなくなりました。 そのため前回の16Bit長のレジスタ値のマイナス表現でpythonが認識しているbit幅に拡張する場合どう描くべきかをC言語のプログラムを使い見てみます。 その前に補数について少し触れておくと 計算機内部では、マイナス値がどのように扱われているかという事を見てみると 1Byte=8bit長の2進数で表現可能で計算機内部では5という数字は 00000101 という2進数です。 この5をある数字から引きたい場合、計算機の中でどのようなことが起きるかというとビットを反転させる解くことが起きていますなので5は 11111010 という2進数になりこれを1の補数といいます。 1の補数表現の5にある数字を足すと例えば十進法の10を足すと十進法の10は2進法で 00001010 なので 11111010+00001010 = 100000100 となりますが8bit幅なので最上位の1が無くなり 00000100 = 十進法の4 となります。 上の2進数の式を10進法で見てみると 250 + 10 = 260 で8bitで表される最大数は255なのであふれた分を計算すると5という10-5の答えが得られます。 では1の補数で計算するとなぜ答えが4になるかというと計算機内部で最上位ビットを符号とした場合 2進数の10000000は-0というおかしな値が存在しているためで、この分符号反転した時点で1を足さないとつじつまが合わないということが起きます。このようにビット反転して1を足した補数を2の補数と呼びます。 2の補数で計算してみると 11111011+00001010 = 100000101 となり2進数でも正しい値が出てきます。 これを踏まえた上で、16Bit幅のマイナス値をpythonのint型に拡張する場合どうするかをpythonではBit幅が確定されていないのでC言語で試してみたいと思います。 ーーーーーーーーーーーーーーーーーーーーーーーーーーーー 以下プログラム #include <stdio.h> void main() { unsigned short n = 0xfff5; _______ short m; ____ printf("単純にマイナス %04x->%d(%08x)\n",n,-n,-n); ____ // 16Bit幅で2の補数表現に変換 ____ m=(-n ^ 0xffff)+1; ____ printf("2の補数表現に変換 %08x -> %d\n",m,m); ____ printf("-11のビット確認 %08x -> %d\n",(short)-11,(short)-11); } ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーここまで なお_はスペースを示します。 最初のpirntfではunsigned short(32bit)の変数に0xfff5(16bit)をいれて単純にマイナスに変換すると32Bit幅で2の補数値が計算され0xffff000bとなります。 そのため下位16ビット幅で2の補数を計算してみると 0xfffffff5という値に拡張されていることがわかります。(2番目のprintf) 念のため32Bit長の-11が32bitはばで0xfffffff5であることを確認してみます。(3番目のprintf) ということでpythonで拡張できるかを以下のプログラムで確認してみると ーーーーーーーーーーーーーーーーーーーーーーーーーーーー ここから python #!/usr/bin/python n=0xfff5 print("%x -> %d\n" % (n,(-n ^ 0xffff)+1)) ーーーーーーーーーーーーーーーーーーーーーーーーーーーー ここまで ということで16Bitのマイナス値をPythonの持つ不確定長の整数型に上記の式で拡張できることが検証できます。 今回使用したCのソースとPythonのソースはここからダウンロードできます。  

  • らずぱいでIoT

らずぱいでIoT 第7回(温度、気圧、湿度の計算準備)

noimage

らずぱいでIoT 第7回(温度、気圧、湿度の計算準備)

以前に、awkで計算した際に計算式で使用したdig_T1~dig_T3の算出を行いましたがBME280のチップ説明書によるとawkのプロラム内でdig_T2とdig_T3はsigned shortのためマイナスの0x8000の符号ビットが1の場合マイナスで扱う必要があるため正常な計算ができない可能性があります。 ただし、何度か読みだしたdig_T2,dig_T3はマイナスの値になることはなく常温程度ならマイナスにはならないのかもしれません。 awkではビット演算がサポートされてないためShift Rotateのような演算関数を作りそのうえでビット演算関数を作らない限り演算できないので実現は難しい(アセンブラにできて高級言語でできないことはあり得ないですが)のですが、pythonの場合は温度、気圧、湿度を計算するためのパラメータを求めるときにビット演算が可能なため肩を合わせることも可能になります。 上の表は各パラメータの算出を行うため、レジスタのどの位置を読むとどのパラメータになるかを示しています。前回のプログラムではcalib をDictにしたのはこのデータを読み出すためにはアドレスを指定して読みだしたほうがわかりやすいプログラムになるためです。 で今回追加した部分は以下のようになります。 ーーーーーーーーーーーーーーーーーーーーーーーー以下プログラム dig_T[1] = (calib[0x89] << 8 | calib[0x88]) dig_T[2] = (calib[0x8B] << 8 | calib[0x8A]) dig_T[3] = (calib[0x8D] << 8 | calib[0x8C]) dig_P[1] = (calib[0x8F] << 8 | calib[0x8E]) dig_P[2] = (calib[0x91] << 8 | calib[0x90]) dig_P[3] = (calib[0x93] << 8 | calib[0x92]) dig_P[4] = (calib[0x95] << 8 | calib[0x94]) dig_P[5] = (calib[0x97] << 8 | calib[0x96]) dig_P[6] = (calib[0x99] << 8 | calib[0x98]) dig_P[7] = (calib[0x9B] << 8 | calib[0x9A]) dig_P[8] = (calib[0x9D] << 8 | calib[0x9C]) dig_P[9] = (calib[0x9F] << 8 | calib[0x9E]) dig_H[1] = calib[0xA1] dig_H[2] = (calib[0xE2] << 8 | calib[0xE1]) dig_H[3] = (calib[0xE3]) dig_H[4] = (calib[0xE4] << 4 | calib[0xE5] & 0xf) dig_H[5] = (calib[0xE6] << 4 | calib[0xE5] >> 4) dig_H[6] = (calib[0xE7]) ーーーーーーーーーーーーーーーーーーーーーーーーここまで 前回は、dig_T,dig_P,dig_HはListで初期化していましたがプログラムを書く際これらもDictで初期化しておいたほうがわかりやすくかけるため初期化部分をDictにしている事に注意してください。 今回の全体ソースと日本語のチップ説明書をZIPにしてありますのでここからダウンロードしてください。    

  • らずぱいでIoT

らずぱいでIoT 第6回(Pythonで初書き)

noimage

らずぱいでIoT 第6回(Pythonで初書き)

今回は、温度、気圧、湿度を読み出すためのパラメータを書込んで補正データとRawデータを読取る部分をpythonで書いてみました。 書込みパラメータは第4回のシェルスクリプトでRawデータを読むを参考にしてください。 ーーーーーーーーーーーーーーーーーーーー 以下プログラム #!/usr/bin/python import smbus import time SMBUS_NUMBER = 1 SMBUS_ADDR = 0x77 SMBUS_REG_CONF = 0xF5 SMBUS_REG_CTRL_MEAS = 0xF4 SMBUS_REG_CTRL_HUM = 0xF2 dig_T = [] dig_P = [] dig_H = [] calib = {} n = 0x88 while n <= 0xA1: ____ calib[n] = 0 ____ n = n + 1 n = 0xE1 while n <= 0xF0: ____ calib[n] = 0 ____ n = n + 1 n = 0xF7 while n <= 0xFE: ____ calib[n] = 0 ____ n = n + 1 bus = smbus.SMBus(SMBUS_NUMBER) bus.write_byte_data(SMBUS_ADDR,SMBUS_REG_CONF,0xA0) bus.write_byte_data(SMBUS_ADDR,SMBUS_REG_CTRL_HUM,0x01) bus.write_byte_data(SMBUS_ADDR,SMBUS_REG_CTRL_MEAS,0x25) time.sleep(0.1) for k in calib.keys(): ____ calib[k] = bus.read_byte_data(SMBUS_ADDR, k) for k,v in calib.items(): ____ print "0x%02X -> 0x%02X" % (k,v) ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー ここまで このプログラムを書くにあたり、工夫した点はDictを使いレジスタアドレスとデータの関係性を作り上げている点にあります。 レジスタのアドレス等はデータシートに出ています。 こうすることによりレジスタの読取り部分をすっきりと書くことができたのではないかと思います。 ここではソース中のスペースを _ で表している事にご注意ください。 今回のソースはここからダウンロードできます。 何分Pythonは初書きのためつたないところがあるかもしれませんがご容赦ください。

  • らずぱいでIoT

らずぱいでIoT 番外編1(Windows10でsshが標準に!)

noimage

らずぱいでIoT 番外編1(Windows10でsshが標準に!)

なんと驚きました。 Winodws10のコマンドプロンプトからsshが標準で使えるようになってました。 ネタ元 http://www.atmarkit.co.jp/ait/articles/1811/22/news018.html sshだけではなく cURL や tar も使えるようになっているようです。 sshクライアント環境はほぼフルでそろっているようでsftpやssh-keygenも入っているようです。 これは、sshの公開鍵接続も可能になっているという事だと思われSSHを介してLinuxサーバー上にある様々な情報を得ることができます。 ちなみに、下記の画像はコマンドプロンプトからローカルサーバーに接続した例です。 これでCygwinのない環境でもsshがWindowsから使えるようになりました。 これを使うとラズパイにもすぐつながりますね!!

1 2