Page 1 of 2

Pulse-In function example

Posted: 15 Sep 2006 09:11
by marko
This code demonstrates using Pulse-In Function (similar to PBP "PULSIN" command) for counting pulses in given time period. This a blocking call. This demo waits for input signal (high level) to start counting pulses. It counts pulses for 1000 miliseconds. Then it prints results on LCD which is connected on PORTB. Here is the link for download:

Download pulsein.zip

---
Best Regards

Posted: 19 Feb 2008 22:11
by jomref
Using TMR0 in 16bit counter and 8MHz osc with 1:8 prescale do I get a TMR rollover every ms(millisec). Trying to figure Pulsein_demo but I must have a bad day. Can anyone help me with this simple math?

Posted: 19 Feb 2008 23:41
by janni
jomref wrote:Using TMR0 in 16bit counter and 8MHz osc with 1:8 prescale do I get a TMR rollover every ms(millisec)?
Nope, every 262ms in timer mode. You'll get ca. 1ms with 8 bit Timer0 mode.

pulsin command

Posted: 20 Feb 2008 05:32
by drumissimo
Marko,

To continue with the "wishlist" request, could the duration in the function below be time the pulse is at a certain transition (either high or low)?
Which would actually measure the pulse width in milliseconds for any input pin?

sub function Pulse_In(dim byref port as byte, dim pin, state as byte, dim duration as word)as word

regards,
drumissimo

Posted: 26 Aug 2008 10:41
by Acetronics
Hi, Marko

PULSIN returns the time a pin stays in a given state, and not how many pulses were incoming during a given time ...

What you described is "COUNT" called function ...

Alain

Posted: 26 Aug 2008 11:19
by trust issues
Haha looks like you guys beat me to it. I finished a design for a Pulse In library for P18's and have just been working on one for P16's.
Mine has 2 methods, one for accuracy between 0-3Khz and one for above that.

Posted: 27 Aug 2008 10:47
by DDJ
Hi Guys
Does the pulse_in function really just measure the time and not the pulses? If so, which function measures pulses and where do I find it ?
Is it similar to "counter" in proton ?

Thanks

Posted: 27 Aug 2008 12:33
by Charlie
Is it similar to "counter" in proton
No. MB does not have a counter command. You will have to use a timer for that.

How ?

Posted: 27 Aug 2008 13:13
by DDJ
How do I use a counter to measure pulses ? Please explain in step by step if possible.
Thanks

Posted: 27 Aug 2008 13:54
by Charlie
Well to use the counter command here is a example.
Dim puls as word

Main:

puls = Counter,PORTA.0,1000 ' count a pulse every secondon porta.1
rpm=puls*60 ' convert pulses per second to Revs per min.

and print to a LCD.

But..... Mb don't have the counter command. so you will have to do it the hard way. sorry.

Counter

Posted: 27 Aug 2008 15:15
by DDJ
Thanks Charlie

By saying I have to do it the hard way round, is that with a counter. Please have a look at my code. I'm trying to measure pulses from a cd4093 and write them to a lcd. I have a capacitive fuel sensor connected to the cd4093. I have the bargraph on the 2nd line of a 8x2 lcd and the pulses on the first line. I just don't know how to convert the pulse count to a value on the lcd.

Code: Select all

'Pulse-in LCD 8 x 2
'16F684
program pulse
dim count1 as word
dim bar as byte
dim border as byte
dim location as byte
dim text3 as string[4]
    text4 as string[4]
dim counter,
    msec,
    num_impulse as word
    text1 as word
    txt         as char[30]

sub procedure interrupt
   inc(counter)                               ' Increment value of counter on every interrupt
   if counter = 1 then                        ' Has 1ms elapsed?
     counter = 0                              ' Clear the counter
     inc(msec)                                ' Increment msec on every 1 ms
   end if
   TMR0 = 5
   ClearBit(INTCON, T0IF)                     ' Clear the TMR0IF flag
   SetBit(INTCON, T0IE)                       ' Enable TMR0 interrupt
end sub

sub function Pulse_In(dim byref port as byte, dim pin, state as byte, dim duration as word)as word
dim tmp as word                               ' Temporary variable
    old as byte                               ' Previous pin state value

  while TestBit(port, pin) = state            ' Wait for pulses
  wend                                        ' Note that the program will stop here
                                              '   if there are no pulses

  while TestBit(port, pin) <> state           ' Wait for rising (falling) edge
  wend                                        ' Note that the program will stop here
                                              '   if there are no pulses

  tmp  = 0                                    ' Clear temporary variable
  msec = 0                                    ' Clear number of ms
  old  = TestBit(port, pin)                   ' Get current pin state

  while duration > msec                       ' Check if duration is reached
     if (TestBit(port, pin)) <> old then      ' Check if pin state has changed
        inc(tmp)                              ' Increment number of pulses
        old = TestBit(port, pin)              ' Get current pin state
     end if
  wend

    result = (tmp >> 1) + 1                   ' Assign result value
end sub
sub procedure LCD_BarGraph_Init
      bar = 0
     for location = 64 to 104 step 8
     Lcd_Cmd(location)
     border = bar or 21
     LCD_Chr_CP(0)
     LCD_Chr_CP(border)
     LCD_Chr_CP(bar)
     LCD_Chr_CP(bar)
     LCD_Chr_CP(bar)
     LCD_Chr_CP(bar)
     LCD_Chr_CP(border)
     LCD_Chr_CP(0)
     bar = bar or 32
     bar = bar >> 1
     next location
end sub
sub procedure LCD_BarGraph_Draw(dim Row as byte, dim Column_Start as byte, dim Column_End as byte, dim Value as byte)
    while Value >= 5
          Lcd_Chr(Row, Column_Start, 5)
          Column_Start = Column_Start + 1
          Value = Value - 5
    wend
    while Column_Start <> Column_End + 1
          Lcd_Chr(Row, Column_Start, Value)
          Value = 0
          Column_Start = Column_Start + 1
     wend
     end sub

main:
  ANSEL = 0                                   'mods by DDJ
  OPTION_REG = 2                              ' Assign prescaler to TMR0 (1:8)
  TRISC  = $00                                ' Designate PORTC as output
  PORTC  = $FF                                ' Initialize PORTC
  CMCON0 = 7
  TRISA  = $FF                                ' Designate PORTA as input (for signal)

  counter= $00                                ' Initialize the counter
  TMR0  = 5
  INTCON = $A0                                ' Enable TMRO interrupt

  msec = 0                                    ' Clear msec
  num_impulse = 0                             ' Clear num_impulse


  'ADCON1 = $FF                               'mod by DDJ  PORTB all digital
  'CMCON  = $06                               'mod by DDJ  Comparators off
  
  text3 = "E"
  text4 = "F"
  Lcd_Config(PORTC,3,2,1,0,PORTC,4,7,5)       ' Initialize LCD connected to PORTC
  LCD_BarGraph_Init()
  Lcd_Cmd(LCD_CLEAR)                          ' Send command to LCD "clear display"
  Lcd_Cmd(LCD_CURSOR_OFF)                     ' Send command "cursor off"

  while 1 = 1

  num_impulse = Pulse_In(PORTA, 2, 1, 2000)   ' Count HI pulses on PORTA.2, for 1000ms

  count1 = num_impulse

     WordToStr(count1, txt)                 ' Convert results to string for LCD output
     lcd_out(1,1,txt)

     LCD_BarGraph_Draw(2, 2, 7, 6)    'value scale = 1 to 30 for 0 to full bar

     Lcd_Out(2, 8, text4)
     Lcd_Out(2, 1, text3)



    wend
  
  
  

  'lcd_Out(1, 1, "Pulses")           ' Print txt to LCD
 ' Lcd_Out(1, 1, txt)                          ' Print number of pulses to LCD

  'wend                                        ' Wait forever (stop)
end.

Thanks a lot for your help

Re: Pulse-In function example

Posted: 27 Aug 2008 18:08
by Dany
Hi Marko, what is the purpose of the "Counter" variable? It toggles continuously between 0 and 1 (it is always zero when entering the interrupt routine, subsequently incremented and again set to zero), and and is not used further.

Code: Select all

procedure interrupt;
begin
   inc(counter);                                // Increment value of counter on every interrupt
   if counter = 1 then                          // Has 1ms elapsed?
     begin
        counter := 0;                           // Clear the counter
        inc(msec);                              // Increment msec on every 1 ms
     end;
   TMR0 := 5;
   ClearBit(INTCON, T0IF);                      // Clear the TMR0IF flag
   SetBit(INTCON, T0IE);                        // Enable TMR0 interrupt
end;
Thanks in advance. :D

(I assume it is a leftover from the time that the measuretime always was 1 sec, and not parameterized...)

Re: Counter

Posted: 27 Aug 2008 18:24
by Dany
DDJ wrote:

Code: Select all

  num_impulse = Pulse_In(PORTA, 2, 1, 2000)   ' Count HI pulses on PORTA.2, for 1000ms
Hi, something is wrong here: or the code is wrong, or the comment is wrong (I think): 2000 versus 1000 millisecs.
DDJ wrote:I'm trying to measure pulses from a cd4093 and write them to a lcd.
This is a little bit vague "to measure pulses". What the code does in measuring the number of pulses per time (in your case a time of 2 seconds). So, it is the "frequency" (in your case half the frequency, since you measure for 2 seconds) that is measured. I assume this is indeed what is wanted :?:

Re: Counter

Posted: 27 Aug 2008 18:35
by Dany
DDJ wrote:I just don't know how to convert the pulse count to a value on the lcd.

Code: Select all

  
  'lcd_Out(1, 1, "Pulses")           ' Print txt to LCD
 ' Lcd_Out(1, 1, txt)                          ' Print number of pulses to LCD

  'wend                                        ' Wait forever (stop)
end.

Thanks a lot for your help
What about

Code: Select all

 
  lcd_Out(1, 1, "Pulses")           ' Print txt to LCD
  WordToStr(num_impulse, txt)
  Lcd_Out(1, 1, txt)                          ' Print number of pulses to  
LCD
:?:

erratum:
I now see that you had it already, does this not work?

Code: Select all

count1 = num_impulse

     WordToStr(count1, txt)                 ' Convert results to string for LCD output
     lcd_out(1,1,txt) 

Posted: 27 Aug 2008 18:45
by Dany

Code: Select all

count1 = num_impulse
     WordToStr(count1, txt)                 ' Convert results to string for LCD output
     Lcd_out(1,1,txt)
     LCD_BarGraph_Draw(2, 2, 7, count1)    'value scale = 1 to 30 for 0 to full bar
Above would be at first glance adapted to show the pulsecount also on the bar graph. There is only one small problem: the last parameter of "LCD_BarGraph_Draw" is of a byte type in stead of a word type. :D