element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet & Tria Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • About Us
    About the element14 Community
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Japan
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      •  Vietnam
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Low Power IoT Design Challenge
  • Challenges & Projects
  • Design Challenges
  • Low Power IoT Design Challenge
  • More
  • Cancel
Low Power IoT Design Challenge
Blog Smart Air Quality Monitor #4 - Connecting Air Quality Sensor ZMOD4510 to CY8CKIT-062S2-43012 with I2C
  • Blog
  • Forum
  • Documents
  • Polls
  • Files
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: vlasov01
  • Date Created: 30 Oct 2021 11:50 AM Date Created
  • Views 1780 views
  • Likes 1 like
  • Comments 5 comments
  • logic analyzer
  • zmod4510
  • cypress modus toolbox 2.4
  • air quality
  • fpu
  • m4f
  • low power iot design challenge
  • psoc 62
  • i2c communication
Related
Recommended

Smart Air Quality Monitor #4 - Connecting Air Quality Sensor ZMOD4510 to CY8CKIT-062S2-43012 with I2C

vlasov01
vlasov01
30 Oct 2021

From Arduino Nano 33 IoT to CY8CKIT-062S2-43012

In my previous post Smart Air Quality Monitor #3 - Exploring Air Quality Sensor ZMOD4510 and Pmod Type 6A (Extended I2C)  I've described my journey of connecting the air quality sensor with Arduino Nano 22 IoT. The sensor was connected using the I2C bus protocol to MCU and was able to measure air quality. Now I need to repeat it with the CY8CKIT-062S2-43012 kit.

 

 

I2C Master Project

Some of Cypress's boards have PMOD interfaces, but the CY8CKIT-062S2-43012 board doesn't have it. As I need to use the I2C interface to interact with ZMOD4510 ModusToolbox comes with a set of prebuilt projects and one of them was to showcase I2C interaction by controlling the built-in LED.  I've used Project Creator to import this project. I've typed "I2C" to filter the projects. and then I've selected it.

image

I've connected the board to my PC using USB and then build and deployed this project.

image

After a few minutes, the initial build was completed. But the firmware was not uploaded due to the following warning:

image

It was the result I've my upgrade of ModusToolbox from 2.3.1 to 2.4. I've uploaded the new KitProg3 firmware to remove this blocker.

vlasov01@remote:~/ModusToolbox/tools_2.4/fw-loader/bin$ ./fw-loader --info
Cypress Firmware Updater, Version: 3.3.0.1370
(C) Copyright 2018-2021 by Cypress Semiconductor Corporation (an Infineon company)
All Rights Reserved


Info: Start API initialization
Info: Connected - KitProg3 CMSIS-DAP BULK-0C1416A4002A9400
Info: Hardware initialization complete 485 ms
vlasov01@remote:~/ModusToolbox/tools_2.4/fw-loader/bin$ sudo ./fw-loader --update-kp3
[sudo] password for vlasov01:
Cypress Firmware Updater, Version: 3.3.0.1370
(C) Copyright 2018-2021 by Cypress Semiconductor Corporation (an Infineon company)
All Rights Reserved


Info: Start API initialization
Info: Connected - KitProg3 CMSIS-DAP BULK-0C1416A4002A9400
Info: Hardware initialization complete 486 ms
Found KP firmware image: "/home/vlasov01/ModusToolbox/tools_2.4/kp-firmware/kitprog3.cyacd"
Device 'KitProg3 CMSIS-DAP BULK-0C1416A4002A9400' opened successfully
Info: Kit FW is 'KitProg3' ver. 2.30 b1155.  Upgrade file is 'KitProg3' ver. 2.30 b1155.
Info: Disconnected - KitProg3 CMSIS-DAP BULK-0C1416A4002A9400
Info: Connected - KitProg3 Bootloader-A4000216140C2A94
Info: Bootloader Version: Major 1, Minor 1, Build 60
Info: FW Upgrade to version: 2.30 b1155
Info: Bootloading of KitProg FW...
Info: Verifying of KitProg FW...
Info: Bootloading of DAPLink...
Info: Verifying of DAPLink...
Info: Upgrade completed
Info: Disconnected - KitProg3 Bootloader-A4000216140C2A94
Info: Connected - KitProg3 CMSIS-DAP BULK-0C1416A4002A9400
FW update completed successfully

 

And then I've uploaded the project firmware to the board. This time it was successful.

 

