Code Examples Forum Discussions
This code example can be used for interfacing of XENSIVTM Photoacoustic Spectroscopy (PAS) CO2 sensor with PSoC6 via I2C using available PSoC6 library. The document then explains the extension of the implementation to a CO2 traffic light.
Introduction
The document describes the procedure to interface XENSIV™ PAS CO2 sensor with PSoC6 evaluation board. The basic implementation covers the interfacing the sensor with PSoC6 and the CO2 levels measured is printed in the serial terminal. In this article based on the measured CO2 levels, three LED’s of different colors (green, orange/yellow and red) are individually turned on.
Hardware
The hardware required for the implementation are
- PSoC™ 6 Wi-Fi Bluetooth® pioneer kit
- XENSIV™ PAS CO2 mini-evaluation board or XENSIVTM PAS CO2 Shield2Go board
Figure 1. (a) XENSIV™ PAS CO2 Mini Evaluation Board (b) XENSIV™ PAS CO2 Shield2Go board
The setup using PAS CO2 mini evaluation board can be understood from the figure shown below.
Figure 2. Wiring connection for interfacing XENSIVTM PAS CO2 mini-evaluation board with PSoC™ 6 Wi-Fi Bluetooth® pioneer kit via I2C
The 12 V required for the sensor operation needs to be supplied externally. Please also keep the ground common in all the connections to ensure proper functionality.
PAS CO2 Shield2Go board can be used instead of the mini-evaluation board. The Shield2Go board can be interfaced with the PSoC™ 6 Wi-Fi Bluetooth® pioneer kit as shown in the figure below. Here the advantage is that there is no need for providing 12 V externally.
Figure 3. Wiring connection for interfacing XENSIVTM PAS CO2 Shield2Go board with PSoC™ 6 Wi-Fi Bluetooth® pioneer kit, via I2C
Once the hardware setup is ready, using any of the above options, please proceed to the software setup mentioned in the next section.
Software Setup
Steps required for the software implementation are listed below
Step 1: Please follow the steps from https://github.com/Infineon/sensor-xensiv-pasco2 to have the initial software setup in Modus Toolbox
Step 2: Include the following code for defining the GPIO pins for controlling red, yellow/orange and green LEDs. The calculated CO2 ppm values needs to be compared and used to determine the states of LED’s. For that purpose, a comparator loop can be added as shown below.
#include "cyhal.h"
#include "cybsp.h"
#include "cy_retarget_io.h"
#include "xensiv_pasco2_mtb.h"
/*******************************************************************************
* Macros
*******************************************************************************/
#define PIN_XENSIV_PASCO2_I2C_SDA CYBSP_I2C_SDA
#define PIN_XENSIV_PASCO2_I2C_SCL CYBSP_I2C_SCL
#if defined(USE_CYSBSYSDEV_KIT_01_WINGBOARD)
/* Output pin for sensor PSEL line */
#define PIN_XENSIV_PASCO2_PSEL P5_3
/* Output pin for PAS CO2 Wing Board power switch */
#define PIN_XENSIV_PASCO2_POWER_SWITCH P10_5
#endif
#define I2C_MASTER_FREQUENCY (100000U)
/* Wait time for sensor ready (milliseconds) */
#define WAIT_SENSOR_RDY_MS (2000)
/* The CO2 concentration value acquired by the sensor depends on the external atmospheric pressure.
To compensate for this effect, pressure values can be acquired from a pressure sensor such as an
Infineon XENSIV™ DPS3xx. (https://github.com/Infineon/sensor-xensiv-dps3xx) */
#define DEFAULT_PRESSURE_REF_HPA (0x3F7) /* Default atmospheric pressure to compensate for (hPa) */
/*Defining GPIO pins for LEDs*/
#define PIN_R P9_1
#define PIN_Y P9_4
#define PIN_G P9_7
/***********************************/
/*******************************************************************************
* Global Variables
*******************************************************************************/
static cyhal_i2c_t cyhal_i2c;
static xensiv_pasco2_t xensiv_pasco2;
int main(void)
{
/*Initializing GPIO pins for LEDs*/
cyhal_gpio_init(PIN_R, CYHAL_GPIO_DIR_OUTPUT,CYHAL_GPIO_DRIVE_STRONG, false);
cyhal_gpio_init(PIN_Y, CYHAL_GPIO_DIR_OUTPUT,CYHAL_GPIO_DRIVE_STRONG, false);
cyhal_gpio_init(PIN_G, CYHAL_GPIO_DIR_OUTPUT,CYHAL_GPIO_DRIVE_STRONG, false);
cy_rslt_t result = CY_RSLT_SUCCESS;
/* Initialize the device and board peripherals */
result = cybsp_init();
CY_ASSERT(result == CY_RSLT_SUCCESS);
__enable_irq();
/* Initialize retarget-io to use the debug UART port. */
result = cy_retarget_io_init(CYBSP_DEBUG_UART_TX, CYBSP_DEBUG_UART_RX, CY_RETARGET_IO_BAUDRATE);
CY_ASSERT(result == CY_RSLT_SUCCESS);
printf("XENSIV PAS CO2 Example\r\n");
/* Initialize I2C */
cyhal_i2c_cfg_t i2c_master_config = {CYHAL_I2C_MODE_MASTER,
0,
I2C_MASTER_FREQUENCY};
result = cyhal_i2c_init(&cyhal_i2c, PIN_XENSIV_PASCO2_I2C_SDA, PIN_XENSIV_PASCO2_I2C_SCL, NULL);
CY_ASSERT(result == CY_RSLT_SUCCESS);
result = cyhal_i2c_configure(&cyhal_i2c, &i2c_master_config);
CY_ASSERT(result == CY_RSLT_SUCCESS);
#if defined(USE_CYSBSYSDEV_KIT_01_WINGBOARD)
/* Initialize and enable PAS CO2 Wing Board I2C channel communication*/
result = cyhal_gpio_init(PIN_XENSIV_PASCO2_PSEL, CYHAL_GPIO_DIR_OUTPUT, CYHAL_GPIO_DRIVE_STRONG, false);
CY_ASSERT(result == CY_RSLT_SUCCESS);
/* Initialize and enable PAS CO2 Wing Board power switch */
result = cyhal_gpio_init(PIN_XENSIV_PASCO2_POWER_SWITCH, CYHAL_GPIO_DIR_OUTPUT, CYHAL_GPIO_DRIVE_STRONG, true);
CY_ASSERT(result == CY_RSLT_SUCCESS);
#endif
cyhal_system_delay_ms(WAIT_SENSOR_RDY_MS);
/* Initialize PAS CO2 sensor with default parameter values */
result = xensiv_pasco2_mtb_init_i2c(&xensiv_pasco2, &cyhal_i2c);
if (result != CY_RSLT_SUCCESS)
{
printf("PAS CO2 device initialization error");
CY_ASSERT(0);
}
#if defined(USE_CYSBSYSDEV_KIT_01_WINGBOARD)
/* Configure PAS CO2 Wing board interrupt to enable 12V boost converter in wingboard */
xensiv_pasco2_interrupt_config_t int_config =
{
.b.int_func = XENSIV_PASCO2_INTERRUPT_FUNCTION_NONE,
.b.int_typ = (uint32_t)XENSIV_PASCO2_INTERRUPT_TYPE_LOW_ACTIVE
};
result = xensiv_pasco2_set_interrupt_config(&xensiv_pasco2, int_config);
if (result != CY_RSLT_SUCCESS)
{
printf("PAS CO2 interrupt configuration error");
CY_ASSERT(0);
}
#endif
uint16_t ppm;
/*Defining CO2 ppm levels for safe and warning*/
uint16_t co2ppmsafe = 800;
uint16_t co2ppmwarn = 1100;
for (;;)
{
result = xensiv_pasco2_mtb_read(&xensiv_pasco2, DEFAULT_PRESSURE_REF_HPA, &ppm);
if (result == CY_RSLT_SUCCESS)
{
printf("CO2 %d ppm.\r\n", ppm);
if(ppm<=co2ppmsafe)
{
cyhal_gpio_write(PIN_G,true);
cyhal_gpio_write(PIN_Y,0);
cyhal_gpio_write(PIN_R,0);
}
else if(ppm>co2ppmsafe && ppm<=co2ppmwarn)
{
cyhal_gpio_write(PIN_G,0);
cyhal_gpio_write(PIN_Y,true);
cyhal_gpio_write(PIN_R,0);
}
else if (ppm>co2ppmwarn)
{
cyhal_gpio_write(PIN_G,0);
cyhal_gpio_write(PIN_Y,0);
cyhal_gpio_write(PIN_R,true);
}
}
cyhal_system_delay_ms(10);
}
}
Step 3: The output can be seen in the terminal as shown in Figure 4.
Figure 4. CO2 ppm levels being printed in the serial terminal
The LED’s will be turned on/off based on the CO2 ppm values measured as seen in Figure 5.
Figure 5. LEDs showing the status of CO2 ppm levels, (a) safe state, (b) warning state and (c) danger state
Green LED can show that the environment is safe. Orange/Yellow LED can show a warning state and can be used to initiate some preventive measures. The preventive measures can be as simple as controlling the air conditioning unit or opening the windows. The Red LED can indicate a worst working environment and should be followed by strict actions like vacating the room. A better understanding of effects of CO2 levels on human comfort levels can be understood from Figure 6.
Figure 6. Human comfort levels based on CO2 ppm levels
Working condition is very comfortable for CO2 levels below 800 ppm. Beyond this level the conditions start deteriorating and working condition becomes difficult as CO2 levels reaches 1200 ppm. It is not recommended to continue working with CO2 levels more than 1200 ppm and is considered danger. Continuing working in these conditions can cause headache and sleepiness initially. Further higher levels of CO2 is harmful for human life and is extremely dangerous.
References
Show LessDescription Overview
I wrote code to make a sound using the slider of the CY8CKIT-042 PSoC 4 Pioneer Kit.
1. Get a position on the slider.
2. Set the PWM value according to the location and output as sound.
3. If the position changes, change the value of PWM.
4. If the finger is separated, the PWM output stops.
Prerequisites
• Evaluation Board: CY8CKIT-042 PSoC 4 Pioneer Kit
• Piezoelectric buzzer
• IDE name: PSoC Creator 4.4
procedure
1.P3.5 and GND Connected the buzzer to the PIN.
2. Run the project attached to this topic and touch the slider on the evaluation board with your finger to make a sound.
If you want to change the connection of the buzzer, please change it from the Pin settings.
Show Less
Dears,
please find my solution for the calculation of the parity value for 32-bit data words in 64K SRAM blocks with 32-bit access attached. The code is based on the algorithm described in the TRAVEO™ T2G Automotive Body Controller
Entry Family Architecture TRM, Document No. 002-19314 Rev. *H, section 10.3.4 ECC Parity Generation by Software.
The function uint8_t ECC32_RAM_parity(uint32_t ram_addr, uint32_t data) returns the correct parity value when called with the ram_address (has to be 32 bit alligned) and the data stored in this address.
Use this function also to calculate parity values for data with one or more bit errors.
There are examples in the SDL with correct parity values:
SDL 7.8.0, T2G_Sample_Driver_Library_7.8.0\tviibe1m\src\examples\sram\ecc\main_cm0plus.c.
Excerpt:
#define RAM_0_ADDRESS (0x08000800)
#define RAM_0_DATA (0x5A5A5A5A)
#define RAM_0_CORRECT_PARITY (0x6E)
#define RAM_0_ONEBIT_PARITY (0x6F)
#define RAM_0_TWOBIT_PARITY (0x6D)
If you ask me, #define RAM_0_ONEBIT_PARITY (0x6F) is an error. The parity value for data 5a5a5a5a with a one bit toggle error should be one of 2d, 2b, 28, 27, 24, 65, 22, 63, 60, 3f, 3c, 7d, 3a, 7b, 78, 36, 74, 72, f, c, 4d, a, 4b, 48, 6, 47, 44, 42, 1e, 5f, 5c, 56, all values in hex, depending on the bit location 0..31 of the toggled bit.
The presented parity value for a two bit error 0x6D I did not verify.
Please be aware that the attached code example is not tested and for educational purposes only. Expect errors and omissions. Do not use it in a real application. Best write and test your own code.
BR
JJack
Show Less
This is a code example which is used to interface the TLE5012B angle sensor in the TLE9879 board. This helps in receiving the angular information about the motor which is present on TLE9879 board. Please look at the pictures attached for configuration details. TLE9879 EVALKIT
Show Less
Different radar configurations between set of frames are required to enable different kinds of measurements simultaneously.
For example, To have a different number of chirps per frame between the first few frames and the next few frames. Alternatively, when someone requires a specific number of samples per chirp in the first few frames and a different number of samples per chirp in the next few frames.
For instance, if one needs to have 64 samples per chirp for first 10 frames and 256 samples per chirp for the next 10 frames. Or, if one wants first 5 frames to have 16 chirps per frame and next 5 to have 128 chirps per frame.
This code example demonstrates how this can be achieved on DEMO BGT60TR13C radar using Python and ifxAvian Library. Below is a template for the same, and a code example is also attached below.
define config1
define config2
while(...)
{
setConfig(config1)
for(...)
{
get_next_frame()
processFrame()
...}
stop_acquisition()
setConfig(config2)
for(...)
{
get_next_frame()
processFrame()
...}
stop_acquisition()
}
Output: It can be observed in the output on how the max_range and speed_resolution are changing between two sets of frames.
Show Less
Hi,
I am looking for the CY3635 Wireless USB N:1 DVK hub/sensor firmware. I can only find the host software/docs below. I need the PSoC firmware i.e. the .c and .h files.
Show Less
Hi,
Here is my code sample of measuring a pin capacitance using the CapSense component.
I used CY8CKIT-044 but I hope that porting this to ather PSoC 4 which is supporting CapSense won't be difficult.
The key function is "CapSense_GetSensorCapacitance()" which is available only when "Enable self-test library" is checked.
I've used this function a few times before, but as usual I mislocated my code(s).
So this time I decide that to post this sample here will be useful (at least for me).
Schematic
CapSense configuration
[ Basic Tab]
CSD tuning mode : SmartSense (Hardware parameters only)
"SmartSense (Full Auto-Tune)" is not supported for the "self-test library"
[ Advanced Tab]
"Enable self-test library" is checked.
Pins
Note: I used P3[4] which is a built in electrode of CY8CKIT-044
but any pin supported by the CapSense component should work.
Tera Term log
main.c
#include "project.h"
#include "stdio.h"
#define TEXT_LEN 64
char str[TEXT_LEN+1] ;
#define print(s) UART_UartPutString(s)
void cls(void)
{
print("\x1b[2J") ;
CyDelay(100) ;
print("\x1b[;H") ;
CyDelay(100) ;
}
void splash(char *title)
{
cls() ;
snprintf(str, TEXT_LEN, "%s (%s %s)\n\r",title, __DATE__, __TIME__) ;
print(str) ;
}
volatile int sw2_pushed = 0 ;
CY_ISR(sw2_isr)
{
SW2_ClearInterrupt() ;
sw2_pushed = 1 ;
}
void init_hardware(void)
{
CyGlobalIntEnable; /* Enable global interrupts. */
UART_Start() ;
SW2_ClearInterrupt() ;
sw2_int_ClearPending() ;
sw2_int_StartEx(sw2_isr) ;
CapSense_Start() ;
}
void print_measure_error(uint32_t status)
{
switch(status) {
case CapSense_TST_MEASUREMENT_SUCCESS: print("SUCCESS") ; break ;
case CapSense_TST_MEASUREMENT_BAD_PARAM: print("BAD PARAM") ; break ;
case CapSense_TST_MEASUREMENT_LOW_LIMIT: print("LOW LIMIT") ; break ;
case CapSense_TST_MEASUREMENT_HIGH_LIMIT: print("HIGH LIMIT") ; break ;
case CapSense_TST_MEASUREMENT_ERROR: print("Measurement Error") ; break ;
default:
snprintf(str, TEXT_LEN, "Unknown Error: 0x%08X", status) ;
print(str) ;
break ;
}
print("\n\r") ;
}
uint32_t button_cap = 0u ;
void measure_cap(void)
{
CapSense_TST_MEASUREMENT_STATUS_ENUM measurementStatus ;
while(CapSense_NOT_BUSY != CapSense_IsBusy()) {
/* wait for capsence to be free */
}
button_cap = CapSense_GetSensorCapacitance(
CapSense_BUTTON0_WDGT_ID,
CapSense_BUTTON0_SNS0_ID,
&measurementStatus) ;
if (measurementStatus == CapSense_TST_MEASUREMENT_SUCCESS) {
snprintf(str, TEXT_LEN, "capacitance: %d.%03d pF\n\r",
button_cap/1000, button_cap % 1000) ;
print(str) ;
} else {
print_measure_error(measurementStatus) ;
}
}
int main(void)
{
init_hardware() ;
splash("Pin Capacitance Measure Test") ;
print("Push SW2 to measure\n\r") ;
for(;;)
{
if (sw2_pushed) {
sw2_pushed = 0 ;
measure_cap() ;
}
}
}
Some more background
There was a discussion about measuring a pin capacitance.
https://community.infineon.com/t5/PSoC-4/Analog-Digital-pin-control/m-p/455832#M45427
After I posted my sample, I noticed that there was a typo in the comment.
/* wait for capsent to be free */
So I wanted to fix it, then I noticed another minor problem which is in case the measurement encounters an error,
the printed error message does not have a new line, so next message will be printed just after that error message.
After all, although basic function has not been changed, some more touch ups were applied from my previous post.
(1) Typo in a comment
(2) New line added after error report
(3) Clear pending pin interrupts before starting the ISR
(4) Some code clean ups
(5) The value was in fF, now shown in pF
(6) Schematic rearranged (no functional changes)
moto
Show Less
This example demonstrates RTOS use case with semaphores to trigger tasks using FreeRTOS on two cores separately.
- LEDs will blink in sequence based on the way semaphores are activated.
- Three tasks are configured and used with for each CM7 core.
Test environment:
- CYTVII-B-H-8M-320-CPU Rev. C Board
- CYTVII-B-E-BB Rev.A Board
- IAR version 8.42
- SDL version 7.7.0
Description Overview
Attached project outputs the following signals
1. PWM signal (2) that rises with a fixed time delay(3) relative to the rising and falling edge of the PWM signal (1)
2. (1) Period = (2) Period × 2
3. Update the High width of (1) and (3) during operation
Required Environment
• Evaluation board: KIT_A2G_TC364_5V_TRB_S (Starter Kit containing TC364 Triboard, using LQFP version )
• IDE name: ADS 1.5.4
• Oscilloscope
• ADS project attached below
procedure
1. Connect oscilloscope probes to P13.2 and P13.0.
2. When the project attached to this topic is operated, the waveform shown in the image below can be observed, in which the High width and DELAY of the second PWM (2) change periodically.
Software Protection Units (SWPU) is one of the four protection units implemented in TRAVEOTM T2G devices. It is further classified into:
- Flash Write Protection Units (FWPU)
- eFuse Write Protection Units (EWPU)
- eFuse Read Protection Units (ERPU)
This code example explains the usage of FWPU for creating Hardware Security Module (HSM) exclusive flash region (For more information refer - AN219843 Protection configuration in TRAVEO™ T2G MCU . For further information on SWPU, refer Section 6.5 in TRAVEOTM T2G Technical Reference Manual).
HSM flash region refers to the memory region which contains the HSM core’s firmware and the application. In TRAVEOTM T2G, HSM core refers to the ARM® Cortex® M0+ CPU and HSM client refers to the ARM® Cortex® M4 or M7 CPU. It is thus essential to ensure only the HSM core or the appropriate bus masters of the microcontroller can access to this region.
In this example, the HSM core configures an FWPU region in supervisory flash (SFLASH) with the appropriate access attributes. This provides write protection for the HSM flash region. The HSM client tries to erase this region using the system call “erase sector”. This request fails because the HSM client has different access attributes than the configured FWPU. We will see the return status code of the system call.
The code was developed in IAR Embedded Workbench for ARM® (EWARM) with Sample Driver Library (SDL). The code example uses TRAVEOTM II Body Entry kit board. The IAR linker scripts in SDL has predefined section named “sflash_app_prot” which spans over the SFLASH region (0x1700_7600 – 0x1700_77FF). This is where the SWPU object is placed.
The following points describe the working of the attached program files.
“main_cm0plus.c”:
- Initialization of necessary macros and access attributes.
- Configuration of the structure “cy_stc_si_app_prot_t” for defining FWPU with necessary access attributes. Placing the same in section “sflash_app_prot” in SFLASH.
- Configuration of access attributes of HSM client and setting active Protection Context (PC) of HSM client as PC3.
- Enabling the HSM client.
“main_cm4.c”:
- Initialization of necessary macros and objects for invoking a system call.
- Invoking the system call “erase sector” in blocking mode over the FWPU protected region.
- Updating the return value variable “apiStatus” with the response status code of the system call.
The “cy_si_config.h” file contains the necessary structure definitions for the structure “cy_stc_si_app_prot_t”. The return value “apiStatus” gets updated with a value “f000’0005” as shown in Figure 1. This means “FLASH or eFuse bytes are read/write protected via protection units” (Refer Section 37.5 of TRAVEOTM T2G Technical Reference Manual).
Figure 1: apiStatus return value
Thus, by configuring an FWPU object with the appropriate access attributes, we have shown that the execution of the system call “erase sector” is blocked and the corresponding return status code of the system call is updated.
NOTE :
- The register “PROT_SMPU_MS14_CTL” that is responsible for configuring the access attributes of the HSM client can be further protected by configuring the appropriate fixed Peripheral Protection Unit (PPU) that protects the access to this register. This ensures that once this fixed PPU is set, the HSM client won’t have access to this register anymore and thus can’t revert the register back to its default value.
- If any system calls are requested over an FWPU protected region, it is the requestor’s access attributes that are evaluated against FWPU access attributes.
- Configuring a Shared Memory Protection Unit (SMPU) over the HSM flash region gives flash read protection only and not flash write protection. Configuring an FWPU is the only way to provide flash write protection.