## NRF24LE1 how to set PWM frequency?

8 posts / 0 new
Author
Message

I have been working with NRF24LE1 and I am asking this here in the general programming section because this forum is highly active compared to the nordic official forum. Now I read the data sheet and I am unable to decipher on how to set the PWM frequency and duty cycle on the NRF24LE1. The information is cryptic and there is no example given in the data sheet. Please have a look at he below snapshot of the datasheet.

How to understand this information. Cclk is 16Mhz so it is 16000000. PWM frequency needed is 20khz and PWM duty cycle needed is 1ms to 2ms. Anyone who is experienced in read such data sheets can help me here? To what value should I set PWMCON and PWMDC0/1 so that I get the desired values...? Please also explained me how to deciphered the above table to arrive at those values.

Let me tell you how I decipher this as a newbie. Now CCLK is 16,000,000 for 16Mhz clock. I chose PWM0 as output so bit 0 is 1 and bit 1 is 0. Now I need to find out what PWMCON is so the formula for PWMCON for 20Khz PWM freq will be. (16000000/(255 x 20000))-1 = 160/51 -1 which is approximately 2. Hence PWMCON[5:2] will be 0010. There fore PWMCON will be 11001001 which is 0xC9. But this dint work when I put in this value for PWMCON as the servo did not rotate. Here is my code.

Here is my code:

```#include "reg24le1.h" // I/O header file for NRF24LE1
#include "hal_delay.h" // header file containing delay functions

// main function
void main()
{
int i = 0, j = 0; // loop variable
P0DIR = 0; // Port 0 as output
PWMCON = 0xc9; // enable PWM1

// infinte loop
while(1)
{
for(i= 180; i--; i > 0)
{
PWMDC0 = i ; // change duty cycle
delay_ms(10); // delay of 10 ms
}

}

}```

Last Edited: Sat. Mar 2, 2019 - 01:09 AM

Can anyone give me an idea as to what is going wrong?

What servo works at 20kHz?

I see my mistake there. The standard servo works at 50Hz signal but nrf24le1 cannot be set to PWM at 50Hz because the minimum it can do is 4KHz. So I have to do a software based PWM using timers like the arduino servo library does but I dont exactly understand the terms in the arduino servo library so that I can replace them with their nrf24le1 equivalents.

oK . So I found some servo code here for nrf24le1 using timers https://github.com/laneboysrc/nrf24l01-rc

But now I see these statements

__sfr __at (0x80) P0;

I use these statements in Keil developer for nrf24le1 and I get an error. So what is the equivalent statement for these which will not generate any errors? This is the error I am getting if I include these statements ..\main.c(30): error C129: missing ';' before '__at'

What shall I do?

In another parallel effort for servos I looked into the servo library for arduino. I have to convert the following functions specific to AVR to nrf24le1 functions.

