raspberry piのlcd

3.5inchのlcd
aliexpressでraspberry pi用のlcdが安く売っていたので、買ってみた。3.5inchでタッチパネルもついている。届いたものを見てみたら、メーカーも何も分からないので、いろいろと試行錯誤しながら設定してみた。結果としては、WaveShareのdriverで動いたので、WaveShare製なのかも知れない。

ここの情報を見ながら設定を行った。必要なドライバーをdownloadして、展開する。

wget http://www.waveshare.com/w/upload/7/74/LCD-show-170309.tar.gz
tar xvf LCD-show-*.tar.gz
説明を読むと、新しいraspbianでは、LCD-show/boot/config35.txtの中のdtoverlay=ads7846の行をコメントアウトする必要があるようだ。そして、LCD35-showを実行すると、LCDが表示されるようになり、LCD-hdmiを実行すると、hdmiに表示するようになる。/boot/cmdline.txtと/boot/config.txtは書き換えられるので、backupしておいた方が無難だろう。 タッチスクリーンもすぐに使えるようになった

GUIに関しては、liteから手でインストールした。

sudo apt-get install --no-install-recommends xserver-xorg
sudo apt-get install --no-install-recommends xinit
sudo apt-get install raspberrypi-ui-mods
キーボード入力もできるようにmatchbox-keyboardも入れた。

しかし、3.5inchは小さいので、その画面だけで何かをするのは、なかなか難しいそうだ。

Read more...

DAコンバーター

MCP4922とarduino UNO

DACとしては、以前はMCP4922を使っていたが、最近は MCP4726を使うようになった。前者のinterfaceはSPIで、後者はI2Cである。arduinoでMCP4922を使ったことが無かったので、プログラムを書いてみた。

arduino UNOのSPIは、SS(10), MOSI(11), MISO(12), SCK(13)の4pinを使って行なわれる。今回は、ICにコマンドを送るだけなので、MISOは使わない。また、MCP4922のLDACは9pinに、SHDNはVccに接続した。SPIの使い方は、SPI.hを組み込んで、モードをセットして、書き込む。

serialからDAのデータを受け取るときに、どのような処理をしようか迷ったが、parseIntを使うと、数字をintに変換してくれるので、正の数だとchAを、負の数だとchBにデータを送るようにしてみた。

#include <SPI.h>
#define LDAC   9
void setup(){
  Serial.begin(9600);
  pinMode(LDAC,OUTPUT);
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  SPI.setClockDivider(SPI_CLOCK_DIV8);
  SPI.setDataMode(SPI_MODE0);
}
void loop() {
  if(Serial.available()>0){
    int i=Serial.parseInt();
    digitalWrite(LDAC,HIGH);
    digitalWrite(SS,LOW);
    if(i<0){i=-i-1;i|=0x8000;}
    i|=0x3000;
    SPI.transfer(i >> 8);
    SPI.transfer(i & 0xff);
    digitalWrite(SS,HIGH);
    digitalWrite(LDAC,LOW);
    delay(500);
  }
}
Read more...

ADコンバーター

MCP3425とarduino UNO

最近はADCとしては、MCP3425をよく使っている。内部標準電圧を使用するので参照電圧は不要だし、差動入力で負の電圧も読めるし、i2cなので通信に必要な信号の数が少ないというという利点がある。2.048Vまでの電圧を符号を含めて16bitでADCでき、小さな電圧に対しては8倍まで増幅して読むことも可能である。これをarduino UNOで使うときに、符号の部分でつまづくことがあるので、メモをしておこうと思う。

配線は非常に単純で、電源と測定する電圧とSDA,SCLをつなげば良い。pull upはAVRがしてくれるので、気にしなくても良い。ただし、SDAとSCLはそれぞれA4とA5につながっているので、それらのピンは使えなくなる。

下のプログラムでは、i2cで通信するときには、アドレス0x68を指定して、レジスタに0x88を書き込んでいる。これは、one shot modeで 16bit増幅なしで測定を開始するということを意味する。このモードでは1/15秒で測定が終了する。測定が終了したかを調べることもできるが、その通信によるノイズが入らないように、十分に時間が経ってから、データを読み出す。Wire.read()で1byteのdataを読み出すが、この関数の型はintである。arduino UNOでのintは16bitなので、符号を気にせずに計算する式で、符号もうまく処理できるようだ。何の工夫も無いコードであるが、一応符号も考慮しているのである。しかし、16bit以外のモードではこうは行かないので、注意しなければならない。

