Gadget Renesas

Linking Ideas and Electronics

GR Atelier

Title:Let's try the function on GR-KURUMI, I2C vol.

Displayed Name:@chobichan

Let's try the function on GR-KURUMI, I2C vol.

Concept / Overview
With Wire library, you can use I2C device easily, let's try!
####

Let's try I2C

With Wire library, you can use I2C device easily.There are a lot of I2C devices in the market, picking up here, temperature-humidity sensor as representing for input direction, character LCD for output direction.

Using “AE-HDC1000” for temperature-humidity sensor, “AQM1602A-RN-GBW” for LDC.

Both are useful devices with less wiring due to its I2C correspondence, AKIZUKI products.

 

 

 

####

About temperature - humidity sensor AE-HDC1000

AE-HDC1000 is the module on board for users to mount the sensor HDC1000 easily.
The resister is not required on breadboard since 10KΩ pull-up resister necessary for I2C is already set up on it.

The measurable range is temperature -20C ~85C, humidity 0% ~100%.
Like to highlight that power consumption is extremely low, it is the most suitable for the devices for battery run.

 

 

Here is the sample code for the program 
which output temperature or humidity regularly to serial.

/*GR-KURUMI Sketch Template Version: V1.12*/
#include  
#include    //I2Cを使う為に宣言

#if !defined( _MULTITASK_H_ )
#define  dly_tsk(tim)  delay(tim)
#define  rot_rdq()
#define  loc_cpu()     interrupts()
#define  unl_cpu()     noInterrupts()
#endif /*_MULTITASK_H_ */

int HDC1000blkWrite(unsigned char addr, const unsigned char *dat, unsigned int len);
int HDC1000blkRead( unsigned char reg, unsigned char data[], int len );
int HDC1000writeConfig(unsigned short config);
void HDC1000readConfig(unsigned short *config);
void HDC1000readDeviceID(unsigned short *id);
void HDC1000readManufactureID(unsigned short *manu);
void HDC1000readSerialID0(unsigned short *id0);
void HDC1000readSerialID1(unsigned short *id1);
void HDC1000readSerialID2(unsigned short *id2);
int HDC1000readTemperature(unsigned short *tmp,unsigned short *humi);
float HDC1000temperature2Degree( unsigned short temperature );
float HDC1000humidity2Percent( unsigned short humidity );

//HDC1000の内部レジスタアドレス
#define  HDC1000_ADR          (0x40 >> 0)
#define  HDC1000_TEMPERATURE  0x00
#define  HDC1000_HUMIDITY     0x01
#define  HDC1000_CONFIG       0x02
#define  HDC1000_SERIAL_ID2   0xfb
#define  HDC1000_SERIAL_ID1   0xfc
#define  HDC1000_SERIAL_ID0   0xfd
#define  HDC1000_MANU_ID      0xfe
#define  HDC1000_DEVICE_ID    0xff

void setup()
{
  Serial.begin(9600);
  Wire.begin();  //for display and temp sensor

  HDC1000writeConfig(0x8000);  //reset
  delay(10);
  HDC1000writeConfig(0x1000);  //config set resolution 14bit 0b0000 0000 00000000

  while( 1 )
  {
    unsigned short tempUS,humiUS;
    HDC1000readTemperature( &tempUS, &humiUS );  //温度、湿度データを取得

    float tempF = HDC1000temperature2Degree( tempUS ) + 0.05f;  //変換値を摂氏に換算
    float humiF = HDC1000humidity2Percent( humiUS ) + 0.05f;  //変換値をパーセントに換算
    char buf[32];
    sprintf( buf, "%f", tempF );
    String Temp = "Temperature:";
    Temp += buf;
    Temp += "c";

    sprintf( buf, "%f", humiF );
    String Humi = "Humidity:";
    Humi += buf;
    Humi += "%";

    Serial.println( Temp );
    Serial.println( Humi );

    delay(10 * 1000UL);
  }
}

// the loop routine runs over and over again forever:
void loop()
{
}