```/************ static functions common to all instances ***********************/

static inline void handle_interrupts(timer16_Sequence_t timer, volatile uint16_t *TCNTn, volatile uint16_t* OCRnA)
{
if( Channel[timer] < 0 )
*TCNTn = 0; // channel set to -1 indicated that refresh interval completed so reset the timer
else{
if( SERVO_INDEX(timer,Channel[timer]) < ServoCount && SERVO(timer,Channel[timer]).Pin.isActive == true )
digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,LOW); // pulse this channel low if activated
}

Channel[timer]++;    // increment to the next channel
if( SERVO_INDEX(timer,Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) {
*OCRnA = *TCNTn + SERVO(timer,Channel[timer]).ticks;
if(SERVO(timer,Channel[timer]).Pin.isActive == true)     // check if activated
digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,HIGH); // its an active channel so pulse it high
}
else {
// finished all channels so wait for the refresh period to expire before starting over
if( ((unsigned)*TCNTn) + 4 < usToTicks(REFRESH_INTERVAL) )  // allow a few ticks to ensure the next OCR1A not missed
*OCRnA = (unsigned int)usToTicks(REFRESH_INTERVAL);
else
*OCRnA = *TCNTn + 4;  // at least REFRESH_INTERVAL has elapsed
Channel[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel
}
}

#ifndef WIRING // Wiring pre-defines signal handlers so don't define any if compiling for the Wiring platform
// Interrupt handlers for Arduino
#if defined(_useTimer1)
SIGNAL (TIMER1_COMPA_vect)
{
handle_interrupts(_timer1, &TCNT1, &OCR1A);
}
#endif

#if defined(_useTimer3)
SIGNAL (TIMER3_COMPA_vect)
{
handle_interrupts(_timer3, &TCNT3, &OCR3A);
}
#endif

#if defined(_useTimer4)
SIGNAL (TIMER4_COMPA_vect)
{
handle_interrupts(_timer4, &TCNT4, &OCR4A);
}
#endif

#if defined(_useTimer5)
SIGNAL (TIMER5_COMPA_vect)
{
handle_interrupts(_timer5, &TCNT5, &OCR5A);
}
#endif

#elif defined WIRING
// Interrupt handlers for Wiring
#if defined(_useTimer1)
void Timer1Service()
{
handle_interrupts(_timer1, &TCNT1, &OCR1A);
}
#endif
#if defined(_useTimer3)
void Timer3Service()
{
handle_interrupts(_timer3, &TCNT3, &OCR3A);
}
#endif
#endif

static void initISR(timer16_Sequence_t timer)
{
#if defined (_useTimer1)
if(timer == _timer1) {
TCCR1A = 0;             // normal counting mode
TCCR1B = _BV(CS11);     // set prescaler of 8
TCNT1 = 0;              // clear the timer count
#if defined(__AVR_ATmega8__)|| defined(__AVR_ATmega128__)
TIFR |= _BV(OCF1A);      // clear any pending interrupts;
TIMSK |=  _BV(OCIE1A) ;  // enable the output compare interrupt
#else
// here if not ATmega8 or ATmega128
TIFR1 |= _BV(OCF1A);     // clear any pending interrupts;
TIMSK1 |=  _BV(OCIE1A) ; // enable the output compare interrupt
#endif
#if defined(WIRING)
timerAttach(TIMER1OUTCOMPAREA_INT, Timer1Service);
#endif
}
#endif

#if defined (_useTimer3)
if(timer == _timer3) {
TCCR3A = 0;             // normal counting mode
TCCR3B = _BV(CS31);     // set prescaler of 8
TCNT3 = 0;              // clear the timer count
#if defined(__AVR_ATmega128__)
TIFR |= _BV(OCF3A);     // clear any pending interrupts;
ETIMSK |= _BV(OCIE3A);  // enable the output compare interrupt
#else
TIFR3 = _BV(OCF3A);     // clear any pending interrupts;
TIMSK3 =  _BV(OCIE3A) ; // enable the output compare interrupt
#endif
#if defined(WIRING)
timerAttach(TIMER3OUTCOMPAREA_INT, Timer3Service);  // for Wiring platform only
#endif
}
#endif

#if defined (_useTimer4)
if(timer == _timer4) {
TCCR4A = 0;             // normal counting mode
TCCR4B = _BV(CS41);     // set prescaler of 8
TCNT4 = 0;              // clear the timer count
TIFR4 = _BV(OCF4A);     // clear any pending interrupts;
TIMSK4 =  _BV(OCIE4A) ; // enable the output compare interrupt
}
#endif

#if defined (_useTimer5)
if(timer == _timer5) {
TCCR5A = 0;             // normal counting mode
TCCR5B = _BV(CS51);     // set prescaler of 8
TCNT5 = 0;              // clear the timer count
TIFR5 = _BV(OCF5A);     // clear any pending interrupts;
TIMSK5 =  _BV(OCIE5A) ; // enable the output compare interrupt
}
#endif
}

static void finISR(timer16_Sequence_t timer)
{
//disable use of the given timer
#if defined WIRING   // Wiring
if(timer == _timer1) {
#if defined(__AVR_ATmega1281__)||defined(__AVR_ATmega2561__)
TIMSK1 &=  ~_BV(OCIE1A) ;  // disable timer 1 output compare interrupt
#else
TIMSK &=  ~_BV(OCIE1A) ;  // disable timer 1 output compare interrupt
#endif
timerDetach(TIMER1OUTCOMPAREA_INT);
}
else if(timer == _timer3) {
#if defined(__AVR_ATmega1281__)||defined(__AVR_ATmega2561__)
TIMSK3 &= ~_BV(OCIE3A);    // disable the timer3 output compare A interrupt
#else
ETIMSK &= ~_BV(OCIE3A);    // disable the timer3 output compare A interrupt
#endif
timerDetach(TIMER3OUTCOMPAREA_INT);
}
#else
//For arduino - in future: call here to a currently undefined function to reset the timer
(void) timer;  // squash "unused parameter 'timer' [-Wunused-parameter]" warning
#endif
}

static boolean isTimerActive(timer16_Sequence_t timer)
{
// returns true if any servo is active on this timer
for(uint8_t channel=0; channel < SERVOS_PER_TIMER; channel++) {
if(SERVO(timer,channel).Pin.isActive == true)
return true;
}
return false;
}

/****************** end of static functions ******************************/```

