Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
en:iot-open:practical:hardware:sut:stm32:emb9b_1 [2024/03/02 22:27] – [FAQ] ktokarzen:iot-open:practical:hardware:sut:stm32:emb9b_1 [2024/05/02 12:02] (current) – created ktokarz
Line 1: Line 1:
-====== STM_9AUse of RGB LEDs ===== +====== STM_9BReading colour sensor ===== 
-This scenario presents how to handle the brightness control of the tri-coloured LEDsOne is observable via cameraas presented in the figure (component 9A), while another is hidden inside the black enclosure and lights a colour sensor (component 9B)Both LEDs are electrically bound and cannot be controlled independently. Those LEDs have 3 colour channels, controlled independentlyR (Red), G (Green) and B (Blue)Mixing of those colours creates other ones, such as pink and violet. Each R G B channel can be controlled with a separate GPIO to switch it on or off or control brightness using a PWM signal, as presented in this tutorial.+A colour sensor (TCS 34725) can detect the brightness and colour of the light emitted. It works with the I2C busIn our laboratory, the sensor has a fixed 0x29 address. The sensor is in the black enclosure, ensuring no ambient light impacts readingsThe only light source is an RGB LED, controlled as described in the scenario [[en:iot-open:practical:hardware:sut:stm32:emb9a_1|]]This is another LED connected parallel to the one you can observe in the camera.
  
 ===== Prerequisites ===== ===== Prerequisites =====
-A good understanding of the PWM signal and duty cycle is necessary. We also use built-in timers to control the PWM hardware channels of the STM32WB55 chip. In this casewe do not use an external library; insteadwe use the hardware timer library built in the Arduino framework for STM32WB55 so that no additional external libraries will be included in the project.+To implement this scenario, it is necessary to get familiar with at least one of the following scenarios first: 
 +  * [[en:iot-open:practical:hardware:sut:stm32:emb5_1|]], 
 +  * [[en:iot-open:practical:hardware:sut:stm32:emb6_1|]], 
 +  * [[en:iot-open:practical:hardware:sut:stm32:emb7_1|]], 
 +and obligatory: 
 +  * [[en:iot-open:practical:hardware:sut:stm32:emb9a_1|]].
  
 +To simplify TCS sensor use, we will use a dedicated library:
 +<code bash>
 +lib_deps = adafruit/Adafruit TCS34725@^1.4.4
 +</code>
 +<note important>Also, remember to add the LCD handling library, as present in the EMB9 scenario, unless you decide to use another output device.</note>
 ===== Suggested Readings and Knowledge Resources ===== ===== Suggested Readings and Knowledge Resources =====
   * [[en:iot-open:introductiontoembeddedprogramming2:cppfundamentals]]   * [[en:iot-open:introductiontoembeddedprogramming2:cppfundamentals]]
-  * [[en:iot-open:hardware2:stm32]] +  * [[en:iot-open:hardware2:stm32|]]
-  * [[en:iot-open:hardware2:actuators_light|]]+
   * [[en:iot-open:practical:hardware:sut:stm32|]]   * [[en:iot-open:practical:hardware:sut:stm32|]]
