Dear all,
I am very new to Arduino and I search to make work a PM2.5 air quality sensor. Manufacturer sent me a code but it is a .c file/code so I suppose I need to adapt this code for arduino. Do you have any advise ? Thank you very much.
Here is the code
// I2C header
typedef enum{
I2C_ADR = 0x08, // default sensor I2C address
I2C_WRITE = 0x00, // write bit in header
I2C_READ = 0x01, // read bit in header
I2C_RW_MASK = 0x01 // bit position of read/write bit in header
}etI2cHeader;
// I2C acknowledge
typedef enum{
ACK = 0,
NO_ACK = 1,
}etI2cAck;
typedef enum{
NO_ERROR = 0x00, // no error
ACK_ERROR = 0x01, // no acknowledgment error
CHECKSUM_ERROR = 0x02 // checksum mismatch error
}etError;
void DelayMicroSeconds(u32t nbrOfUs) ///5us
{
uint32_t k;
while (nbrOfUs--)
{
for (k = 0; k < 44; k++);
}
}
//==============================================================================
void I2c_StartCondition(void){
//==============================================================================
SDA_OPEN();
DelayMicroSeconds(5);
SCL_OPEN();
DelayMicroSeconds(5);
SDA_LOW();
DelayMicroSeconds(5); // hold time start condition (t_HD;STA) 10
SCL_LOW();
DelayMicroSeconds(2); // 10
}
//==============================================================================
void I2c_StopCondition(void){
//==============================================================================
SCL_LOW();
DelayMicroSeconds(3);
SDA_LOW();
DelayMicroSeconds(5);
SCL_OPEN();
DelayMicroSeconds(5); // set-up time stop condition (t_SU;STO) 10
SDA_OPEN();
DelayMicroSeconds(5); // 10
}
//==============================================================================
etError I2c_WriteByte(u8t txByte){
//==============================================================================
u8t mask;
etError error = NO_ERROR;
for(mask = 0x80; mask > 0; mask >>= 1)// shift bit for masking (8 times)
{
if((mask & txByte) == 0)
SDA_LOW(); // masking txByte, write bit to SDA-Line
else
SDA_OPEN();
DelayMicroSeconds(3); // data set-up time (t_SU;DAT) 3
SCL_OPEN(); // generate clock pulse on SCL
DelayMicroSeconds(5); // SCL high time (t_HIGH) 5
SCL_LOW();
DelayMicroSeconds(2); // data hold time(t_HD;DAT) 3
}
DelayMicroSeconds(3);
SDA_OPEN(); // release SDA-line
SCL_OPEN(); // clk #9 for ack
DelayMicroSeconds(3); // data set-up time (t_SU;DAT) 3
if(SDA_READ)
error = ACK_ERROR; // check ack from i2c slave
DelayMicroSeconds(2); // data set-up time (t_SU;DAT) 2
SCL_LOW();
DelayMicroSeconds(2); // wait to see byte package on scope 10
return error; // return error code
}
//==============================================================================
u8t I2c_ReadByte(etI2cAck ack){
//==============================================================================
u8t mask;
u8t rxByte = NO_ERROR;
SDA_OPEN(); // release SDA-line
for(mask = 0x80; mask > 0; mask >>= 1) // shift bit for masking (8 times)
{
DelayMicroSeconds(3); // SCL high time (t_HIGH) 2
SCL_OPEN(); // start clock on SCL-line
DelayMicroSeconds(3); // SCL high time (t_HIGH) 2
if(SDA_READ) rxByte = rxByte | mask; // read bit
DelayMicroSeconds(2); // SCL high time (t_HIGH) 2
SCL_LOW();
DelayMicroSeconds(2); // data hold time(t_HD;DAT)
}
if(ack == ACK)
SDA_LOW(); // send acknowledge if necessary
else
SDA_OPEN();
DelayMicroSeconds(3); // data set-up time (t_SU;DAT)
SCL_OPEN(); // clk #9 for ack
DelayMicroSeconds(5); // SCL high time (t_HIGH) 5
SCL_LOW();
SDA_OPEN(); // release SDA-line
DelayMicroSeconds(2); // wait to see byte package on scope 10
return rxByte; // return error code
}
//--------------------------------------------------
// Description :
// Input Value :
// Output Value :
//--------------------------------------------------
unsigned char Calc_CRC8( unsigned char *data, unsigned char Num)
{
unsigned char bit,byte,crc=0xFF;
for(byte=0; byte<Num; byte++)
{
crc^=(data[byte]);
for(bit=8;bit>0;--bit)
{
if(crc&0x80)
crc=(crc<<1)^0x31;
else
crc=(crc<<1);
}
}
return crc;
}
//进入测量
etError APM10_EnterMeasure(void)
{
//==============================================================================
etError error; // error code
// read command result & checksum from sensor
I2c_StartCondition();
error = I2c_WriteByte(I2C_ADR << 1 | I2C_WRITE);
I2c_WriteByte(0x00);
I2c_WriteByte(0x10);
I2c_WriteByte(0x05);
I2c_WriteByte(0x00);
I2c_WriteByte(0xF6);
I2c_StopCondition();
return error;
}
//读取数据
//==============================================================================
etError APM10_ReadData(u8t *buf, u8t len)
{
//==============================================================================
etError error; // error code
u8t i;
I2c_StartCondition();
error = I2c_WriteByte(I2C_ADR << 1 | I2C_WRITE);
I2c_WriteByte(0x03);
I2c_WriteByte(0x00);
I2c_StopCondition();
I2c_StartCondition();
I2c_WriteByte(I2C_ADR << 1 | I2C_READ);
for(i=0; i<len-1; i++)
{
buf[i] = I2c_ReadByte(ACK);
}
buf[i] = I2c_ReadByte(NO_ACK);
I2c_StopCondition();
return error;
}
uint8_t PM2_5_buf[16];
int main(void)
{
GPIO_Init_Config(); //IO INIT
TIM3_Config(); //TIM INIT
GPIO_ResetBits(GPIOA, GPIO_Pin_5);//SET PIN 为低,IIC通信模式工作
LCD_Init(); //LCD 初始化
Delay_Nms(1000); //DELAY 1S
APM10_EnterMeasure(); //进入测量状态
while(1)
{
if(B_1500ms_flag) //1.5S定时
{
B_1500ms_flag = FALSE;
APM10_ReadData(PM2_5_buf, 6);//读取数据
if(PM2_5_buf[5] == Calc_CRC8(&PM2_5_buf[3], 2))//数据校验
{
sprintf((char *)&print_buf[0], "%d ug/m3 ", ((PM2_5_buf[3]<<8)+PM2_5_buf[4]));//校验正确,数据高低位合并 //最大量程1000
LCD_WriteLineASCII_Std(8, 7, 0, "I2C:"); //数据显示
LCD_WriteLineASCII_Std(56, 7, 0,print_buf);
}
else
{
LCD_WriteLineASCII_Std(8, 7, 0, "I2C:"); //校验错误
LCD_WriteLineASCII_Std(56, 7, 0, "NO DATA ");
}
}
}
}