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

n-AN36 change the Button to PWM

I would like to modificate the LED Button application example. The LED characteristic should stay as it is, only the Button characteristic should be changed. I want to use the button characteristic to send the value of a pwm signal. When the device is in connection, it should always send the value of the pwm signal.

Goal of the changes :

1.)

The button_state value should be send all the time and not only when the button is pressed. I`m not sure, but I think that the button will be detected in the button_event_handler. If my presumption is true, how can I change that the value of the button_state will always be send?

2.)

The value of the button_state should have a range from 0-100 and not only 1 or 0. Where in the code the value of the button_state will be set ?

And do I have to change configuration of the value?

EDIT

main.c

  • Hi

    1. I guess a timer function is what you are asking for. A timer will generate interrupts periodically to send PWM value periodically. The easiest way to implement a timer is to use the app_timer library which is very low current. You can see an example of app_timer usage in e.g. the ble_app_bps example in the nRF51 SDK v6.1, look at the timers_init() and applicaiton_timers_start() functions in main. For more accurate timer, use a TIMER peripheral, but that consumes substantially more current.

    2. The button_event_handler in the main file in ble_app_lbs is called whenever the button is pressed. You can do the same as the button press does when sending the PWM value, i.e. put the code:

          err_code = ble_lbs_on_button_change(&m_lbs, button_action);
          if (err_code != NRF_SUCCESS &&
              err_code != BLE_ERROR_INVALID_CONN_HANDLE &&
              err_code != NRF_ERROR_INVALID_STATE)
          {
              APP_ERROR_CHECK(err_code);
          }
      

    into a timer handler instead of the button handler. The ble_lbs_on_button_change function accepts uint8_t value so you can send values 0-255 to this function, so that should great with PWM value range of 0-100.

    Update 5.2.2015 I attach a modified ble_app_lbs example that measures the PWM duty cycle on input pin P0.00 and sends the value over BLE. I basically included into the ble_app_lbs the code from the pwm_analyzer example in nRF51 SDK 6.1.0.

    nrf51-ble-app-lbs-SDK6.0_with_pwm_analyzer.zip

    Update 2 5.2.2015 To test the example, just create a PWM signal on pin P0.00, I did that with a signal generator. Pressing button does not generate a PWM signal like it did in the pwm_analyzer example. Then connect with a central device and enable services, then you should see the measurements appearing on the central device, i.e. on the button characteristic.

  • The thing is, I dont want to generate a pwm signal. I would like to analyze an external pwm signal and send the value of the PWM over BLE.

  • Yes, you should be able to send PWM value or any other 1 byte value over BLE with the method I mention above.

    I guess you could sample the PWM with the ADC on every timer interrupt and then send the sampled value over the BLE link. Or did you have something else in mind?

  • There is a pwm_analyzer example in the SDK 6.1 . I tried to add this example in my application, but I have problems port these peripherals over to the nrf_soc API framework.

  • What are you having problems with exactly? You should be able to use the functionality in the pwm_analyzer example by simply copying the code into the ble_app_lbs example. Instead of writing the PWM value to PORT1 like in the pwm_analyzer exampe, you call the ble_lbs_on_button_change with the pwm value.

    One thing to keep in mind is that the NVIC is blocked by the softdevice so you should use the sd_nvic functions instead when enabling the GPIOTE interrupt. An example of setting a peripheral interrupt when using the softdeivce can be found e.g. here, in line 825. Also when you set the ppi channels you must use the the sd_ppi functions, e.g. sd_ppi_channel_enable_set

Related