This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Controlling AC fan using pwm library

HI team,

I am a beginner of Nordic nrf52840 DK, I would like to control the AC ceiling fan using the nrf52840 board with pwm library. As, I can see we can use either single channel or multi- channel for setting up the frequency of the pwm pin. In order to control the ac fan i am using zero crossing detector (H11AA1) so, that for every zero crossing the Triac(BT136) is triggered and pwm is set to the given duty cycle.  But, what i am getting is only PWM sampling output, and the ZCD is always showing '0'. I am taking the ZCD as input assigned to gpio pin 30 and for every zero crossing i should get the given duty cycle output on GPIO pin 31 which is connected to load.

Kindly, give me suggestions or some kind of related code for getting the output. 

Here, below is the code i am trying to execute.

#include <stdbool.h>
#include <stdint.h>
#include "nrf.h"
#include "app_error.h"
#include "bsp.h"
#include "nrf_delay.h"
#include "app_pwm.h"
#include "nrf_gpio.h"
#include "nrf_gpiote.h"

#define data 31
#define zerocrossing 30


//nrf_gpio_pin_dir_t zerocrossing= NRF_GPIO_PIN_DIR_INPUT;


APP_PWM_INSTANCE(PWM1,1);                 // Create the instance "PWM1" using TIMER1.

static volatile bool ready_flag;          // A flag indicating PWM status.


void pwm_ready_callback(uint32_t pwm_id)   // PWM callback function
{
    ready_flag = true;
}




int main()
{
    nrf_gpio_cfg_input(zerocrossing,NRF_GPIO_PIN_NOPULL);
    ret_code_t err_code;  



    //app_pwm_config_t pwm1_cfg = APP_PWM_DEFAULT_CONFIG_1CH(20000L,data);
    app_pwm_config_t pwm1_cfg = APP_PWM_DEFAULT_CONFIG_2CH(20000L,data,zerocrossing);

        
    /* Switch the polarity of the second channel. */
    pwm1_cfg.pin_polarity[1] = APP_PWM_POLARITY_ACTIVE_HIGH;

    /* Initialize and enable PWM. */
    err_code = app_pwm_init(&PWM1,&pwm1_cfg,pwm_ready_callback);
    APP_ERROR_CHECK(err_code);
    app_pwm_enable(&PWM1);   

    while (true)
        {
        
            
            if(nrf_gpio_pin_read(zerocrossing)==0)
                {
                    
                    printf("entered loop\n");
                    printf("%d \t",nrf_gpio_pin_read(zerocrossing));
                    printf("%d \t",nrf_gpio_pin_out_read(data));

                    /* Set the duty cycle - keep trying until PWM is ready... */
                    while (app_pwm_channel_duty_set(&PWM1,0,40) == NRF_ERROR_BUSY);

                    /* ... or wait for callback. */
                    while (!ready_flag);
                    APP_ERROR_CHECK(app_pwm_channel_duty_set(&PWM1,1,40));
                    nrf_delay_ms(100);
                    nrf_gpiote_task_disable;
                    
                }

            else{
                    printf("exited loop \n");
                    app_pwm_disable(&PWM1);
                    nrf_gpio_pin_clear(data);

                }
                          
        }
    

}

  • Hi,

    So if pin 30 is low, you should have a PWM singal on pin 31? And when pin 30 is high, the PWM signal on pin 31 should stop?

    As a fast prototype, maybe you could try something like this?

    /**
     * Copyright (c) 2014 - 2018, Nordic Semiconductor ASA
     *
     * All rights reserved.
     *
     * 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, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, 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 Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     *
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     *
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     *
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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.
     *
     */
    
    #include <stdbool.h>
    #include "nrf.h"
    #include "nrf_drv_gpiote.h"
    #include "app_error.h"
    #include "boards.h"
    #include "bsp.h"
    //#include "nrf_delay.h"
    #include "app_pwm.h"
    
    
    #define PIN_IN 30
    
    #define DATA 31
    
    APP_PWM_INSTANCE(PWM1,1);                 // Create the instance "PWM1" using TIMER1.
    
    static volatile bool ready_flag;          // A flag indicating PWM status.
    
    void pwm_ready_callback(uint32_t pwm_id)    // PWM callback function
    {
        ready_flag = true;
    }
    
    
    void in_pin_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
    {
    
      if (action == NRF_GPIOTE_POLARITY_TOGGLE)
      {
          if (!nrf_drv_gpiote_in_is_set(pin)) // From High to low.
          {
             //Start PWM, set duty cycle to desired value
             /* Set the duty cycle - keep trying until PWM is ready... */
             while (app_pwm_channel_duty_set(&PWM1,0,50) == NRF_ERROR_BUSY);
          } 
          else  // From Low to high.
          {
             //Stop PWM, set duty cycle to 0
             while (app_pwm_channel_duty_set(&PWM1,0,0) == NRF_ERROR_BUSY); 
          }
      }  
    }
    /**
     * @brief Function for configuring: PIN_IN pin for input,
     * and configures GPIOTE to give an interrupt on pin change.
     */
    static void gpio_init(void)
    {
        ret_code_t err_code;
    
        err_code = nrf_drv_gpiote_init();
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_TOGGLE(true);
        in_config.pull = NRF_GPIO_PIN_PULLUP;
    
        err_code = nrf_drv_gpiote_in_init(PIN_IN, &in_config, in_pin_handler);
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_gpiote_in_event_enable(PIN_IN, true);
    }
    
    static void pwm_init()
    {
        uint32_t err_code;
        app_pwm_config_t pwm1_cfg = APP_PWM_DEFAULT_CONFIG_1CH(20000L,DATA);
        /* Initialize and enable PWM. */
        err_code = app_pwm_init(&PWM1,&pwm1_cfg,pwm_ready_callback);
        APP_ERROR_CHECK(err_code);
        app_pwm_enable(&PWM1);   
    }
    
    /**
     * @brief Function for application main entry.
     */
    int main(void)
    {
        gpio_init();
        pwm_init();
    
        while (true)
        {
            __WFE();
        }
    }
    
    
    /** @} */
    

Related