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

pwm dimming led rgb with trouble on third and thourth channel.

i am having trouble with pwm module 2. only two of the channels are working but not the third nor the fourth. i tried pwm module 1 but im having the same problem there. i cant tell what im missing :/

the third channel only works if i declare it on its with "NRF_PWM2->PSEL.OUT" and passing only zeros to other elements in "pwm_seq[4]" even tho i did not activate the other channels/assign them to any physical pin.

please help.

void initRgbPwm(int32_t pwmFreq)  
{                                      			
		rgbCounterTop = 0;	
		uint32_t baseFreq = 500000;
		uint8_t preSc = 5;
		while(rgbCounterTop <= 100 && baseFreq <= 16000000)
		{
			rgbCounterTop = (baseFreq / pwmFreq);
			if(rgbCounterTop <= 100 && baseFreq <= 16000000)
			{
				baseFreq = baseFreq * 2;
				preSc--;
			}	else break;
		}
		
		If(rgbCounterTop > 100)   
		{
				uint16_t pwm_seq[4] = {0, 0, 0, 0};
			
			NRF_PWM2->PSEL.OUT[0] = 0x0000001A;	// red rgb.
			NRF_PWM2->PSEL.OUT[1] = 0x00000006;	// green rgb.
			NRF_PWM2->PSEL.OUT[2] = 0x0000001B;	// blue rgb.
			
			NRF_PWM2->ENABLE = 1;   
			NRF_PWM2->MODE = 0;   
			NRF_PWM2->PRESCALER = preSc;   
			NRF_PWM2->COUNTERTOP = rgbCounterTop;    
			NRF_PWM2->LOOP = 0;   
			NRF_PWM2->DECODER = 0X00000102;    
			NRF_PWM2->SEQ[0].PTR  = ((uint32_t)(pwm_seq) << PWM_SEQ_PTR_PTR_Pos);    
			NRF_PWM2->SEQ[0].CNT  = ((sizeof(pwm_seq) / sizeof(uint16_t)) << PWM_SEQ_CNT_CNT_Pos);   
			NRF_PWM2->TASKS_SEQSTART[0] = 1;    
		}
}

void rgbPwm(uint8_t dutyCycleRed, uint8_t dutyCycleGreen, uint8_t dutyCycleBlue)
{
	uint16_t dutyCycleCh1 = (dutyCycleRed * rgbCounterTop)/100;  
	uint16_t dutyCycleCh2 = (dutyCycleGreen * rgbCounterTop)/100; 
	uint16_t dutyCycleCh3 = (dutyCycleBlue * rgbCounterTop)/100; 
	
	uint16_t pwm_seq[4] = {dutyCycleCh1  | 0x8000, dutyCycleCh2  | 0x8000, dutyCycleCh3  | 0x8000, 0};

	NRF_PWM2->SEQ[0].PTR  = ((uint32_t)(pwm_seq) << PWM_SEQ_PTR_PTR_Pos);
	NRF_PWM2->SEQ[0].CNT  = ((sizeof(pwm_seq) / sizeof(uint16_t)) << PWM_SEQ_CNT_CNT_Pos);
	NRF_PWM2->TASKS_SEQSTART[0] = 1;
}
Parents
  • A good start will be do declare pwm_seq as static:

    static uint16_t pwm_seq[4] = {dutyCycleCh1  | 0x8000, dutyCycleCh2  | 0x8000, dutyCycleCh3  | 0x8000, 0};
    

    If you don't do this, pwm_seq will be placed in the stack and NRF_PWM2->SEQ[0].PTR will point to a place in stack. After the function ends pwm_seq will not exist anymore, or more specific the place in the stack where it was may be overwritten by another function.

    The static keyword will place the variable some place else in RAM and it will exist throughout the lifetime of the program. See here for more info, or read about static and automatic variables in C.

Reply
  • A good start will be do declare pwm_seq as static:

    static uint16_t pwm_seq[4] = {dutyCycleCh1  | 0x8000, dutyCycleCh2  | 0x8000, dutyCycleCh3  | 0x8000, 0};
    

    If you don't do this, pwm_seq will be placed in the stack and NRF_PWM2->SEQ[0].PTR will point to a place in stack. After the function ends pwm_seq will not exist anymore, or more specific the place in the stack where it was may be overwritten by another function.

    The static keyword will place the variable some place else in RAM and it will exist throughout the lifetime of the program. See here for more info, or read about static and automatic variables in C.

Children
No Data
Related