STM32F401 NUCLEO- PWM AND LED

ChibiOS public support forum for topics related to the STMicroelectronics STM32 family of micro-controllers.

Moderator: RoccoMarco

Post Reply
bennydeber
Posts: 5
Joined: Thu Jul 20, 2017 6:25 pm
Has thanked: 1 time
Been thanked: 1 time

STM32F401 NUCLEO- PWM AND LED

Post by bennydeber »

Hi,
in these days i'm trying to learn something about "ChibiOS's world" and I am using an STM32F401 Nucleo-64.
I've already tried very simple projects, now i would like to learn something more about pwm. That's what i'd like to do:
Push user button->generation of pwm signal with variable duty cycle->the green led switch on slowly;

That's what i do:

Code: Select all

#include "ch.h"
#include "hal.h"


BaseSequentialStream * chp = (BaseSequentialStream *) &SD2;

static uint32_t value;
static bool button_pressed = FALSE;

//PWM
static void pwmpcb(PWMDriver *pwmp) {

  (void)pwmp;
  if(value)
    palSetPad(GPIOA, GPIOA_LED_GREEN);
}

static void pwmc1cb(PWMDriver *pwmp) {

  (void)pwmp;
  palClearPad(GPIOA, GPIOA_LED_GREEN);
}

//configuration
static PWMConfig pwmcfg = {
  1000000,                                   
  1000,                                     
  pwmpcb,
  {
   {PWM_OUTPUT_ACTIVE_HIGH, pwmc1cb},
   {PWM_OUTPUT_DISABLED, NULL},
   {PWM_OUTPUT_DISABLED, NULL},
   {PWM_OUTPUT_DISABLED, NULL}
  },
  0,
  0
};



static THD_WORKING_AREA(waThd1, 512);
static THD_FUNCTION(Thd1, arg) {


  (void) arg;
    chRegSetThreadName("user");

    while(TRUE) {

      //
      if(palReadPad(GPIOC, GPIOC_BUTTON)) {
        chThdSleepMilliseconds(50);
      //
        if(!palReadPad(GPIOC, GPIOC_BUTTON)) {
      //
          button_pressed = TRUE;

        }
      }
      chThdSleepMilliseconds(1);
    }

}


static THD_WORKING_AREA(waThd2, 512);
static THD_FUNCTION(Thd2, arg) {
  unsigned ii;
  (void) arg;

    chRegSetThreadName("Led");
    pwmStart(&PWMD1, &pwmcfg);

    if(button_pressed) {

      for (ii = 0.01; ii <10 ; ii+0.1) {

    while(TRUE) {

      value = ii * 10000;

      if(value< 100){
        value= 0;
        pwmDisableChannel(&PWMD1, 0);
        palClearPad(GPIOA, GPIOA_LED_GREEN);
      }
      else if(value> 9900){
        value = 10000;
        pwmDisableChannel(&PWMD1, 0);
        palSetPad(GPIOA, GPIOA_LED_GREEN);
      }
      else{
        pwmEnableChannel(&PWMD1, 0, PWM_PERCENTAGE_TO_WIDTH(&PWMD1,value));
        pwmEnableChannelNotification(&PWMD1, 0);
        pwmEnablePeriodicNotification(&PWMD1);
      }
      chThdSleepMilliseconds(1);
    }
      }
    }

}
int main(void) {

 
  halInit();
  chSysInit();

  //
  palSetPadMode(GPIOA, 0, PAL_MODE_INPUT_ANALOG);

 //
  sdStart(&SD2, NULL);

  chThdCreateStatic(waThd1, sizeof(waThd1), NORMALPRIO + 1, Thd1, NULL);
  chThdCreateStatic(waThd2, sizeof(waThd2), NORMALPRIO - 1, Thd2, NULL);


  while (TRUE) {


    chThdSleepMilliseconds(500);

}
}



The code doesn't work, I hope someone can help me.
Thank you.
User avatar
tfAteba
Posts: 551
Joined: Fri Oct 16, 2015 11:03 pm
Has thanked: 91 times
Been thanked: 50 times

Re: STM32F401 NUCLEO- PWM AND LED

Post by tfAteba »

Hi Bennydeber,

Your code is a bit complicated to archive your goal.
I think Rocco Marco isi the recommended person to answer to your question because your code is based on what He does in sampling and dimming article locate at: http://www.playembedded.org/blog/en/2015/02/16/sampling-and-dimming/