#include <Wire.h>
void setup(){
  Wire.begin();
  Serial.begin(9600);
  delay(100);
}
void loop(){
  Wire.beginTransmission(0x68);
  Wire.write(0x88);
  Wire.endTransmission();
  delay(100);
  Wire.requestFrom(0x68,2);
  Serial.println(Wire.read()*256+Wire.read());
  delay(500);
}
Read more...

backportを使って

jessieのkicad
kicadを使って回路を考えていたが、開こうとすると、“some files could not be found"というエラーが出て、うまく行かない。いろいろと調べたら、debian jessieだと、backportのkicadを使うと良いらしい。/etc/apt/source.listに

deb http://httpredir.debian.org/debian jessie-backports main contrib non-free

を加えて、

aptitude update
aptitude -t jessie-backports install kicad

として、インストールした。でも、前のバージョンで作ったやつは、動かないようなので、作り直しだ。

Read more...

beamerのエラー

図の取り込みとbb
beamerを使ってtexでコンパイルしようとしたら、図の取り込みのところでエラーが出る。bbが無いから作ろうとしているが、すでにきちんと作ってある。こういうときは、dvipdfmxオプションなどが抜けていることが、今回はきちんと指定してある。エラーメッセージをよく見て、

platex --shell-escape tempj

としたらうまくいった。

Read more...

同じアドレスを持つデバイス

アドレスの重複するデバイスとI2Cで通信 I2Cでは,複数のデバイスと二本の信号線だけで通信することができます.しかしそれには,アドレスが重複していないという条件が必要です.同じアドレスのデバイスが二個あり,これらと通信するためには,二系統のI2Cを使うか,切り替え機能のあるICを使って,通信を実現することができ,そうしている人が多いようである. ICを使って切り替えるとしても,デバイスを選択するために信号線が必要なので,その信号線を使って通信を行なってしまえば,新たなICを使わないでも二個のデバイスと通信ができる.この際,SCLは共通に使って,SDAをそれぞれのデバイスに一本ずつ使えば,三本の信号線で二個のデバイスと通信できる.逆に,クロックが送られなければ通信は行なわれないと考えて,SDAを共通にして,SCLをそれぞれのデバイスに割り当てることもできるだろう.前者の場合には,クロックが共通なので,同時に二個のデバイスと,同じバイト数の通信を行なうことになる.後者の場合には,別々のタイミングで,それぞれのデバイスと通信することになる. 上記の考えを拡張すると,アドレスが重複しているn個のデバイスとの通信は,(n+1)本の信号線を使うと実現できることが分かる.ほぼ同じデータをやりとりする場合には,SCL共通の方が一度に通信できるという点で優れており,送受信するデータ数やタイミングがデバイス毎に違う場合には,SDA共通が良いだろう. arduinoを使って,SCL共通でこれを実現するためのプログラムを試しに書いてみた.mulWireBegin()で初期化を行い,mulWireBeginTransmittion()とmulWireWrite()とmulWireEndTransmittion()を使って,デバイスに送信する.受信は,mulWireRequestFrom()とmulWireRead()とmulWireEndRequest()を使って行なう.バッファなどは無く,これらのコマンドの実行と同時に通信が行なわれるので,受信のときにもその終了操作を行なうコマンドが必要になる点が,通常のarduinoのI2Cのコマンドと異なる.参考にソースを載せておくが,まだ動作確認を行なっていないので,動作は保証できません. #define MulWireDelay 6 // 6 micro second 100kHz #define mwNUM 2 #define mwSCL A5 uint8_t mwSDA[mwNUM]={A4,A3}; uint8_t mwadrs[mwNUM]={0x68,0x68}; void mulWireBegin(){ char i; pinMode(mwSCL,OUTPUT); for(i=0;i<mwNUM;i++){pinMode(mwSDA[i],OUTPUT);} digitalWrite(mwSCL,HIGH); for(i=0;i<mwNUM;i++){digitalWrite(mwSDA[i],HIGH);} delay(10); } void mulWireBeginTransmission(uint8_t *adrs){ char i; for(i=0;i<mwNUM;i++){digitalWrite(mwSDA[i],LOW);} delayMicroseconds(MulWireDelay); digitalWrite(mwSCL,LOW); mulWireData(2,adrs); //*2 } void mulWireRequestFrom(uint8_t *adrs){ char i; for(i=0;i<mwNUM;i++){digitalWrite(mwSDA[i],LOW);} delayMicroseconds(MulWireDelay); digitalWrite(mwSCL,LOW); mulWireData(3,adrs); //*2+1 } void mulWireEndTransmission(){ char i; for(i=0;i<mwNUM;i++){digitalWrite(mwSDA[i],LOW);} delayMicroseconds(MulWireDelay); digitalWrite(mwSCL,HIGH); delayMicroseconds(MulWireDelay); for(i=0;i<mwNUM;i++){digitalWrite(mwSDA[i],HIGH);} } void mulWireEndRequest(){ mulWireEndTransmission(); } uint8_t mulWireWrite(uint8_t *data){ mulWireData(0,data); } uint8_t mulWireData(char mode,uint8_t *data){ // mode: 0:raw, 2:*2, 3:*2+1 char i,m,a; uint8_t temp; m=(mode>1)?
Read more...

