Pages: [1]   Go Down
Print
Author Topic: ถามเรื่อง PIC16F877 ใช้SHT11 และ เซนเชอร์แก๊ส MQ2หน่อยค&#  (Read 16684 times)
0 Members and 4 Guests are viewing this topic.
exitpomai
Jr. Member
**
Offline Offline

Posts: 16


Email
« on: February 14, 2011, 01:27:50 PM »

พอดีต้องเขียนโปรแกรมวัดอุณภูมิกับความชื้น และรับค่าanalogจากขาRA1ของ 16F877
แล้วคอมไพไม่ผ่านครับ มันบอก undefined identifier Read_ADC

ตามรูปเลยครับ

แต่แต่เขียนโปรแกรม เซนเซอร์แก๊สอย่างเดียวก็ทำงานได้ปกติครับ
Code:
//SHT1x Sensor temperature & Humidity
//Read sensor and diaplay to RS232
//Compiler CCS Version 3.249

#case
#include <16F877.h>
#use delay(clock=4000000)

//#device ADC=10
#fuses HS
#fuses XT,PUT,BROWNOUT,NOWDT,NOPROTECT,NOLVP
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7)
#include <math.h>
#use fast_io(A)

#device ADC=10


#define Vbe 0.0048875855327468230694037145650049
#define RA1_ANNALOG

#define SHT1xDATA  PIN_B4
#define SHT1xSCK   PIN_B5
#define noACK 0
#define ACK   1

// SHT1x address=000 is currently supported
// SHT1x command code
                            //adr  command  r/w
#define STATUS_REG_W 0x06   //000   0011    0
#define STATUS_REG_R 0x07   //000   0011    1
#define MEASURE_TEMP 0x03   //000   0001    1
#define MEASURE_HUMI 0x05   //000   0010    1
#define RESET        0x1E   //000   1111    0

// constant use for SHT1x Humidity Measurement
#define C1  -4.0
#define C2  0.0405
#define C3  -0.0000028

// constant use for SHT1x Temperature Measurement
#define D1  -40.0
#define D2  0.01

// constant use for SHT1x True Humidity Measurement
#define T1  0.01
#define T2  0.00008

//PIC16F6X8
#define  CMCON   0x1F
#define  PORTA 0x05
#define  PORTB 0x06


void InitialChip(void);

//SHT1x Transmission Start condition
void SHTStart()
{
   output_high(SHT1xDATA);
   output_low(SHT1xSCK);
   output_high(SHT1xSCK);
   output_low(SHT1xDATA);
   output_low(SHT1xSCK);
   output_high(SHT1xSCK);
   output_high(SHT1xDATA);
   output_low(SHT1xSCK);

}

// SHT1x Connection Reset:
void SHTConReset()
{
int i;

   output_high(SHT1xDATA);

   for (i=0; i<9; i++)
   {
      output_high(SHT1xSCK);
      delay_us(2);
      output_low(SHT1xSCK);
      delay_us(2);
   }
   SHTStart();
}

// SHT1x Address & Command Mode with address=000
int SHTWrite(int Data)
{
int i;

   for (i=0x80;i>0;i/=2)        //shift bit for masking data
   {
    if(i&Data)
     output_high(SHT1xDATA);
    else  
     output_low(SHT1xDATA);

     delay_us(2);               //Snend Clock each bit
     output_high(SHT1xSCK);
     delay_us(2);
     output_low(SHT1xSCK);
   }

   output_float(SHT1xDATA);     //Change DATA Line to Input
   delay_us(2);

   output_high(SHT1xSCK);       //Clock for Acknowledge
   delay_us(2);

   i= input(SHT1xDATA);         //Get Acknowledge

   output_low(SHT1xSCK);
   delay_ms(250);
   return (i);
}