I have the following defined for nrf24le1

```
#define INTERRUPT_IPF          0   // Interrupt from pin
#define INTERRUPT_T0           1   // Timer0 Overflow
#define INTERRUPT_POFIRQ       2   // Power failure interrupt
#define INTERRUPT_T1           3   // Timer1 Overflow
#define INTERRUPT_UART0        4   // UART0, Receive & Transmitt interrupt
#define INTERRUPT_T2           5   // Timer2 Overflow / external reload
#define INTERRUPT_RFRDY        8   // RF SPI ready interrupt
#define INTERRUPT_RFIRQ        9   // RF interrupt
#define INTERRUPT_SERIAL       10  // SPI or 2-wire interrupt
#define INTERRUPT_WUOPIRQ      11  // Wakeup on pin interrupt
#define INTERRUPT_MISCIRQ      12  // Misc interrupt
#define INTERRUPT_TICK         13  // Internal Wakeup```

How do I do that? Is the information sufficient enough?

ISRs here:

```#ifndef _ISRDEF24LE1_H_
#define _ISRDEF24LE1_H_

#ifdef __ICC8051__

#define EXT_INT0_ISR() \
_Pragma("vector=0x0003") \
__interrupt void ext_int0_isr(void)

#define T0_ISR() \
_Pragma("vector=0x000b") \
__interrupt void t0_isr(void)

#define AES_RDY_ISR() \
_Pragma("vector=0x0013") \
__interrupt void aes_rdy_isr(void)

#define T1_ISR() \
_Pragma("vector=0x001b") \
__interrupt void t1_isr(void)

#define UART0_ISR() \
_Pragma("vector=0x0023") \
__interrupt void uart0_isr(void)

#define T2_ISR() \
_Pragma("vector=0x002b") \
__interrupt void t2_isr(void)

#define RF_RDY_ISR() \
_Pragma("vector=0x0043") \
__interrupt void rf_rdy_isr(void)

#define NRF_ISR() \
_Pragma("vector=0x004b") \
__interrupt void nrf_isr(void)

#define SER_ISR() \
_Pragma("vector=0x0053") \
__interrupt void serial_isr(void)

#define WUOP_ISR() \
_Pragma("vector=0x005b") \
__interrupt void wuop_isr(void)

#define MISC_ISR() \
_Pragma("vector=0x0063") \
__interrupt void misc_isr(void)

_Pragma("vector=0x0063") \

#define TICK_ISR() \
_Pragma("vector=0x006b") \
__interrupt void tick_isr(void)

#endif /*__ICC8051__*/

#ifdef __C51__

#define EXT_INT0_ISR()  void ext_int0_isr(void) interrupt INTERRUPT_IPF     // External Interrupt0 (P0.3) (0x03)
#define T0_ISR()        void t0_isr(void)       interrupt INTERRUPT_T0      // Timer0 Overflow (0x0b)
#define AES_RDY_ISR()   void aes_rdy_isr(void)  interrupt INTERRUPT_POFIRQ  // Power failure interrupt (0x13)
#define T1_ISR()        void t1_isr(void)       interrupt INTERRUPT_T1      // Timer1 Overflow (0x1b)
#define UART0_ISR()     void uart0_isr(void)    interrupt INTERRUPT_UART0   // UART0, Receive & Transmitt interrupt (0x0023)
#define T2_ISR()        void t2_isr(void)       interrupt INTERRUPT_T2      // Timer2 Overflow (0x2b)
#define RF_RDY_ISR()    void rf_rdy_isr(void)   interrupt INTERRUPT_RFRDY   // RF SPI ready interrupt (0x43)
#define NRF_ISR()       void nrf_isr(void)      interrupt INTERRUPT_RFIRQ   // RF interrupt (0x4b)
#define SER_ISR()       void serial_isr(void)   interrupt INTERRUPT_SERIAL  // SERIAL / SPI interrupt (0x53)
#define WUOP_ISR()      void wuop_isr(void)     interrupt INTERRUPT_WUOPIRQ // Wake on pin interrupt (0x5b)
#define MISC_ISR()      void misc_isr(void)     interrupt INTERRUPT_MISCIRQ // MISC interrupt (0x63)
#define TICK_ISR()      void tick_isr(void)     interrupt INTERRUPT_TICK    // Internal wakeup interrupt (0x6b)```

Last Edited: Mon. Mar 4, 2019 - 04:13 AM

You're really in the wrong place for help with an 8051 device. It took me a while to figure out what the hell you were trying to do.

Jim

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get \$5 free gold/silver https://www.onegold.com/join/713...