/****************************************************************************/
/* I2C block Write                                                          */
/****************************************************************************/
int HDC1000blkWrite(unsigned char addr, const unsigned char *dat, unsigned int len)
{
  Wire.beginTransmission(addr);
  Wire.write(dat,len);
  return Wire.endTransmission();
}

/*************************************************************************/
/* any bytes data read                                                   */
/*************************************************************************/
int HDC1000blkRead( unsigned char reg, unsigned char data[], int len )
{
  Wire.beginTransmission( HDC1000_ADR );
  Wire.write( reg );
  Wire.endTransmission(false); //endTransmission but keep the connection active

  Wire.requestFrom( HDC1000_ADR, len ); //Ask for bytes, once done, bus is released by default

  unsigned long baseTime = millis();
  while( Wire.available() < len ) //Hang out until we get the # of bytes we expect
  {
    if( (millis() - baseTime) > 100UL ) return (-1);
  }

  for(int i = 0 ; i < len; i++)
    data[i] = Wire.read();    

  return 0;
}

/*************************************************************************/
/* write configration                                                    */
/*************************************************************************/
int HDC1000writeConfig(unsigned short config)
{
  unsigned char cmd[3];

  cmd[0] = HDC1000_CONFIG;
  cmd[1] = (unsigned char)(config >> 8);
  cmd[2] = (unsigned char)config;

  return HDC1000blkWrite( HDC1000_ADR, cmd, sizeof(cmd) );
}

/*************************************************************************/
/* read configration                                                     */
/*************************************************************************/
void HDC1000readConfig(unsigned short *config)
{
  unsigned char temp[2];

  HDC1000blkRead( HDC1000_CONFIG, temp, sizeof(temp) );

  *config = (temp[0] << 8) | temp[1];
}


/*************************************************************************/
/* read device id                                                     */
/*************************************************************************/
void HDC1000readDeviceID(unsigned short *id)
{
  unsigned char temp[2];

  HDC1000blkRead( HDC1000_DEVICE_ID, temp, sizeof(temp) );

  *id = (temp[0] << 8) | temp[1];
}

/*************************************************************************/
/* read manufacture id                                                   */
/*************************************************************************/
void HDC1000readManufactureID(unsigned short *manu)
{
  unsigned char temp[2];

  HDC1000blkRead( HDC1000_MANU_ID, temp, sizeof(temp) );

  *manu = (temp[0] << 8) | temp[1];
}

/*************************************************************************/
/* read serial id  msb                                                   */
/*************************************************************************/
void HDC1000readSerialID2(unsigned short *id2)
{
  unsigned char temp[2];

  HDC1000blkRead( HDC1000_SERIAL_ID2, temp, sizeof(temp) );

  *id2 = (temp[0] << 8) | temp[1];
}

/*************************************************************************/
/* read serial id  middle                                                */
/*************************************************************************/
void HDC1000readSerialID1(unsigned short *id1)
{
  unsigned char temp[2];

  HDC1000blkRead( HDC1000_SERIAL_ID1, temp, sizeof(temp) );

  *id1 = (temp[0] << 8) | temp[1];
}

/*************************************************************************/
/* read serial id  lsb                                                   */
/*************************************************************************/
void HDC1000readSerialID0(unsigned short *id0)
{
  unsigned char temp[2];

  HDC1000blkRead( HDC1000_SERIAL_ID0, temp, sizeof(temp) );

  *id0 = (temp[0] << 8) | temp[1];
}

/*************************************************************************/
/* read temperatue                                                       */
/*************************************************************************/
int HDC1000readTemperature(unsigned short *tmp,unsigned short *humi)
{
  unsigned char temp[4];

  temp[0] = HDC1000_TEMPERATURE;
  HDC1000blkWrite( HDC1000_ADR, (const unsigned char *)temp, 1 );
  dly_tsk(7 * 2);
  Wire.requestFrom( HDC1000_ADR, sizeof(temp) ); //Ask for bytes, once done, bus is released by default
  unsigned long nextTime = millis() + 100UL;
  while( Wire.available() < sizeof(temp) ) //Hang out until we get the # of bytes we expect
  {
    if( nextTime < millis() ) return (-1);
  }
  for(int i = 0 ; i < sizeof(temp); i++)
    temp[i] = Wire.read();    

  *tmp = (temp[0] << 8) | temp[1];
  *humi = (temp[2] << 8) | temp[3];

  return 0;
}