//Read data from SHT1x
long SHTRead(void)
{
int i;
long lTmp,lVal1,lVal2,lValue;

   lVal1=0;
   lVal2=0;

//get MSB from SHT1x
   for (i=0; i<8; i++)
   {
    lVal1<<=1;
    output_high(SHT1xSCK);          //Send Clock Hight
    lTmp = input(SHT1xDATA);        //Read Data Bit
    //delay_us(2);
    output_low(SHT1xSCK);           //Send Clock Low
    //delay_us(2);

    if(lTmp)
     lVal1|=1;                      //store in lVal1
   }

//Acknowledge routine for Next byte
   output_low(SHT1xDATA);
   output_high(SHT1xSCK);
   //delay_us(2);

   output_float(SHT1xDATA);         //Change to Input
   output_low(SHT1xSCK);
   //delay_us(2);

//get LSB from SHT1x
   for (i=0; i<8; i++)
   {
    lVal2<<=1;
    output_high(SHT1xSCK);          //Send Clock Hight
    lTmp = input(SHT1xDATA);        //Read Data Bit  
    //delay_us(2);
    output_low(SHT1xSCK);           //Send Clock Low
    //delay_us(2);

    if(lTmp)
      lVal2|=1;                     //store in lVal2
   }
  

   lValue = make16(lVal1,lVal2);    //Makes a 16 bit number out of two 8 bit numbers.
   return(lValue);
}
// SHT1x Soft Reset
// resets the interface, clears the status register to default values
// wait minimum 11ms before next command
void SHTSoftReset()
{
  SHTConReset();
  SHTWrite(RESET);
}

// calculate dewpoint
float sht1x_calc_dewpoint(float fRh,float fTemp)
{
   float fDewpoint;
   float fLogEW;

   fLogEW = ((7.5*fTemp)/(237.3+fTemp))+log10(fRh)-1.33923;
   fDewpoint = ((0.66077-log10(fLogEW))*(237.3))/(log10(fLogEW)-8.16077);
   return(fDewpoint);
}
void InitialChip(void)
{
    //setup_comparator(NC_NC_NC_NC);   //Input Digital
    set_tris_b(0B00000000);
    set_tris_c(0B10000000);
}

// Main Program
main()
{
float fRh_lin;
float fRh_true;
float fTemp_true;
float fDew_point;

long lValue_rh;
long lValue_temp;
int R;
int16 value;
float volt;

setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel(1);




   InitialChip();
   delay_ms(200);

   SHTConReset();

   while (TRUE)
   {
     // delay >11ms before next command
      delay_ms(12);

      SHTStart();                                                        //@1 start transmission
      R=SHTWrite(MEASURE_TEMP);           //@2 measure temperature
      if(R==1)
      {
       printf("Sensor Error\n");
       delay_ms(1000);
       continue;
      }

      lValue_temp = SHTRead();

      // temperature calculation
      fTemp_true = (D1+(D2*lValue_temp));

      // delay 11ms before next command
      delay_ms(12);

      // start transmission
      SHTStart();

      // measure relative humidity
      SHTWrite(MEASURE_HUMI);
      lValue_rh = SHTRead();

      // relative humidity calculation
      fRh_lin = (C1+(C2*lValue_rh)+(C3*lValue_rh*lValue_rh));
      fRh_true = (((fTemp_true-25)*(T1+(T2*lValue_rh)))+fRh_lin);

      // dewpoint calculation
      fDew_point = sht1x_calc_dewpoint(fRh_true,fTemp_true);
      
      //GAS Sensor
      value=Read_ADC();
      volt=Vbe*(float)value;


      printf("T=%3.2f C\r\n",fTemp_true);
      printf("H=%3.2f%%\r\n",fRh_true);
      printf("Dew Point: %3.6fC \r\n\r\n",fDew_point);
      printf("\n\rADC:%ld",value);
      printf("\n\rVoltage:%f\n",volt);
      delay_ms(1000);
   }
}
« Last Edit: February 14, 2011, 01:32:39 PM by exitpomai » Logged
exitpomai
Jr. Member
**
Offline Offline

Posts: 16


Email
« Reply #1 on: February 14, 2011, 01:34:18 PM »

Logged
mcuprojects
Jr. Member
**
Offline Offline

Posts: 18


Email
« Reply #2 on: February 14, 2011, 04:49:11 PM »



ลองคอมเม้นตรง Read_ADC(); ออกครับ แล้ว ลองคอมไพล์ใหม่ครับ
ถ้าคอมไพล์ผ่านแล้ว ไม่ขึ้น ERROR

