Test application for the STMicroelectronics X-NUCLEO-LED61A1 LED Control Expansion Board showing several LED control modes, built against mbed OS.
Dependencies: X_NUCLEO_LED61A1
Fork of LedDimming_LED61A1 by
LED Control with the X-NUCLEO-LED61A1 Expansion Board
This application provides an example of usage of the X-NUCLEO-LED61A1 LED Control Expansion Board. It shows how to control a LED stripe load connected to the board through the following control modes:
- Manual PWM Dimming;
- Manual Analog Dimming;
- Sinusoidal PWM Dimming;
- Sinusoidal Analog Dimming;
- Photo-based Analog Dimming.
The button of the MCU board, when available, can be used in the following ways:
- Short Button Press [<0.5s] for Manual Dimming;
- Medium Button Press to Switch Demo;
- Long Button Press [>2s] to Switch Power ON/OFF.
The program starts in mode 1.
main.cpp
- Committer:
- Davidroid
- Date:
- 2017-07-03
- Revision:
- 16:e39f206f26c8
- Parent:
- 15:ea1e402ce919
File content as of revision 16:e39f206f26c8:
/**
******************************************************************************
* @file main.cpp
* @author Davide Aliprandi, STMicroelectronics
* @version V1.0.0
* @date February 4h, 2016
* @brief mbed test application for the STMicroelectronics X-NUCLEO-LED61A1
* LED Control Expansion Board showing several LED control modes.
******************************************************************************
* @attention
*
* <h2><center>© COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
/* mbed specific header files. */
#include "mbed.h"
#include "rtos.h"
/* Component specific header files. */
#include "Led6001.h"
/* Definitions ---------------------------------------------------------------*/
/* PI. */
#ifndef M_PI
#define M_PI (3.14159265358979323846f)
#endif
/* Loop period in micro-seconds. */
#define LOOP_PERIOD_us (1E5)
/* Sin period in micro-seconds. */
#define PWM_SIN_PERIOD_us (1E7)
#define ANALOG_SIN_PERIOD_us (1E7)
/* Duration of button press in milli-seconds. */
#define SWITCH_DEMO_BUTTON_PRESS_ms (500)
#define SWITCH_POWER_BUTTON_PRESS_ms (2000)
/* Dimming Step. */
#define DIMMING_STEP (0.05f)
/* Types ---------------------------------------------------------------------*/
/* Demos. */
typedef enum
{
MANUAL_PWM_DIMMING = 0,
MANUAL_ANALOG_DIMMING,
AUTOMATIC_PWM_DIMMING,
AUTOMATIC_ANALOG_DIMMING,
PHOTO_BASED_ANALOG_DIMMING,
LED_DEMO_SIZE
} led_demo_t;
/* Actions. */
typedef enum
{
SWITCH_POWER = 0,
SWITCH_DEMO,
SWITCH_STATE,
NO_ACTION
} led_action_t;
/* Variables -----------------------------------------------------------------*/
/* Main loop's ticker. */
static Ticker ticker;
/* User Button's interrupt. */
static InterruptIn button(USER_BUTTON);
/* MCU Board's Led which provides the user with a visual feedback on
the user button's status (ON = pressed, OFF = released). */
DigitalOut button_pressed_led(LED1);
/* LED Control Component. */
Led6001 *led;
/* Interrupt flags. */
static volatile bool ticker_irq_triggered = false;
static volatile bool button_irq_triggered = false;
static volatile bool xfault_irq_triggered = false;
/* Demo State. */
static volatile led_demo_t demo;
static volatile led_action_t action;
static volatile bool power_on;
/* Demos' Names. */
static char* demos[] =
{
"Manual PWM Dimming",
"Manual Analog Dimming",
"Sinusoidal PWM Dimming",
"Sinusoidal Analog Dimming",
"Photo-based Analog Dimming"
};
/* Functions -----------------------------------------------------------------*/
/**
* @brief Initializing the demo.
* @param None.
* @retval None.
*/
void init_demo(void)
{
power_on = true;
action = SWITCH_DEMO;
demo = (led_demo_t) (LED_DEMO_SIZE - 1);
}
/**
* @brief Handling the LED capabilities and executing several demos.
* @param None.
* @retval None.
*/
void led_handler(void)
{
static int tick = 0;
static float pwm_dimming;
static float analog_dimming;
/* Handling the power switch. */
if (action == SWITCH_POWER)
{
/* Switching the LED power ON/OFF. */
power_on = !power_on;
if (power_on)
{
/* Initializing PWM and Analog dimming to maximum values. */
pwm_dimming = 1.0f;
analog_dimming = 1.0f;
}
else
{
/* Printing to the console. */
printf("%-56s\r", "Power OFF");
/* Powering OFF the LED. */
led->power_off();
}
}
/* Handling the LED dimming when powered ON. */
if (power_on)
{
/* Switching to the next demo. */
if (action == SWITCH_DEMO)
{
pwm_dimming = 1.0f;
analog_dimming = 1.0f;
tick = 0;
demo = (led_demo_t) ((demo + 1) % LED_DEMO_SIZE);
}
/* Setting the LED dimming depending on the selected demo. */
switch (demo)
{
/* Changing PWM dimming according to the user button. */
case MANUAL_PWM_DIMMING:
if (action == SWITCH_STATE)
{
pwm_dimming -= DIMMING_STEP;
pwm_dimming = (pwm_dimming < 0.0f ? 1.0f : pwm_dimming);
}
break;
/* Changing Analog dimming according to the user button. */
case MANUAL_ANALOG_DIMMING:
if (action == SWITCH_STATE)
{
analog_dimming -= DIMMING_STEP;
analog_dimming = (analog_dimming < 0.0f ? 1.0f : analog_dimming);
}
break;
/* Changing PWM dimming continuously. */
case AUTOMATIC_PWM_DIMMING:
pwm_dimming = 0.5f * sin(2 * M_PI * (tick++ * LOOP_PERIOD_us) / PWM_SIN_PERIOD_us) + 0.5f;
tick %= (int) (PWM_SIN_PERIOD_us / LOOP_PERIOD_us);
action = SWITCH_STATE;
break;
/* Changing Analog dimming continuously. */
case AUTOMATIC_ANALOG_DIMMING:
analog_dimming = 0.5f * sin(2 * M_PI * (tick++ * LOOP_PERIOD_us) / ANALOG_SIN_PERIOD_us) + 0.5f;
tick %= (int) (ANALOG_SIN_PERIOD_us / LOOP_PERIOD_us);
action = SWITCH_STATE;
break;
/* Setting Analog dimming according to the photo sensor. */
case PHOTO_BASED_ANALOG_DIMMING:
analog_dimming = 1.0f - led->get_current();
action = SWITCH_STATE;
break;
}
/* Writing PWM and Analog dimming values to the LED. */
if (action != NO_ACTION)
{
/* Printing to the console. */
printf("%d) %-26s --> Dimming: %0.2f\r", demo + 1, demos[demo], demo == MANUAL_PWM_DIMMING || demo == AUTOMATIC_PWM_DIMMING ? pwm_dimming : analog_dimming);
/* Writing PWM and Analog dimming values to the LED. */
led->set_pwm_dimming(pwm_dimming);
led->set_analog_dimming(analog_dimming);
}
}
/* Resetting the action. */
action = NO_ACTION;
}
/**
* @brief Interrupt Request for the main loop's ticker related interrupt.
* @param None.
* @retval None.
*/
void ticker_irq(void)
{
ticker_irq_triggered = true;
}
/**
* @brief Interrupt Request for the user button's interrupt.
* @param None.
* @retval None.
*/
void button_irq(void)
{
button_irq_triggered = true;
button.disable_irq();
}
/**
* @brief Interrupt Request for the component's XFAULT interrupt.
* @param None.
* @retval None.
*/
void xfault_irq(void)
{
xfault_irq_triggered = true;
led->disable_xfault_irq();
}
/**
* @brief Interrupt Handler for the user button's interrupt.
* @param None.
* @retval None.
*/
void button_handler(void)
{
/* User Button's timer to measure the time the button remains pressed. */
static Timer button_pressed_timer;
bool button_pressed_flag = (button.read() == 0 ? true : false);
if (button_pressed_flag)
{
button_pressed_led = 1;
button_pressed_timer.start();
}
else
{
button_pressed_led = 0;
button_pressed_timer.stop();
/* Either changing current demo's state or switching to the next demo. */
int time_pressed = button_pressed_timer.read_ms();
if (time_pressed < SWITCH_DEMO_BUTTON_PRESS_ms)
action = SWITCH_STATE;
else if (time_pressed < SWITCH_POWER_BUTTON_PRESS_ms)
action = SWITCH_DEMO;
else
action = SWITCH_POWER;
button_pressed_timer.reset();
}
button.enable_irq();
}
/**
* @brief Interrupt Handler for the component's XFAULT interrupt.
* @param None.
* @retval None.
*/
void xfault_handler(void)
{
/* Printing to the console. */
printf("XFAULT Interrupt detected! Re-initializing LED driver...");
/* Re-starting-up LED Control Component. */
led->start_up();
/* Printing to the console. */
printf("Done.\r\n\n");
/* Re-initializing the demo. */
init_demo();
led->enable_xfault_irq();
}
/* Main ----------------------------------------------------------------------*/
int main()
{
/*----- Initialization. -----*/
/* Printing to the console. */
printf("LED Control Application Example\r\n\n" \
"Demos:\r\n");
int demo = 0;
for (demo = 0; demo < LED_DEMO_SIZE; demo++)
printf("%d) %-26s\r\n", demo + 1, demos[demo]);
printf("\r\nActions:\r\n" \
"+ Short Button Press [<%.1fs] --> Manual Dimming\r\n" \
"+ Medium Button Press --> Switch Demo\r\n" \
"+ Long Button Press [>%.1fs] --> Switch Power ON/OFF\r\n\n" \
, SWITCH_DEMO_BUTTON_PRESS_ms / 1000.0f, SWITCH_POWER_BUTTON_PRESS_ms / 1000.0f);
/* Initializing LED Control Component. */
led = new Led6001(D4, A3, D6, D5);
if (led->init() != COMPONENT_OK)
exit(EXIT_FAILURE);
/* Attaching interrupt request functions. */
button.fall(button_irq);
button.rise(button_irq);
led->attach_xfault_irq(&xfault_irq);
led->enable_xfault_irq();
ticker.attach_us(ticker_irq, LOOP_PERIOD_us);
/* Starting-up LED Control Component. */
led->start_up();
/* Initializing the demo. */
init_demo();
/*----- LED Control. -----*/
/* Either performing the component handler, interrupt handlers, or waiting for events. */
while (true)
{
if (ticker_irq_triggered)
{
ticker_irq_triggered = false;
led_handler();
} else if (button_irq_triggered)
{
button_irq_triggered = false;
button_handler();
} else if (xfault_irq_triggered)
{
xfault_irq_triggered = false;
xfault_handler();
} else {
/* It is recommended that SEVONPEND in the System Control Register is NOT set. */
__WFE();
}
}
}
