Trying to understand why bit shifting allows PWM output to work correctly

z_iron

Joined May 24, 2020
23
Hi, student new to pic here. I've written a simple piece of code that reads the value of a potentiometer using ADC and generates a PWM output to dim an LED.

C:
void main(void)
{
// initialize the device
SYSTEM_Initialize();
PWM_IN1_Enable();

while (1)
{
}
}
The code above works and the led dims as the pot is turned. My question is regarding the " >>10 " piece of code in where the ADC result is set into 'adcResult' Without it the led turned on or off randomly as the pot was turned and after adding ">>10" (Instruction guide I followed added this bit shift and didn't explain why properly), the LED began to dim with the pot and work correctly. How does bit shifting to the right 10 bits make the LED dim gradually? What's happening here?

Using: PIC16F18446 (LPC Curiosity board standard PIC)
Using: MPLABx 5.40

Papabravo

Joined Feb 24, 2006
15,535
Where are the significant bits in the A/D conversion? Are they left justified in the most significant bits or are they right justified in the least significant bits? It matters just a little bit.

djsfantasi

Joined Apr 11, 2010
7,566
Also, what is the range of results for the analog read? And what is the range of inputs for the PWM command?

On an Arduino (which I am familiar with) the analog read returns on integer in the range of 0-1023. The PWM command takes a value from 0-255. So, you have to map 0-1023 to 0-255.

You’re micro is getting a PWM value from 511-1023, definitely an odd mapping.

As far as but shifting 10 bits, that seems odd, too. That is dividing by 1024. In my example? Instead of using the map() command, dividing by 4 performs that map. Or, equivalently, shifting right two bits.

z_iron

Joined May 24, 2020
23
Where are the significant bits in the A/D conversion? Are they left justified in the most significant bits or are they right justified in the least significant bits? It matters just a little bit.
The bits are left justified. MSBs in the upper reg (ADRESH)

z_iron

Joined May 24, 2020
23
Also, what is the range of results for the analog read? And what is the range of inputs for the PWM command?

On an Arduino (which I am familiar with) the analog read returns on integer in the range of 0-1023. The PWM command takes a value from 0-255. So, you have to map 0-1023 to 0-255.

You’re micro is getting a PWM value from 511-1023, definitely an odd mapping.

As far as but shifting 10 bits, that seems odd, too. That is dividing by 1024. In my example? Instead of using the map() command, dividing by 4 performs that map. Or, equivalently, shifting right two bits.
I've commented out the map function i made. I should've removed it in the post as it has no relevance for my question. Apologies.

upand_at_them

Joined May 15, 2010
762
If that PIC is like all of the others I've used the ADC value is left-justified by default. Shifting right by 10 bits (it's a 12-bit ADC value) gives you the upper 2 bits of the value. So you should be getting 4 steps.

z_iron

Joined May 24, 2020
23
If that PIC is like all of the others I've used the ADC value is left-justified by default. Shifting right by 10 bits (it's a 12-bit ADC value) gives you the upper 2 bits of the value. So you should be getting 4 steps.
I still don't understand whats happening here. My understanding is that if only the upper 2 bits remain and if there are 2^2 steps then the pot needs to be moved to a small amount in order to affect the LED (4 steps instead of 1024), why is it then does the pot turn the entire way to go from dim to full brightness (I want this but have got here by luck).

upand_at_them

Joined May 15, 2010
762
No, it needs to be moved a large amount, because those two bits are the upper two bits not the lower two. Think of a 0-1000 scale and only using the hundreds place. 0 through 99 are the same.

Last edited:

Papabravo

Joined Feb 24, 2006
15,535
The bits are left justified. MSBs in the upper reg (ADRESH)
So the PWM value is the most significant 6 bits of the A/D conversion. That means there are potentially 64 discrete settings, and if the total rotation is about 300°, that means each change in PWM value requires about 4.75°.

upand_at_them

Joined May 15, 2010
762
Oh, right. I forgot about that...12 bits in 16 bits of register....leaving 6 bits after the shift.

Papabravo

Joined Feb 24, 2006
15,535
Oh, right. I forgot about that...12 bits in 16 bits of register....leaving 6 bits after the shift.
Easy to miss those small details, especially if you have never missed them before. I have so I am no longer susceptible to that oversight.
Kinda like immunity to most(?) viruses.