ให้คลิกที่เมนู เลือก open all files

มันจะโชว์ไฟล์ที่เรียกใช้งานทั้งหมดครับ ซึ่งจะรวมไปด้วยไฟล์ 16F877.h ครับ ให้เราคลิกเข้าไปดูไฟล์ครับ ตรง ADC มันจะมีเขียนบอกคำสั่งไว้ครับ รวมค่าคงที่ต่างๆ

////////////////////////////////////////////////////////////////// ADC
// ADC Functions: SETUP_ADC(), SETUP_ADC_PORTS() (aka SETUP_PORT_A),
//                SET_ADC_CHANNEL(), READ_ADC()
// Constants used for SETUP_ADC() are:
#define ADC_OFF                0          // ADC Off
#define ADC_CLOCK_DIV_2    0x100
#define ADC_CLOCK_DIV_8     0x40
#define ADC_CLOCK_DIV_32    0x80
#define ADC_CLOCK_INTERNAL  0xc0          // Internal 2-6us

ที่ผมเคยเจอนะครับบางทีค่าคงที่ที่มันประกาศไว้ บางเวอร์ชั่นของ CCS มันก้อไม่เหมือนกันครับ
Logged
gundam
Global Moderator
Hero Member
*****
Offline Offline

Posts: 292



« Reply #3 on: February 14, 2011, 08:18:19 PM »

เหตุที่คอมไพล์เลอร์แจ้งว่า undefined identifier Read_ADC
- โปรแกรมใช้ด้านบนใช้ #case หรือเปล่าครับ เพราะจะให้คอมไพล์ให้สนใจตัวเล็ก/ตัวใหญ่
ดังนั้นจึงต้องใช้ read_adc(); (สังเกตุได้ว่า built in function ของคอมไพล์เลอร์ จะไม่ผสมตัวเล็ก/ตัวใหญ่)
- เบอร์ที่ท่านใช้ไม่มี A2D ครับ แต่นี่คุณใช้ 16F877 (มี A2D) แสดงว่าน่าจะเป็นข้อแรกครับ
« Last Edit: February 15, 2011, 10:52:54 AM by gundam » Logged
exitpomai
Jr. Member
**
Offline Offline

Posts: 16


Email
« Reply #4 on: February 14, 2011, 08:19:55 PM »

ทำแบบที่คุณ mcuprojects บอกแล้วครับ

แล้วต้องใช้คำสั่งไหนอะครับถึงจะใช้งานได้
ลองดูหลายคำสั่งแล้วอะครับ ยังไม่ได้เลยครับ

แล้วทำไมถึงใช้ #device ADC=10  ไม่ได้อะครับ
ไม่ขึ้นว่า
Can not change device type this far into code
Logged
gundam
Global Moderator
Hero Member
*****
Offline Offline

Posts: 292



« Reply #5 on: February 14, 2011, 08:24:54 PM »

ลองเปลี่ยนเป็น read_adc(); ตัวเล็กทั้งหมดครับ
Logged
exitpomai
Jr. Member
**
Offline Offline

Posts: 16


Email
« Reply #6 on: February 14, 2011, 08:32:10 PM »

ลองเปลี่ยนเป็น read_adc(); ตัวเล็กทั้งหมดครับ

เปลี่ยนเป็นตัวเล็กแล้วครับ ตอนนี้ได้แล้วครับ
แต่วัดแรงดันไม่ตรงอะครับ ปกติต้องประมาณ 4.98V.
แต่วัดได้สูงสุดแค่ 2V ครับ

แล้วถามอีกนิดนึงครับ
ทำไมถึงใช้ #device ADC=10  ไม่ได้อะครับ
ไม่ขึ้นว่า
Can not change device type this far into code
Logged
exitpomai
Jr. Member
**
Offline Offline

Posts: 16


Email
« Reply #7 on: February 14, 2011, 08:57:16 PM »

พอรู้แล้วครับ

คือตอนนี้ ADC มันทำงานแค่8bit อะครับ
จะทำยังไงให้มันทำงาน 10 bit อะครับ
Logged
MicroX
Global Moderator
Full Member
*****
Offline Offline

Posts: 103


Senior


Email
« Reply #8 on: February 15, 2011, 09:53:15 AM »

ใน code ที่คุณให้มามี #fuses HS เกินมาให้ลบออก
เราใช้ clock 4MHz จึงใช้ #fuses XT

8 บิทหรือ 10 bit เป็นความระเอียดครับ
8  บิทสามารถวัดได้ 0-255
10 บิทสามารถวัดได้ 0-1024

ส่วนความถูกต้อง ตัวเลขจะต้องออกมาใกล้ๆ กันไม่ใช่ห่างกันแบบ 2V กับ 4.98V
การใช้งาน ADC ขนาด10บิท
ให้ใช้คำสัง ADC=10  ไว้หลัง #include <16F877.h>

#case
#include <16F877.h>
#device ADC=10
#use delay(clock=4000000)
#fuses XT,PUT,BROWNOUT,NOWDT,NOPROTECT,NOLVP
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7)

...

ตัวอย่างการใช้งาน ADC ขนาด10บิท

int16 value
...
value = read_adc();
printf("ADC %ld V",value*(5.0/1023));



แก้คำผิดโดย gundam
« Last Edit: February 15, 2011, 04:11:27 PM by gundam » Logged
gundam
Global Moderator
Hero Member
*****
Offline Offline

Posts: 292



« Reply #9 on: February 15, 2011, 10:41:39 AM »

NOTE: ใช้ XTAL กับ #fuse ให้ถูกด้วยครับ

clock 4  MHz ใช้ #fuses XT
clock 20 MHz ใช้ #fuses HS
Logged
exitpomai
Jr. Member
**
Offline Offline

Posts: 16


Email
« Reply #10 on: February 20, 2011, 04:11:58 PM »

ขอบคุณมากครับ
พอดีไม่มีหนังสือที่ใช้ศึกษาอย่างจริงจังเลยครับ
อาศัยอ่านในเน็ตเอาตลอด

พอจะมีหนังสือเล่มไหนแนะนำบ้างครับ
Logged
MicroX
Global Moderator
Full Member
*****
Offline Offline

Posts: 103


Senior


Email
« Reply #11 on: February 21, 2011, 08:05:30 AM »


หนังสือPICWORK EXAMPLE&C SOURCECODE

http://www.es.co.th/detail.asp?Prod=99905845


BOOK ALL ABOUT CCS C COMPILER

http://www.es.co.th/detail.asp?Prod=99922553
Logged
jermjoidpol
มาใหม่
*
Offline Offline

Posts: 1


« Reply #12 on: March 03, 2011, 03:28:25 PM »

ผมใช้ sht 15 กับ c51  DS89C450 แต่ค่าที่ออกมากลับออกมาเป็น 0 ตลอดเลยครับช่วยผมแก้หน่อยนะครับ

/**************************************************************
Project:meteorolrgical wireless monitoring (using SHT15)
filename:Text1.c
compliler: Keil
***************************************************************/


#include<intrins.h>
#include<DS89C4xx.h>
#include<stdio.h>




sbit DATA=P1^0;
sbit SCK=P1^1;

#define ACK 1
#define noACK 0

#define TEMP 0
#define HUMI 1

//adr command

#define MEASURE_TEMP 0x03  // 000   00011
#define MEASURE_HUMI 0x05  // 000   00101



 
//------------------------------------------------------
char write_byte(unsigned char value)
//------------------------------------------------------
  {
     unsigned char i,error=0;
    for(i=0x80;i>0;i/=2)
  {
     if(i& value)DATA=1;
   else DATA=0;
   SCK=1;  //generate clock
   _nop_(); //pulsewidth aaprox. 5us
   _nop_();
   _nop_();
   SCK=0;
  }
   DATA=1; //release DATA-line
   SCK=1;
   error=DATA;   //check ack (DATA will be pulled down by SHT15)
   SCK=0;
   return error; //error=1:no ACK
  }






//------------------------------------------------------
 char read_byte(unsigned char ack)
//-----------------------------------------------------
   {
   unsigned char i,val=0;
   for(i=0x80;i>0;i/=2)
   {
      SCK=1;
      if(DATA) val=(val|i);   //read bit
      SCK=0;
   }
      DATA=!ack; //send ack
      SCK=1; //cl:-)h for ack
      _nop_();
      _nop_();
      _nop_();
      SCK=0;
      DATA=1; //release DATA-line
      return val;
   }



   
//----------------------------------------
  void trans_start(void)
//----------------------------------------
// generate transmission start
   { 
   DATA=1;
   SCK=0; //initial state
    _nop_();
     SCK=1;
     _nop_();
     DATA=0;
     _nop_();
     SCK=0;
     _nop_();
   _nop_();
   _nop_();
     SCK=1;
    _nop_();
    DATA=1;
    _nop_();
     SCK=0;
   }





//---------------------------------------
void connectionreset(void)
//----------------------------------------
//DATA-line=1 , at least 9 SCK
   {
      unsigned char i;
       DATA=1;
       SCK=0;
    for (i=0;i<9;i++)
    {
      SCK=1;
         SCK=0;
    }
    trans_start();
   }





//----------------------------------------------
char measure(unsigned char mode)
//----------------------------------------------
   {
         unsigned char t,error=0;
      unsigned int i,Temp_val,Humi_val;   //send command to sensor
      trans_start();
      if(mode==TEMP)  error+=write_byte(MEASURE_TEMP);
      else if  (mode==HUMI)  error+=write_byte(MEASURE_HUMI);
      for(i=0;i<65535;i++)
        if (DATA==0) break; //wait until sensor has finished the measurement
      if(DATA) error+=1;
      t=read_byte(ACK); // read first byte(MSB)
      i=t;
      i=i<<8;   //shift 8 bit
      t=read_byte(ACK);//read second byte(LSB)
      i=i|t;
      if(mode==TEMP) Temp_val=i;
      else if(mode==HUMI) Humi_val=i;
      return error;
      return(Temp_val);
      return(Humi_val);

}





//------------------------
initial_uart()
//------------------------
//9600 bps @11.059MHz
  {
     SCON0 = 0x52;
    TMOD = 0x20;
    TCON = 0x69;
    TH1 = 0xfd;
    TR1=1;
}



 


//-----------------------------------------------------
 void cal_sht15(float temper,float humid)
//------------------------------------------------------
//calulate temperatue and humidity
 {
    const float c1=-4.0; //for 12 bit
   const float c2=0.0405; //for 12 bit
   const float c3=-0.0000028; //for 12 bit
   const float t1=0.01; //for 14 bit  5v
   const float t2=0.00008; //for 14 bit  5v

   float rh=humid;   // humidity 12 bit
   float t=temper; // temperature 14 bit
   float rh_lin; // humidity linear
   float rh_true;     // temperature compensated humidity
   float Temp;              //temperature


   Temp=(0.01*t)-40;
   rh_lin=c1+(c2*rh)+(c3*rh*rh);
   rh_true=(Temp-25)*(t1+t2*rh)+rh_lin;

   if(rh_true>100) rh_true=100 ;
   if(rh_true<0.05) rh_true=0.05;
   temper=Temp;
   humid=rh_true;

 }


 

//***********************************************************
void main()
//***********************************************************
{
   unsigned char error;
    unsigned int i,Humi_val,Temp_val;
    float Temp_val_f,Humi_val_f;

    initial_uart();  //set serial

while(1)
{
   error=0;
   connectionreset();
   error+=measure(TEMP);
   error+=measure(HUMI);
   if(error!=0) connectionreset();
   else
{
    Temp_val_f=(float)Temp_val;
    Humi_val_f=(float)Humi_val;
   cal_sht15(Temp_val_f,Humi_val_f);
   printf("temp:%3.2fC humi:%3.2f%% \n",Temp_val_f,Humi_val_f);
 
}

  //------wait approx 0.8s to avoid heating up sht-------
 for(i=0;i<40000;i++);
 
   //-----------------------------------------------------
  }
 }


ปล. ช่วยผมทีนะครับลำบากมากเลยครับแก้ไม่ได้ซักที
Logged
Pages: [1]   Go Up
Print
 
Jump to: