CH32V003 Programming: Unlock the Power of the Sensirion SHTC3 Sensor

CH32V003 Programming: Unlock the Power of the Sensirion SHTC3 Sensor on I2C

In my previous artcile you saw how to use I2C with CH32V003, which was quite easy using the example code itself.

CH32V003 Programming: Unlock the Power of the Sensirion SHTC3 Sensor 1

In this article we will see how to interface a Sensirion’s Temperature Humidity Sensor SHTC3 which has I2C Interface. I have an Adafruit SHTC3 breakout board which I will connect for the testing.

CH32V003 Programming: Unlock the Power of the Sensirion SHTC3 Sensor 2

The only connection we need with development board are 3.3V, GND, I2C SCL, I2C SDA. For Debugger/Programmer we need 3.3V, GND and SWIO.

I would suggest you go through the Sensirion’s datasheet to understand how the sensor works and how we will get the data out of sensor, which commands we need to send and what is the response I am going to get out of it. Please don’t jump directly to checking the code and testing it.

CH32V003 Programming: Unlock the Power of the Sensirion SHTC3 Sensor 3

Configuring the I2C interface is same, we are using PC1(SDA) and PC2(SCL) so the configuration looks like this:

void IIC_Init(u32 bound, u16 address)
{
    GPIO_InitTypeDef GPIO_InitStructure={0};
    I2C_InitTypeDef I2C_InitTSturcture={0};

    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE );
    RCC_APB1PeriphClockCmd( RCC_APB1Periph_I2C1, ENABLE );

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init( GPIOC, &GPIO_InitStructure );

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init( GPIOC, &GPIO_InitStructure );

    I2C_InitTSturcture.I2C_ClockSpeed = bound;
    I2C_InitTSturcture.I2C_Mode = I2C_Mode_I2C;
    I2C_InitTSturcture.I2C_DutyCycle = I2C_DutyCycle_2;
    I2C_InitTSturcture.I2C_OwnAddress1 = address;
    I2C_InitTSturcture.I2C_Ack = I2C_Ack_Enable;
    I2C_InitTSturcture.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_Init( I2C1, &I2C_InitTSturcture );

    I2C_Cmd( I2C1, ENABLE );

    I2C_AcknowledgeConfig( I2C1, ENABLE );
}

Now in order to read temperature humidity data from the sensor there is a procedure.

  1. Wakeup command
  2. Measurement command
  3. Read out command
  4. Sleep Command (this will be optional if you want to make sensor sleep or not)

Wakeup Command we can send like this:

void SHTC3Wakeup(uint8_t deviceAddress)
{
    while( I2C_GetFlagStatus( I2C1, I2C_FLAG_BUSY ) != RESET );
    I2C_GenerateSTART( I2C1, ENABLE );

    while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_MODE_SELECT ) );
    I2C_Send7bitAddress( I2C1, (deviceAddress << 1), I2C_Direction_Transmitter );

    while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ) );

    I2C_SendData( I2C1, (u8)(0x35) );
    while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );

    I2C_SendData( I2C1, (u8)(0x17) );
    while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );

    I2C_GenerateSTOP( I2C1, ENABLE );
}

There are multiple option for measurement command: Clock stretching or not, Temperature data first or Humidity Data first, depending on your requirement you can each either of them.

CH32V003 Programming: Unlock the Power of the Sensirion SHTC3 Sensor 4
//Temperature Data First, Clock stretching Enabled
void SHTC3MeasureCMDTFCE(uint8_t deviceAddress)
{
    while( I2C_GetFlagStatus( I2C1, I2C_FLAG_BUSY ) != RESET );
    I2C_GenerateSTART( I2C1, ENABLE );

    while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_MODE_SELECT ) );
    I2C_Send7bitAddress( I2C1, (deviceAddress << 1), I2C_Direction_Transmitter );

    while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ) );

    I2C_SendData( I2C1, (u8)(0x78) );
    while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );

    I2C_SendData( I2C1, (u8)(0x66) );
    while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );

    I2C_GenerateSTOP( I2C1, ENABLE );

}

You can improve this code by making Macro for command and even sending data in a loop instead of hardcoding send data two times.

After sending the measurement command, sensor takes some time to be ready with the data. As per the datasheet it might take around 12mSec. So, I have given around 50mSec delay and after that I have read the data in the main code. Will show you that.

CH32V003 Programming: Unlock the Power of the Sensirion SHTC3 Sensor 5
CH32V003 Programming: Unlock the Power of the Sensirion SHTC3 Sensor 6

After measurement command, we can Read the data by sending I2C with Read header and get six bytes, first two bytes will be temperature data, followed by the CRC for temperature data and then two bytes of Humidity followed by its CRC. You can decide if you want to use CRC or not.

Code the read Six byes and then converting temperature data to real value is shown below:

void I2CReadBytes(uint8_t deviceAddress, uint8_t *dataBuffer, uint16_t length)
{
    I2C_GenerateSTART( I2C1, ENABLE );
    while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_MODE_SELECT ) );

    I2C_Send7bitAddress( I2C1, deviceAddress<<1, I2C_Direction_Receiver );

    while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED ) );
    I2C_AcknowledgeConfig( I2C1, ENABLE );
    //length--;
    while(length)
    {
        if( I2C_GetFlagStatus( I2C1, I2C_FLAG_RXNE ) !=  RESET )
        {
            dataBuffer[0] = I2C_ReceiveData( I2C1 );
            dataBuffer++;
            length--;
            if(length ==1) I2C_AcknowledgeConfig( I2C1, DISABLE );
        }
    }
    I2C_GenerateSTOP( I2C1, ENABLE );

} 

The main code which is calling these functions is as shown below:

You can see I have not used floating point variable for temperature and humidity real value calculations becuse with floating point code size was becoming 2000 bytes bigger.

With the code below, if temperature is 27.2 you will get 272 as the integer value, similarly if humidity is 79.4, you will get 794.

For Temperature, Humidity Real Value conversion please refer the datasheet.

CH32V003 Programming: Unlock the Power of the Sensirion SHTC3 Sensor 7
int main(void)
{
    uint8_t data[6];

    SystemCoreClockUpdate();
    Delay_Init();

    IIC_Init( 50000, 0x70);

    while(1)
    {
        SHTC3Wakeup(0x70);
        Delay_Ms(1);

        SHTC3MeasureCMDTFCE(0x70);
        Delay_Ms(50);

        I2CReadBytes(0x70, &data, 6);

        T1 = (((data[0]*256 + data[1]) * 1750)/65536)-450;

        H1 = ((data[3]*256 + data[4])*1000)/65536;

        Delay_Ms(1000);
    }

}
CH32V003 Programming: Unlock the Power of the Sensirion SHTC3 Sensor 8

These are some waveform screen shots from my Saleae Logic analyzer, I highly recommend buying one, it helps a lot in the debugging during development.

CH32V003 Programming: Unlock the Power of the Sensirion SHTC3 Sensor 9
Wakeup Command
CH32V003 Programming: Unlock the Power of the Sensirion SHTC3 Sensor 10
Measurement Mode Command (here I have used a different command compared to code)
CH32V003 Programming: Unlock the Power of the Sensirion SHTC3 Sensor 11
Temperature Humidity Data

I hope you have understood well how to interface Sensirion’s SHTC3 Temperature Humidity Sensor with CH32V003 MCU over I2C.

I will be creating many more such examples with real devices, sensor and with different interface of this MCU. Hope you will get to learn from these articles.


See also:

  1. Setting up the Development Environment for CH32V003: Compile and Run first example code
  2. CH32V003: GPIO as Output
  3. CH32V003: GPIO as Input (Polling, Interrupt)
  4. CH32V003: UART Transmit / Receive data
  5. CH32V003: PWM output
  6. CH32V003: How to use an ADC
  7. CH32V003: How to use I2C
  8. CH32V003: How to use SPI
  9. CH32V003: Timer based Periodic Interrupt
  10. CH32V003: How to read 64-bit Unique ID

I am currently working as an embedded systems design consultant and helping companies build custom embedded products, develop test automation solution for their PCB.

If you have any feedback about the blog, you can share in the comments below or you can also contact me directly.


Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.