Strange Behaviour with Conditional Compile


Closed Thread
Results 1 to 6 of 6
  1. #1

    Default Strange Behaviour with Conditional Compile

    With the line "#DEFINE USE_LCD_FOR_DEBUG" commented out the chip works perfectly; the PWM duty cycle sent to the SN754410 driver spins up the attached motor slowly and the trim pot attached to ADC 1 works smoothly in adjusting the speed.

    When I uncomment it, though, (so I can see the debug info on the LCD) the motor immediately starts spinning when power is connected and the ADC behaviour is lagging, as if it takes more time to get the results.

    I'm using a 16F1825 chip. What's weird is that this was working just fine with my old LCD @ 2400 baud but since I accidentally fried that and had to get a new one I changed it to 9600 baud as that's the default with the new serial LCD I got from SparkFun (I also needed to comment out "BAUDCON.4 = 1" with this LCD as otherwise it displayed garbage)

    Code:
    '#DEFINE USE_LCD_FOR_DEBUG   ; comment out for non-debug use
    
    
    ' ***************************************************************
    ' TODOs
    ' ***************************************************************
    ' 1. Need to calibrate motor RPMs so they spin at the same rate
    '    -> Separate "MotorDuty" EEPROM variables?
       
       
    ' ***************************************************************
    ' Pin Connections
    ' ***************************************************************
    
    ' Vdd      -> pin 1         -> +5V   
    ' RA5      -> pin 2         -> Blue LED (USART motor control indicator)
    ' RA4      -> pin 3         -> Green LED (ADC motor control indicator)
    ' RC5/Rx   -> pin 5         -> EUSART receive
    ' RC4/Tx   -> pin 6         -> EUSART transmit (LCD)
    ' RC2      -> pin 8         -> Port motor direction signal (motor 2)
    ' RC1/CCP4 -> pin 9         -> Port/Stbd motor PWM output (motor 1 & 2)
    ' RC0      -> pin 10        -> Stbd motor direction signal (motor 1)
    ' RA2/INT  -> pin 11        -> Motor control option select button
    ' RA1      -> pin 12        -> trim pot input
    ' Vss      -> pin 14        -> GND
       
    DEFINE OSC 16               ; Set oscillator 16Mhz
    
    ' EUSART Settings for Tx/Rc (e.g. LCD)
    ' > use Mister E PIC Multi-Calc application to get register/DEFINE settings
    ' > as the values are dependent on the OSC and desired baud rate
    
    DEFINE HSER_RCSTA 90h      ' Enable serial port & continuous receive
    DEFINE HSER_TXSTA 24h      ' Enable transmit, BRGH = 1
    DEFINE HSER_CLROERR 1      ' Clear overflow automatically
    DEFINE HSER_SPBRG 160      ' 9600 Baud @ 16MHz, -0.08%
                                   
    ' ***************************************************************
    ' Device Fuses
    ' ***************************************************************
    
    #CONFIG
       __config _CONFIG1, _FOSC_INTOSC & _WDTE_ON & _PWRTE_ON & _MCLRE_OFF & _CP_OFF & _CPD_OFF
       __config _CONFIG2, _PLLEN_OFF & _STVREN_ON & _BORV_LO & _LVP_OFF
    #ENDCONFIG
    
    ' ***************************************************************
    ' Initialization
    ' ***************************************************************
    
    OSCCON    = %01111000       ; 16MHz internal osc
    
    pause 100
    
    APFCON0.2 = 0               ; Tx on RC4 for LCD display
    APFCON0.7 = 0               ; Rx on RC5
    
    ' Some LCD serial modules need inverted data, some do not
    ' Enable the line below if needed, but for SparkFun SerLCD it should be
    ' commented out
    
    'BAUDCON.4 = 1               ; Transmit inverted data to the Tx pin  
    
    ' From Mister E's Multi-Calc for EUSART:
    ' *****************************************************************
    SPBRGH = 1
    BAUDCON.3 = 1               ' Enable 16 bit baudrate generator
    ' *****************************************************************
    
    ANSELC    = 0               ; Digital only for all PortC pins
    TRISC     = %00001000	    ; Make all pins output except for RC3
                                ; (motor control option button input)
    
    ANSELA    = %00000010       ; Analog on PORTA.1 (AN1) only
    TRISA     = %00000110	    ; Make all pins output except for RA1 & RA2
                                ; (trim pot input & button input)
    
    FVRCON    = 0               ; Fixed Voltage Reference is disabled
    ADCON0    = %00000101       ; ADC enabled on AN1 (RA1) only; ADC conversion
                                ; enabled
    PAUSEUS 20                  ; Wait for the analog switch 'glitch' to die down
    ADCON1    = %00110000       ; Left-justified results in 8-bits; Frc as timer
    
    ' The INT pin can be used to generate an asynchronous edge-triggered interrupt.
    ' This interrupt is enabled by setting the INTE bit of the INTCON register. The 
    ' INTEDG bit of the OPTION_REG register determines on which edge the interrupt 
    ' will occur. When the INTEDG bit is set, the rising edge will cause the 
    ' interrupt. When the INTEDG bit is clear, the falling edge will cause 
    ' the interrupt. The INTF bit of the INTCON register will be set when a valid 
    ' edge appears on the INT pin. If the GIE and INTE bits are also set, the 
    ' processor will redirect program execution to the interrupt vector.
    OPTION_REG.6 = 1           ; 1=Rising edge (default) or button "PRESS";
                               ; 0=Falling edge or button "RELEASE"
    
    #IFDEF USE_LCD_FOR_DEBUG
    '   Display control codes for SerLCD serial LCD (SparkFun part #LCD-09395)
    '   (see 'Dropbox\PBP Projects\PIC Datasheets\SerLCD_V2_5 Datasheet.pdf' 
    '   for list of control codes)
        LCD_INST   CON 254       ' instruction
        LCD_CLR    CON 1         ' Clear screen
        LCD_L1     CON 128       ' LCD line 1
        LCD_L2     CON 192       ' LCD line 2
        LCD_BR_CMD CON 124       ' command character for adjusting backlight brightness
        LCD_BR_LVL CON 140       ' 140==40%
    #ENDIF
    
    ' ***************************************************************
    ' Includes
    ' ***************************************************************
    
    INCLUDE "DT_INTS-14.bas"    ' Base Interrupt System
    INCLUDE "ReEnterPBP.bas"    ' Include if using PBP interrupts
                                ' --> copy both files to PBP main folder 
                                ' (i.e. c:\pbp3)
    
    ;-- Place a copy of these variables in your Main program -------------------
    ;--   The compiler will tell you which lines to un-comment                --
    ;--   Do Not un-comment these lines                                       --
    ;---------------------------------------------------------------------------
    ;wsave   VAR BYTE    $20     SYSTEM      ' location for W if in bank0
    ;wsave   VAR BYTE    $70     SYSTEM      ' alternate save location for W 
                                             ' if using $70, comment wsave1-3
    
    ' --- IF any of these three lines cause an error ?? ------------------------
    '       Comment them out to fix the problem ----
    ' -- Which variables are needed, depends on the Chip you are using -- 
    ;wsave1  VAR BYTE    $A0     SYSTEM      ' location for W if in bank1
    ;wsave2  VAR BYTE    $120    SYSTEM      ' location for W if in bank2
    ;wsave3  VAR BYTE    $1A0    SYSTEM      ' location for W if in bank3
    ' --------------------------------------------------------------------------
    
    ' ***************************************************************
    ' ASM Interrupt Definitions
    ' ***************************************************************
    
    ASM
    INT_LIST  macro    ; IntSource,               Label,  Type, ResetFlag?
            INT_Handler    INT_INT, _Mtr_Speed_Ctrl_Btn,   PBP,  yes
        endm
        INT_CREATE     ; Creates the interrupt processor
    ENDASM
    
    ' ***************************************************************
    ' Set up registers for PWM on CCP3 & CCP4
    ' ***************************************************************
    
    'CCP3CON = %00001100         ; Use CCP3 in PWM mode
    CCP4CON = %00001100         ; Use CCP4 in PWM mode
    
    ' Use Mister E's PICMultiCalc_1.3.1.exe application (Windows only)   
    ' to determine prescaler and PR2 values for given OSC frequency (e.g. 16Mhz)
    ' and duty cycle (use 100% to see highest actual value)
                           
    T2CON   = %00000101         ; Timer2 on with 1:4 prescaler
    PR2     = 62                ; For 16Mhz OSC the desired output freq of 15,873Hz
                                ; is achieved with this PR2 value (8-bit resolution
                                ; with 1:4 prescaler)
                                
                                ; PWM freq must be ~ 16-20kHz to reduce noise
    
    PreSpinVal  CON 30          ; Value to subtract from MinDutyToSpin for motor spin up 
    MinDutyToSpin CON 75        ; 75 for 8-bit resolution
    MinDuty     CON 80          ; Minimum speed to rotate motor for this application
    SpinUpPause VAR BYTE        ; Pause during motor spin up
    SpinUpPause = 75
    #IFDEF USE_LCD_FOR_DEBUG
        SpinUpPause = 17        ; Less pause is needed when using LCD
    #ENDIF
    MaxDuty     VAR BYTE        ; According to Darrel:
                                ;   MaxDuty = (PR2 + 1) * 4
    
    MaxDuty = (PR2 + 1) * 4     ; 252 but with prescaler resolution it's actually 
                                ; 250 (8-bit)
    
    MotorDuty   VAR BYTE        ; Actual duty cycle for motor
    i           VAR BYTE
    
    MaxADCVal   CON 255         ; 255 for 8-bit; 1023 for 10-bit
    VrefInVal    VAR BYTE        ; stores ADCIN result read from trim pot
    compVal     VAR BYTE        ; stores last-changed ADC value
    
    MOTOR_1_DIR    VAR PORTC.0  ; Alias PORTC.0 as "MOTOR_1_DIR"
    'MOTOR_1_PWM    VAR PORTA.2  ; Alias PORTA.2 as "MOTOR_1_PWM"
    MOTOR_2_DIR    VAR PORTC.2  ; Alias PORTC.2 as "MOTOR_2_DIR"
    MOTOR_2_PWM    VAR PORTC.1  ; Alias PORTC.1 as "MOTOR_2_PWM"
    
    ButtonPress    VAR PORTA.2  ; Alias PORTA.2 as "ButtonPress"
    LED_ADC        VAR PORTA.4  ; Alias PORTA.4 as "LED_ADC"
    LED_USART      VAR PORTA.5  ; Alias PORTA.4 as "LED_USART"
        
    Old_Mtr_Ctrl_Opt VAR BIT    ; Stoes last set motor speed control option
                                                               
    ' ***************************************************************
    ' Read EEPROM value(s)
    ' ***************************************************************
    '   1 = Trim pot via ADC
    '   0 = Serial data via USART Rc (external source)
    
    Mtr_Ctrl_Opt_Default CON  1
    EE_Mtr_Ctrl_Opt      DATA Mtr_Ctrl_Opt_Default
    Mtr_Ctrl_Opt         VAR  BIT
    READ EE_Mtr_Ctrl_Opt, Mtr_Ctrl_Opt
    
    ' ***************************************************************
    ' Set default values
    ' ***************************************************************
    
    ' Set initial value of comparison variable
    Old_Mtr_Ctrl_Opt =  Mtr_Ctrl_Opt
    
    ' Turn on appropriate LED indicator
    LED_ADC   = Mtr_Ctrl_Opt
    LED_USART = !Mtr_Ctrl_Opt  ; inverts value of Mtr_Ctrl_Opt
    
    'if Mtr_Ctrl_Opt = 1 then
    '    HIGH LED_ADC
    '    LOW  LED_USART
    'else
    '    LOW  LED_ADC
    '    HIGH LED_USART
    'endif
    
    LOW MOTOR_1_DIR             ; Set stbd motor (motor 1) to fwd (CW)
    'LOW MOTOR_1_PWM
    LOW MOTOR_2_DIR             ; Set port motor (motor 2) to fwd (CW)
    LOW MOTOR_2_PWM             ; (motor will be connected in reverse in model for 
                                ; CCW movement)
    
    ' Should only need to do this one time to adjust backlight brightness
    '#IFDEF USE_LCD_FOR_DEBUG
    '    HSEROUT [LCD_BR_CMD, LCD_BR_LVL]
    '    PAUSE 5
    '#ENDIF
    
    #IFDEF USE_LCD_FOR_DEBUG
        pause 1000
        HSEROUT [LCD_INST, LCD_CLR, "LCD Init"]
        pause 5
        HSEROUT [LCD_INST, LCD_L2, "  SerLCD_V2_5"]
        pause 2000
    #ENDIF
    
    #IFDEF USE_LCD_FOR_DEBUG
        HSEROUT [LCD_INST, LCD_CLR]
        pause 5
        HSEROUT ["Mtr_Ctrl_Opt=", DEC Mtr_Ctrl_Opt, " "]
        pause 2000
    #ENDIF
    
    GOSUB Do_Speed_Chk
    compVal = VrefInVal          ; set initial compare value
    GOSUB Map_VrefInVal_to_PWM_Duty
    
    #IFDEF USE_LCD_FOR_DEBUG
        HSEROUT [LCD_INST, LCD_CLR]
        pause 5
        HSEROUT ["MotorDuty=",DEC MotorDuty,"  "]
        pause 2000
    #ENDIF
    
    ' Spin up motors to MotorDuty
    ' (Below a value of 'MinDutyToSpin', the motors don't move at all)
    FOR i = 0 to MotorDuty
    'FOR i = (MinDutyToSpin - PreSpinVal) to MotorDuty
    '    CCP3CON.4 = i.0
    '    CCP3CON.5 = i.1
    '    CCPR3L    = i >> 2
    
        CCP4CON.4 = i.0
        CCP4CON.5 = i.1
        CCPR4L    = i >> 2 
                
        pause SpinUpPause
    
        #IFDEF USE_LCD_FOR_DEBUG
            HSEROUT [LCD_INST, LCD_CLR]
            pause 5
            HSEROUT ["i=",DEC i,"  "]
        #ENDIF
    NEXT i
    
    #IFDEF USE_LCD_FOR_DEBUG
        HSEROUT [LCD_INST, LCD_CLR]
        pause 5
        HSEROUT ["Final set Duty:", LCD_INST, LCD_L2,"     ",DEC MotorDuty]
    #ENDIF
    
    ; Henrik Olson says I don't need this
    ; -----------------------------------
    ;INTCON    = %10010000       ' Global int enabled (GIE), INTE enabled, INTF flag bit 0 clr
    ; -----------------------------------
    
    @ INT_ENABLE   INT_INT      ; INT Port Change Interrupt
    
    Main:
        ' Check if motor speed control option has changed
        IF Mtr_Ctrl_Opt <> Old_Mtr_Ctrl_Opt Then
            ' Turn on appropriate LED indicator
            LED_ADC   = Mtr_Ctrl_Opt
            LED_USART = !Mtr_Ctrl_Opt      ; inverts value of Mtr_Ctrl_Opt
            
            ' Save selected motor speed control option
            WRITE EE_Mtr_Ctrl_Opt, Mtr_Ctrl_Opt
            PAUSE 100
                
            Old_Mtr_Ctrl_Opt = Mtr_Ctrl_Opt
        EndIF 
    
        gosub Do_Speed_Chk
        pause 100
    
        If VrefInVal <> compVal Then
            #IFDEF USE_LCD_FOR_DEBUG
                HSEROUT [LCD_INST, LCD_CLR]
                pause 5
                HSEROUT ["new VrefInVal=", DEC VrefInVal, "   "]
            #ENDIF
           
            compVal = VrefInVal
            GOSUB Map_VrefInVal_to_PWM_Duty
            gosub ChngMotorHPWM
        endif
    
    GOTO Main
    
    Do_Speed_Chk:
        IF Mtr_Ctrl_Opt = 1 then
            ' Read trim pot Vref to set motor speed
            PAUSEUS 50              ' Wait for A/D channel acquisition time
            ADCON0.1 = 1            ' Start conversion
            
            WHILE ADCON0.1 = 1      ' Wait for it to complete
            WEND
        
            VrefInVal = ADRESH
        else
            ' Get data from USART Rc channel
        
        ENDIF
    
        return
    
    ChngMotorHPWM:
    
    '    CCP3CON.4 = MotorDuty.0
    '    CCP3CON.5 = MotorDuty.1
    '    CCPR3L    = MotorDuty >> 2
    
        CCP4CON.4 = MotorDuty.0
        CCP4CON.5 = MotorDuty.1
        CCPR4L    = MotorDuty >> 2
        
        RETURN
    
    Map_VrefInVal_to_PWM_Duty:
    '   Arduino Map function to emulate:
    '   ===============================
    '   map(value, fromLow, fromHigh, toLow, toHigh)
    
    '   long map(long x, long in_min, long in_max, long out_min, long out_max)
    '   {
    '     return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
    '   }
    
    '   TODO: If switching from onboard trim pot to ext trim pot and there isn't one
    '         one connected to the 3-pin connector, may need to make in_min greater 
    '         than 0
    
        MotorDuty = (compVal - 0) * (MaxDuty - MinDuty)/(MaxADCVal - 0) + MinDuty
    '    MotorDuty = (compVal ** 39322) + MinDuty  ' Same as 100 + VrefInValue * 0.600006 but likely faster than 100+VrefInValue*6/10
        
        #IFDEF USE_LCD_FOR_DEBUG
            HSEROUT [LCD_INST, LCD_CLR]
            pause 5
            HSEROUT ["compVal=",DEC compVal,"  ",LCD_INST, LCD_L2]
            pause 1500
            HSEROUT ["MotorDuty=",DEC MotorDuty,"  "]
        #ENDIF
    
        RETURN
    
    END
    
    ' ***************************************************************
    ' [INT - interrupt handler]
    ' ***************************************************************
    Mtr_Speed_Ctrl_Btn:
        ' Toggle motor speed control option (values are 0 or 1)
        Mtr_Ctrl_Opt = NOT Mtr_Ctrl_Opt
    
        ' Shouldn't need to do this as the interrupt handler was defined above
        ' to have ResetFlag = yes
    ;    INTCON.1  = 0    ' Clear RA2/INT External Interrupt Flag
    @ INT_RETURN
    Why would the conditional compile define cause such weird behaviour? Is it because I'm now transmitting serially @ 9600 baud? Are there other configuration parameters I need with this LCD?

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


    Did you find this post helpful? Yes | No

    Default Re: Strange Behaviour with Conditional Compile

    Hi,
    You have a lot of PAUSE statements within the LCD sections, most noticable is the PAUSE 1500 (1.5 seconds!) in the Map_VrefInVal_to_PWM_Duty subroutine which you call each time thru your Main routine. When you don't include the LCD sections in the code it runs MUCH faster compared to when you DO include the LCD sections.

    /Henrik.

  3. #3


    Did you find this post helpful? Yes | No

    Default Re: Strange Behaviour with Conditional Compile

    Quote Originally Posted by HenrikOlsson View Post
    Hi,
    You have a lot of PAUSE statements within the LCD sections, most noticable is the PAUSE 1500 (1.5 seconds!) in the Map_VrefInVal_to_PWM_Duty subroutine which you call each time thru your Main routine. When you don't include the LCD sections in the code it runs MUCH faster compared to when you DO include the LCD sections.

    /Henrik.
    Thanks Henrik. That would definitely seem to explain the slow reaction to reading ADC during the main loop, but why would the duty cycle on the PWM output go HIGH as soon as power is turned on?

  4. #4
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default Re: Strange Behaviour with Conditional Compile

    Hi

    You might want to make sure that the dutycycle is set to 0 before enabling the PWM module.
    As it is now, when you "activate" the LCD sections, there will be a 7 second delay between the PWM module being enabled (you setting CCP4CON at the start of the program) and the time at which the ramp up actually starts, ie when you actually set the dutycycle to 0.

    /Henrik.

  5. #5


    Did you find this post helpful? Yes | No

    Default Re: Strange Behaviour with Conditional Compile

    Thanks again, Henrik. Do you mean I should have:

    Code:
        CCP4CON.4 = 0
        CCP4CON.5 = 0
        CCPR4L    = 0
    before the CCP4CON register setting?

    I will try that out tonight, as well as reducing the PAUSE statements.

  6. #6


    Did you find this post helpful? Yes | No

    Default Re: Strange Behaviour with Conditional Compile

    As usual, you were right Henrik. I added the code above right after turning on CCP/PWM on CCP4 and reduced all the pauses within the #IFDEF USE_LCD_FOR_DEBUG and now everything works as before. It was obvious once you pointed it out, so thanks again for being so patient.

Similar Threads

  1. Conditional compile
    By pedja089 in forum PBP3
    Replies: 2
    Last Post: - 16th January 2014, 21:25
  2. Strange IT behaviour
    By MikeBZH in forum mel PIC BASIC Pro
    Replies: 7
    Last Post: - 10th February 2012, 09:00
  3. Strange behaviour
    By financecatalyst in forum mel PIC BASIC Pro
    Replies: 5
    Last Post: - 8th October 2009, 22:35
  4. Strange HSEROUT behaviour
    By Charles Linquis in forum mel PIC BASIC Pro
    Replies: 10
    Last Post: - 7th July 2006, 23:37
  5. strange int behaviour
    By tom in forum mel PIC BASIC Pro
    Replies: 4
    Last Post: - 17th November 2005, 15:41

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