Sampling ADCIN at 1ms for 1 second


Closed Thread
Results 1 to 10 of 10
  1. #1
    Join Date
    Jul 2008
    Location
    devon
    Posts
    15

    Default Sampling ADCIN at 1ms for 1 second

    Hi again,
    Can anyone give me code for reading adcin at exactly 1ms intervals for 1 second. I'm using a 20Mhz OSC on a 16F876. The code below is too slow presumeably as I haven't allowed for the execution times of the other instructions. Any pointers gladly receved. Ta

    for x = 1 to 1000
    adcin 1,potv
    hserout [dec x," ",dec potv,13,10]
    pause 1 '1ms delay
    next x

  2. #2
    Join Date
    Jul 2003
    Posts
    2,358


    Did you find this post helpful? Yes | No

    Default

    Be sensible... you're NOT going to get a thousand HSEROUT's executed in ONE SECOND! Unless of course you've set a BAUD RATE of a couple of MILLION bps?

    Get a calculator, work out how many bits ONE of your HSEROUT commands is going to send... then at your chosen BAUD rate how long that is going to take to transmit. From that, you can work out how many characters you'll be able to transmit in one second.

  3. #3
    Join Date
    Jul 2008
    Location
    devon
    Posts
    15


    Did you find this post helpful? Yes | No

    Default

    Thanks.
    I will create an array before I send it to the PC. It's important that the sampling rate is 1ms.
    Now to find out how to set up a 1000 element byte array!

  4. #4
    Join Date
    Jul 2003
    Posts
    2,358


    Did you find this post helpful? Yes | No

    Default

    And it's NOT going to happen with a PIC16F876... it just hasn't got that much RAM!!!

    You're going to need some high-speed external memory to hold your samples.

  5. #5
    Join Date
    Sep 2005
    Location
    Campbell, CA
    Posts
    1,107


    Did you find this post helpful? Yes | No

    Default

    An 18F8723 (for example) can deal with 3000 byte arrays.
    Charles Linquist

  6. #6
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    Oh I don't know, doesn't sound that hard to me.

    @ 20mhz, 115200 baud is easy with the USART, higher is also possible, but 115200 is all you need for this.
    @115200 the bit period is ~8.7us, and a full byte (10-bits) is ~87us.
    The longest HSEROUT line will be "1000 255",13,10 or 10 bytes. for a total of ~870us. (less than 1ms)

    The ADCIN statement slows things down for no reason.
    Since the ADC is only looking at 1 Channel, you don't have to worry about Acquisition times.
    And by controlling the ADC manually, the conversion happens at the same time as the HSEROUT so it's influence will be negligible.

    Then using a Timer to measure the 1ms intervals and ...
    Here's an example ...
    Code:
    <font color="#000080">@ DEVICE  HS_OSC, WDT_OFF
    </font><font color="#008000"><b>DEFINE </b></font><b>OSC </b><font color="#800000"><b>20
    </b></font><font color="#0000FF"><b><i>; Set your Analog Pins as needed here
    
    </i></b></font><font color="#008000"><b>DEFINE </b></font><b>HSER_RCSTA </b><font color="#800000"><b>90</b></font><b>h              </b><font color="#0000FF"><b><i>' Enable serial port &amp; continuous receive
    </i></b></font><font color="#008000"><b>DEFINE </b></font><b>HSER_TXSTA </b><font color="#800000"><b>24</b></font><b>h              </b><font color="#0000FF"><b><i>' Enable transmit, BRGH = 1
    </i></b></font><font color="#008000"><b>DEFINE </b></font><b>HSER_SPBRG </b><font color="#800000"><b>10               </b></font><font color="#0000FF"><b><i>' 115200 Baud @ 20MHz, -1.36%
    
    </i></b></font><b>GoDone </b><font color="#008000"><b>VAR </b></font><b>ADCON0</b>.<font color="#800000"><b>2                </b></font><font color="#0000FF"><b><i>; A/D start conversion bit
    </i></b></font><b>T0IF   </b><font color="#008000"><b>VAR </b></font><b>INTCON</b>.<font color="#800000"><b>2                </b></font><font color="#0000FF"><b><i>; TMR0 overflow flag   
    </i></b></font><b>x      </b><font color="#008000"><b>VAR WORD                    </b></font><font color="#0000FF"><b><i>; sample counter
    </i></b></font><b>TempB  </b><font color="#008000"><b>VAR BYTE
    
    </b></font><b>OPTION_REG </b>= <font color="#800000"><b>%11010100             </b></font><font color="#0000FF"><b><i>; TMR0 1:32 prescaler, internal clk
    </i></b></font><b>ADCON0     </b>= <font color="#800000"><b>%10001001             </b></font><font color="#0000FF"><b><i>; Fosc/32, AN1, DONE, module ON
    </i></b></font><font color="#008000"><b>HSEROUT </b></font>[<font color="#800000"><b>27</b></font>,<font color="#FF0000">&quot;[2J&quot;</font>]                 <font color="#0000FF"><b><i>; ANSI clear screen
    
    </i></b></font><b>Ready</b>:
      <font color="#008000"><b>HSEROUT </b></font>[<font color="#FF0000">&quot;Ready to take samples: Press any key to begin&quot;</font>]
      <font color="#008000"><b>HSERIN  </b></font>[<b>TempB</b>]
      <font color="#008000"><b>HSEROUT </b></font>[<font color="#800000"><b>13</b></font>,<font color="#800000"><b>10</b></font>]
      
      <font color="#008000"><b>FOR </b></font><b>x </b>= <font color="#800000"><b>1 </b></font><font color="#008000"><b>to </b></font><font color="#800000"><b>1000
          </b></font><font color="#008000"><b>WHILE </b></font>!<b>T0IF </b>: <font color="#008000"><b>WEND
          </b></font><b>TMR0 </b>= <font color="#800000"><b>100           </b></font><font color="#0000FF"><b><i>; load timer for 1ms
          </i></b></font><b>T0IF </b>= <font color="#800000"><b>0            </b></font><font color="#0000FF"><b><i>; reset the overflow flag
          </i></b></font><b>GoDone </b>= <font color="#800000"><b>1          </b></font><font color="#0000FF"><b><i>; start the A/D conversion
          ; The time it takes for the A/D conversion (~20us) is less than the 
          ; time to send a single byte from the USART (~87us). So the conversion 
          ; will always be complete by the time it gets to DEC ADRESH
          </i></b></font><font color="#008000"><b>HSEROUT </b></font>[<font color="#008000"><b>DEC </b></font><b>x</b>,<font color="#FF0000">&quot; &quot;</font>,<font color="#008000"><b>DEC </b></font><b>ADRESH</b>,<font color="#800000"><b>13</b></font>,<font color="#800000"><b>10</b></font>]
          <font color="#0000FF"><b><i>; The longest hserout line would be &quot;1000 255&quot;,13,10 (10 bytes)
          ; @ 115200 baud each byte takes 86.8us for a total of 868us (under 1ms)
          
          </i></b></font><font color="#008000"><b>IF </b></font><b>T0IF </b><font color="#008000"><b>THEN HSEROUT </b></font>[<font color="#800000"><b>13</b></font>,<font color="#800000"><b>10</b></font>, <b>_
              </b><font color="#FF0000">&quot;ERROR: Loop time too SLOW. T0IF bit already set.&quot;</font>,<font color="#800000"><b>13</b></font>,<font color="#800000"><b>10</b></font>]
      <font color="#008000"><b>NEXT </b></font><b>x
    </b><font color="#008000"><b>GOTO </b></font><b>Ready
    
    </b>
    I put a check at the end of the loop to warn if the loop took too long. It never does.
    Tested on a 16F737.

    Using Timer0, the interval is not EXACTLY 1ms, but the coding was easier. (+/- 6us per sample)
    Switching to Timer1 would make it more accurate. (+/- 0.6 us)
    Last edited by Darrel Taylor; - 19th May 2009 at 04:27.
    DT

  7. #7
    Join Date
    Jul 2008
    Location
    devon
    Posts
    15


    Did you find this post helpful? Yes | No

    Default

    Thanks Darrel. This worked for me but...

    When I add it to my code which initiates movement of the thing I wish to measure I get the timeout error T0IF at the 101st reading. I've tried understanding your code but the details are above my level! Any ideas where I'm going wrong? Here is the code:

    @ DEVICE HS_OSC,LVP_OFF,WDT_OFF,PROTECT_OFF,BOD_OFF,PWRT_OF F
    DEFINE OSC 20
    DEFINE HSER_EVEN 1 'serial
    DEFINE HSER_BITS 7 'serial
    DEFINE HSER_BAUD 115200 'serial
    DEFINE CCP1_REG PORTC ' Hpwm 1 pin port
    DEFINE CCP1_BIT 2 ' Hpwm 1 pin bit
    DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
    DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
    DEFINE HSER_SPBRG 10 ' 115200 Baud @ 20MHz, -1.36%
    DEFINE HSER_CLROERR 1 ' serial automatic clear overrun error

    trisb = %11000000 ' set port b 0-5 o/ps 6&7 i/ps
    OPTION_REG = %11010100 ; TMR0 1:32 prescaler, internal clk
    ADCON0 = %10001001 ; Fosc/32, AN1, DONE, module ON

    'declare variables
    GoDone VAR ADCON0.2 ; A/D start conversion bit
    T0IF VAR INTCON.2 ; TMR0 overflow flag
    x var word
    RCIF VAR PIR1.5
    VB_TO_PIC VAR byte ' data from VB to PIC
    PIC_TO_VB var byte ' data from PIC to VB

    'initialise
    portb.0 = 0
    portb.1 = 0
    portb.2 = 0
    portb.3 = 0
    hpwm 1,0,2000
    PAUSE 100

    MAIN:
    portb.0 = 0
    IF RCIF THEN
    pause 100
    sound portb.0,[60,10]
    portb.0 = 0 'to avoid buzzer continuing...?
    HSERIN [VB_TO_PIC] 'RCIF is reset by reading HSERIN (need twice??)
    select case VB_TO_PIC
    case "1"
    gosub open_response
    case "2"
    HSEROUT [VB_TO_PIC," TWO",13,10]
    case else
    HSEROUT [VB_TO_PIC," Error",13,10]
    end select
    ENDIF
    GOTO MAIN

    open_response:
    portb.1 = 1 'enable
    portb.3 = 0 'open direction
    hpwm 1,255,2000
    'sample data
    FOR x = 1 to 1000
    WHILE !T0IF : WEND
    TMR0 = 101 ; load timer for 1ms ##time out here##
    T0IF = 0 ; reset the overflow flag
    GoDone = 1 ; start the A/D conversion
    ; The time it takes for the A/D conversion (~20us) is less than the
    ; time to send a single byte from the USART (~87us). So the conversion
    ; will always be complete by the time it gets to DEC ADRESH
    HSEROUT [DEC x," ",DEC ADRESH,13,10]
    ; The longest hserout line would be "1000 255",13,10 (10 bytes)
    ; @ 115200 baud each byte takes 86.8us for a total of 868us (under 1ms)
    IF T0IF THEN HSEROUT [13,10, _
    "ERROR: Loop time too SLOW. T0IF bit already set.",13,10]
    NEXT x
    gosub power_down
    return

    power_down:
    portb.1 = 0 'disable H-Bridge
    hpwm 1,0,2000 'Set PWM to zero
    return

    end

  8. #8
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    It's the ...
    Code:
    DEFINE HSER_EVEN 1 'serial
    DEFINE HSER_BITS 7 'serial
    It takes a lot of time to count bits and generate a parity for each byte.

    Can you use 8-N-1?
    DT

  9. #9
    Join Date
    Jul 2008
    Location
    devon
    Posts
    15


    Did you find this post helpful? Yes | No

    Default

    Genius!
    I had dabbled with the port settings but was stabbing in the dark.
    If the T0IF error text does occur it's gobbledygook but it doesn't occur often.
    Thanks

  10. #10
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    It shouldn't happen at all.

    Putting TMR0 = back to 100, (or 99), might help.
    <br>
    DT

Similar Threads

  1. ADCIN and PIC18F4331 Arghhhhh !
    By GrandPa in forum mel PIC BASIC Pro
    Replies: 7
    Last Post: - 6th December 2010, 20:27
  2. How to make adcin stable?
    By Pic2008 in forum mel PIC BASIC Pro
    Replies: 11
    Last Post: - 20th January 2009, 07:41
  3. ADCIN problems with PIC16F73
    By passion1 in forum mel PIC BASIC Pro
    Replies: 19
    Last Post: - 26th July 2007, 11:38
  4. ADCIN - AD settings are wrong
    By teverett in forum mel PIC BASIC Pro
    Replies: 5
    Last Post: - 4th December 2006, 16:32
  5. help using adcin
    By harryweb in forum mel PIC BASIC Pro
    Replies: 5
    Last Post: - 31st January 2006, 07:46

Members who have read this thread : 0

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