それぞれのコマンドでやっていること

arduino UNOでI2C
I2Cを使うと,二本の信号線でアドレスの異なる128個のICと通信できる.AVRやESP8266でI2Cを使ったことはあったが,arduino UNOでI2Cをやろうとしたら,少し間違えたので,その仕組みを調べてみた. 初期化はWire.begin()で行なう. ICに命令を送るときには,Wire.beginTransmission(adrs)とWire.write(data)とWire.endTransmission()を使う.ソースを見てみると,beginTransmissionではアドレスを定義するだけで,実際には通信は行なわず.writeではバッファに書き込んで,ここでも通信は行なわない.実際に通信が行なわれるのは,endTransmissionのときで,twi_writeToというコマンドを使って,アドレスやデータが送られる. 一方データを読み込むときには,Wire.requestFrom(adrs,bytes)とWire.read()を使うのだが,最初はbeginTransmissionとreadなどでやろうとしてしまった.読み込みでも,アドレスの送信を行なうので,そう考えてしまった.しかし,実際には,requestFromのときにtwi_readFromというコマンドを使って一気にバッファに読み込んでおり,このコマンドが無いと読み込みは行なわれない.その後で使うreadでは,バッファから読み込んでいるだけなのである. 書き込みの時はコマンドを三つ使って,読み込みの時は二つなのは,対称性が悪いなと思っていたが,このように,コマンドの内容を理解すると,そうなってしまう必然性が分かった.

Read more...

大容量のHDD

exfatをdebianで読むには
大容量のHDDを繋いだら、認識はするのだが、exfatは見つから無いというエラーが出て使えない。調べてみたら、exfat-fuseとexfat-utilsを入れれば使えるようになるようだ。実際aptitudeで入れたら、ファイラーからマウントして使えるようになった。

Read more...

raspberry pi zero発売

待ちに待った発売
2017年の第一四半期に日本で発売と発表されて依頼、なかなか情報が出なかったraspberry pi zeroですが、やっと明日発売されるようです。税抜き650円と、A+の四分の一である。pi zeroを動かす上で問題になるのが、HDMIがminiである点だ。既に入手している人達は、結構値段のする変換アダプタを使っている人が多いようだが、百均でも売っているのを見つけて、すでに準備済である。しかし、発売されてもすぐに入手するのは困難だろうから、少し落ちつくのを待つことにしよう。

Read more...

IoTで温度、湿度、気圧を記録

BME280とESP8266
esp8266を使って温度のログを取っていたが、ようやく温度、湿度、気圧の記録を取れるようになった。BME280からI2Cを使ってデータを取得して、それをwifiでuploadする、と書くと簡単そうだが、BME280を扱うのに、それなりに苦労した。途中で一つeps8266を殺してしまった。 I2Cの通信自体は、それほど難しく無いが、ピン番号を間違えていて、しばらく苦戦してしまった。次に苦労したのが、BME280から取得したデータの変換だ。BME280の中に、校正するためのパラメーターが入っていて、これらを用いて複雑な計算をすると、温度などの値が得られる。これらを内部であらかじめやってくれていると楽なのにと思うのだが、計算が大変だからか、自分で計算しないといけない。パラメータの格納の順序が、私の書いたサブルーチンと相性が悪く、その変換のために、プログラムが汚くなってしまった。また、32bitや64bitのsignedやunsignedの変数をいろいろと使った式で、かなり複雑な計算をする必要がある。最初は32bitの変数としてlongを使っていたが、おそらくこれが32bitでは無いようで、signedのときに変な挙動をした。あからさまにint32_tなどと書かないと負の数のときに、値が変になってしまう。 これらの苦労を経て、なんとか記録を開始することができた。今後、これらのデータを使って、いろいろと検討することができるだろう。

Read more...