goo blog サービス終了のお知らせ 

寝ても覚めてもPSoC

電子工作とマイコンをやりはじめました。
ど素人ですので配信する情報の取り扱いには十分注意してください。

PSoCで方位センサーを使う[RDCM802]

2011年02月03日 | PSoC
方位センサーといえば、もう一つ持っていることを思い出した
秋月電子で買った RDCM802 という方位センサーです。
このセンサーは方角を8方向であらわします。前回のHMC6352は360度なので、それと比べると見劣りしますが...
なんと8方向のくせに磁石を近づけると狂いますw えぇーい、この軟弱者!!(バシッ)
しかも、恵方の南南東の識別ができないジャマイカ

このICは基板にも問題がありました。いつものヘッダーピンをハンダ付けする穴がないので、軟弱な僕は使うのを敬遠していました。調べてなんとか取り付け方が判明し、ハンダしてブレッドボードに差し込めました。ピンがハの字に開いちゃったけど...
とにかく、このタイミングを逃したら一生使わないだろうという妙な感覚があったw

インターフェースは3bitパラレルです。HMC6352はI2Cでしたが更に簡単に扱えますね
回路図も必要ないぐらいで、RDCM802のD0をP0[2]、D1をP0[3]、D2をP0[4]に接続すれば終わりですw
ちなみに僕の環境下では、方角を一つずらすと良い感じになりました。(北東なら北、東を指したら北東って感じです)
それか方位境界あたりが正しい方角を示しているのかもしれません。

このセンサーは扱いは簡単だけど価格も高い(500円ぐらいと思ったら3400円もするorz)し精度も荒いしサイズも大きいので使い所が難しいと思いました。普通ならHMC6352の方を選択するのではないでしょうか。マイコンいらずで大まかな方角がわかるってのが最大の魅力?

文句は垂れたけど、方位がわかるのってなんか楽しいな~ww




プロジェクトファイルです。
デザイナ: 5.0 SP6
デバイス: CY8C27143 5V
コンパイラ:ImageCraft
PSoC_RDCM802.zip


うーん、それはそうと、そろそろデザイナー5.1にするかな~

PSoCで方位センサーを使う[HMC6352]

2011年01月31日 | PSoC
今年の恵方は南南東だそうです。
南南東を向いて恵方巻きを食べると良いらしい。

そこで以前買っておいたデジタル出力の方位センサーHMC6352を使って方角を調べてみようと思いました
大げさで無理やり感たっぷりですが、使い道を考えてないのに好奇心だけで高いセンサーを買ってしまったと、今は反省しているww

HMC6352のインターフェースはI2CなのでI2Cmモジュールを使いました。
I2Cmで'A'コマンドを発行すると2バイトの方位データが出力させるので、それを読み込むだけです。とてもシンプル。

コンパスと比較するとなかなか良い具合に方角を示してくれます。
当たり前(?)ですが、磁石等の影響をけっこう受けます。
ちなみに更新レートを1Hzに変更してみたけど、なぜか反映されない。EEPROMにはちゃんと値が保存されているのに。はてさて、なんか手順を間違ってるのかな??(別に20Hzで更新されても問題ないけど...)

ってことで、だいたい160度を示した方角で恵方巻きを食べればOKかな




回路図です。



プロジェクトファイルです。
デザイナ: 5.0 SP6
デバイス: CY8C29466 5V
コンパイラ:ImageCraft
PSoC_HMC6352.zip


結論。方位を表示するだけだったら100円ショップで方位磁針(コンパス)を買ったほうが安くて小さく、電池いらずで断然お得ですwww
僕の作るのはだいたいこんな結末ですが、これが素人趣味って奴かな。

ImageCraftでsprintf

2011年01月28日 | PSoC
どうやらデザイナー5.0SP6からsprintfが使えるようになっていたらしい。
https://secure.cypress.com/?id=4&rID=43630

正直、シランカッタ....orz

csprintf( buf, "%d", value );
と数値を文字列に変換できる。

しかし、
csprintf( buf, "%04d", value );
のように桁指定や0フォーマットはダメのようだ。

僕は桁揃えをしたがるタイプなのでこの関数はあまり使わないだろうけど、無いとは大違いなので有難いのは確か。

とても残念なのはデフォルトでfloat(%f)を使えるようになってない事。

PSoCで距離センサーを使う[GP2Y0A21] その2

2011年01月24日 | PSoC
計測器を使ってみてわかった事は、うさちゃんはトイレでもくつろぐという事実www
以前はトイレにいる場面を見たことがなかったので、トイレはおしっこの時しか立ち寄らない場所だと思っていました。しかし実際はそうではなく、毛繕いをしたりしていた!(それでも全体的な割合は非常に少ないですが)
こうなるとオシッコ回数の計測は今の方法ではまるで正確性がありません。残念。

また、使ってみると問題も発生しました。
電池の持ちが悪いのです連続稼動させると8~9時間程度で動作しなくなります。
消費電流(DC-DCコンバーター後)は約65mA。エボルタが2000mAなので30時間は持つ計算に。
DCコンバーターの変換効率(?)というのがあるらしいので、それでもまぁ24時間は持つだろうと思っていましたが、甘かったようです。(配線効率?も良くない??)
消耗した電池の電圧を測ってみると0.9Vぐらい。あれれ、スペック的にはまだ100mAは供給できるはずでは?
電池からDC-DCコンバーターまでは100mA流れています。しかし、DCコンバーター以降は9.6mAしか流れていません...
うーむ、何かが間違っていそうだけど、わからんです。出力ラインに大き目のコンデンサでも付ければ少しはマシになりますかね~???

しょうがないのでとりあえずスイッチを付け、必要なときだけONにするようにしました。
まぁ確かに留守のときにブザーならしても意味が無いといえばそうだけど...。
なんかしっくりこないなぁ。

PSoCで距離センサーを使う[GP2Y0A21]

2011年01月20日 | PSoC
昨年末にウサギを飼うことになったw
チビうさちゃん、なかなか可愛いね! これからでかくなるらしいけどwww


で、現在トイレの躾けをしているのだが、なかなか時間がかかりそうだ...orz
そこで、トイレでおしっこしたらご褒美におやつを与え、その行為が良い事であると覚えてもらえれば少しは効率がよくなるのでは?と考えました。
問題はケージと居住空間の距離があるため、トイレでおしっこをするタイミングを何らかの方法でキャッチする必要があるということです。ずーーっとうさちゃんの行動を見続けるのは不可能。また、行動直後におやつをあげないと、なぜおやつがもらえたかがわからなくなるらしい。トイレに移動したら、離れた場所でその情報を素早く知りたい。

という事でPSoCの出番です!
センサーでトイレに移動したかを判定し、無線で手元の受信機に送信。音とLEDでお知らせする。ついでにトイレ回数もカウントすれば体調管理もできそう。

とりあえずセンサーが必要だけど何が良いかと手持ちの中からピックアップしてみた。
1.焦電型赤外線センサー
2.赤外線距離センサー
3.非接触温度センサー

1が良さそうだけど、今のところPSoCで扱えていません。アナログ難しいっす※アプリケーションノートを見つけたので近々やってみたい。
2は計測範囲が狭すぎるかもしれないが、扱いは割と簡単。
3は周りの温度に影響されそう(特に夏場。ウサギの体温は38℃~40℃らしい)。
結局2の赤外線距離センサー(GP2Y)を使うことにしました。
おしっこする場所によっては計測漏れしそうですが、当面これでいきます。

無線はお手軽のXBee
センサー側の電源はACから取る事にしました。ポリスイッチやダイオードをつけて対策していますが、長期稼動は不安です
赤外線距離センサーは右下で下向きに付いています(あたりまえかw)。一応距離を近似値で算出していますが使い物になりません テーブル作って補間した方が良いようです。
PSoC(CY8C27143)はディスプレイの下に隠れています。


モニター側は充電式のエボルタ1本です。DC-DCコンバータで3.3Vに昇圧しています。初めてDCコンバーターを使いました XBeeの50mAぐらいが大きいですが全体で100mAもいっていないと思います。


これでうさちゃんがトイレに入ったら音(電子ブザー)と光(LED)でお知らせしてくれます。ウホッ!嬉しい~w
この秋月で買った電子ブザーは3.3Vでも大きな音が鳴るのが良いですね


センサー側の回路図です。


モニター側の回路図です。


プロジェクトファイルです。
デザイナ: 5.0 SP6
デバイス: CY8C27143 5V,3.3V
コンパイラ:ImageCraft
PSoC_RabbitSensor.zip

Interfacing to a Graphics LCD from PSoC - AN2147

2011年01月14日 | PSoC
年の初めはLCDネタで...というわけではありませんが、PSoCのTwitterで見つけたSG12864Aのアプリケーションノートです。
コントローラーが KS0108 用ですが(SG12864AはKS0107)ほとんど一緒かと思います。

■Interfacing to a Graphics LCD from PSoC - AN2147
http://www.cypress.com/?rID=2626


1年を振り返って

2010年12月31日 | その他
気が付けば2010年もあと僅か。ヤバイヤバイ。
ほんと、早いなぁ~

今年は、やっぱりMake:が大きかったかな。
当初は出展を考えていなかったけど、なんとなくノリと勢いで出てしまった。
今は反省している。半分ぐらいw

Make:以外は、何やったっけ?というぐらい記憶がない。何もやってない気がする。
少し電子工作の熱が冷めたのも影響ありとは思うけど。
とにかくハンダ付けをしていない。ほとんどしてない。ほぼブレッドボード。
これはいかんよなぁ...

うん、来年はなるべくハンダ付けするようにしよう







PSoCでキャラクタLCDでカスタム文字を表示[SC1602B]

2010年12月01日 | PSoC
よくあるキャラクタLCD(SC1602Bシリーズ等のインターフェースICにHD44780を使っている物)には8個のCGRAM領域があります。そこにパターンを書き込んでやれば、独自のフォントを表示できます。
これをPSoCのLCDモジュールを使ってやってみました。
(LCDモジュールのバー表示も同じ処理でやっていると思います。)

...まぁ、これもネットでは散々出ているネタなので説明はググってください



シンプルなCGRAM用(5x8ドット)フォント作成ツールです。C言語のソース形式で出力できます。
LCD_MakeFont.zip

プロジェクトファイルです。
デザイナ: 5.0 SP6
デバイス: CY8C29466 5V
コンパイラ:ImageCraft
PSoC_LCD_CGRAM.zip

グラフィックLCD[SG12864A]について

2010年11月18日 | 電子工作
最近、あまり作っていないのでグラフィックLCD(SUNLIKE社 SG12864A)についてまとめておきます。

SG12864Aは、横128ドット、縦64ドットを表せるグラフィックLCDです。
色数は残念ながらモノクロですが、8bitマイコンで扱いやすいと言えます。
このLCDは検索すると沢山使い方がヒットするので、要点だけにします。
CS1やE、DB0等の接続端子についてはググってください。
制御コマンド等についてはこちらを見てください。

いつものようにおかしなところがあったら、各自脳内で補完してください。

【SG12864A仕様】
動作電圧: 5.0V
コントローラー: KS0107
I/F: 8bitパラレル
色数: モノクロ
解像度: 128x64

【SG12864AのVRAM構造】

※図は電子工作の実験室さんからお借りしました。(加筆修正済み)

128x64ドットと言っても、64x64ドット表示部を2つ並べています。
左右それぞれのアクセス対象をCS1、CS2で切り替えます。
縦8ドット分をPageという単位で表し、横64ドット分をColumnで表します。
従って、フォント等のイメージデータは縦8ドット分にスライスした形式で持つとアクセスが楽になります。

このへんは、電子工作の実験室さんの説明がわかりやすいので引用します。
---------------------------------------------------------------------------
このグラフィックLCDは図のように左右2つの64×64ドットの表示部として構成されています。
いずれも全く同じ機能を持っていて、CS1とCS2で選択することで別々に制御する必要があります。
それぞれの座標は下図のようになっていて、左上が原点(0, 0)で、右下端が(63, 63)と2つの表示部が独立した座標になっています。
上から8LineずつまとめてPageと呼び、Pageの内部は横方向に64本ので構成されていて、この1本の縦方向の8Line分が1バイトのデータとして制御されます。
注意が必要なのは、1バイトの上側がデータビットの0ビット目となっていることです。
場所の指定方法はCS1かCS2で左右のどちらかを選択し、さらにPageとColum Addressで特定のバイトを指定します。
---------------------------------------------------------------------------


【SG12864Aの初期化】
1.左右のLCDをONにする[setDisplay()]
2.表示開始ラインを0にする[setStartline( 0 )]

void setDisplay( void )
{
  set_E( 0 ); .....E pinをLowにする
  set_RW( 0 ); .....R/W pinをLowにする
  set_DI( 0 ); .....D/I pinをLowにする
  set_CS1( 1 );.....CS1 pinをHighにする
  set_CS2( 1 );.....CS2 pinをHighにする
  PORT_DB = 0x3F;....DB0~DB7に0x3Fを出力する(LCD ON)
  set_E( 1 ); .....E pinをHighにする
  set_E( 0 ); .....E pinをLowにする
}

void setStartline( unsigned char ln )
{
  set_E( 0 ); ......E pinをLowにする
  set_RW( 0 ); ......R/W pinをLowにする
  set_DI( 0 ); ......D/I pinをLowにする
  set_CS1( 1 );......CS1 pinをHighにする
  set_CS2( 1 );......CS2 pinをHighにする
  PORT_DB = 0xC0+(ln&0x3F);DB0~DB7に開始ラインを出力する
  set_E( 1 ); ......E pinをHighにする
  set_E( 0 ); ......E pinをLowにする
}

【VRAMにデータを書き込む】
1.書き込むLCDを指定する[setCS1()、setCS2()]
2.Pageで縦位置を指定する[setPage( page )]
 ※Pageは一度設定すると、再度設定しなおすまで値が保持されます。
3.Columnで横位置を指定する[setColumn( colm )]
 ※Columnは設定すると、データを書き込み毎に自動的に+1されます。
4.データを書き込む[writeData( dat )]
 ※書き込む単位は1バイト(8bit)単位となります。

// global
unsigned char cs1 = 0;
unsigned char cs2 = 0;

void setCS1( unsigned char fg )
{
  if( fg == 0 ){
    cs1 = 0;
  }else{
    cs1 = 1;
  }
}

void setCS2( unsigned char fg )
{
  if( fg == 0 ){
    cs2 = 0;
  }else{
    cs2 = 1;
  }
}

void setPage( unsigned char pg )
{
  set_E( 0 ); ......E pinをLowにする
  set_RW( 0 ); ......R/W pinをLowにする
  set_DI( 0 ); ......D/I pinをLowにする
  set_CS1( cs1 );.....cs1が1なら左側を設定
  set_CS2( cs2 );.....cs2が1なら右側を設定
  PORT_DB = 0xB8+(pg&0x07);DB0~DB7に縦(Page)位置を出力する
  set_E( 1 ); ......E pinをHighにする
  set_E( 0 ); ......E pinをLowにする
}

void setColmn( unsigned char cl )
{
  set_E( 0 ); ......E pinをLowにする
  set_RW( 0 ); ......R/W pinをLowにする
  set_DI( 0 ); ......D/I pinをLowにする
  set_CS1( cs1 );.....cs1が1なら左側を設定
  set_CS2( cs2 );.....cs2が1なら右側を設定
  PORT_DB = 0x40+(cl&0x07);DB0~DB7に横(Column)位置を出力する
  set_E( 1 ); ......E pinをHighにする
  set_E( 0 ); ......E pinをLowにする
}

void writeData( unsigned char val )
{
  set_E( 0 ); ......E pinをLowにする
  set_RW( 0 ); ......R/W pinをLowにする
  set_DI( 1 ); ......D/I pinをHighにする
  set_CS1( cs1 );.....cs1が1なら左側に書き込み
  set_CS2( cs2 );.....cs2が1なら右側に書き込み
  PORT_DB = val; .....DB0~DB7にデータを出力する
  set_E( 1 ); ......E pinをHighにする
  set_E( 0 ); ......E pinをLowにする
}

例えば、以下のようにすると画面左上に3本線が表示されます。
unsigned char x;
setCS1( 1 ); setCS2( 0 );
setPage( 0 );
setColumn( 0 ); // Xアドレス(Column)の自動+1を利用する
for( x = 0; x <64; x++ ){ 
  writeData( 0x2A );
}

表示エリアを拡大すると、以下のようになります。
(0,0)        (63,0)
□□□□□ □□□
■■■■■ ■■■
□□□□□ □□□
■■■■■~■■■
□□□□□ □□□
■■■■■ ■■■
□□□□□ □□□
□□□□□ □□□

また、画面クリアは以下のようにCS1とCS2を両方ONにして一度に書き込みます。
unsigned char x, y;
setCS1( 1 ); setCS2( 1 ); ※両画面同時に書き換える
for( y = 0; y <8; y++ ){ 
  setPage( y );
  setColumn( 0 );
  for( x = 0; x <64; x++ ){
    writeData( 0 );
  }
}

【VRAMのデータを読み込む】
1.書き込むLCDを指定する[setCS1()、setCS2()]
2.Pageで縦位置を指定する[setPage( page )]
3.Columnで横位置を指定する[setColumn( colm )]
4.データを読み込む[readData()]
 ※読み込みはダミー読み込みと確定読み込みの2回行う必要があります。
 ※読み込む単位は1バイト(8bit)単位となります。

unsigned char readData()
{
  unsigned char val;

  // ダミー読み込み
  set_E( 0 ); ......E pinをLowにする
  set_RW( 1 ); ......R/W pinをHighにする
  set_DI( 1 ); ......D/I pinをHighにする
  set_CS1( cs1 );.....cs1が1なら左側を読み込み
  set_CS2( cs2 );.....cs2が1なら右側を読み込み
  set_E( 1 ); ......E pinをHighにする
  val = PORT_DB; .....DB0~DB7からデータを受け取る
  set_E( 0 ); ......E pinをLowにする

  // 確定読み込み
  set_E( 0 ); ......E pinをLowにする
  set_RW( 1 ); ......R/W pinをHighにする
  set_DI( 1 ); ......D/I pinをHighにする
  set_CS1( cs1 );.....cs1が1なら左側を読み込み
  set_CS2( cs2 );.....cs2が1なら右側を読み込み
  set_E( 1 ); ......E pinをHighにする
  val = PORT_DB; .....DB0~DB7からデータを受け取る
  set_E( 0 ); ......E pinをLowにする

  return val;
}

※PSoCの場合、PORTのDRIVE設定(PRTxDM0、PRTxDM1、PRTxDM2)を読み込み前にHigh-Z、読み込み後にStrongにする必要があります。


【VRAMの指定位置にドットを書く】
void setPixel( int x, int y )
{
  unsigned char tpg; // page
  unsigned char tcol; // colmn
  BOOL tcs1; // cs1
  BOOL tcs2; // cs2
  unsigned char tx, ty;
  unsigned char bitpos;
  unsigned char val;
  unsigned char sb;
  unsigned char setbit[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };

  tx = x;
  ty = y;

  if( tx <64 ){
    tcs1 = TRUE; tcs2 = FALSE; // 左側LCDにアクセス
  }else{
    tcs1 = FALSE; tcs2 = TRUE; // 右側LCDにアクセス
    tx = tx-64; // tx = 0...63に収める
  }
  tx &= 0x3f; // X = 0...63に収める
  ty &= 0x3f; // Y = 0...63に収める

  tpg = ty/8; // Pageアドレスは y座標÷8
  tcol = tx;
  bitpos = ty%8;
  sb = setbit[bitpos]; // 書き込む値

  setCS1( tcs1 );
  setCS2( tcs2 );
  setPage( tpg );
  setColumn( tcol );
  val = readData();        // ドットデータ読み込み(縦8ドット単位)
  val |= sb;           // ドットを打つ

                   // ページアドレスは同じなので設定する必要はない
  setColumn( tcol ); // Xアドレスは増加するので再設定が必要
  writeData( v );         // データ書き込み
}

【キャラクタ文字を描画する】
扱いを簡単にするため、ここでは8x8ドットを基本としたキャラクタ座標で文字(8x8ドットを表示するようにします。
キャラクタ座標になると、横位置は0~15、縦位置は0~7で指定する事になります。つまり、横16文字縦8文字表示のキャラクタLCDになります。

まずフォントデータを作成します。フォントデータは横8ドット、縦8ドットで構成されているものとします。
このツールを使うとC言語のソース形式で出力できます。
SG12864A_MakeFont

#include "font8x8_YX.h" ...出力されたフォントデータの配列(font8x8_YX[])
void dispChrText( int col, int row, unsigned char code )
{
  int i;
  unsigned char v;
  int ofs = code << 3; ....フォント位置を算出。1文字8バイトのため8倍する
  int x = col << 3;   ....キャラクタ座標をドット座標に直す
  int y = row & 0x07;
  if( x > 63 ){ ........X座標が64以上の場合は右側LCDを有効にする
    x = x-64;
    setCS1( 0 );
    setCS2( 1 );
  }else{
    setCS1( 1 );
    setCS2( 0 );
  }
  setPage( y );
  setColumn( x );

  for( i = 0; i <8; i++ ){
    v = font8x8_YX[ofs+i]; .......フォントを描画
    writeData( v );
  }
}

上の関数は、(col,row)の位置に指定の文字コード(code)を表示します。
引数のとる値は、colは0~15、rowは0~7、codeは0~255となります。
例えば左上の位置に'A'を表示するには以下のようにします。
dispChrText( 0, 0, 'A' );
または
dispChrText( 0, 0, 0x41 );
同じ位置に違う文字を描画すると前の文字は消されます。(上書き)

任意の位置に文字を表示するには以下のようにします。
void dispChr( int sx, int sy, unsigned char code )
{
  int i, j;
  unsigned char v;
  int ofs = code << 3;
  for( i = 0; i <8; i++ ){
    v = font8x8_YX[ofs+i];
    for( j = 0; j <8; j++ ){
      if( (v&0x01) != 0 ){
        setPixel( sx+i, sy+j );
      }
      v = v >> 1;
    }
  }
}
表示位置のsxは0~127、syは0~63で指定できますが描画速度は遅いです。(setPixel関数を使わないようにすれば速く描画できますがコードが複雑になります)
状況によって使い分ける必要がありそうです。


【まとめ】
1.フォント等のイメージデータは縦方向でデータを持つ
2.Pageの値保持、Colmnの自動インクリメント機能をうまく使う。
  特に自動インクリメントはデータのブロック転送に向いています。
3.文字やイメージをキャラクタ座標(8ドット単位)で描画する(重ね合わせ無し)と速い
4.ドットの読み込みは2回必要のため処理が重くなる
5.一度(1フレーム毎)に多くのVRAMを読み書きする場合はメインメモリ上にバッファを持って一括(ブロック)転送した方が速い


【参考】
電子工作の実験室
 →グラフィック液晶表示器用ライブラリ


灰皿ランプ その2

2010年11月14日 | 電子工作
以前、灰皿ランプを作成しました。今でも使っています

今度は嫁の車(軽)用に作ることになりました。
今までは100均のクリップLEDライトを使ってましたが、電池が切れたのとクリップが使いにくいってのがあって、自作することになりました。



前回は単5x2でしたが、今回はコイン電池(CR2032)にしました。
ケースの70%は空白なので単4でもいいんじゃないかと思いましたがwww

LEDはフルカラーイルミネーションLEDにしてみました。以前作ったアクリル板LEDで使った残りです。アクリル板では複数同時に使ったため固体差調整に苦労しましたが、今回は1つなので何でもOK。

できたので早速嫁に見せると、イルミネーションについてブツブツ言われた
とりあえず色がいろいろ変わる方が見やすいとかなんとか言っておさめました。