PDA

View Full Version : 10-Bit PWM using PIC16F1509



Aussie Barry
- 27th February 2015, 03:07
Hi All,

I am working my way through the process of setting up a 10-Bit PWM channel using a PIC16F1509 and have hit a major hurdle - I am stumped and don't know what to do.
My project is for an RGB LED Controller using slider pots to control the PWM signal being fed to the RGB LEDs.
I have the basic principle operating using HPWM commands but this limits the control to 8-bits and I want to take advantage of the device's 10-bit PWM capability.
Using the calculation in the datasheet, I can achieve 10-bit PWM resolution for my desired 250Hz PWM frequency with a 4MHz internal oscillator, PR2 = 255 and TMR2 Prescale = 16
My problem is when I try to set the PWM1CON register or load the high and low PWM duty cycle registers.
My code is as follows:



'************************************************* ***************
'* Name : RGB_LED_Controller_16F1509.pbp *
'* Author : Barry Phillips *
'* Notice : Copyright (c) 2015 Baztronics *
'* : All Rights Reserved *
'* Date : 27/02/2015 *
'* Version : 1.0 *
'* Notes : RGB LED Controller using PIC16F1509 *
'* : *
'************************************************* ***************
#CONFIG
__config _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _BOREN_OFF & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
__config _CONFIG2, _WRT_OFF & _STVREN_OFF & _LPBOR_OFF & _LVP_OFF
#ENDCONFIG

OSCCON= %01101000 'Internal 4MHz Oscillator
DEFINE OSC 4 'Internal RC Oscillator 8MHz

' Connect LCD D4 to RB4 (Pin 13)
' Connect LCD D5 to RB5 (Pin 12)
' Connect LCD D6 to RB6 (Pin 11)
' Connect LCD D7 to RB7 (Pin 10)
' Connect LCD R/S to RC3 (Pin 7)
' Connect LCD E to RC6 (Pin 8)
' Connect POT1 to RA0 (Pin 19)
' Connect POT2 to RA1 (Pin 18)
' Connect POT3 to RC0 (Pin 16)
' Connect POT4 to RC2 (Pin 14)
' Connect PWM1 to RC5 (Pin 5)
' Connect PWM2 to RC7 (Pin 9)
' Connect PWM3 to RA2 (Pin 17)
' Connect PWM4 to RC1 (Pin 15)
' Connect SW1 to RA5 (Pin 2)
' Connect SW2 to RA1 (Pin 3)
' Connect SW3 to RA3 (Pin 4)

@ ERRORLEVEL -306 ' Turn off "Crossing page boundary" error message


' Define LCD registers and bits
Define LCD_DREG PORTB
Define LCD_DBIT 4
Define LCD_RSREG PORTC
Define LCD_RSBIT 3
Define LCD_EREG PORTC
Define LCD_EBIT 6
Define LCD_BITS 4
Define LCD_LINES 4
Pause 500

DEFINE ADC_BITS 10 'Set number of bits in result (8, 10 or 12)
DEFINE ADC_CLOCK 3 'Set clock source (rc = 3)
DEFINE ADC_SAMPLEUS 50 'Set sampling time in microseconds

TRISA = %00111011 'Set PORTA.0, 1, 3, 4 & 5 as digital inputs
TRISB = %00000000 'Set PORTB as all digital outputs
TRISC = %00000101 'Set PORTC.0 & 2 as digital inputs
ANSELA = %00000011 'Set PORTA.0 & 2 as analog inputs
ANSELB = %00000000 'Disable PORTB analog inputs
ANSELC = %00000101 'Set PORTC.0 & 2 as analog inputs

ADCON0 = %00000001 'Enable ADC
ADCON1 = %11010000 'Right Justify
'Fosc/16
'Vref connected to Vdd
FVRCON.7 = 0 'Disable Fixed Voltage Reference
CM1CON0.7 = 0 'Disable Comparitor 1
CM2CON0.7 = 0 'Disable Comparitor 2
INTCON.7 = 0 'Disable Interrupts

T2CON = %00000110 'Enable TMR2 and set PreScale to 16