/*************************************************************************/
/* temperatue to degree                                                  */
/*************************************************************************/
float HDC1000temperature2Degree( unsigned short temperature )
{
  return (float)temperature / 65536.0 * 165.0 - 40.0;
}

/*************************************************************************/
/* humidity to percent                                                   */
/*************************************************************************/
float HDC1000humidity2Percent( unsigned short humidity )
{
  return (float)humidity / 65536.0 * 100.0;
}

These are the outputs of temperature, humidity to serial, using X-CTU (a tool of Xbee) for terminal software.

 

####

About Character LED AQM1602A-RN-GBW

AQM1602A-RN-GBWis LCD which enable character output with 16 characters x 2 lines of ASCII code as well as KATAKANA.
Using ST7032i for controller IC.
Like to highlight the extremely low power consumption, it’s the most suitable for the devices for battery run.

 

Here is the sample code for the program 
which output temperature or humidity regularly to serial.

?/*GR-KURUMI Sketch Template Version: V1.12*/
#include  
#include    //I2Cを使う為に宣言

#if !defined( _MULTITASK_H_ )
#define  dly_tsk(tim)  delay(tim)
#define  rot_rdq()
#define  loc_cpu()     interrupts()
#define  unl_cpu()     noInterrupts()
#endif /*_MULTITASK_H_ */

int HDC1000blkWrite(unsigned char addr, const unsigned char *dat, unsigned int len);
int HDC1000blkRead( unsigned char reg, unsigned char data[], int len );
int HDC1000writeConfig(unsigned short config);
void HDC1000readConfig(unsigned short *config);
void HDC1000readDeviceID(unsigned short *id);
void HDC1000readManufactureID(unsigned short *manu);
void HDC1000readSerialID0(unsigned short *id0);
void HDC1000readSerialID1(unsigned short *id1);
void HDC1000readSerialID2(unsigned short *id2);
int HDC1000readTemperature(unsigned short *tmp,unsigned short *humi);
float HDC1000temperature2Degree( unsigned short temperature );
float HDC1000humidity2Percent( unsigned short humidity );

void ST7032Iinit( void );
void ST7032Iclear( void );
void ST7032IOnOff( unsigned char onoff );
void ST7032Ilocate( int x, int y );
void ST7032Icontrast( unsigned char cnt );
int ST7032IwriteString( const char *str );
int ST7032IwriteString( const char *str, unsigned int len );
int ST7032IwriteString( String str );
void displayUpdate( String line0, String line1 );

//HDC1000の内部レジスタアドレス
#define  HDC1000_ADR          (0x40 >> 0)
#define  HDC1000_TEMPERATURE  0x00
#define  HDC1000_HUMIDITY     0x01
#define  HDC1000_CONFIG       0x02
#define  HDC1000_SERIAL_ID2   0xfb
#define  HDC1000_SERIAL_ID1   0xfc
#define  HDC1000_SERIAL_ID0   0xfd
#define  HDC1000_MANU_ID      0xfe
#define  HDC1000_DEVICE_ID    0xff

//ST7032Iの内部レジスタアドレス
#define  ST7032I_ADR          0x3e
#define  AQM0802A_LINES       2  //
#define  AQM0802A_COLUMN      16  //液晶にはAQM0802AとAQM1602Aが有り、文字数が異なります。
#define  AQM0802A_DISPLAY_ON  0x04
#define  AQM0802A_DISPLAY_OFF 0x00
#define  AQM0802A_CURSOR_ON   0x02
#define  AQM0802A_CURSOR_OFF  0x00
#define  AQM0802A_BLINK_ON    0x01
#define  AQM0802A_BLINK_OFF   0x00
#define  LCD_RESET   6  //lcd reset

void setup()
{
  Wire.begin();  //for display and temp sensor

  HDC1000writeConfig(0x8000);  //reset
  delay(10);
  HDC1000writeConfig(0x1000);  //config set resolution 14bit 0b0000 0000 00000000

  pinMode(LCD_RESET, OUTPUT);  //reset LCD
  digitalWrite(LCD_RESET, HIGH);
  delay(2);
  digitalWrite(LCD_RESET, HIGH);

  ST7032Iinit();  //initialize LCD
  ST7032IOnOff( AQM0802A_DISPLAY_ON | AQM0802A_CURSOR_OFF | AQM0802A_BLINK_OFF );

  while( 1 )
  {
    unsigned short tempUS,humiUS;
    HDC1000readTemperature( &tempUS, &humiUS );  //温度、湿度データを取得

    float tempF = HDC1000temperature2Degree( tempUS ) + 0.05f;  //変換値を摂氏に換算
    float humiF = HDC1000humidity2Percent( humiUS ) + 0.05f;  //変換値をパーセントに換算
    char buf[32];
    sprintf( buf, "%2.1f", tempF );
    String Temp = "Temp:";
    Temp += buf;
    Temp += "c";

    sprintf( buf, "%2.1f", humiF );
    String Humi = "Humi:";
    Humi += buf;
    Humi += "%";

    displayUpdate( Temp, Humi );

    delay(1 * 1000UL);
  }
}

// the loop routine runs over and over again forever:
void loop()
{
}



?/*GR-KURUMI Sketch Template Version: V1.12*/
#include  
#include    //I2Cを使う為に宣言

#if !defined( _MULTITASK_H_ )
#define  dly_tsk(tim)  delay(tim)
#define  rot_rdq()
#define  loc_cpu()     interrupts()
#define  unl_cpu()     noInterrupts()
#endif /*_MULTITASK_H_ */

int HDC1000blkWrite(unsigned char addr, const unsigned char *dat, unsigned int len);
int HDC1000blkRead( unsigned char reg, unsigned char data[], int len );
int HDC1000writeConfig(unsigned short config);
void HDC1000readConfig(unsigned short *config);
void HDC1000readDeviceID(unsigned short *id);
void HDC1000readManufactureID(unsigned short *manu);
void HDC1000readSerialID0(unsigned short *id0);
void HDC1000readSerialID1(unsigned short *id1);
void HDC1000readSerialID2(unsigned short *id2);
int HDC1000readTemperature(unsigned short *tmp,unsigned short *humi);
float HDC1000temperature2Degree( unsigned short temperature );
float HDC1000humidity2Percent( unsigned short humidity );

void ST7032Iinit( void );
void ST7032Iclear( void );
void ST7032IOnOff( unsigned char onoff );
void ST7032Ilocate( int x, int y );
void ST7032Icontrast( unsigned char cnt );
int ST7032IwriteString( const char *str );
int ST7032IwriteString( const char *str, unsigned int len );
int ST7032IwriteString( String str );
void displayUpdate( String line0, String line1 );

//HDC1000の内部レジスタアドレス
#define  HDC1000_ADR          (0x40 >> 0)
#define  HDC1000_TEMPERATURE  0x00
#define  HDC1000_HUMIDITY     0x01
#define  HDC1000_CONFIG       0x02
#define  HDC1000_SERIAL_ID2   0xfb
#define  HDC1000_SERIAL_ID1   0xfc
#define  HDC1000_SERIAL_ID0   0xfd
#define  HDC1000_MANU_ID      0xfe
#define  HDC1000_DEVICE_ID    0xff

