how do I speed up an existing pic18f2525 program ?


Closed Thread
Results 1 to 5 of 5
  1. #1
    Join Date
    Jun 2006
    Location
    Glasgow, Scotland
    Posts
    26

    Smile how do I speed up an existing pic18f2525 program ?

    Hi there, I am trying to get my existing program that outputs 2-3 readings per second of serial data at 19200 at an internal clock frequency of 8Mhz. If I increase the clock frequency to 25Mhz by fitting an external HS crystal, I dont seem to get many more readings per second. PS I changed the Oscillator to HS in the INC file
    Here is my code can anyone advise on what is wrong.

    thanks again in advance John

    Code:
    ' file      : RS232CW.bas 
    ' author    : John Norrie
    ' date      : 26/10/10
    ' purpose   : Seariak output of load and battery condition
    ' includes  : none
    ' notes     : 10.00 te weight Read 16 bit ADC, convert to actual load value,    
    '           : 
    '             inverted 19200 baud value is 16416 used direct wire no 232 driver chip
    '             at pic end. AD7705 gain set to 4,unipolar 20hz  cal test 178k//702R = 1mV/V or     kg
    '             pic pin 18 RX to 9 way 'D' pin 2   crossed at rx end
    '             pic pin 17 TX to 9 way 'D' pin 3   crossed at rx end
    '             AD627 gain resistor 909R 0.1 % = gain of approx 200 
    '             Bridge  output      mV/V for 10.00 te  Cal = 0.681mV/V =      te
    '             Bridge supply 2.5VDC REF03
    '             battery low set at 4.0vdc for 6.0v (4xC type bats) in via 2 x 5M5 resistor potential divider
    ' compiler  : PICBasic Pro Compiler Ver 2.50A   
    
    
       
    
    PAUSE 1000 ' Allow power to stabilize on power-up
            
      '   Variable definition
    '::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    DEFINE OSC 25
    OSCTUNE = %11111100 ' external primary osc block 
    'DEFINE LOADER_USED 1 ' Comment out if not using boot-loader
    INCLUDE "modedefs.bas"
    
            INTCON2.7 = 0   'enable weak pull-ups on PORTB
            output portc.4  ' set pin to output operates cal relay
    'AIN Channel setup        
            DEFINE ADC_BITS 10
            DEFINE ADC_CLOCK 5              ' Set clock source (rc = 3)
            DEFINE ADC_SAMPLEUS 5000           
            ADCON1 = %00001101              ' Set PORTA analog and select chs
            ADCON2 = %10111110              ' Set PORTA analog and right justify res
            ADCON0 = %00000001              ' Set enable analog 
    'AD7705 setup
           
            output portb.7  'adc Clock pin
            output portA.5  'AD7705 Data in pin
            input portA.4   ' AD7705 Data out pin 
            input portA.3   'AD7705 Ready pin
            input portA.0   ' Battery voltage input
            input portA.1   ' Overload setting voltage input
            symbol SCK=PORTB.7 'Clock pin
            Symbol SI=PORTA.5 ' AD7705 Data in pin
            Symbol SO=PORTA.4' AD7705 Data out pin 
            Symbol ADCready = PortA.3 'AD7705 Ready pin
            'Symbol CS = PORTA.2'AD7705 Chip Select pin
            symbol CalOut=PORTc.4
            
         
    'AD7705 variables
            adcSend var Byte 'byte sent to communication register of AD7705
            adcrec  var Byte 'byte received from AD7705:only for communication register, set-up register and clock register (8 bit registers)
            ad1     var Word 'ad converter value read from AD7705
            'ad2     var Word 'ad converter value read from AD7705 
    ' ADC variables        
            Volt1       var word
            VoltsA      var word
            Voltx       var word
            Total1      var word
            i           var byte
            pass        var byte
            MaxVal      var byte
            MinVal      var byte 
            Load        var word 
            ADCvalue    var word
            gtare       var byte
            counts      var byte  
            ScaleBits   con 4096 '12 bit 
            z VAR Byte
            c VAR Byte
            B0 var byte
            B1 VAR BYTE
            B2 VAR word
            d0 VAR BYTE
            d1 VAR BYTE
            d2 VAR BYTE
            d3 VAR BYTE
            p0 VAR BYTE
            p1 VAR BYTE
            p2 VAR BYTE
            p3 VAR BYTE
            t0 VAR BYTE
            t1 VAR BYTE
            t2 VAR BYTE
            t3 VAR BYTE
            
            x VAR Byte
            p VAR Byte
            a VAR Byte
            b VAR Byte
            v VAR Byte
            tm var word
            ' Define keypad program variables
         col        var byte ' Keypad column
         row        var byte ' Keypad row
         key        var byte ' Key value
         press      var byte
         db         var byte
            Total VAR WORD
            totaly var word
            Value VAR WORD
            Value1 VAR WORD
            Tare VAR WORD
            TXBat var word
            TXBat1 var word
            RXBat var byte
            Loadx var word
            Loady var word
            Range var word
            NewVal var word
            
            Calval    var word
            Cal1      var byte  
            peak       var Word
            peak1      var byte
            peak2      var byte
            load1      var byte
            load2      var byte
            CX         var byte
            DAout      var word
            cal1 = 100
               B0 = 0
            B2 = 0
            tare = 0
            Range = 2000
            Calval = 850
            volt1 = 0
            peak = 0
            CX = 1
            calout = 0
            key = 20
            counts = 0
    'EEPROMDATA:
    'write 1,Cal1
    'write 4,Calval.byte0 :write 5,Calval.byte1
    'write 6,Range.byte0 :write 7,Range.byte1 
    Read 1,Cal1 
    Read 6,Range.byte0 :Read 7,Range.byte1 
    'Read 2,Tare.byte0 :read 3,Tare.byte1
    if range < 1000 then range = 2000
    if range > 2500 then range = 2000
    if Cal1 < 1 then Cal1 = 100
    if Cal1 > 255 then Cal1 = 100 
    Calval = Cal1 + 600  
    Tare = 0
    
            
    ' Main software
    Start:   
            
            gosub MAX7705
            gosub calibrate
            gOTO Main
            
    Main:   
            
            gosub ADCloop
            gosub GetBatValue
            volt1 = Newval
            gosub AutoZero 
            gosub GetDigits   
            SEROUT2 PortC.6,16416,["L",#d3,#d2,".",#d1,#d0,"B",#t2,#t1,#t0]   '19200 baud
            goto Main
    
     GetDigits:
     d3 = Volt1 Dig 3 
     d2 = Volt1 Dig 2 
     d1 = Volt1 Dig 1 
     d0 = Volt1 Dig 0
     t3 = txbat Dig 3 
     t2 = txbat Dig 2 
     t1 = txbat Dig 1 
     t0 = txbat Dig 0
     
     return              
    MAX7705: 
            tare = 0
            gosub MX7705Ini
            pause 50
            gosub mxch1
            gosub mxcal1
            return
            
    ADCloop:   
               gosub getad1
               return
    getad1: 'for counterA = 0 to 15
            Total1 = 0
            For x = 1 to 8  
               adcsend=$38 ' Read the 16 bit DATA Register, channel 0.
            shiftout SI, SCK, 5, [adcsend\8] ' adcsend read command and data register address
            shiftin SO, SCK, 6, [ad1\16] ' Read 16 bit data
            While ADCready = 1 'wait for valid data to be received
            Wend 'wait for valid data to be received
            value1 = abs (ad1/8)
            Total1 = Total1 + value1
            next x
            value1 = abs (Total1/16)      '65535/8 = 8192
            if value1 < 1  then value1 = 0
            if value1 > 4096 then value1 = 4096
            value = value1 * Range
            NewVal = div32  ScaleBits  ' scalebits = 4096 (12 active bits)
            return
            
    GetAdValue: 
            Total1 = 0
            For x = 1 to 8  
               adcsend=$38 ' Read the 16 bit DATA Register, channel 0.
            shiftout SI, SCK, 5, [adcsend\8] ' adcsend read command and data register address
            shiftin SO, SCK, 6, [ad1\16] ' Read 16 bit data
            While ADCready = 1 'wait for valid data to be received
            Wend 'wait for valid data to be received
            ADCvalue = abs (ad1/8)
            Total1 = Total1 + ADCvalue
            next x
            ADCvalue = abs (Total1/16)  ' 4096 bits
            return        
    
    
                   
    AutoZero:
    If volt1 < 3 then
    counts = counts + 1
    goto  AutoZ
    else
    counts = 0
    endif
    return
    AutoZ:
    if counts = 5 then
    volt1 = 0
    counts = 0
    endif
    return
    
    MX7705Ini:
           'Reset MX7705
           adcsend=$ff
           adcrec=$ff
        shiftout SI, SCK, 5, [adcsend\8] ' adcsend command to communication register
        shiftout SI, SCK, 5, [adcrec\8] ' adcsend value to the selecte register
        shiftout SI, SCK, 5, [adcsend\8] ' adcsend command to communication register
        shiftout SI, SCK, 5, [adcrec\8] ' adcsend value to the selecte register
        return
    'SetADGAIN:
    ' if gainval = 1 then ADGAIN = $44  'decimal  68  gain = 1
    ' if gainval = 2 then ADGAIN = $4c  'decimal  76  gain = 2
    ' if gainval = 3 then ADGAIN = $54  'decimal  84  gain = 4
    ' if gainval = 4 then ADGAIN = $5c  'decimal  92  gain = 8
    ' if gainval = 5 then ADGAIN = $64  'decimal 100  gain = 16
    ' if gainval = 6 then ADGAIN = $6c  'decimal 108  gain = 32
    ' if gainval = 7 then ADGAIN = $74  'decimal 116  gain = 64
    ' if gainval = 8 then ADGAIN = $7c  'decimal 124  gain = 128
    ' return    
    mxch1:'CH1 AD7705 set-up Start. SEE AD7705.XLS  FOR TABLE OF SETTINGS
    adcsend=$20 ' WRITE TO THE COMMUNICATIONS REGISTER. SELECT CHANNEL 0 AND SET NEXT OPERATION AS A WRITE TO THE CLOCK REG
    ' CLOCK REGISTER.(0x20)
    adcrec=$00 ' write on clock register: clock division=1, clock bit=1, master clock enabled (bit set to 0),
    ' bit output rate set to 20hz
    gosub mxsend
    'adcsend=$28
    'GOSUB adread
    return
    
    mxcal1: 'CH1 Calib 'self-calibration
    adcsend=$10 ' WRITE TO THE COMMUNICATIONS REGISTER. SELECT CHANNEL 0 AND SET NEXT OPERATION AS A WRITE TO THE SETUP REGISTER.(0x10).
    adcrec=$54 ' WRITE TO THE SETUP REGISTER. SET SELF-CALIBRATION MODE, GAIN TO 4, UNIPOLAR MODE, BUFFERED MODE.
    ' BEGIN SELF-CALIBRATION/CONVERSION BY CLEARING FSYNC.(0x44)
    gosub mxsend
    gosub adcrdy
    'adcsend=$8
    'GOSUB adread
    return
    mxsend: 
    shiftout SI, SCK, 5, [adcsend\8] ' adcsend command to communication register
    shiftout SI, SCK, 5, [adcrec\8] ' adcsend value to the selecte register
    return
    
    adcrdy:
    While ADCready = 1:Wend 'wait for valid data to be adceived. Er angivet under self calibration mode.
    ' Note that after the self calibration, AD7705 start free conversion cycle.
    Return
    ' ----------------------------------------------------------------------------
    ' Get Battery level Value A to D routine
    ' ----------------------------------------------------------------------------
     
                                     '  usable battery 2.7-5.4vdc (4xAAbats)
    GetBatValue:                     'potential divider of 2x 5m6 res accross bat
            Total = 0                ' 0-1024 bits for 0-10.00 vin (o/p max650)
            For z = 1 to 64             'Average of 64 readings to reduce noise
                ADCIN 0, value1
                Total = Total + value1
            next
            TXbat = Total >> 6                ' Same as divide by 64
            TXbat =  TXbat-722                'usable range 300 bits
            TXbat = TXbat/3 
            if Txbat < 1 then Txbat = 0
            if Txbat > 100  then Txbat = 100
            if TXbat < 20  then 
            freqout portc.2, 500,5 'gosub Battlow     '10.0 volt level         '1024 bits for 12.9vdc usable range 
            else
            freqout portc.2,10,10
            endif 
        return
            
       GetRange:
       REAd 6,Range.byte0 :read 7,Range.byte1 
       if range < 1000 then range = 2000
       if range > 4096 then range = 2000  
       goto Main
     
    ' ----------------------------------------------------------------------------
    ' Auto calibrate
    ' ----------------------------------------------------------------------------
     
     calibrate: 
     portc.4 = 0
     PAUSE 5000
     gosub getadvalue
     if ADCvalue > 800 then 
     goto GetRange
     else 
     gosub GetAdValue
     Loadx = ADCvalue
     portc.4 = 1: pause 5000  ' Apply calibration signal & wait 5 sec's
     gosub GetAdValue
     Loady = ADCvalue
     portc.4 = 0             ' Switch off  calibration signal 
     Loady = abs (Loady - Loadx)
     gosub calspan 
     Return
     endif   
    ' ----------------------------------------------------------------------------
    ' Calspan
    ' ----------------------------------------------------------------------------
     
     calspan: 
     if (calval < 650 ) or ( calval > 999) then calval = 750
     x = Calval * ScaleBits
     Range = div32 Loady
     peak = 0
     write 6,Range.byte0 :write 7,Range.byte1
     return
    Last edited by ScaleRobotics; - 1st November 2010 at 15:26. Reason: added code tags

  2. #2
    Join Date
    May 2004
    Location
    NW France
    Posts
    3,615


    Did you find this post helpful? Yes | No

    Default

    Hi,

    1) I do not think you have to modify the OSCTUNE register ...

    2) Place PAUSE 1000 AFTER " DEFINE OSC ..."

    3) You can use PLL x 4 Setting, with a 10 to 16 Mhz Xtal ... will give 40 to 64 Mhz Osc speed. Should be enough ...
    40 and 48 Mhz are commonly admitted ... 64 is experimental ... but works fine !!!

    You first have to change your 18F2525.inc file ( in the PBP/ INC folder ) for :

    Code:
    ;****************************************************************
    ;*  18F2525.INC                                                 *
    ;*                                                              *
    ;*  By        : Leonard Zerman, Jeff Schmoyer                   *
    ;*  Notice    : Copyright (c) 2008 microEngineering Labs, Inc.  *
    ;*              All Rights Reserved                             *
    ;*  Date      : 09/15/08                                        *
    ;*  Version   : 2.60                                            *
    ;*  Notes     :                                                 *
    ;****************************************************************
            NOLIST
        ifdef PM_USED
            LIST
            "Error: PM does not support this device.  Use MPASM."
            NOLIST
        else
            LIST
            LIST p = 18F2525, r = dec, w = -311, w = -230, f = inhx32
            INCLUDE "P18F2525.INC" ; MPASM  Header
            ;__CONFIG    _CONFIG1H, _OSC_HS_1H & _FCMEN_OFF_1H & _IESO_OFF_1H
            ;__CONFIG    _CONFIG2H, _WDT_ON_2H & _WDTPS_512_2H
            ;__CONFIG    _CONFIG3H, _CCP2MX_PORTC_3H & _PBADEN_OFF_3H 
    _LPT1OSC_OFF_3H & _MCLRE_ON_3H
            ;__CONFIG    _CONFIG4L,  _STVREN_ON_4L & _LVP_OFF_4L & _XINST_OFF_4L
      Messg " Think to WRITE the correct  CONFIGURATION ... "
      Messg " Think to WRITE the correct  CONFIGURATION ... "
      Messg " Think to WRITE the correct  CONFIGURATION ... "
            NOLIST
        endif
            LIST
    EEPROM_START EQU 0F00000h
    BLOCK_SIZE EQU 64
    THEN

    add to the top of your code, just past the Header :

    Code:
    '*****************************************************************************
    'Config processeur
    '*****************************************************************************
    @   __CONFIG    _CONFIG1H, _IESO_OFF_1H & _OSC_HSPLL_1H & _FCMEN_OFF_1H
    @   __CONFIG    _CONFIG2L, _BOREN_OFF_2L & _PWRT_ON_2L
    @   __CONFIG    _CONFIG2H, _WDT_OFF_2H & _WDTPS_128_2H
    @   __CONFIG    _CONFIG3H, _MCLRE_ON_3H & _LPT1OSC_OFF_3H & _PBADEN_OFF_3H & _CCP2MX_PORTBE_3H
    @   __CONFIG    _CONFIG4L, _STVREN_OFF_4L & _LVP_OFF_4L & _DEBUG_OFF_4L & _XINST_OFF_4L
    @   __CONFIG    _CONFIG5L, _CP0_OFF_5L & _CP1_OFF_5L
    @   __CONFIG    _CONFIG5H, _CPB_OFF_5H & _CPD_OFF_5H
    @   __CONFIG    _CONFIG6L, _WRT0_OFF_6L & _WRT1_OFF_6L
    @   __CONFIG    _CONFIG6H, _WRTB_OFF_6H & _WRTC_OFF_6H & _WRTD_OFF_6H 
    @   __CONFIG    _CONFIG7L, _EBTR0_OFF_7L & _EBTR1_OFF_7L
    @   __CONFIG    _CONFIG7H, _EBTRB_OFF_7H
    You'll have to use " DEFINE OSC xx " Where XX will be 4 x your choosen Xtal frequency.

    an also think to modify Serin2/Serout2 to match your Osc speed ...

    after that ... check your program flow ... if not enough !!!

    Alain
    Last edited by Acetronics2; - 1st November 2010 at 17:34.
    ************************************************** ***********************
    Why insist on using 32 Bits when you're not even able to deal with the first 8 ones ??? ehhhhhh ...
    ************************************************** ***********************
    IF there is the word "Problem" in your question ...
    certainly the answer is " RTFM " or " RTFDataSheet " !!!
    *****************************************

  3. #3
    Join Date
    Jun 2006
    Location
    Glasgow, Scotland
    Posts
    26


    Did you find this post helpful? Yes | No

    Default

    Hi Alain, Thanks for your help. It turns out that the main reason I cant get it to go faster seems to be the time it needs to carry out the analog to digital conversions if I took out the get ADCloop and the getbatlevel it goes like the clappers. If I reintroduce either it slows right down. I have all the averaging loops for both and the signals are still steady and the speed went up to 40 samples per second. I then reduced the times it went to get the battary level to every 150 samples. I am now getting 80 samples per second which is quite acceptable. It didnt seem to make a differance changing the clock to 40mHz using HSPLL and a 10Mhz crystal, but I have left it at that.

    Again many thanks Alain for your help. Its great knowing that this forum is here with such helpful people.

    cheers and many thanks John

  4. #4
    Join Date
    Sep 2007
    Location
    USA, CA
    Posts
    271


    Did you find this post helpful? Yes | No

    Default

    I realize you have reached your target, but here are some tips to help in the future.

    The shiftin/shiftout commands are dreadfully, painfully, pathetically slow. And also very slow. If you use an onboard a/d, or at the least, use the hardware SPI module to talk to an external a/d, you will gain a huge amount of thru-put... On the order of 10x faster, if the off-chip a/d can handle it.

    Another trick is to send the data as raw values, and format it on the receiving end since it's fixed width. That will save a minimum of 30% in your case, 20% if you want to leave an alignment byte.

  5. #5
    Join Date
    May 2004
    Location
    NW France
    Posts
    3,615


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by J_norrie View Post
    Hi Alain, Thanks for your help. It turns out that the main reason I cant get it to go faster seems to be the time it needs to carry out the analog to digital conversions
    Hi, John

    You also could reduce Adc sampling time to 100 or 200 µs ... instead of 5 ms !

    Alain
    ************************************************** ***********************
    Why insist on using 32 Bits when you're not even able to deal with the first 8 ones ??? ehhhhhh ...
    ************************************************** ***********************
    IF there is the word "Problem" in your question ...
    certainly the answer is " RTFM " or " RTFDataSheet " !!!
    *****************************************

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