' Set up PWM Registers
PWM1CON = %11000000
PR2 = %11111111

POT1 VAR WORD
POT2 VAR WORD
POT3 VAR WORD
POT4 VAR WORD
ScaledPot1 VAR WORD
Dummy VAR WORD


LCDOUT $FE, $1
LCDOUT $FE, $80, " ** BAZTRONICS ** "
LCDOUT $FE, $C0, "RGB LED Controller "
LCDOUT $FE, $94, " Version 1.1 "
LCDOUT $FE, $D4, " "
Pause 2000
LCDOUT $FE, $1

Start:
ADCIN 0, POT1
LCDOUT $FE, $80, "POT1 = ", DEC POT1, " ", DEC ScaledPot1, " "
ADCIN 1, POT2
LCDOUT $FE, $C0, "POT2 = ", DEC POT2, " "
ADCIN 4, POT3
LCDOUT $FE, $94, "POT3 = ", DEC POT3, " "
ADCIN 6, POT4
LCDOUT $FE, $D4, "POT4 = ", DEC POT4, " "
Pause 100
PWM1DCH = POT1.HIGHBYTE
PWM1DCL = POT1.LOWBYTE
GOTO Start

End


When I try to compile this code I get syntax error messages for the following lines:
PWM1CON = %11000000
PWM1DCH = POT1.HIGHBYTE
PWM1DCL = POT1.LOWBYTE

I cannot see anything wrong with the syntax in these three lines of code. Can anyone shed some light on what it is wrong?

I am using PBP3 (Version 3.0.5.4)) and MCS (Version 5.0.0.0)

Cheers
Barry
VK2XBP

richard
- 27th February 2015, 03:44
your code complies ok for me
chk pic16f15009 microcontroller selected and mpasm assembler selected


for 10 bit pwm you need to
pot1<<6 before you load the regs


pot1=pot1<<6
PWM1DCH = POT1.HIGHBYTE
PWM1DCL = POT1.LOWBYTE

ps
I'm assuming pot1 is 0-1023 value of course


you could be clever here an not right justify adc reading and save a step

richard
- 27th February 2015, 03:58
I am using PBP3 (Version 3.0.7.4)) and MCS (Version 5.0.0.5)

Aussie Barry
- 27th February 2015, 04:40
Thanks Richard.

I updated the versions of PBP3 and MCS and everything now compiles...

Cheers
Barry
VK2XBP

CuriousOne
- 19th January 2020, 12:18
Having same idea, to control RGB led using PWM, but how you did it with 1 hardware channel PWM?

mpgmike
- 19th January 2020, 18:10
Great question! I don't know. I would suggest if you have 3 different targets (R + B + G) each requiring a different PWM DC%, you will need a PIC with 3 separate PWM channels.

CuriousOne
- 19th January 2020, 19:31
And that appears to be a hard task - most MCUs as I've checked from datasheet, have "synchronised" PWM outputs, which mostly mirror each other, and also they all run same frequency....

pedja089
- 19th January 2020, 23:02
Take look at SPWM from DT. Or better MIBAM.

mpgmike
- 20th January 2020, 15:37
And that appears to be a hard task - most MCUs as I've checked from datasheet, have "synchronised" PWM outputs, which mostly mirror each other, and also they all run same frequency....
All that means is that the Period for each starts at the same time, and they operate at the same frequency. Each is capable of independent Duty Cycle. That will work for an RGB LED.

Ioannis
- 21st January 2020, 14:47
Mike, that means a PIC should have different CCPxCON registers. As many as the different channels, so the user can define the duty of each independently.

For example, the 16F887 has two and 16F1939 has four CCPxCON registers.

Ioannis

richard
- 22nd January 2020, 01:01
its fairly easy to get 3 different pwm streams from one ccpm module , you just to need to
1. set pulse width for channel
2. set pin steering to channel pin
in a sequentially multiplexed routine
eg


/**
Generated Main Source File


Device : PIC16F1825
Driver Version : 2.00
*/


int pwmv[3];
char cnt = 0;
void ticker(void);