//ST7032Iの内部レジスタアドレス
#define  ST7032I_ADR          0x3e
#define  AQM0802A_LINES       2  //
#define  AQM0802A_COLUMN      16  //液晶にはAQM0802AとAQM1602Aが有り、文字数が異なります。
#define  AQM0802A_DISPLAY_ON  0x04
#define  AQM0802A_DISPLAY_OFF 0x00
#define  AQM0802A_CURSOR_ON   0x02
#define  AQM0802A_CURSOR_OFF  0x00
#define  AQM0802A_BLINK_ON    0x01
#define  AQM0802A_BLINK_OFF   0x00
#define  LCD_RESET   6  //lcd reset

void setup()
{
  Wire.begin();  //for display and temp sensor

  HDC1000writeConfig(0x8000);  //reset
  delay(10);
  HDC1000writeConfig(0x1000);  //config set resolution 14bit 0b0000 0000 00000000

  pinMode(LCD_RESET, OUTPUT);  //reset LCD
  digitalWrite(LCD_RESET, HIGH);
  delay(2);
  digitalWrite(LCD_RESET, HIGH);

  ST7032Iinit();  //initialize LCD
  ST7032IOnOff( AQM0802A_DISPLAY_ON | AQM0802A_CURSOR_OFF | AQM0802A_BLINK_OFF );

  while( 1 )
  {
    unsigned short tempUS,humiUS;
    HDC1000readTemperature( &tempUS, &humiUS );  //温度、湿度データを取得

    float tempF = HDC1000temperature2Degree( tempUS ) + 0.05f;  //変換値を摂氏に換算
    float humiF = HDC1000humidity2Percent( humiUS ) + 0.05f;  //変換値をパーセントに換算
    char buf[32];
    sprintf( buf, "%2.1f", tempF );
    String Temp = "Temp:";
    Temp += buf;
    Temp += "c";

    sprintf( buf, "%2.1f", humiF );
    String Humi = "Humi:";
    Humi += buf;
    Humi += "%";

    displayUpdate( Temp, Humi );

    delay(1 * 1000UL);
  }
}

// the loop routine runs over and over again forever:
void loop()
{
}

/*************************************************************************/
/* I2C block Write                                                       */
/*************************************************************************/
int ST7032IblkWrite(unsigned char addr, const unsigned char *dat, unsigned int len)
{
  Wire.beginTransmission(addr);
  Wire.write(dat,len);
  return Wire.endTransmission();
}

/*************************************************************************/
/* write command                                                         */
/*************************************************************************/
int ST7032IwriteCommand(unsigned char t_command)
{
  unsigned char cmd[2];

  cmd[0] = 0x00;  //Co=0,RS=0,another bit=0
  cmd[1] = t_command;

  return ST7032IblkWrite( ST7032I_ADR, cmd, sizeof(cmd) );
}

/*************************************************************************/
/* write data                                                            */
/*************************************************************************/
int ST7032IwriteData(unsigned char t_data)
{
  unsigned char dat[2];

  dat[0] = 0x40;  //Co=0,RS=1,another bit=0
  dat[1] = t_data;

  return ST7032IblkWrite( ST7032I_ADR, dat, sizeof(dat) );
}


/*************************************************************************/
/* ST7032I初期化                                                         */
/*************************************************************************/
void ST7032Iinit( void )
{
  dly_tsk(40);
  ST7032IwriteCommand( 0x38 );  //function set
  delayMicroseconds(27);
  ST7032IwriteCommand( 0x39 );  //function set
  delayMicroseconds(27);
  ST7032IwriteCommand( 0x14 );  //internal OSC frequency
  delayMicroseconds(27);
  ST7032IwriteCommand( 0x70 );  //contrast set
  delayMicroseconds(27);
  ST7032IwriteCommand( 0x56 );  //power/icon/contrast control
  delayMicroseconds(27);
  ST7032IwriteCommand( 0x6c );  //follower control
  //delayMicroseconds(27);
  dly_tsk( 200 );
  ST7032IwriteCommand( 0x38 );  //function set
  delayMicroseconds(27);
  ST7032IwriteCommand( 0x01 );  //clear display
  delayMicroseconds(27);
  ST7032IwriteCommand( 0x0c );  //display on/off control
  dly_tsk(2);
}