Then I've switched the power off from the board and connected P6_0 (SCL) to P9_0 and P6_1 (SCA) to P9_1 as described in the project documentation.

SCL and SCA are defined in https://www.cypress.com/file/175671/download  as

  • Serial data (SDA) is the I2C data signal. It is a bidirectional data signal used to transmit or receive all bus data.
  • Serial clock (SCL) is the master-generated I2C clock. Although the slave never generates the clock signal, it may hold the clock low, stalling the bus until it is ready to send data or ACK/NAK the latest data or address.

image

And the LED on the board started blinking as expected.

 

I2C Wrapper for ZMOD4510

 

I've followed the documentation provided with ZMOD4510 firmware. It asked to create a hardware-specific wrapper for the I2C bus, so the ZMOD4510 library can use it. Another requirement is to create a new main.c file with the right sequence of interacting with the ZMOD4510 library. I've completed both of these changes and added the following files to the project.

i2c_wrapper_psoc6.h

hal_psoc6.h

i2c_wrapper_psoc6.c

hal_psoc6.c

 

As well I've modified main.c as per ZMOD4510  documentation to initialize the sensor and added a loop to read data from the sensor.

#include "zmod4510_config_oaq2.h"
#include "zmod4xxx.h"
#include "zmod4xxx_hal.h"
#include "oaq_2nd_gen.h"
#include "i2c_wrapper_psoc6.h"
#include "hal_psoc6.h"
#include <stdlib.h>
/*******************************************************************************
 * Function Name: main
 ********************************************************************************
 * Summary:
 * This is the main function for CM4 CPU.
 *   1. I2C Master sends command packet to the ZMOD4510 slave
 *   2. I2C Master reads the response packet
 *
 * Parameters:
 *  void
 *
 * Return:
 *  int
 *
 *******************************************************************************/


/* Global variables */
zmod4xxx_dev_t dev;


/* The ambient compensation needs humidity and temperature measurements! */
float humidity_pct;
float temperature_degc;


/* Sensor target variables */
uint8_t zmod4xxx_status;
uint8_t adc_result[ZMOD4510_ADC_DATA_LEN];
uint8_t prod_data[ZMOD4510_PROD_DATA_LEN];


oaq_2nd_gen_handle_t algo_handle;
oaq_2nd_gen_results_t algo_results;


void error_handle() {
printf("\r\n**************Fatal Error***********\r\n");
handle_error();
}
int16_t measurements_counter = 0;
void loop() {
/* lib_ret -> Return of Library
* api_ret -> Return of API
*/
int8_t lib_ret;
zmod4xxx_err api_ret;
uint8_t polling_counter = 0;


api_ret = zmod4xxx_start_measurement(&dev);
measurements_counter++;
if (api_ret) {
printf("ERROR %i during start of measurements, exiting program!\r\n\n", api_ret);
error_handle();
}


//psoc6_delay(15); //50);
do {
api_ret = zmod4xxx_read_status(&dev, &zmod4xxx_status);
if (api_ret) {
printf("ERROR %i during read of sensor status:%i, wait:%i\r\n", api_ret, zmod4xxx_status, polling_counter);
zmod4xxx_status = api_ret;
//printf("Error %i during read of sensor status, exiting program!", api_ret);
//error_handle();
}
printf("><");
psoc6_delay(15); //15);
polling_counter++;


} while ((zmod4xxx_status & STATUS_SEQUENCER_RUNNING_MASK)
&& (polling_counter <= ZMOD4510_OAQ2_COUNTER_LIMIT));


if (ZMOD4510_OAQ2_COUNTER_LIMIT <= polling_counter) {
api_ret = zmod4xxx_check_error_event(&dev);
if (api_ret) {
printf("ERROR %i during check event, exiting program!", api_ret);
error_handle();
}
printf("ERROR ERROR_GAS_TIMEOUT during read of sensor status, exiting program!");
error_handle();
} else {
polling_counter = 0;
}


api_ret = zmod4xxx_read_adc_result(&dev, adc_result);
if (api_ret) {
printf("ERROR %i during read of ADC results, exiting program!",
api_ret);
error_handle();
}
printf("\r\n"); //first 901 measurements are for stabilization
int z = 0;
for (int i = 0; i < ZMOD4510_ADC_DATA_LEN; i++) {
z += abs(adc_result[i]);
printf("adc[%i]=%i ", i, adc_result[i]);//kOhm
}


if (z == 0) {
printf(" WARN No ADC result, measurement[%i]\r\n", measurements_counter);
} else {
/* Humidity and temperature measurements are needed for ambient compensation.
*  It is highly recommended to have a real humidity and temperature sensor
*  for these values! */
humidity_pct = 50.0; // 50% RH
temperature_degc = 20.0; // 20 degC


// get sensor results with API
lib_ret = calc_oaq_2nd_gen(&algo_handle, &dev, adc_result, humidity_pct, temperature_degc, &algo_results);
if ((OAQ_2ND_GEN_STABILIZATION != lib_ret) && (OAQ_2ND_GEN_OK != lib_ret)) {
printf("ERROR when calculating algorithm, exiting program!");
error_handle();
} else {
//printf("\r\n*********** Measurements ***********\r\n");
//first 901 measurements are for stabilization
printf("\r\n measurement[%i]", measurements_counter);
for (int i = 0; i < 8; i++) {
printf(" Rmox[%i]=%4.2fk ", i, algo_results.rmox[i] / 1e3); //kOhm
}
printf(" O3_ppb=%4.2f", algo_results.O3_conc_ppb);
printf(" Fast AQI=%i", algo_results.FAST_AQI);
printf(" EPA AQI=%i", algo_results.EPA_AQI);
if (lib_ret == OAQ_2ND_GEN_STABILIZATION) {
printf(" Warmup!\r\n");
} else {
printf(" Valid!\r\n");
}
}
}
/* Delay (1980ms). This delay is necessary to keep the right measurement timing and
* call a measurement every 1.998 seconds with a maximum of 5% deviation.*/
psoc6_delay(1980);
}
void setup(void) {
int8_t ret;
zmod4xxx_err api_ret;
api_ret = init_hardware(&dev);
if (api_ret) {
printf("ERROR %i during initialize hardware, exiting program!\r\n\n", api_ret);
error_handle();
}
/* \x1b[2J\x1b[;H - ANSI ESC sequence for clear screen */
//printf("\x1b[2J\x1b[;H");
printf("*************************\r\n");
printf("PSoC 6 MCU I2C ZMOD4510 \r\n");
printf("**************************\r\n\n");


dev.i2c_addr = ZMOD4510_I2C_ADDR;
dev.pid = ZMOD4510_PID;
dev.init_conf = &zmod_oaq_sensor_type[INIT];
dev.meas_conf = &zmod_oaq_sensor_type[MEASURE];
dev.prod_data = prod_data;


api_ret = zmod4xxx_read_sensor_info(&dev);
printf("*****ZMOD4510 read the sensor info************\r\n\n");
if (api_ret) {
printf("ERROR %i ZMOD4510 during read the sensor info, exiting program!\r\n\n", api_ret);
error_handle();
}


printf("*****ZMOD4510 read the tracking number************\r\n");
uint8_t track_number[ZMOD4XXX_LEN_TRACKING];
api_ret = zmod4xxx_read_tracking_number(&dev, track_number);
if (api_ret) {
printf("ERROR %i during read the tracking number, exiting program!\r\n\n", api_ret);
error_handle();
}
printf("sensor tracking number: x");
for (uint8_t i=0;i<ZMOD4XXX_LEN_TRACKING;i++)
printf("%x",track_number[i]);
printf("\r\n");


printf("*****ZMOD4510 prepare the sensor************\r\n\n");
api_ret = zmod4xxx_prepare_sensor(&dev);
if (api_ret) {
printf("ERROR %i in the sensor preparation, exiting program!\r\n\n", api_ret);
error_handle();
}
printf("INFO *****ZMOD4510 the library initialization************\r\n\n");
ret = init_oaq_2nd_gen(&algo_handle, &dev);
if (ret) {
printf("ERROR %i during the library initialization, exiting program!\r\n\n", api_ret);
error_handle();
}
}


int main(void) {
setup();
printf("INFO *****ZMOD4510 measurements************\r\n\n");
for (;;) {
loop();
//psoc6_i2c_write(i2c_addr, reg_addr, buf, len);
/* Give delay between commands. */
//cyhal_system_delay_ms(CMD_TO_CMD_DELAY);
/* Read adc value */
//psoc6_i2c_read(i2c_addr, reg_addr, buf, len);
}
}

 

But I was getting the I2C Bus error. After some investigation, I've found the issue. The I2C example was configured to act as a master (control) and a slave (LED) at the same time. It was defined in resource_map.h file by I2C_MODE define, which was set to I2C_MODE_BOTH. After I've changed it to I2C_MODE_MASTER it started working without the I2C Bus error.

#define I2C_MODE                    (I2C_MODE_MASTER)

 

 

 

Logic Analyzer

 

The sensor board was interacting over the I2C protocol, but I was not able to initialize it properly and I was not been able to get valid readings from the sensor, I've got a strong suggestion from the ZMOD4510 support to use Logic Analyzer. Fortunately, I have one. I've connected it to the board and configured for I2C protocol.

image

So I've collected and compared the results of interaction between the sensor board and Arduino Nano 33 IoT and CY8CKIT-062S2-43012 by exporting data to Excel file. I found one difference. The Arduino code was not reading the sensor tracking number. But it is a required call according to the support.

 

ZMOD4510 findings

Another suggestion was to power off/on the sensor. And it really helped. The ZMOD4510 sensor has its own MCU and state. So the reset of Arduino Nano 33 IoT or CY8CKIT-062S2-43012 is not propagating to the sensor with a simple I2C connection. The power cycling of ZMOD4510 allowed resetting its state and proper initializing sequence.

 

I've started getting raw data from the sensor. At first, the sensor requires to make 901 measurements during warmup after each power cycling. As I need to wait 2 seconds between measurements it takes 30 minutes to get it to the operational state. This finding has a very important consequence. It needs to be constantly powered on or it requires in advance planning to turn it on for 30 minutes before it can be used to measure air quality.

 

adc[0]=17 adc[1]=124 adc[2]=242 adc[3]=138 adc[4]=204 adc[5]=207 adc[6]=195 adc[7]=28 adc[8]=193 adc[9]=221 adc[10]=192 adc[11]=119 adc[12]=191 adc[13]=229 adc[14]=191 adc[15]=42 adc[16]=190 adc[17]=74
 measurement[3] Rmox[0]=77282.53k  Rmox[1]=1039.17k  Rmox[2]=787.41k  Rmox[3]=762.24k  Rmox[4]=735.48k  Rmox[5]=724.98k  Rmox[6]=711.87k  Rmox[7]=696.65k  O3_ppb=0.00 Fast AQI=0 EPA AQI=0 Warmup!
...
adc[0]=17 adc[1]=98 adc[2]=229 adc[3]=139 adc[4]=107 adc[5]=14 adc[6]=96 adc[7]=226 adc[8]=96 adc[9]=84 adc[10]=95 adc[11]=164 adc[12]=95 adc[13]=251 adc[14]=95 adc[15]=140 adc[16]=95 adc[17]=109
 measurement[1146] Rmox[0]=3305.20k  Rmox[1]=143.40k  Rmox[2]=118.96k  Rmox[3]=117.73k  Rmox[4]=116.21k  Rmox[5]=116.96k  Rmox[6]=116.01k  Rmox[7]=115.74k  O3_ppb=0.00 Fast AQI=0 EPA AQI=0 Valid!

 

 

Another finding is that even I'm getting the readings from the sensor and they seem valid, I'm not getting the valid output from the ZMOD4510 algorithm. The key values are all equal to 0 ->

O3_ppb=0.00

Fast AQI=0

EPA AQI=0

O3_ppb=0.00 Fast AQI=0 EPA AQI=0

I may need to investigate further why it is the case. Maybe the FPU library is not configured properly or some other issues.

 

Update #1

I've switched to M4F arm-none-eabi-gcc library ( lib_oaq_2nd_gen.a ) and switched VFP_SELECT to hardfp in the Makefile. But I've got the same result from the algorithm output again.

  • Sign in to reply
  • marwa
    marwa over 3 years ago

    can you tell me please why the value of RMOX[0]  is more higher then other Rmox[1,2,3....]

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • marwa
    marwa over 3 years ago

    can you please explain to me why it gives 8 number of ROX     and why ROX(0) is more higher then other  Rox1,2,3,4,5,6,7

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • marwa
    marwa over 3 years ago

    can you please explain to me why it gives 8 number of ROX     and why ROX(0) is òor hiyer then other 

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • vlasov01
    vlasov01 over 4 years ago in reply to asokfair

    Yes, it is required based on my understanding of the documentation: "First 901 samples used for sensor stabilization." And it requires a delay of "1.998 seconds with a maximum of 5% deviation" between measurements.

    But it has a very low power budget. So it may be not an issue to keep it on all the time for many use cases like air quality monitor.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • asokfair
    asokfair over 4 years ago

    Oh my god , that's bad 30mins wait time ! Its required on every power cycle?

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2026 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube