In the previous blog, I shared the PSoC Creator projects to interface a PSoC 6 device with the DHT-11 sensor. The previous blog also covered details regarding the DHT-11 sensor and its working. In this blog, we will be creating the project on ModusToolbox 2.1 to achieve the same functionality with a few additional features. You can download ModusToolbox 2.1 here and learn about the new exciting features of ModusToolbox 2.1 release here.
We will start by creating an Empty_PSoC6_App. You can create a new project by clicking on New Application in Quick Panel. Select the BSP of your choice. I will be using the CY8CPROTO-062-4343W Kit for this blog. Select the Empty_PSoC6_App, you can rename the project if needed. Click on Create. You can even create the project using the CLI option which you can learn more about here.
Now that we have an empty project ready, we need to add the libraries that we will be using for this project. In this project, we will be using the retarget-io and the FreeRTOS middleware libraries. To do that, click on Library Manager under Tools in the Quick Panel and select retarget-io (under Board Utils) and freertos (under PSoC 6 Middleware) as shown. You can now build the project to confirm that there are no errors so far. The ‘project directory’ is now the ‘application directory’. So, in this case, the application directory will be the folder Empty_PSoC6_App or the name of your application in case you have renamed it.
I have predominantly used the code from the Temperature_Sensor_Direct project from my previous blog. The PSoC Creator project was created using PDL. The project would still work if I just copy the entire code and place it in the main.c file. All I have to do is select the right pin in the Device Configurator and name it accordingly. But the problem here is that this makes my project device-dependent. What I mean by this is that if at all I change my device, I will have to reconfigure the pin. With the release of ModusToolbox 2.0 and 2.1, you would have noticed most of us talk about ‘device agnosticity’. The idea is that the project should work without any changes even when the device is changed. If you are just curious and you want to try out your project on all your devices or if you are as fickle-minded as I am you will soon realize that this is a lifesaver, especially in a project that uses a lot of hardware blocks.
To achieve that, I will be using the Hardware Abstraction Layer (HAL) and the Board Support Package (BSP) feature. HAL allows me to easily initialize all my hardware resources in my source code and BSP takes care of the pin allotment of some of the common resources in each device. For example, if I have to use an LED that is on my kit, I can just use the CYBSP_USER_LED macro. This macro is defined specific to each device. Now even if I change my device, I can be assured that I will be using the appropriate LED pin itself. I will be talking in detail about how these features are used in the project when going through each of the source files.
In this project, I have also used FreeRTOS to create separate tasks so that each task can just be picked up and used in any FreeRTOS project.
To keep the code modular and perspicuous, I have separated the application into three source files –
main.c file contains the initialization code and the task creation code. You can consider this as the master code and in this file, the FreeRTOS scheduler is started. All the pin/middleware initialization code can be found here. The code first initializes the device and board peripherals and the hardware manager. Next, the retarget-io is initialized. Retarget-io allows you to transmit messages to and from the board via standard printf/scanf functions using a UART SCB block. Just by including cy_retarget_io.h file and initializing the middleware you can use printf and scanf statements directly. So, it saves the time and effort needed to manually map the printf/scanf functions to the UART block. The DATA pin is initialized as shown below –Each HAL API starts with cyhal followed by the name of the driver and then the functionality. In this case, the API initializes a GPIO pin. The LED is also initialized in a similar way. You can refer to the following link to learn about the different HAL drivers and their usage: HAL Documentation.
The next part is the initialization of FreeRTOS objects. A queue is used for communication of sensor readings between the tasks. The queue-handle is passed as an argument to the tasks. The two tasks, namely, DHT_Task and Print_Task are created with DHT_Task having a higher priority.
Moving on to dht_task.c file. As I have mentioned before, this primarily consists of the code used in the Temperature_Sensor_Direct project. I have changed the PDL functions to its HAL counterparts –
- CY_GPIO_Write() => cyhal_gpio_write()
- CY_GPIO_Read() => cyhal_gpio_read()
- CyDelay() => cyhal_system_delay_ms()
- CyDelayUs() => cyhal_system_delay_us()
The task reads the sensor values and if the value is valid, an LED is toggled, and the readings are sent to a queue. If the queue is full, the task will wait until the queue has a vacancy. Now in case there is a connection failure or the sensor values read are not valid, the error code along with the previous data is sent to the queue. As the sampling rate of the sensor is approximately 2 seconds the task then goes into the blocked state for 2 seconds. After this, the cycle repeats.
print_task.c, as the name suggests, contains the Print_Task function. This task has the lowest priority and executes only when all other tasks are in the blocked state. It receives the sensor reading from the queue and prints the value into the serial terminal. If the queue is empty, the task enters the blocked state until DHT_Task sends the reading to the queue.
I have attached all the .c/.h files, put in source folder, with this blog. You can go ahead and place this folder in the application directory of the new project that you created and delete the default main.c that was in the project. That’s it! The auto-discovery feature in ModusToolbox will take care of the rest. No more ‘Add to Project’!
You can build the project, program the device, and connect the sensor and voila! you now have a simple FreeRTOS project to read the temperature and humidity value using the DHT-11 sensor and print it on a serial terminal. The best part is that it is a ModusToolbox 2.1 project! For your reference, the entire project is shared on our Community Code Examples Git Repo and you can check it out using this link. To know how to import the project, refer to the ReadMe file.
Hopefully, by now you will have a basic idea on how to use ModusToolbox 2.1 to develop simple FreeRTOS applications.
Here are a couple of things you can do next:
> Try changing the BSP in Library Manager and programming a different device to check out the device-agnostic feature.
> The task is in the blocked state for 2 seconds which means that the PSoC 6 is in the idle state most of the time. You can try exploring the low power capability of PSoC 6. Keep in mind that you should be using the Tickless Idle Mode capability of FreeRTOS for this to work. You can use this code example for reference - CE223508 – PSoC 6 MCU Implementing BLE Multi-connection (4 Slaves)
> You can combine this task with any other FreeRTOS task and create an application. Feel free to post your cool applications and share them with the community!