-  * [[en:iot-open:embeddedcommunicationprotocols2:pwm|]]+  * [[en:iot-open:embeddedcommunicationprotocols2:twi|]] 
 +  * [[en:iot-open:hardware2:sensors_optical|]] 
 +  * [[https://cdn-shop.adafruit.com/datasheets/TCS34725.pdf|TCS sensor documentation]]
 ===== Hands-on Lab Scenario ===== ===== Hands-on Lab Scenario =====
  
 ==== Task to be implemented ==== ==== Task to be implemented ====
-Implement program that will light LEDs consecutively with R, G, and BUse 50% of the maximum brightnessUse a PWM signal to control each GPIO for R, G and B, each colour separately to let you easily observe itYou can also experiment with various duty cycle settings for all channels to obtain different LED colours.+Create solution where you control an RGB LED and read its colour and brightness using a TCS sensorPresent results on the LCD, e.g. in the form of "Colour: <value>" where "value" refers to the colour intensity. You should change LED brightness at least 10 times (10 different brightness) for each colour while continuously reading the TCS sensor and presenting data in the LCD. Experiment with mixing colours and check either the sensor can distinguish brightness separately, when i.e. both RGD LED's colours are on: Red+Green or Red+Blue (or any other combination you wish). 
 + 
 +<note tip>There are at least two ways to handle this task: 
 +  * simple: a dummy loop where you set RGB LED values, read from TCS and display on LCD, 
 +  * advanced: where the data is read and presented on the LCD in one or two asynchronous routines run by timers. 
 +</note> 
  
 ==== Start ==== ==== Start ====
-The hardware timer library implements functions which allow us to control the duty cycle of the PWM signal and express it in percentages. In the laboratory equipment, all three LEDs are connected to one hardware timer instanceThanks to this LEDs operate as three separate channels of a single timer. +Check if you can see the LCD and RGB LED in the camera view 
-As the PWM duty cycle is expressed in percentages, the minimum value is 0, and the max (full brightness) is 100. Note that full brightness may be too bright for the observation camera, so consider using a range between 0 and 50%.+<note important>Remember not to use the full brightness of the RGB LED because you won'be able to observe other elements due to the camera's low dynamics. Assuming you express duty cycle in percentswe suggest a range between 0 and 50.</note>
  
 ==== Steps ==== ==== Steps ====
-To use PWM in STM32WB55it is best to use a built-in hardware timer library.  +In the steps belowwe present only the part for reading from the TCS sensorControl of RGB LED with PWM and handling LCD is presented in the other lab scenarios that you need to follow accordingly and merge with the code below. 
-<code> +
-#include <HardwareTimer.h> +
-</code> +
-The hardware timer uses internal timer modules and allows us to define channels attached to the timerWe will use 1 channel per colour (R, G and B, so 3 in total). A PWM frequency is controlled with the timer to be shared for all 3 R, G and B channels. Channels control the PWM duty cycle.+
 === Step 1 === === Step 1 ===
-Include the library, and define PIN assignments to channels and PWM frequency (100Hz):+Included necessary libraries:
 <code c> <code c>
-#include <HardwareTimer.h> +#include <Wire.h> 
- +#include "Adafruit_TCS34725.h"
-// Pins definition for RGB LED +
-#define LED_PWM_GREEN D3  //Arduino numbering D3, STM numbering PA_10 +
-#define LED_PWM_BLUE  D6  //Arduino numbering D6, STM numbering PA_8 +
-#define LED_PWM_RED   D9  //Arduino numbering D9, STM numbering PA_9 +
- +
-#define PWM_freq 100+
 </code> </code>
-GPIO pins controlling  LEDS are D9 (Red), D3 (Green) and D6 (Blue), respectively. 
  
 === Step 2 === === Step 2 ===
-Define variables for the timer object and handlers of channels.+Declare and instantiate TCS controller class and related variables for readings:
 <code c> <code c>
-// PWM variables definitions +static Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_300MS, TCS34725_GAIN_1X)
-HardwareTimer *MyTimLED              //Hardware Timer for PWM +uint16_t rgb, c, colorTemp, lux; 
-uint32_t channelRchannelGchannelB//RGB channels+static bool isTCSOk = false;
 </code> </code>
 +A word of explanation regarding the parameters: 
 +  * ''TCS34725_INTEGRATIONTIME_300MS'' is time in ms while the TCS sensor is exposed for the light to grab readings,
 +  * ''TCS34725_GAIN_1X'' is the sensor's gain - it helps reading in low light, but that is not true in our lab as our RGB LED light sensor is very bright, even in low duty cycle.
 +
 +Refer to the Q&A section for the ranges. 
  
-Instantiate the timer object and initialise the channels for PWM and make them dark (1% duty cycle):+=== Step === 
 +Initialise the sensor (in ''void Setup()'') and check it is OK:
 <code c> <code c>
-//Create Timer instance type based on the chosen LED pin (the same timer is used for all LEDs).   +  isTCSOk tcs.begin();
-TIM_TypeDef *Instance (TIM_TypeDef *)pinmap_peripheral(digitalPinToPinName(LED_PWM_RED), PinMap_PWM); +
-     +
-//Define three separate channels for LEDs +
-channelR = STM_PIN_CHANNEL(pinmap_function(digitalPinToPinName(LED_PWM_RED), PinMap_PWM)); +
-channelG = STM_PIN_CHANNEL(pinmap_function(digitalPinToPinName(LED_PWM_GREEN), PinMap_PWM)); +
-channelB = STM_PIN_CHANNEL(pinmap_function(digitalPinToPinName(LED_PWM_BLUE), PinMap_PWM)); +
- +
-// Instantiate HardwareTimer objectThanks to 'new' instantiation, HardwareTimer is not destructed when setup() function is finished. +
-MyTimLED = new HardwareTimer(Instance); +
- +
-// Configure and start PWM +
-MyTimLED->setPWM(channelR,LED_PWM_RED,PWM_freq,1);   /* 100 Hertz, 1% dutycycle. */ +
-MyTimLED->setPWM(channelG,LED_PWM_GREEN,PWM_freq,1); /* 100 Hertz, 1% dutycycle. */ +
-MyTimLED->setPWM(channelB,LED_PWM_BLUE,PWM_freq,1);  /* 100 Hertz, 1% dutycycle. */+
 </code> </code>
 +You communicate with the TCS sensor via the I2C interface. In standard and typical configurations there is no need to instantiate the ''Wire'' I2C communication stack explicitly, nor provide the default I2C address of the TCS sensor (0x29) so ''begin'' is parameterless. Other overloaded functions for the ''begin'' let you provide all technical parameters.
  
-To modify the intensity of the chosen LED after initialisation use the setCaptureCompare function. In the following example, the duty_cycle_value can vary between 0 and 100. +=== Step 4 === 
-<code c> +Besides reading raw values for channels R, G, B and C, the ''tcs'' controller class provides additional functions to calculate colour temperature (in K) and colour intensity in Luxes.
-MyTimLED->setCaptureCompare(channelR, duty_cycle_value, PERCENT_COMPARE_FORMAT);   //modify duty cycle +
-<code>+
  
-=== Step 3 === +To readuse the following code:
-Write a loop for each colour (RG, then B) to light the colour from dark to max value. +
-<note important> Full duty cycle (100%) will be too bright for the remote access video camera to handle it. Use some reasonable range such as 0..50% is strongly advised.</note> +
-Mind to compose code to increase and decrease each colour. A hint is below (for channelR):+
 <code c> <code c>
-  // Increase brightness +  if(isTCSOk) 
-  for (int duty_cycle_value = 0; duty_cycle_value <= 50; duty_cycle_value++) { +  
-    // Gradually increase duty cycle for Red LED +    tcs.getRawData(&r, &g, &b, &c); 
-    MyTimLED->setCaptureCompare(channelRduty_cycle_valuePERCENT_COMPARE_FORMAT); +    colorTemp = tcs.calculateColorTemperature_dn40(rgb, c); 
-    delay(20); // Delay for smooth transition+    lux = tcs.calculateLux(r, g, b);
   }   }
 +</code>
 +R, G, and B reflect filtered values for Red, Green and Blue, respectively, while C (clear) is a non-filtered read that reflects brightness. Please be aware that there is no straightforward relation between R, G, B and C channels. 
  
-  delay(100);+==== Result validation ==== 
 +Driving R, G and B channels for RGB LED that lights the sensors, you should be able to observe changes in the readings, accordingly.
  
-  // Decrease brightness +===== FAQ ===== 
-  for (int duty_cycle_value = 50; duty_cycle_value >= 0; duty_cycle_value--) { +**What is the range of the values for the integration time of the TCS sensor?**: 
-    // Gradually decrease duty cycle for Red LED +<code c> 
-    MyTimLED->setCaptureCompare(channelR, duty_cycle_value, PERCENT_COMPARE_FORMAT); +#define TCS34725_INTEGRATIONTIME_2_4MS                                         \ 
-    delay(20)// Delay for smooth transition +  (0xFF) /**< 2.4ms - 1 cycle - Max Count: 1024 */ 
-  }+#define TCS34725_INTEGRATIONTIME_24MS                                          \ 
 +  (0xF6) /**< 24.0ms - 10 cycles - Max Count: 10240 */ 
 +#define TCS34725_INTEGRATIONTIME_50MS                                          \ 
 +  (0xEB) /**< 50.4ms 21 cycles Max Count: 21504 */ 
 +#define TCS34725_INTEGRATIONTIME_60MS                                          \ 
 +  (0xE7/**< 60.0ms - 25 cycles - Max Count: 25700 */ 
 +#define TCS34725_INTEGRATIONTIME_101MS                                         \ 
 +  (0xD6) /**< 100.8ms - 42 cycles - Max Count: 43008 *
 +#define TCS34725_INTEGRATIONTIME_120MS                                         \ 
 +  (0xCE) /**< 120.0ms 50 cycles - Max Count: 51200 */ 
 +#define TCS34725_INTEGRATIONTIME_154MS                                         \ 
 +  (0xC0/**< 153.6ms - 64 cycles - Max Count: 65535 */ 
 +#define TCS34725_INTEGRATIONTIME_180MS                                         \ 
 +  (0xB5) /**< 180.0ms - 75 cycles - Max Count: 65535 */ 
 +#define TCS34725_INTEGRATIONTIME_199MS                                         \ 
 +  (0xAD) /**< 199.2ms - 83 cycles - Max Count: 65535 */ 
 +#define TCS34725_INTEGRATIONTIME_240MS                                         \ 
 +  (0x9C) /**< 240.0ms - 100 cycles - Max Count: 65535 */ 
 +#define TCS34725_INTEGRATIONTIME_300MS                                         \ 
 +  (0x83) /**< 300.0ms - 125 cycles - Max Count: 65535 */ 
 +#define TCS34725_INTEGRATIONTIME_360MS                                         \ 
 +  (0x6A) /**< 360.0ms - 150 cycles - Max Count: 65535 */ 
 +#define TCS34725_INTEGRATIONTIME_401MS                                         \ 
 +  (0x59) /**< 400.8ms - 167 cycles - Max Count: 65535 */ 
 +#define TCS34725_INTEGRATIONTIME_420MS                                         \ 
 +  (0x51) /**< 420.0ms - 175 cycles - Max Count: 65535 */ 
 +#define TCS34725_INTEGRATIONTIME_480MS                                         \ 
 +  (0x38) /**< 480.0ms - 200 cycles - Max Count: 65535 */ 
 +#define TCS34725_INTEGRATIONTIME_499MS                                         \ 
 +  (0x30) /**< 499.2ms - 208 cycles - Max Count: 65535 */ 
 +#define TCS34725_INTEGRATIONTIME_540MS                                         \ 
 +  (0x1F) /**< 540.0ms - 225 cycles - Max Count: 65535 */ 
 +#define TCS34725_INTEGRATIONTIME_600MS                                         \ 
 +  (0x06) /**< 600.0ms - 250 cycles - Max Count: 65535 */ 
 +#define TCS34725_INTEGRATIONTIME_614MS                                         \ 
 +  (0x00) /**< 614.4ms - 256 cycles - Max Count: 65535 */ 
 +</code>
  
 +**What is the range of the values for the gain of the TCS sensor?**:
 +<code c>
 +typedef enum {
 +  TCS34725_GAIN_1X = 0x00,  /*  No gain  */
 +  TCS34725_GAIN_4X = 0x01,  /*  4x gain  */
 +  TCS34725_GAIN_16X = 0x02, /*  16x gain */
 +  TCS34725_GAIN_60X = 0x03  /*  60x gain */
 +} tcs34725Gain_t;
 </code> </code>
-==== Result validation ==== 
-You should be able to observe the pulsing colours of the RGB LED, increasing and decreasing brightness linearly. 
  
-===== FAQ ===== +**C channel reading is 0 and R, G or B readings are not reasonable**: It is possibly because of overdrive of the sensor with a light source (too bright). Consider lowering the RGB LED's intensity or changing the sensor's integration time and gain (shorter timelower gain).
-**What is the maximum number of channels?**: the MCU we use here is STM32WB55 on the Nucleo board. The pins available are connected to timer 1 with three PWM channels (connected to our RGB LED) and timer 2 with 4 PWM channels (with two of them connected to the servo and fan described in other scenarios). A single timer can generate PWM signals with independent duty cycles and identical frequency. +
-\\ +
-**What is the maximum bit resolution for PWM?**: Maximum resolution is 16 bits. Note that we can express the duty cycle in a variety of formats. In the presented example we expressed it in percentage so it varies between 1 and 100. It can be also expressed in ticksHertz, microseconds, and 1-16 bits numbers. +
-\\ +
-**What PWM frequency should I use?**: there is no straightforward answer to this question: assuming you observe LED remotely with a camera, even 50Hz would be enough. But it would give a severe flickering experience to the live user, on the other hand. In the example above, we propose 5kHz, which this MCU can easily handle.+
  
 +<WRAP noprint>
 ===== Project information ===== ===== Project information =====
 {{:en:iot-open:logo_iot_200_px.png?200|}}\\ {{:en:iot-open:logo_iot_200_px.png?200|}}\\
Line 120: Line 155:
 {{:en:iot-open:ccbync.png?100|}} {{:en:iot-open:ccbync.png?100|}}
 </figure> </figure>
- +</WRAP>
- +
en/iot-open/practical/hardware/sut/stm32/emb9b_1.1709418441.txt.gz · Last modified: 2024/03/02 22:27 by ktokarz
CC Attribution-Share Alike 4.0 International
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0