.C to arduino for PM25 sensor

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     ");			
				}
			}

	}
}

Install the Arduino IDE. That's a good environment for handling c code.
I use it and it works well.

Dear Railroader,

Thank you for your answer !
I am using it. So I am adapting some parts of it, do you know by any chance what can I use to replace « SDA_LOW » « SDA_LOW » « SDA_READ » in this code and make it work ? Thank you.

For SDA commands, Arduino returns « was not declared in this scope ». Ty.

Those undeclared commands refer to a library You didn't include in the code.
Please post a link to the datasheet of that device.

The code you were sent is too low-level compared to the Wire library used in the Arduino world.
You don't fiddle SDA and SCL by bit banging unless you really have to.

Adapt some simple example using the Wire library and query your sensor with own/new code.

IF your sensor is same as
Overview | PM2.5 Air Quality Sensor | Adafruit Learning System

Adafruit has written the lib code and example.

Sure here you are !

APM10 datasheet.pdf (1,5 Mo)

Hmm I don’t think so because there is no error in the code if I open it in VSCode. I suppose I just need to adapt.

Ok will try ! Thank you

As you will see above unfortunately it’s not :frowning: ty