Multiple PWM and port C


Closed Thread
Results 1 to 24 of 24
  1. #1
    Join Date
    Oct 2009
    Posts
    583

    Default Multiple PWM and port C

    Hi,

    Still working on my aquarium lighting controller as I've discovered an issue with using the hardware PWM on the 18F4520. I've opted to use Darrels multi-SWPM files, and after a littler re-write the code compiles and runs, but with some strange quirkyness that I can't seem to get my head round.

    As I already have PCB's made I need to keep the two PWM pins on port C1 and C2. Now when I use these, the RTC clock displays a stupid time of 48:85 and everything locks up as the clock is not out putting the correct time. If I change the multi-spwm pins to port D1 and D2, the clock runs fine with the correct time. Here is the settings I've used for Darrels include file

    Code:
    define SPWMFREQ  100                    ' PWM frequency in Hz    
    
    SPWM1PIN  VAR PORTC.1                   ' SPWM channel 1
    define SPWM1VAR  _B_PWM
    
    SPWM2PIN  VAR PORTC.2                   ' SPWM channel 2
    define SPWM2VAR  _W_PWM
    I've obviously commented out the port settings for the hardware PWM register
    Code:
    '*******************************************************************************
    'Port and Register settings
    '*******************************************************************************
    
    'CCP1CON = %00001100                     'Set CCP1 to PWM 
    'CCP2CON = %00001100                     'Set CCP2 to PWM     
    TRISA  = %11101111              
    TRISB  = %00000011 
    TRISD  = %00000011              
    T0CON  = %11000111
    I basically need to configure portC so that C0, C1 and C2 are digital, C3 and C4 are used for the RTC (SDA and SCL), but I'm struggling

  2. #2
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,607


    Did you find this post helpful? Yes | No

    Default Re: Multiple PWM and port C

    Hi,
    I don't know much about I2C but I suspect that the issue you're having could be timing related. If you're using the PBP commands for I2C then then the communication is bit-banged and software timed. Darrels SPWM routines uses interrupts to do its thing which will disturb the timing of the I2C communication.

    I'm curious what the issue with using hardware PWM actually means. Since the hardware is built to use the CCP modules I'd do everything I possibly could to actually make use of them instead of reverting to bit-banging PWM.

    /Henrik.

  3. #3
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: Multiple PWM and port C

    Hi Henrik,

    The issue with the hardware PWM was that it doesn't produce a nice square wave, and even at 100% (255) duty is still sending a signal rather than full line level. The net result was that the LED drivers were running around 60% when the PIC was outputting full duty cycle. Using Darrels software PWM I get a nice square wave, which at 0 duty cycle I get 0 volts, at 255 duty I get 5v and full Mark to Space ratio. (ie a solid line with no pulses), which is what you would expect.

    I don't think it's a timing issue as I've knocked up a version where the RTC works, and port C1 and C2 drive the LEDs, just when I copy that code to my main program, comment out the reference to CCP registers the resulting HEX causes the clock to function as described.

    My only option is to manually modify the PCB to use port E1 and E2....

  4. #4
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: Multiple PWM and port C

    Interestingly, I have the temp sensor (18B20) on port RA5. If I use RA4 and RA7 as the PWM pins the temperature reading goes heywire, displaying random temperatures like 163C but is often trying to over write the display. With RA4 and RA7 set as the pins for pWM, the clock on C3 and C4 runs fine....

  5. #5
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,607


    Did you find this post helpful? Yes | No

    Default Re: Multiple PWM and port C

    OK, so then it's some kind of interference between the SPWM routines and the rest of the program, perhaps a read-modify-write issue, I don't know. But then you say that you had a version with both SPWM and I2C on the same port (different pins of course) which DID work so I don't know. Hopefully Darrel or someone else who's been using the routines in quesiton will jump in.

    Back to the hardware PWM.... Did you set the registers manually or did you use the HPWM command?
    If you set the registers manually then the number of bits of resolution you get depends on the frequency you select so a dutycycle value of 255 doesn't neccesarily mean 100% - it depends.
    If, on the other hand, you DID use the HPWM command then you should have got 100% with a duty of 255 - given you had told the compiler the correct operating frequency, ie DEFINE OSC xx.

    I still think you should concentrate on getting the CCP modules to do the PWM for you. Post the code for that and I'll take a look.

    /Henrik.

  6. #6
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: Multiple PWM and port C

    Well I just re-loaded the test code that uses port C for both clock and PWM pins and that appears to do the same thing, with 10:10 shown as the time. Mind you I've been cutting and pasting bits of code from one to the other to try and resolve this.

    When using CCP modules I simply used CCP1CON = %00000000 and CCP2CON = %00000000 to set the register and then used PBP HPWM command to drive the pins....

    I'll drop you a PM with the code....

  7. #7
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,607


    Did you find this post helpful? Yes | No

    Default Re: Multiple PWM and port C

    Hi,
    Took a quick look at the code you PM'd me and found this:
    Code:
    'If light=1 then                         ' If the variable is 1 then output full PWM to lights
    '    hpwm 1,255,200        
    '    hpwm 2,255,200
    'endif
    'If light=0 then                       ' If the variable is low then set value to 0 an turn off the lights
    '    hpwm 1,0,200        
    '    hpwm 2,0,200    
    'endif
    If this is where you're trying to set 100% dutycycle but ends up with a "jumpy" signal not at 100% then the problem is most likely that you're trying a frequency (200Hz) far below the specified minimum. If you look at the manual you'll see that for a 18F device running at 20MHz the minimum frequency is 1221Hz.

    The only other place in the code where HPWM was used had a frequency of 5kHz so that should've worked - did it?

    /Henrik.

  8. #8
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: Multiple PWM and port C

    Changing ADCON0 to a value of 7 and changing the SW PWM pins to C1 and C2 made the clock to something, but it's still not running. The clock displayed 45:00 and then counted up in seconds (45:01, 45:02 etc) until it reach 14:10 and then displayed the 45:51. It remained displaying this "time", then changed to 45:52 a minute later, followed by 45:53 etc but there was no change in the case and the LEDs didn't light.

    Not sure if changing ADCON0 to 7 (all digital) had a bearing on things

  9. #9
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: Multiple PWM and port C

    Quote Originally Posted by HenrikOlsson View Post
    Hi,
    Took a quick look at the code you PM'd me and found this:
    Code:
    'If light=1 then                         ' If the variable is 1 then output full PWM to lights
    '    hpwm 1,255,200        
    '    hpwm 2,255,200
    'endif
    'If light=0 then                       ' If the variable is low then set value to 0 an turn off the lights
    '    hpwm 1,0,200        
    '    hpwm 2,0,200    
    'endif
    If this is where you're trying to set 100% dutycycle but ends up with a "jumpy" signal not at 100% then the problem is most likely that you're trying a frequency (200Hz) far below the specified minimum. If you look at the manual you'll see that for a 18F device running at 20MHz the minimum frequency is 1221Hz.

    The only other place in the code where HPWM was used had a frequency of 5kHz so that should've worked - did it?

    /Henrik.
    Hi,

    That section had been commented out from when I was using the hardware modules. It was intended as a manual over-ride so that I could turn the lights on or off via the push of a button. I never ran the module at high frequencies as the LED driver requires a PWM frequency of 100 hz - 1khz and at 1 Khz they resonated with a high pitched sound.

    The original code had
    Code:
    '*******************************************************************************
    'Send pulses to drivers
    
        hpwm 1,W_PWM,200        
        hpwm 2,B_PWM,200
        
    '*******************************************************************************
    Where W_PWM and B_PWM increased from 0 to 255 or decreased from 255 to 0 to fade the LEDs up and down
    Last edited by Scampy; - 11th December 2013 at 17:01.

  10. #10
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: Multiple PWM and port C

    I've just tried cutting and pasting the code into a new page and renamed it - complied and loaded and got the same results when using C1 and C2 as the PWM pins. If I comment out the include "Multi_SPWM.pbp" the program runs fine, but I obviously have no outputs from the two pins.

    So maybe you're right Henrik, in that there is some clash with the timing / or i2c bus ???

  11. #11
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,607


    Did you find this post helpful? Yes | No

    Default Re: Multiple PWM and port C

    Hi,
    Since it seems to work when you're using SPWM on one port (PortB for example) while the I2C is on another (PortC) I don't think it's a timing thing.
    Since it does NOT seem to work when the SPWM is on the SAME port as the I2C I think it's some other sort of interference where the SPWM is messing with the I2C pins, possibly due to R-M-W but I don't know for sure.

    As for the hardware PWM....
    The original code had
    Code:
    '*******************************************************************************
    'Send pulses to drivers
    
        hpwm 1,W_PWM,200        
        hpwm 2,B_PWM,200
        
    '*******************************************************************************
    Well, then that IS the problem you're having - you're trying to run it at TO LOW frequency, which was the point I was trying to make.
    At 20MHz oscillator frequency there is no way to actually get 200Hz from the CCP module, the lowest possible frequency is 1221Hz.

    /Henrik.

  12. #12
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: Multiple PWM and port C

    Ok I've tried a different approach. I noticed that Darrel has revised his multiple PWM Routine Called SPMW_INT rather then the Multi_SPWM So I modified a fresh copy of the code, included that file and the DT_INTS-18 file and the thing compiled. Loaded it to the chip and both the TEMP and CLOCK are acting up. The temp is shown as 163c and the clock as 45:85.

    Here's the main part of the revised code

    Code:
    ASM 
      __CONFIG    _CONFIG1H, _OSC_HS_1H
      __CONFIG    _CONFIG2L, _PWRT_ON_2L  
      __CONFIG    _CONFIG2H, _WDT_ON_2H & _WDTPS_512_2H
      __CONFIG    _CONFIG3H, _MCLRE_ON_3H & _LPT1OSC_OFF_3H & _PBADEN_OFF_3H  
      __CONFIG    _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L
    ENDASM
    
    INCLUDE "DT_INTS-18.bas"            ; Base Interrupt System
    INCLUDE "SPWM_INT.bas"              ; Software PWM module
    
    DEFINE SPWM_FREQ  200                ; SPWM Frequency
    DEFINE SPWM_RES   256               ; SPWM Resolution
    
    ASM
    SPWM_LIST  macro                    ; Define Pin's to use for SPWM
         SPWM_PIN  PORTC, 1, _B_PWM  ; and the associated DutyCycle variables
         SPWM_PIN  PORTC, 2, _W_PWM  ; Notice the underscore before variables
    
      endm
      SPWM_INIT  SPWM_LIST              ; Initialize the Pins
    ENDASM
    
    ASM
    INT_LIST  macro    ; IntSource,        Label,  Type, ResetFlag?
            INT_Handler   TMR1_INT,  SPWMhandler,  ASM,  yes
        endm
        INT_CREATE                      ; Creates the interrupt processor
    ENDASM
    
    @ INT_ENABLE  TMR1_INT              ; enable Timer 1 interrupts
    
    
    INCLUDE "LCDbar_INC.bas"        ' Include the BARgraph routines
     
    
    DEFINE LCD_DREG  PORTB                  ' LCD Data port
    DEFINE LCD_DBIT  0                      ' starting Data bit (0 or 4)
    DEFINE LCD_EREG  PORTB                  ' LCD Enable port
    DEFINE LCD_EBIT  5                      '     Enable bit  (on EasyPIC 5 LCD)
    DEFINE LCD_RSREG PORTB                  ' LCD Register Select port
    DEFINE LCD_RSBIT 4                      '     Register Select bit   (on EasyPIC 5 LCD)
    DEFINE LCD_BITS  4                      ' LCD bus size (4 or 8 bits)
    DEFINE LCD_LINES 4                      ' number of lines on LCD
    DEFINE LCD_COMMANDUS 2000               ' Command delay time in us 
    DEFINE LCD_DATAUS 50                    ' Data delay time in us 
    
    DEFINE  OSC 20                          ' 18F4520, 20mhz crystal
    ADCON1 = $0F
    clear
    
    '*******************************************************************************
    'DS18B20 temp probe setting
    '*******************************************************************************
    
    DQ              VAR     PORTA.5         ' One-wire data pin
    temperature     VAR     WORD            ' Temperature storage
    count_remain    VAR     BYTE            ' Count remaining
    count_per_c     VAR     BYTE            ' Count per degree C
    
    '*******************************************************************************
    'Port and Register settings
    '*******************************************************************************
       
    TRISA  = %11101111              
    TRISB  = %00000011 
    TRISD  = %00000011              
    T0CON  = %11000111
    
    ADCON0 = %00000000;          // AD converter module disabled
    ADCON1 = %00001111;          // All Digital
    ADCON2 = %00000000;          // 
    CMCON = 7   
    
    '*******************************************************************************
    ' Data presets
    '*******************************************************************************
    data @0
        data    00                          'Blue fade IN duration hours
        data    5                          'Blue fade IN duration minutes
        data    00                          'Blues fade OUT duration hours
        data    45                          'Blue fade OUT duration minutes
        data    00                          'Whites fade IN duration hours
        data    7                          'Whites Fade IN duration MINS
        data    00                          'Whites Fade OUT duration HOURS
        data    20                          'Whites Fade OUT duration MINS
        data    255                         'Blue MAX Intensity %
        data    255                         'Whites MAX Intensity %
        data    word 840                    'Blue ON time 14:00
        Data    word 840                    'Whites ON time 14:00
        data    word 1200                   'Blue OFF time  20:00
        Data    word 1200                   'White OFF time 20:00
        Data    word 1200                   'Sump light on time  20:00
        Data    word 1200                   'Sump light off time  8:00
       
                
    '*******************************************************************************
    ' Variables
    '*******************************************************************************
    
    fadesetHR          VAR WORD[2]                   
      fadesetHR1       VAR fadesetHR[0]     'blue fade in hour
      fadesetHR2       VAR fadesetHR[1]     'White fade in hour
      
    fadesetMN          VAR WORD[2]                   
      fadesetMN1       VAR fadesetMN[0]     'blue fade in minutes
      fadesetMN2       VAR fadesetMN[1]     'white fade in minutes
      
    fadeoutHR          VAR WORD[2]                   
      fadeoutHR1       VAR fadeoutHR[0]     'blue fade out hour
      fadeoutHR2       VAR fadeoutHR[1]     'white fade out hour
      
    fadeoutMN          VAR WORD[2]                   
      fadeoutMN1       VAR fadeoutMN[0]     'blue fade out minute
      fadeoutMN2       VAR fadeoutMN[1]     'white fade out minutes
      
    lightsetHR          VAR word[2]                   
      lightsetHR1       VAR lightsetHR[0]   'blue on time hour
      lightsetHR2       VAR lightsetHR[1]   'white on time hour
      
    lightsetMN          VAR word[2]                   
      lightsetMN1       VAR lightsetMN[0]   'blue on time minutes
      lightsetMN2       VAR lightsetMN[1]   'white on time minutes
      
    lightoffHR          VAR word[2]                   
      lightoffHR1       VAR lightoffHR[0]   'blue off time hour
      lightoffHR2       VAR lightoffHR[1]   'white off time hour
      
    lightoffMN          VAR word[2]                   
      lightoffMN1       VAR lightoffMN[0]   'blue off time minutes
      lightoffMN2       VAR lightoffMN[1]   'white off time minutes
    
    
    DecButton var PORTA.0	                ' Press to Decrement Button
    SetButton var PORTA.1                   ' Press to Set/memorise Button
    IncButton var PORTA.2	                ' Press to Increment Button
    
    OnButton var PORTA.0	                ' Press to Decrement Button
    OffButton var PORTA.2	                ' Press to Increment Button
    
    H_butt   VAR PORTA.2                    'hour increase 
    M_butt   VAR PORTA.0                    'minutes increase
    S_butt   VAR PORTA.1                    'set / memorise
    
    Counter1 var word                       'used to store the current time as a digit.  Counts minutes from 0000 at midnight
    
    Blue_on_Time var word                   'stores the blue on time as a digit in minutes, eg 14:00hrs = 840
    Blue_off_Time var word                  'stores the blue off time as a digit in minutes, eg 14:00hrs = 840
    White_on_Time var word                  'stores the white on time as a digit in minutes, eg 14:00hrs = 840
    White_off_Time var word                 'stores the white off time as a digit in minutes, eg 14:00hrs = 840
    
    white_delay_in var byte                 'stores the white fade in pule in seconds
    blue_delay_in VAR byte                  'stores the blue fade in pule in seconds
    white_delay_out var byte                'stores the white fade out pule in seconds
    blue_delay_out VAR byte                 'stores the blue fade out pule in seconds
    
    W_Min           var byte                'Min Light value - Whites
    W_Max           var byte                'Max Light value - Whites
    B_Min           var byte                'Min Light value
    B_Max           var byte                'Max Light value
    
    Old_B_Max var byte
    Old_W_Max var byte
    
    W_PWM           var word                'PWM Variables where the current output values are stored - Whites
    B_PWM           var word                'PWM Variables where the current output values are stored - Royal Blues
    
    old_ss_blue     var byte                'records the previous second in blue fade in
    old_ss_white    var byte                'records the previous second in white fade in
    
    option          var byte                'menu option, used to choose which menu option is required   
    
    Viv             var byte                'used to select the channel the menu selection applies to
    maxbright       var byte                'general variable used to set the max brighness for each channel in menu option
    
    fn              var byte                'general variable to switch between channels in menu options
    Hours           var byte                'used in menu options to set hours for each channel
    Minutes         var byte                'used in menu options to set minutes for each channel
    light           var byte
    
    Sumplighton     Var word                'counter variable for sump on time
    Sumplightoff    Var Word                'counter vairable for sump off time
    Sump_light      Var PORTA.4             'sump light pin     
    sumponHR        VAR byte                'sump light on Hour
    sumponMN        var byte                'sump light on Minutes
    sumpoffHR       var byte                'sump light off Hours
    sumpoffMN       var byte                'sump light off Minutes
    
    daycount        var byte
    
    TimeH           var byte                'variable to store Hours
    TimeM           var byte                'variable to store Minutes
    SS              VAR Byte                'variable to store Seconds
    
    RTCsec          var byte                'RTC Seconds
    RTCMin          var byte		        'RTC Minutes
    RTCHour         var byte	            'RTC Hours
    SetMN           var byte		        'Used to set time Minutes
    SetHR           var byte	            'Used to set time Hours
    SetSS           var byte                'Used to set time Seconds 
                       
    SCLpin          var PORTC.3             'RTC pin - clk
    SDApin          var PORTC.4             'RTC pin - data
    
    CounterA        var byte	            'General purpose Variable
    CounterB        var byte	            'General purpose Variable
    CounterC        var byte	            'General purpose Variable
    CounterD        var byte	            'General purpose Variable
    
    FlashStar       VAR BIT
    
    Blue_Day_Cycle      var word            'Store for which part of the blue day cycle we are in
    White_Day_Cycle     var word            'Store for which part of the white day cycle we are in
    
    
    DAWN    con     0                       'Constants for the current running mode cycle for the lights
    DAY     con     1
    DUSK    con     2
    NIGHT   con     3
    
    '*******************************************************************************
    ;Initialization
    
    LCDOUT $FE,1:FLAGS=0:PAUSE 250:LCDOUT $FE,1:PAUSE 250 ' Initialize LCD
    LCDOUT  $FE,1
    lcdout  $FE,$C0,"   Firmware v1.07   "
    pause   2000                            'wait 2 seconds so they can see it
    lcdout  $FE,1                           'Clear the screen
    
    Gosub read_eprom                        'read in presets for fade in durations and brighness
    
    blue_delay_in = (((fadesetHR[0]*60)+fadesetMN[0])*60)/255   'takes hours and minutes, converts to minutes, then converts to seconds
    white_delay_in = (((fadesetHR[1]/60)+fadesetMN[1])*60)/255  'takes hours and minutes, converts to minutes, then converts to seconds
    blue_delay_out = (((fadeoutHR[0]/60)+fadeoutMN[0])*60)/255  'takes hours and minutes, converts to minutes, then converts to seconds
    white_delay_out = (((fadeoutHR[1]/60)+fadeoutMN[1])*60)/255 'takes hours and minutes, converts to minutes, then converts to seconds
    
    Option = 1                              'sets the menu option default as 1 (set time)
    daycount=0                              'used in sumplight routine to check if gone passed midnight
    
    Sumplightoff =1439
    Sumplighton  =1439                      'sumplight - values used to match counter1 for on off times
    
    setHR = 13                              'initial time following programming or re-boot if RTC not battery backed up
    setMN = 59
    
    'convert initial time to BDC and write it to the DS1307
    CounterA=SetMN
    Gosub ConvertBCD
    RTCMin=CounterB
    
    CounterA=SetHR
    Gosub ConvertBCD
    RTCHour=CounterB
    
    I2Cwrite SDApin,SCLpin,$D0,$00,[RTCSec,RTCMin,RTCHour] 
    
    
    
    '*******************************************************************************
    '************                     Main Program Loop              ***************
    '*******************************************************************************
    
    Main:
    
    If SetButton=0 then                     'if presed jump to the menu
    goto mainmenu
    endif
    
    '*******************************************************************************
    ' check for manual override of the lights
    If H_butt = 0 then                      ' if pressed then change state of varible to 1
    Light=1
    endif
    
    If M_butt = 0 then                      ' if pressed then change state of varible back to 0
    Light=0
    endif
    '*******************************************************************************
    'clock routine
       
    I2CREAD SDApin,SCLpin,$D0,$00,[RTCSec,RTCMin,RTCHour]  ; read DS1307 chip
    
    timeH=(RTCHour>>4)                        'convert the BCD format of the hours register and store in variable timeH
    timeH=(timeH &$03)*10
    timeH=timeH+(RTCHour&$0F)
    
    timeM=(RTCMin>>4)                         'convert the BCD format of the mins register and store in variable timeM
    timeM=(timeM &$07)*10
    timeM=timeM+(RTCMin&$0F)    
    
    ss=(RTCSec>>4)                            'convert the BCD format of the sec register and store in variable ss
    ss=(ss &$07)*10
    ss=ss+(RTCSec&$0F)                     
    
    Counter1 = (TimeH *60)+ TimeM             'take hours and multiply it by 60 then add odd minutes to get the total minutes into counter1
    
    LCDOut $FE,$D4+15,#TimeH DIG 1,#TimeH DIG 0,":",#TimeM DIG 1,#TimeM DIG 0
                 
     
    '*******************************************************************************
    ' check to see if the sump light should be on or off
    
    If daycount = 0 THEN                    ' by default daycount is 0
       If Counter1 => sumplighton Then      ' if the counter matched the sump light on time
         high sump_light                    ' then make the pin high and
         daycount = 1                       ' set the day count to 1
      ENDIF
    ENDIF
    
    IF daycount = 1 THEN                    ' if the daycount is 1 and
      If Counter1 = sumplightoff Then       ' conuter matches sump light off time
        low sump_light                      ' then make the pin low and
        daycount = 0                        ' reset daycount back to 0                       
      ENDIF
    ENDIF
    
    '*******************************************************************************
    'Case Cycle logic 
    
    If Counter1 < Blue_on_Time then
    Blue_day_cycle = NIGHT
    endif
    
    if counter1 > blue_on_time and Counter1 > blue_off_Time and B_PWM > B_Min then
    Blue_day_cycle = DUSK
    endif
    
    if counter1 => blue_on_time and Counter1 < blue_off_Time and B_PWM < B_MAX then
    Blue_day_cycle = DAWN
    endif
    
    
    If Counter1< White_on_Time then
    White_day_cycle = NIGHT
    endif
    
    if counter1 > white_on_time and Counter1 > white_off_Time and W_PWM > W_Min then
    White_day_cycle = DUSK
    endif
    
    if Counter1 => white_on_time  and Counter1 < white_off_Time and W_PWM < W_MAX then
    White_day_cycle = DAWN
    endif
    
    '*******************************************************************************
    'BLUE daily cycle
    
    select case Blue_Day_Cycle
        
    case DAWN 
    lcdout $FE,$80+15,"DAWN "   
    if ss//blue_delay_in = 0 then
    if ss != old_ss_blue then
    B_PWM=B_PWM+1
    old_ss_blue=ss
    endif
    endif
    if B_PWM = b_max then
    Blue_Day_Cycle = DAY
    endif
    
    case DAY
    lcdout $FE,$80+15,"DAY  "
    if B_max < B_PWM then
    B_PWM=B_PWM - 1
    endif 
    if counter1 =blue_off_time then
    Blue_day_cycle = DUSK
    endif
        
    CASE DUSK
    lcdout $FE,$80+15,"DUSK "
    if ss//blue_delay_out= 0 then
    if ss != old_ss_blue then
    B_PWM=B_PWM-1
    old_ss_blue=ss
    endif
    endif
    if B_PWM = B_MIN then 
    Blue_Day_Cycle = NIGHT
    endif
    
    case NIGHT
    lcdout $FE,$80+15,"NIGHT"
    B_PWM=B_min
    end select
    
    '*******************************************************************************
    'WHITE daily cycle
    
    select case White_Day_Cycle
        
    case DAWN 
    lcdout $FE,$C0+15,"DAWN "   
    if ss//white_delay_in= 0 then
    if ss != old_ss_white then
    W_PWM = W_PWM+1
    old_ss_white=ss
    endif
    endif
    if W_PWM = W_max then
    White_Day_Cycle = DAY
    endif
    
    case DAY
    lcdout $FE,$C0+15,"DAY  "
    if W_max < W_PWM then
    W_PWM=W_PWM - 1
    endif
    if counter1 =white_off_time then
    White_day_cycle = DUSK
    endif
        
    CASE DUSK
    lcdout $FE,$C0+15,"DUSK "
    if ss//white_delay_out= 0 then
    if ss != old_ss_white then
    W_PWM=W_PWM-1
    old_ss_white=ss
    endif
    endif
    if W_PWM = W_min then 
    White_Day_Cycle = NIGHT
    endif
    
    case NIGHT
    lcdout $FE,$C0+15,"NIGHT"
    W_PWM=W_min
    end select
    
    '*******************************************************************************
    'tidy up the display for the current percentage to remove stray zero's
    
    If (B_PWM * 100)/255 = 100 then
    lcdout $FE,$80,"BL ",$FE,$80+3,dec3 (B_PWM *100)/255,"%"
    endif
    
    If (B_PWM * 100)/255 =0 or (B_PWM * 100)/255 <10 then
    lcdout $FE,$80,"BL ",$FE,$80+3,dec1 (B_PWM *100)/255,"% "
    endif
    
    if (B_PWM * 100)/255 >=10 and (B_PWM * 100)/255 <100 then
    lcdout $FE,$80,"BL ",$FE,$80+3,dec2 (B_PWM *100)/255,"%  "
    endif
    
    If (W_PWM*100)/255 >= 100 then
    lcdout $FE,$C0,"WT ",$FE,$C0+3,dec3 (W_PWM *100)/255,"%"
    endif
    
    If (W_PWM * 100)/255 <=0 or (W_PWM * 100)/255 <10 then
    lcdout $FE,$C0,"WT ",$FE,$C0+3,dec1 (W_PWM *100)/255,"% "
    endif
    
    if (W_PWM * 100)/255 >=10 AND (W_PWM * 100)/255 <100 then
    lcdout $FE,$C0,"WT ",$FE,$C0+3,dec2 (W_PWM *100)/255,"%  "
    endif
    '*******************************************************************************
    'Get and display the temperature
    
        OWOUT DQ, 1, [$CC, $44]                 ' Start temperature conversion
        OWOUT DQ, 1, [$CC, $BE]                 ' Read the temperature
        OWIN DQ, 0, [temperature.LOWBYTE, temperature.HIGHBYTE]
        temperature = temperature */ 1600
        lcdout $FE,$D4+0,"TEMP ",DEC(temperature / 100),$DF,"C"
    '*******************************************************************************
    'generate bar graph on LCD
    
        ; syntax- BARgraph   Value, Row, Col, Width, Range, Style
       @         BARgraph  _B_PWM,   1,   8,    6,   255,  lines
       @         BARgraph  _W_PWM,   2,   8,    6,   255,  lines
    
      
    GOTO Main
    Darrels code seems to allow frequencies of 100hz which makes this ideal.... if it can be made to work

    I appreciate all your help....Hopefully Darrel can shed some light

    Oh and meant to add that it runs really slowly (displays the firmware splash screen for around fifteen seconds rather than the three or so
    Last edited by Scampy; - 11th December 2013 at 19:10.

  13. #13
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,607


    Did you find this post helpful? Yes | No

    Default Re: Multiple PWM and port C

    Hi,
    The reason it runs slow is due to the interrupt driven PWM routines. You have a PWM frequency of 200Hz and a resolution of 256 steps, this results in an interrupt frequency of 51200Hz.
    According to Darrels page (if I'm on the right one) each "PWM-channel" needs 20 instructions - in your case 51200 * 20 * 2 = 2,048,000 instructions per second, just for running the 2 PWM channels. At 20MHz there's 5,000,000 instructions per second to play with which means that 40% of the processors time is spent running the PWM.

    You tell PBP that you're running at 20MHz but then the assembly interrupts silently eats away 40%.

    In this case each and every Hz you decrease the PWM frequency will give more time to the actual PBP program, if 100Hz is "all" you need then don't try running it at 200Hz. But again, it doesn't seem to be the timing per se that makes it NOT work since it using different ports for the PWM and I2C works.

    /Henrik.

  14. #14
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: Multiple PWM and port C

    Thanks for the explanation...

    I think I'll go back to using port D for the outputs and revert back to the mulit_swpm file. Not ideal, as I'll have to modify the PCB, but at least it works without the delays or screwing up the clock etc. If I get chance I'll try this on the old 16F877A chip rather than an 18F to see if this issue is chip related...

  15. #15
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: Multiple PWM and port C

    I've recorded the wave form when using the hardware PWM modules on the chip to explain the issue I'm getting.



    If you compare this to using the multi_swpm file and port D you notice there are loads of spikes in the HWPM signal and some harmonics ? - the amplitude is also a lot less (I had to increase the volume for the HWPM to get a similar trace)


  16. #16
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,607


    Did you find this post helpful? Yes | No

    Default Re: Multiple PWM and port C

    As I've said a couple of times now:
    You can not run the hardware PWM at a frequency below 1221Hz - it's not a bug in PBP and not a hardware issue with the PIC or the circuit, it's just the way it is.

    The reason is because TMR2, which is used for the PWM timebase is 8 bits wide and has a prescaler with a maximum ratio of 1:16. At 20MHz the timer ticks at 5MHz, so 5,000,000/256/16=1220.7Hz. If you try anything lower than that it will not work properly and I'm pretty sure that's what you're seeing when trying to run it at 200Hz.

    To prove or disprove, try it again at 1500Hz and see if the waveform looks better. I understand that it won't work in your particular application due to the LED drivers but it'll show that actual problem is that you're trying to run the PWM at a frequency (200Hz) which the module is incapable of producing.

    /Henrik.

  17. #17
    Join Date
    May 2013
    Location
    australia
    Posts
    2,631


    Did you find this post helpful? Yes | No

    Default Re: Multiple PWM and port C

    all the spwm interrupts will muck up the i2c and onwire timing . you will probably need to disable the ints during the actual data transfers

  18. #18
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,607


    Did you find this post helpful? Yes | No

    Default Re: Multiple PWM and port C

    Hi Richard,
    That was my initial thought as well but then Scampy wrote:
    Interestingly, I have the temp sensor (18B20) on port RA5. If I use RA4 and RA7 as the PWM pins the temperature reading goes heywire, displaying random temperatures like 163C but is often trying to over write the display. With RA4 and RA7 set as the pins for pWM, the clock on C3 and C4 runs fine...
    Which indicates that as long as the PWM is not on the same port as the I2C it does seem to work - only when the PWM and I2C (or 1Wire) is on the same port does it act up.
    If it was a timing issue then I can't see how moving the I2C to a different port than the PWM would make it work. I'm leaning more towards some kind of port or tris register overwrite causing the issue, perhaps a R-M-W but of course I can't say for sure.

    /Henrik.

  19. #19
    Join Date
    May 2013
    Location
    australia
    Posts
    2,631


    Did you find this post helpful? Yes | No

    Default Re: Multiple PWM and port C

    hi henrick
    it could be that the port value gets changed by the int routine between a read modify write action in the i2c or onewire routines, or vice versa
    simply stetting the timer int off before the i2c and one wire transactions and restoring it afterwards should be easy enough to try . if that works its an easy fix

  20. #20
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,607


    Did you find this post helpful? Yes | No

    Default Re: Multiple PWM and port C

    Hi,
    I agree, it's easy to try and and an easy fix provided it doesn't result in any obvious glitches or blinking effect on the LEDs being driven by the PWM.
    But why would the PWM routine change bits that it (the PWM routine) has nothing to do with. Something is going on for sure but I can't really figure out a real good reason.

    /Henrik.

  21. #21
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: Multiple PWM and port C

    OK guys you've lost me.

    I think the work around for now is to simply use pins D1 and D2 as the output and solder links on the PCB - This way I get a working solution of true square wave of 0-5v running at a frequency that suits the LED drivers, and code that runs at a suitable speed.

    Thanks again for all your input....

  22. #22
    Join Date
    Jan 2005
    Location
    Montreal, Quebec, Canada
    Posts
    3,154


    Did you find this post helpful? Yes | No

    Default Re: Multiple PWM and port C

    Have you tested different caps to filter that noise on square waves?

    Robert

  23. #23
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: Multiple PWM and port C

    Ok, for the past few days I've been running the code on the development board using D2 and D3 as the output pins for the PWM - all was fine so I placed the chip in the controller and over the weekend it's been running fine, and with the added bonus that the LDD LED drivers don't sing like they used to when using the hardware generators on the PIC.

    So I've now started to add in the next module for the project, serial communications. Thanks to Robert's post in my other thread I've used MisterE's tool to generate the port definitions etc, and after a slight hardware issue with the USB/serial cable used a simple echo program to test the comms - it worked fine, using the Comms tool in Microcode Studio I was able to connect to the port, and whatever I sent from the PC was echoed back in the RX panel...I then opened the current working version of my code and simply inserted the line
    Code:
    Hserout ["Blues  ",DEC(B_PWM * 100)/255, 13, 10] ' Send text followed by carriage return and linefeed
    which should simple send the value of B_PWM as a percentage to the PC. However when I compiled the code and ran it, then set the clock to the time the lights were on, the PWM remained at 0 and didn't increase. The RTC ran, and the menu options worked so the code was looping, but for some reason I never got an output from the software pins or the LCD. If I commented out the Hserout line the code works perfectly.

    It seems another conflict when running DT's multi_pwm with port C, and again its coms related.

  24. #24
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: Multiple PWM and port C

    Uhmmmm
    Adding a pause 1000 after the line seems to of resolved the issue (head scratch !!!)

Similar Threads

  1. Multiple PWM pins
    By Scampy in forum mel PIC BASIC Pro
    Replies: 2
    Last Post: - 17th November 2013, 19:23
  2. Darrel's Multiple Software PWM
    By passion1 in forum mel PIC BASIC Pro
    Replies: 10
    Last Post: - 15th October 2013, 15:21
  3. Drive multiple LED with one PWM
    By microuser in forum General
    Replies: 3
    Last Post: - 27th September 2007, 13:26
  4. Multiple Pics to One serial port
    By Rleonard in forum Serial
    Replies: 1
    Last Post: - 18th January 2007, 18:30
  5. Multiple IR LEDs from 1 port using transistor
    By belpe123 in forum General
    Replies: 3
    Last Post: - 20th May 2005, 22:07

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts