Tuto. 4 - I2C temperature

PIC tutorial 4 - I2C temperature

Print
Category: PIC Tutorials
Published Date Written by Francois

Tutorial 4a

Fig. 1a Board 3 with LCD display and I2C temperature sensor 1

Description:

In the 4th tutorial, we'll cover some I2C communication with temperature sensors, and data conversion.
You will need a processor board, a power supply, the LCD display and one of the I2C temperature sensor.

The tutorial will work with an I2C and Temperature sensor libraries. The sensor library will be able to manage either type of sensor (MCP9803 or DS1631)

You can download the files for this tutorial in the zip file pic_tutorial4.zip.

The boards can be powered by one of the PSU boards (powered from USB port), or between 2.7 to 5V.

Requirements:

Processor boardAny board (board 3 in example)

Extension(s)LCD Display

 I2C temperature sensor 1 or 2

Power supplyPSU 1, 2 or 3. Depends on board used.

LanguageCCS C

ProgrammerPicKIT 2


Program:

#define board_id 4 // define processor board used

#define I2C_Temp_Chip 1 // 1 for MCP9803 or 2 for DS1631

#include "I2C_Temp_on_LCD.h" // load header and libraries

signed int16 temp; // varaible to stoer temperature

void main() {
  boot_up();
  init_display(); // initialise LCD display
  init_I2C_temp(); // initialise temperature sensor (resolution...)
  #if (I2C_Temp_Chip == 1 ) // display text depending on sensor used
    printf(display_putc, " Temp MCP9803 ");
  #else
    printf(display_putc, " Temp DS1631");
  #endif
  while (true) { // main looptemp = readt_I2C_temp(); display_gotoxy(0,1); printf(display_putc, "%3.1w", temp); display_print_degree(); display_putc('C'); display_putc(' '); delay_ms(1000); } }
#define board_id 3
#define I2C_Temp_Chip 1 // Set I2C temperature chip to sensor 1 (MCP9803)
#include "lib\mainboard.c"
#include "lib\lcd_lib.c"
#include "lib\i2c_lib.c"
#include "lib\I2C_Temp_lib.c"
signed int16 temp;
void main() {
  boot_up();
  init_display();
  init_I2C_temp();
  while (true) {
    temp = readt_I2C_temp();
    #if (I2C_Temp_Chip == 1 )
      printf(display_putc, "\fTemp MCP9803: %3.1w", temp);
    #else
      printf(display_putc, "\fTemp DS1631: %3.1w", temp);
    #endif
    display_print_degree();
    display_putc('C');
    delay_ms(1000);
  }
}

The program defines the processor board used and the type of I2C temperature sensor used (1 or 2 for MCP9803 or DS1631).  It is defined intially as 1, so we'll use an MCP9803 sensor.

We then loads the header file, which also loads the libraries for the processor, lcd display and I2C sensors.

Once all libraries are loaded, we declare a signed integer to store the temperature in celsius. The processor board, LCD display and temperature sensor are initialised..
The main loop is then entered: we read the temperature from the sensor in celsius, and display it on the LCD display. The temperature is displayed using 3 digits, and 1 decimal. Depending on the sensor type, the message displayed is slightly different. The \f caracter forces the display to blank before displaying the rest.
We finish with the degree sign, a C charater for Celsius and a delay of 1s, before starting the loop again.

This is the header file:

#ifndef _CONFIG_APP_H
  #define CONFIG_APP_H
  // following codes defines the platforms as well as the hardware configuration
  #if ((board_id == 1) | (board_id == 2)) // if using board 1 or 2, use alphanumeric display
    #define DISPLAY_TYPE "Alpha"
  #else // else use the nokia graphic LCD
    #define DISPLAY_TYPE "3310"
  #endif

  #include "../lib/Boards/mainboard.c" // load boards library
  #include "../lib/Display/lcd_display.c" // load LCD display library
  #include "../lib/Sensors/I2C_Temp.c" // Load I2C temperature sensor
#endif

It defines which LCD display to use based on the processor board and loads the required libraries.

Now the I2C temperature sensor library:

#ifndef _I2C_temp_LIB // make sure library is not already loaded
  #define _I2C_temp_LIB
  #include "../lib/Common/I2C.c" // load I2C generic library
  #ifndef I2C_Temp_Chip // set chip used if not defined
    #define I2C_Temp_Chip 1 // 1 for MCP9803, 2 for DS1631
  #endif

  void config_I2C_temp(BYTE data) { // senda byte to config register of sensor
    i2c_start(); // start I2C communication
    #if (I2C_Temp_Chip == 1 ) // point to config register
      i2c_write(I2C_temp); // on sensor 1
      i2c_write(0x01);
    #else
      i2c_write(I2C_temp2); // or sensor 2
      i2c_write(0xac);
    #endif
    i2c_write(data); // and send data
    i2c_stop(); // stop I2C communication
  }

  void init_I2C_temp() { // Initialise the temperature sensor
    #if (I2C_Temp_Chip == 1 ) // Setup DAC to 12 bits
      config_I2C_temp(0x60);
    #else
      config_I2C_temp(0x0c);
      i2c_start(); // and start conversions for DS1631
      i2c_write(I2C_temp2);
      i2c_write(0x51);
      i2c_stop();
    #endif
  }

  WORD read_I2C_temp() { // reads temperature register from sensor
    BYTE temph, templ;
    signed int16 datat;
    i2c_start();
    #if (I2C_Temp_Chip == 1 )
      i2c_write(I2C_temp);
      i2c_write(0x00); // point to temperature register
      i2c_start(); // sends a restart on the I2C bus
      i2c_write(I2C_temp+1); // address sensor in read mode
    #else
      i2c_write(I2C_temp2);
      i2c_write(0xAA); // point to temperature register
      i2c_start(); // sends a restart on the I2C bus
      i2c_write(I2C_temp2+1); // address sensor in read mode
    #endif
    temph=i2c_read(); // reads 2 bytes (msb first)
    templ=i2c_read(0);
    i2c_stop(); // stop I2C communication
    datat=(signed int16) temph; // combine msb and lsb in 16 bits value
    datat = datat<<4;
    datat=datat + (templ >> 4); // the lsb of the value is on the upper 4 bits of the second read.
    return(datat);
  }

  signed int16 readt_I2C_temp() { // Returns temperature in Celsius
    WORD datat;
    datat = read_I2C_temp();
    return (float)datat*0.625;
  }
#endif

It loads the generic I2C library, checks that a chip has been selected (default to MCP9803 if not) and declares some functions to control the chips:

  • config_I2C_temp: sends a byte to the configuration register of the sensor
  • init_I2C_temp: configure the sensor in 12 bits mode, and start the conversions
  • read_I2C_temp: returns the temperature register of the sensor as a 16 bits value
  • readt_I2C_temp: returns the temperature from the sensor in celsius

The I2C generic library is detailed below:_lib.c first check that it knows what processor board is used. It then loads a list of slave I2C addresses stored in I2C_Addr.h.
Depending on the processor, it then configure the I2C interface. For each processor, we defines the pin used for the SCL and SDA signals, and setup the I2C interface.

The I2C_present function returns 1 if the slave at the address specified is present on the I2C bus, or 0 if not.

#ifndef _I2C_LIB // load it only if hasn't been loaded already
  #define _I2C_LIB
  #include "../lib/Common/I2C.h" // load header file

  BYTE I2C_present(BYTE addr) {
    BYTE ack,present;
    i2c_start();
    ack = i2c_write(addr);
    i2c_stop();
    switch (ack) {
      case 0:
        present = 1;
        break;
      case 1:
        present = 0;
        break;
      default:
        present = 2;
        break;
    }
    return present;
  }

  void i2c_poll(BYTE addr) {
    while(true) {
      i2c_start();
      if (i2c_write(addr) == 0) {
        break;
      }
    }
    i2c_stop();
  }
#endif

The header file defines how the I2C interface is configured, and load sone predefined I2C addresses for the tutorials.

It also defines 2 functions:

  • I2C_present: checks if a component with a given address (addr) is on the I2C bus. It returms a byte with the following values: 0: device not detected (No Ack received), 1: device present (Ack received), 2: collision on the bus (In multimaster mode)
  • i2c_poll: waits undefinitely until the device at address addr returns an Ack.

The header file of the I2C library defines how I2C is setup and configured on the processor board.

#ifndef _I2C_H
  #define _I2C_H
  #include "../lib/Common/I2C_Addr.h" // load I2C components addresses
  #ifndef board_id
    #error "variable board_id not defined"
  #else //* 1: 16F819, 2: 16F628, 3: 16F873A, 4: 18F2320, 5: 18F26J11
    #if (board_id == 1 )// Board 16F819
      #ifndef P_SDA
        #define P_SDA PIN_B1
      #endif
      #ifndef P_SCL
        #define P_SCL PIN_B4
      #endif
      #use I2C(master, sda=P_SDA, scl=P_SCL, stream = I2C_stream)
    #elif (board_id == 2) // Board 16F628
      #ifndef P_SDA
        #define P_SDA PIN_B1
      #endif
      #ifndef P_SCL
        #define P_SCL PIN_B4
      #endif
      #use I2C(master, sda=P_SDA, scl=P_SCL)
    #elif (board_id == 3) // Board 16F873A
      #ifndef P_SDA
        #define P_SDA PIN_C4
      #endif
      #ifndef P_SCL
        #define P_SCL PIN_C3
      #endif
      #use I2C(master, sda=P_SDA, scl=P_SCL, FORCE_HW, stream = I2C_stream)
    #elif (board_id == 4) // Board 18F2320
      #ifndef P_SDA
        #define P_SDA PIN_C4
      #endif
      #ifndef P_SCL
        #define P_SCL PIN_C3
      #endif
      #use I2C(master, sda=P_SDA, scl=P_SCL, stream = I2C_stream)
    #elif (board_id == 5) // Board 18F26J11
      #ifndef P_SDA
        #define P_SDA PIN_C4
      #endif
      #ifndef P_SCL
        #define P_SCL PIN_C3
      #endif
      #use I2C(master, sda=P_SDA, scl=P_SCL, stream = I2C_stream)
    #else
      #error "Board board_id not supported"
    #endif
  #endif

  // function prototypes
  BYTE I2C_present(BYTE addr);
  void i2c_poll(BYTE addr);
#endif

I2C_Addr.h simply defines I2C components with their slave I2C address. The address can usually be configured by microswitches on the boards.

#ifndef _I2C_ADDR_H
  #define _I2C_ADDR_H
  // Boards Addresses
  #define I2C_clock 0xA0 // I2C clock (PCF8583)
  #define I2C_clock2 0xD0 // I2C clock2 (DS1307)
  #define I2C_eeprom 0xA2 // I2C EEPROM (24C64)
  #define I2C_temp 0x90 // I2C Temperature sensor (MCP9803)
  #define I2C_temp2 0x92 // I2C Temperature sensor 2 (DS1631)
  #define I2C_keyb 0x40 // I2C keyboard
  #define I2C_8bits 0x42 // I2C 8 Bits (PCF8574)
  #define I2C_IOexp 0x44 // I2C IO extender (MCP23016)
  #define I2C_Accel 0x3A // I2C Accelerometer (LIS302)
  #define I2C_GLCD 0x7A // I2C/SPI graphic LCD display
#endif


Tutorial 4b

Fig. 1b Board 3 with LCD display and I2C temperature sensor 2

Compile the project and program the target with a PicKIT 2 programmer for example. Connect the processor board to the LCD display board on port B and the I2C temperature sensor on the I2C connector, making sure the jumpers on the board match the slave address defined in I2C_Addr.h.

Power up the boards.
The temperature from the sensor will be displayed on the first line of the display.

To change sensor type, just define I2C_Temp_Chip as 2 and recompile. The program is then set for a DS1631 sensor.


Files and links:

Tutorial 4 source files.
Processor board 3.
LCD Display board.
I2C temperature sensor 1.
I2C temperature sensor 2.

Post your comments...

  • PleraViarma

    Posted at 2012-02-08 18:54:46

    Funny Metal Bullet For My Valentine - Suffocating Under Words Of Sorrow ww kelly_rowland_ft._david_guetta_-_commander_ Kingdom Come-Aint Crying At Tne Moon пильца кнопка MTB COSH Feryad

    Reply to comment

Copyright 2011. Poker Games. Copyright © 2012 riaDesign