« 2012年6月 | トップページ | 2012年8月 »

2012年7月

2012年7月22日 (日)

PICのお勉強(33) C言語編 LM35DZの出力をオペアンプで5倍にしてみる

Lm358n PIC16F88+温度センサLM35DZの温度計の話の続きです。
 気温が28.6℃だとLM35DZの出力が286mVなのですが,AD変換の分解能が約5mVですから,温度の分解能も0.5℃になってしまいます。これではつまらないので,0.1℃単位で温度表示できるように,温度センサの出力をオペアンプで5倍に増幅してやりました。
Lm358 LM358Nという1個20円のオペアンプを使いました。ソースは,前回のやつの
tmp=adconv()*4.53; ってとこを
tmp=adconv(); と変えただけです。
10kVRで,表示温度の微調整ができます。これは結構実用的なものができたかも(^-^)

| | コメント (0) | トラックバック (0)

2012年7月21日 (土)

PICのお勉強(32) C言語編 LM35DZで測った温度を7セグLEDに表示する

Lm35dz7seg 温度センサLM35DZの出力をPIC16F88でAD変換して,3桁の7セグLEDに表示してみました。
この7セグLEDは,ダイナミックドライブ用に内部で配線されてて11ピンのものです。こりゃ便利ですね。
ソースはこれ→lesson32.c

 7セグLEDへの表示は,TMR0割り込みで実行していますが,小数点をつけるのに少々苦労しました。
結局,小数点つきの0~9の表示用数字データを作って配列に入れておき,これを使うことにしました。PORTB=p[tmp1+10]なんてあたりに苦労のあとが忍ばれますなあ(笑)
7seg3 気温が28.5℃だと,AD変換の結果,tmpという変数に285という値が入りますから,これを100で割ってから,さらに10で割ったときの余りを求めて「2」という数字を得て,tmpを10で割ってからさらに10で割ったときの余りを求めて「8」という数字を得ます。最後にtmpを10で割ったときの余りを求めて「5」という数字を得ます。これで3桁ぶんの数字が得られるのです。LCDの場合と違ってめんどくさいですねー。

/**************************************
16F88 HI-TECH C v.9.83
温度計 LM35DZをRA0(AN0)に接続 7segLED表示
**************************************/

#define _LEGACY_HEADERS
#include "pic.h"
#include "stdlib.h"
#define _XTAL_FREQ 8000000
__CONFIG(DEBUGDIS & LVPDIS & BORDIS & MCLRDIS & PWRTEN & WDTDIS & INTIO);
__CONFIG(FCMDIS & IESODIS);

unsigned int adconv(),tmp,tmp0,tmp1,tmp2;
unsigned char i=0;
unsigned int p[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F, //0,1,2,3,4,5,6,7,8,9
0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0xa7,0xff,0xef}; //0.,1.,2.,3.,4.,5.,6.,7.,8.,9.

static void interrupt warikomi(void)//割り込み処理で7セグLED表示
{
TMR0IF = 0; //TMR0割り込み禁止
i++;
if(i==3){
i=0;
}

switch(i){
case 0:
PORTA=0b00011000;
PORTB=p[tmp0];
break;
case 1:
PORTA=0b00010100;
PORTB=p[tmp1+10];
break;
case 2:
PORTA=0b00001100;
PORTB=p[tmp2];
break;
}
}

void main()
{
OSCCON = 0b0111000; // 内蔵OSC 8MHz
ADCS2 = 0; //AD変換クロック値設定
ADCS1 = 0;
ADCS0 = 1;
ADFM = 1; // AD変換結果は右詰めで格納
VCFG1 = 0; // 基準電圧はVddとVss
VCFG0 = 0;
ANSEL = 0b00000001; // RA0(AN0)はアナログ
TRISA = 0b00000001; // RA0(AN0)入力
TRISB = 0b00000000; // すべて出力
PORTA = 0b00011100;
PORTB = 0b00000000;

OPTION = 0x00;
TMR0 = 0x00; //TMR0は0からスタート
TMR0IE = 1; //TMR0割り込み許可
GIE = 1; //すべての割り込み許可

while (1)
{
tmp=adconv()*4.53;
tmp2=(tmp/100)%10;
tmp1=(tmp/10)%10;
tmp0=tmp%10;
__delay_ms(100); //100msの時間待ち
}
}

