Title:Let's try the function on GR-KURUMI, I2C vol.
Displayed Name:@chobichan
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.
General hard engineer... occasionally writing for technical magazine.