But here is an example I made some time ago to learn PWM in ChibiOS.

The code just dim an LED connected to the PIN D7(PA_8) of the Nucleo board, look at the pinout here: https://developer.mbed.org/platforms/ST-Nucleo-F401RE/
To dim the LED I'm using the function dimmingPwm where the duty cycle of the PWM is change every 10ms.

When the dimming part is done, the green onboard LED start to blink by using a Thread.
I think this code is quite simple, so you can start to compare it with what you did to find you problem.

Here is the code:

Code: Select all

#include "ch.h"
#include "hal.h"

uint32_t pwmVal = 0; /* PWM value use to change the duty cycle. */

static void pwmpcb(PWMDriver *pwmp) {

  (void)pwmp;
}

static void pwmc1cb(PWMDriver *pwmp) {

  (void)pwmp;
}

static PWMConfig pwmcfg = {
  1000000,                                /* 10MHz PWM clock frequency.   */
  1000,                                   /* Initial PWM period 1mS.      */
  pwmpcb,
  {
   {PWM_OUTPUT_ACTIVE_HIGH, pwmc1cb},
   {PWM_OUTPUT_DISABLED, NULL},
   {PWM_OUTPUT_DISABLED, NULL},
   {PWM_OUTPUT_DISABLED, NULL}
  },
  0,
  0
};

/*
 * @biref LED blinker thread.
 */
static THD_WORKING_AREA(waThread1, 128);
static THD_FUNCTION(Thread1, arg) {
  (void)arg;

  chRegSetThreadName("LED thread");
  systime_t time = chVTGetSystemTimeX();

  while (true) {
    time += MS2ST(100);
    palTogglePad(GPIOA, GPIOA_LED_GREEN);
    chThdSleepUntil(time);
  }
}

/**
 * @brief Function used to change PWM value on PIN D7 of the Nucleo Board.
 */
void dimmingPwm(void) {
  uint8_t loop = 0;

  for (loop = 0; loop < 5; loop++) {

    for (pwmVal = 0; pwmVal < 10000; pwmVal += 100) {
      pwmEnableChannel(&PWMD1, 0, PWM_PERCENTAGE_TO_WIDTH(&PWMD1, pwmVal));
      pwmEnableChannelNotification(&PWMD1, 0);
      chThdSleepMilliseconds(10);
    }

    for (pwmVal = 10000; pwmVal > 0; pwmVal -= 100) {
      pwmEnableChannel(&PWMD1, 0, PWM_PERCENTAGE_TO_WIDTH(&PWMD1, pwmVal));
      pwmEnableChannelNotification(&PWMD1, 0);
      chThdSleepMilliseconds(10);
    }
  }
}

/*
 * Application entry point.
 */
int main(void) {

  /*
   * System initializations.
   * - HAL initialization, this also initializes the configured device drivers
   *   and performs the board-specific initializations.
   * - Kernel initialization, the main() function becomes a thread and the
   *   RTOS is active.
   */
  halInit();
  chSysInit();

  /*
   * Initializes the PWM driver 2 and ICU driver 3.
   * GPIOA8 is the PWM output.
   * GPIOC6 is the ICU input.
   * The two pins have to be externally connected together.
   */
  pwmStart(&PWMD1, &pwmcfg);
  pwmEnablePeriodicNotification(&PWMD1);
  palSetPadMode(GPIOA, 8, PAL_MODE_ALTERNATE(1));

  /*
   * Test the PWM configuration and generation.
   */
  dimmingPwm();

  /*
   * Creates the blinker thread.
   */
  chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);

  /*
   * Normal main() thread activity, in this demo it does nothing.
   */
  while (true) {
    chThdSleepMilliseconds(500);
  }
  return 0;
}


PS: A good place to look when learning to use ChibiOS is also the demos folder and the testhal folder.
For what I remember the code I made was based on testhal/STM32/STM32F4xx/PWM-ICU. Take a look to that folder.
User avatar
RoccoMarco
Posts: 655
Joined: Wed Apr 24, 2013 4:11 pm
Has thanked: 83 times
Been thanked: 67 times

Re: STM32F401 NUCLEO- PWM AND LED

Post by RoccoMarco »

Hey,
I suggest you to take a look on my blog.
There are a lot of articles about that:
ChibiOS and STM32 - Getting Started
Post Reply