#include "mcc_generated_files/mcc.h"


/*
Main application
*/
void main(void) {
// initialize the device
SYSTEM_Initialize();
TMR1_SetInterruptHandler(ticker);
// When using interrupts, you need to set the Global and Peripheral Interrupt Enable bits
// Use the following macros to:
PSTR1CON = 0x10;
// Enable the Global Interrupts
INTERRUPT_GlobalInterruptEnable();


// Enable the Peripheral Interrupts
INTERRUPT_PeripheralInterruptEnable();


// Disable the Global Interrupts
//INTERRUPT_GlobalInterruptDisable();


// Disable the Peripheral Interrupts
//INTERRUPT_PeripheralInterruptDisable();


while (1) {
pwmv[cnt] = ADC_GetConversion(cnt);
__delay_ms(300);
cnt++;
cnt &= 3;
// Add your application code
}
}


void ticker(void) {
static char inx = 0;
CCPR1L = pwmv[inx] >>8;
CCP1CON = ((pwmv[inx]&0xc0)>>2) | 0xC;
PSTR1CON = 0x10 | (2 << inx);
inx++;
inx &= 3;
}




this sort of led modulation is exactly how those p10 led modules work

Ioannis
- 22nd January 2020, 08:02
Hi Richard. Thanks for posting this. I was not aware this was possible.

But, doesn't this have glitches in the signal when steering is changing channel?

Have to try this in real hardware.

Ioannis

richard
- 22nd January 2020, 08:16
24.4.6.1 Steering Synchronization
The STRxSYNC bit of the PSTRxCON register gives
the user two selections of when the steering event will
happen. When the STRxSYNC bit is ‘0’, the steering
event will happen at the end of the instruction that
writes to the PSTRxCON register. In this case, the
output signal at the Px<D:A> pins may be an
incomplete PWM waveform. This operation is useful
when the user firmware needs to immediately remove
a PWM signal from the pin.
When the STRxSYNC bit is ‘1’, the effective steering
update will happen at the beginning of the next PWM
period. In this case, steering on/off the PWM output will
always produce a complete PWM waveform.



in the isr you could add a PSTR1CON = 0 before setting new pwm value
or maybe even read the data sheet re glitch free pwm updates

i didn't go to too much effort for this.

Ioannis
- 22nd January 2020, 16:04
Well, after reading the Steering on 16F887 I think it is not possible to have 4 different PWM signals at the same time on a chip that lacks more channels.

The 887 has 2 channels, so 2 different PWM signals can be produced by hardware. I really do not have fully understood what steering is there for but I am sure not for more free channels.

The datasheet says that the SAME PWM signal can be simultaneously available on multiple pins. Not different PWM signals.

I hope I am wrong but that is what data sheet says as I understand it.

Ioannis

tumbleweed
- 23rd January 2020, 00:14
its fairly easy to get 3 different pwm streams from one ccpm module , you just to need to...
Maybe I'm missing something here.

What does LED1 do while the signal goes out to LED2 and then LED3?

richard
- 23rd January 2020, 00:28
What does LED1 do while the signal goes out to LED2 and then LED3?


its unlit for 4mS of a 6mS drive signal period . pov makes the gap invisible at that rate


the pwm freq is 2kHz the isr switches the pwm drive @ 2mS intervals . for a pov objective its quite effective
its basically the same as how a 1/4 scan or a 1/8 scan led panel works, except its 1/3 scan

try it .

CuriousOne
- 24th January 2020, 05:44
POV might make it invisible to eye, but cameras see all that flickering very well, and giving very poor recording. So unfortunately, that is not the way to go...

tumbleweed
- 24th January 2020, 10:23
Plus, I would think having the led off 2/3 of the time would decrease the brightness quite a bit.

Ioannis
- 24th January 2020, 11:09
It is kinda multiplexed PWM signal I think.

Ioannis

richard
- 17th February 2020, 09:28
Plus, I would think having the led off 2/3 of the time would decrease the brightness quite a bit.

it won't do for room lighting, it's still useful though

mp4 attached