/*************************************************************************/
/* clear display                                                         */
/*************************************************************************/
void ST7032Iclear( void )
{
  ST7032IwriteCommand( 0x01 );  //clear display
  dly_tsk(2);
}


/*************************************************************************/
/* display on/off                                                        */
/*************************************************************************/
void ST7032IOnOff( unsigned char onoff )
{
  ST7032IwriteCommand( onoff | 0x08 );  //display on/off,cursor on/off,blink on/off
  dly_tsk(2);
}


/*************************************************************************/
/* locate                                                                */
/*************************************************************************/
void ST7032Ilocate( int x, int y )
{
  int temp = x + (y * AQM0802A_COLUMN);

  if(temp >= AQM0802A_COLUMN) temp = (temp - AQM0802A_COLUMN) + 0x40;

  ST7032IwriteCommand( (unsigned char)temp | 0x80 );  //set ddram address
  dly_tsk(2);
}


/*************************************************************************/
/* set contrast         */
/*************************************************************************/
void ST7032Icontrast( unsigned char cnt )
{
  //コントラスト調整
  ST7032IwriteCommand( 0x2a );  //RE=1
  ST7032IwriteCommand( 0x79 );  //SD=1
  ST7032IwriteCommand( 0x81 );  //contrast set
  ST7032IwriteCommand( cnt );  //contrast max
  ST7032IwriteCommand( 0x78 );  //SD=0
  ST7032IwriteCommand( 0x28 );  //set character size is normal.
  dly_tsk(100);
}


/*************************************************************************/
/* write strings                                                         */
/*************************************************************************/
int ST7032IwriteString( const char *str )
{
  unsigned char dat[1 * AQM0802A_COLUMN + 1];
  int len = strlen(str);

  dat[0] = 0x40;  //Co=0,RS=1,another bit=0
  len = (len > sizeof(dat) - 1) ? sizeof(dat) - 1 : len;
  memcpy( &dat[1], str, len );

  return ST7032IblkWrite( ST7032I_ADR, dat, len + 1 );
}


/*************************************************************************/
/* write strings                                                         */
/*************************************************************************/
int ST7032IwriteString( const char *str, unsigned int len )
{
  unsigned char dat[1 * AQM0802A_COLUMN + 1];

  dat[0] = 0x40;  //Co=0,RS=1,another bit=0
  len = (len > sizeof(dat) - 1) ? sizeof(dat) - 1 : len;
  memcpy( &dat[1], str, len );

  return ST7032IblkWrite( ST7032I_ADR, dat, len + 1 );
}


/*************************************************************************/
/* write strings                                                         */
/*************************************************************************/
int ST7032IwriteString( String str )
{
  return ST7032IwriteString( (const char *)&str[0], str.length() );
}

/***************************************************************************/
/* i2c display control and temperature/humidity sensor sampling task       */
/***************************************************************************/
void displayUpdate( String line0, String line1 )
{
  ST7032Iclear();
  ST7032IwriteString( line0 );
  ST7032Ilocate( 0, 1 );
  ST7032IwriteString( line1 );
}


Here is the outputs of temperature, humidity on LED. Please don’t worry that the board is not GR-KURUMI.

 

 

 

 

####

Setting the speed of I2C

Some I2C devices are capable of properly matching with the SCL speed up to the 400KHz. 
While Arduino allow us to set up the frequency in a certain degree with the function Wire.setclock()in their Wire library.
http://playground.arduino.cc/Main/WireLibraryDetailedReference

unfortunately current GR-KURUMI doesn’t support it in its library.Please refer to the source code in the library 
gr_common/RLduino78/libralies/Wire/utility
Open the file twi.h, and find the definition of the SCL frequency in the macro of TWI_FREQ.You can set the SCL frequency by changing this figure.

 

 

Check out the SCL frequency in the oscilloscope.

However, wishing it in the GR-KURUMI library.

 

 

MVP information @chobichan

General hard engineer... occasionally writing for technical magazine.

Follow

share