This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Generate two PWM waves with delay in nRF51822

I want to generate 2 fast PWM waves with 25% duty cycles from nRF51822. They have same frequency of 4MHz but there is half a cycle delay between them. I checked the nrf_pwm library but couldn't find a function can do that. Is there a way around?

Parents
  • Hi

    I do not think either there is a mechanism in the nrf_pwm library that makes the PWMs to be out of phase synchronized. I think the library sets all PWMs to have the same frequency and phase.

    The nrf_pwm library does not anyway support more than 62,5 kHz frequency. Anyway, if you do not intend to change the duty cycle during operation you should be able to use higher frequencies just if you set the duty cycle prior to enabling the PWM. See some hints on this thread. I suspect however that the two PWM's will have the same phase when using the nrf_pwm_library.

    What you could do is to manually use a TIMER peripheral and connect it to 2xGPIOTE channels by using 2xPPI channels. Make TIMER CC register 1 set PWM channel 1 low, make TIMER CC register 2 set PWM channel 2 low, make TIMER CC register 3 set both PWM channels high and reset the TIMER. Thereby you could get fixed duty cycle, out of phase synchronized PWMs with 4MHz frequency and 25% duty cycle. You could use this example as a starting point.

    It might also be possible to implement this with help of the latest drivers in the SDK, see the gpiote example in the SDK for code reference starting point.

    2.9.2015 Looking at this the second time, I think you actually need 4xCC compare registers to do the task. Perhaps the procedure is as follows:

    • Set TIMER prescaler to 0, that way it will operate at 16MHz, and have a tick interval of 62.5ns
    • Set CC register values as CC[0] = 1, CC[1] = 2, CC[2] = 3, CC[3] = 4
    • Configure two GPIOTE channels to toggle two output pins, set initial pin signals to LOW
    • Connect each CC[x] event to a GPIOTE toggle task with a PPI channel
    • Connect CC[0] event to trigger GPIOTE channel 1 task, which will toogle pin 1 from low to high
    • Connect CC[1] event to trigger GPIOTE channel 1 task, which will toggle pin 1 from high to low
    • Connect CC[2] event to trigger GPIOTE channel 2 task, which will toggle pin 2 from low to high
    • Connect CC[3] event to trigger GPIOTE channel 2 task, which will toggle pin 2 from high to low
    • Create a shortcut that will clear the TIMER counter on CC[3] event. The TIMER counter will be cleared every 250ns, i.e. 4MHz

    Let me know if you see any flaws in this idea

  • Hi diode

    I aggree, the CPU is most likely too slow and too undeterministic to start the ADC sampling. It also takes a few microseconds to enter an interrupt handler after a peripheral event is triggered. You would need to use PPI also to start the ADC conversion.

    The ADC conversion time is fixed 20us for 8 bit sampling and fixed 68us for 10-bit sampling.

    If you want to trigger ADC sampling on CC[3] event, you can do that by connecting the NRF_ADC->TASKS_START task with the TIMER CC[3] event by using an extra PPI channel.

    However, if you want to trigger ADC start task after certain amount of PWM cycles, you would need to count the number of PWM cycles. I suppose you could do that by using another TIMER peripheral in COUNTER mode and let e.g. the TIMER_0 CC[3] event trigger TIMER_1 COUNT task, where TIMER_1 is configured in counter mode. Here is an example how to set timer in counter mode. you would then set up a CC compare register for TIMER_1 and let that CC compare event trigger the ADC start task.

Reply
  • Hi diode

    I aggree, the CPU is most likely too slow and too undeterministic to start the ADC sampling. It also takes a few microseconds to enter an interrupt handler after a peripheral event is triggered. You would need to use PPI also to start the ADC conversion.

    The ADC conversion time is fixed 20us for 8 bit sampling and fixed 68us for 10-bit sampling.

    If you want to trigger ADC sampling on CC[3] event, you can do that by connecting the NRF_ADC->TASKS_START task with the TIMER CC[3] event by using an extra PPI channel.

    However, if you want to trigger ADC start task after certain amount of PWM cycles, you would need to count the number of PWM cycles. I suppose you could do that by using another TIMER peripheral in COUNTER mode and let e.g. the TIMER_0 CC[3] event trigger TIMER_1 COUNT task, where TIMER_1 is configured in counter mode. Here is an example how to set timer in counter mode. you would then set up a CC compare register for TIMER_1 and let that CC compare event trigger the ADC start task.

Children
No Data
Related