unsigned int adconv()
{
CHS2 = 0; //AD変換ポート設定 RA0(AN0)
CHS1 = 0;
CHS0 = 0;
ADON = 1; //AD変換ON
__delay_us(20); //アクィジション時間 20us
GODONE = 1; //AD変換開始
while(GODONE); //変換完了待ち
return (ADRESH<<8) + ADRESL;
}


 

| | コメント (0) | トラックバック (0)

2012年7月14日 (土)

PICのお勉強(31) C言語編 LM35DZで温度計

Lm35dz 温度センサLM35DZを使って温度計にしてみました。
 LM35DZは,0℃~100℃を0mV~1000mVでリニアに出力してくれますから,PICに直接つないで簡単に温度表示させることができます。
基準電圧はVddの5Vを使っていますから,分解能は約4.88mVです。A/D変換された値に4.88を掛ければ,温度センサが出力する電圧がmVの単位で得られますから,整数部分と小数部分に分けてLCDに送れば温度表示ができるわけです。こりゃ楽しいですなあ
ソースはこれ→lesson31.c

/************************************
16F88 HI-TECH C v.9.83
温度計 LM35DZをRA0(AN0)に接続 LCD表示
************************************/

#define _LEGACY_HEADERS
#include "pic.h"
#include "stdlib.h"
#include "lcd.h"
#define _XTAL_FREQ 4000000
__CONFIG(DEBUGDIS & LVPDIS & BORDIS & MCLRDIS & PWRTEN & WDTDIS & INTIO);
__CONFIG(FCMDIS & IESODIS);

unsigned int adconv(),tmp,tmp1,tmp2;
char str[7],str1[7],str2[7];

void main()
{
OSCCON = 0b0110000; // 内蔵OSC 4MHz
ADCS2 = 0; //AD変換クロック値設定
ADCS1 = 0;
ADCS0 = 1;
ADFM = 1; // AD変換結果は右詰めで格納
VCFG1 = 0; // 基準電圧はVddとVss
VCFG0 = 0;
ANSEL = 0b00000001; // RA0(AN0)はアナログ
TRISA = 0b00000001; // RA0(AN0)入力
TRISB = 0b00000000; // すべて出力
PORTA = 0b00000000;
PORTB = 0b00000000;

lcd_init(); //SD1602の初期化
while (1)
{
tmp =adconv()*4.88;
tmp1=tmp/10;
tmp2=tmp-tmp1*10;
itoa(str1,tmp1,10);
itoa(str2,tmp2,10);

lcd_goto(0); //カーソルを0行目の先頭に移動する
lcd_puts("キオン ");
lcd_puts(str1);
lcd_puts(".");
lcd_puts(str2);
lcd_putch(0xDF);
lcd_puts("C");
__delay_ms(100); //100msの時間待ち
}
}

unsigned int adconv()
{
CHS2 = 0; //AD変換ポート設定 RA0(AN0)
CHS1 = 0;
CHS0 = 0;
ADON = 1; //AD変換ON
__delay_us(20); //アクィジション時間 20us
GODONE = 1; //AD変換開始
while(GODONE); //変換完了待ち
return (ADRESH<<8) + ADRESL;
}

| | コメント (0) | トラックバック (0)

2012年7月 9日 (月)

PICのお勉強(30) C言語編 AD変換の結果をLCDに表示する

Adsd16024bit_mode 前回の回路にLCDをつけて,A/D変換して得られた10bitの数値データを表示してみました。
 基準電圧が5Vだから1023が5Vにあたり,分解能は約5mVってことになりますね。そこで,データを5倍してmVの単位でLCDに表示しようと思います。要するにこれは電圧計ですな。
ソースはこれ→lesson30.c
 数値データをどうやったらLCDに表示できるのか悩みましたが,itoa(Integer to Asciiって意味?)という便利な関数があるんですな。コレで文字列にしといてLCDに送ればいいみたい。あ,あとlcd.cの「TRISA=0;」をコメントアウトしないといけません。「TRISA = 0b00000001;」としといてもいいけど。
 やってみると,ちゃんと表示されるじゃないですか。アタリマエかもしれないけど嬉しいですなあ。
Lesson30 LCDは,10msごとに表示を書き換えてるので,ちょっとチラチラするんだけど,これはなんか良い方法があるのかなあ? また調べときます(^^;)
 あと,LCDのコントラスト調整についてですが,SD1602の3ピン(VO)にダイオードを1本つけておくだけで,電源電圧が多少変わっても自動的に適正コントラストになるようです。VO端子は0.5V程度の電位にしておけば,適正コントラストになるらしいのですが,ダイオードを使えば約0.6Vになりますものね。ここに書いてありました。素晴らしいアイデアです。

/************************************
16F88 HI-TECH C v.9.83
RA0(AN0)の入力電圧をA/D変換してLCDに表示する
************************************/

#define _LEGACY_HEADERS
#include "pic.h"
#include "stdlib.h"
#include "lcd.h"
#define _XTAL_FREQ 4000000
__CONFIG(CCPRB3 & DEBUGDIS & LVPDIS & BOREN & MCLRDIS & PWRTEN & WDTDIS & INTIO);

unsigned int adconv();
unsigned int tmp;
unsigned int i;
char str[7];

void main()
{
OSCCON = 0b0110000; // 内蔵OSC 4MHz
ADCS2 = 0;     //AD変換クロック値設定
ADCS1 = 0;
ADCS0 = 1;
ADFM = 1; // AD変換結果は右詰めで格納
VCFG1 = 0; // 基準電圧はVddとVss
VCFG0 = 0;
ANSEL = 0b00000001; // RA0(AN0)はアナログ
TRISA = 0b00000001; // RA0(AN0)入力
TRISB = 0b00000000; // すべて出力
PORTA = 0b00000000;
PORTB = 0b00000000;

 lcd_init(); //SD1602の初期化
while (1)
{
tmp = adconv()*5;
itoa(str,tmp,10);

lcd_clear(); //表示クリア
lcd_goto(0); //カーソルを0行目の先頭に移動する
lcd_puts(str);
lcd_puts("mV");
__delay_ms(10); //10msの時間待ち

}
}

unsigned int adconv()
{
CHS2 = 0; //AD変換ポート設定 RA0(AN0)
CHS1 = 0;
CHS0 = 0;
ADON = 1; //AD変換ON
__delay_us(20); //アクイジション時間 20us
GODONE = 1; //AD変換開始
while(GODONE); //変換完了待ち
return (ADRESH<<8) + ADRESL;
}


| | コメント (1) | トラックバック (0)

2012年7月 8日 (日)

PICのお勉強(29) C言語編 16F88でA/D変換

16f88_ad A/D変換をやってみたくて,PICを16F88に変えました。16F84Aとピン配置が同じだからありがたいですね。
 ここの例を参考に,「RA0(AN0)の入力電圧をA/D変換して,RB3につないだLEDの点滅周期を変える」ってのをやってみました。
ソースはこれ→lesson29.c
 やってることは大したことないかもしれないけど,なんだか大きな前進をしたような気がするぞ
 設定すべき項目がたくさんあって大変ですが,16F88の各種機能を設定する特殊レジスタについてはここが大いに参考になります。感謝です。

/************************************
16F88 HI-TECH C v.9.83
RA0(AN0)の入力電圧をA/D変換してLED点滅周期変える
************************************/

#define _LEGACY_HEADERS
#include "pic.h"
#include "stdlib.h"
#define _XTAL_FREQ 4000000
__CONFIG(CCPRB3 & DEBUGDIS & LVPDIS & BOREN & MCLRDIS & PWRTEN & WDTDIS & INTIO);

unsigned int adconv();
unsigned int tmp;
unsigned int i;
char str[7];

void main()
{
OSCCON = 0b0110000; // 内蔵OSC 4MHz
ADCS2 = 0; //AD変換クロック値設定
ADCS1 = 0;
ADCS0 = 1;
ADFM = 1; // AD変換結果は右詰めで格納
VCFG1 = 0; // 基準電圧はVddとVss
VCFG0 = 0;
ANSEL = 0b00000001; // RA0(AN0)はアナログ
TRISA = 0b00000001; // RA0(AN0)入力
TRISB = 0b00000000; // すべて出力
PORTA = 0b00000000;
PORTB = 0b00000000;

while (1)
{
tmp = adconv();
RB3 = 1;
for(i = 0; i<tmp; i++){};
__delay_ms(2);
RB3 = 0;
for(i = 0; i<tmp; i++){};
__delay_ms(2);
}
}

unsigned int adconv()
{
CHS2 = 0; //AD変換ポート設定 RA0(AN0)
CHS1 = 0;
CHS0 = 0;
ADON = 1; //AD変換ON
__delay_us(20); //アクィジョン時間 20us
GODONE = 1; //AD変換開始
while(GODONE); //変換完了待ち
return (ADRESH<<8) + ADRESL;
}

| | コメント (0) | トラックバック (0)

2012年7月 7日 (土)

PICのお勉強(28) C言語編 SD1602を4bitモードで使ってみる

Sd1602_4bit_mode HI-TECH Cのsampleってフォルダを見てたら,LCDemoというフォルダがあって,そこに液晶ディプレイSD1602でも使えそうなヘッダファイルlcd.hとC言語のソースファイルlcd.cとmain.cってのがあることに気づきました。(気づくのが遅い?)
 「これを使えば4bitモードでSD1602を動かせるんじゃね?」と思って,lcd.cのコメントに書いてある通りに配線してみました。セラロックもlcd.cに書いてあるとおり4MHzに変更しました。
 Lesson28 前回作ったlesson27.cを元に,lcd.hを#includeするようにしたり,LCDの表示クリアとかデータ表示とかを書き換えたりしたlesson28.cとlcd.cをMPLABのSource Filesに読み込んでコンパイルしてみました。
 ちょいとエラーが出たので,「PORTD」を「PORTB」に変えて,「ADCON1 = 0x06;」ってのをコメントアウトして再コンパイルしたら,今度はうまく通りました。
 PIC16F84Aに書き込んで動かしてみたところ,ちゃんと動くではありませんか
 ただ,「Hello,world!」のあとにカーソルが出てきてブリンクしてるのが気に入らないので,ちょいとネットで調べてlcd.cの終わりの方に書いてある「lcd_write(0xF)」ってのを「lcd_write(0x0C」に書き換えてやりました。これで,前回と同じ表示になりました。
僕が書き換えたlcd.cはこちらです→ lcd.c

/************************************
16F84A HI-TECH C v.9.83
4bitモードでLCD SD1602のテスト
RB0~RB3 → LCD DB4~DB7 に接続
RA1 → LCD EN に接続
RA2 → LCD RW に接続
RA3 → LCD RS に接続
************************************/
#define _LEGACY_HEADERS
#include "PIC.h"
#include "lcd.h"
#define _XTAL_FREQ 4000000 //4MHz

__CONFIG(HS & WDTDIS & PWRTDIS & UNPROTECT);

void main(void)
{
char s[] = "Hello, world!";

TRISA = 0x00; // 出力端子: RA0~RA4
PORTA = 0x00;
TRISB = 0x00; // 出力端子: RB0~RB7
PORTB = 0x00;

lcd_init(); //SD1602の初期化
while (1)
{
lcd_clear(); //表示クリア
lcd_goto(0); //カーソルを0行目の先頭に移動する
lcd_puts(s); //テキストデータを表示する
__delay_ms(1000); //1000msの時間待ち

lcd_clear(); //表示クリア
lcd_goto(0x40); //カーソルを1行目の先頭に移動する
lcd_puts(s); //テキストデータを表示する
__delay_ms(1000); // 1000msの時間待ち
}
}

前と同じだから,動画は省略。

| | コメント (0) | トラックバック (0)

« 2012年6月 | トップページ | 2012年8月 »