Yesterday 13:11
Forum: Website / Forum Issues
Starter: rcurl
Views: 0
Replies: 8
Go to last post By: AlbertoFS
Yesterday 12:08
Forum: Projects discussion
Starter: AlbertoFS
Views: 0
Replies: 9
Yesterday 12:05
Forum: WIKI Discussion
Starter: AlbertoFS
Views: 0
Replies: 3
+ Reply to Thread
Results 1 to 7 of 7
  1. #1
    Junior Member IstvanK's Avatar
    Join Date
    Nov 2015
    Posts
    6
    Thumbs Up
    Received: 9
    Given: 1
    Total Downloaded
    97.14 MB

    2 Not allowed!

    Default Generating pulsing signals using Arduino millis()-like method

    Here is the code (with comments), everything explained (I hope):
    Code:
    ' Generating pulsing signals using Arduino millis()-like method
    '    (four independent configurable and switchable signals) 
    ' Written for the Proton BASIC compiler v3.6.0.3
    
    ' version 1.0,  Istvan K, 2017   
    
    $define Port PORTB
    ' (max) four outputs: bit 0..3 of the Port
    ' four inputs: bit 4..7 of the Port are used to read (examine) the
    ' appropriate on-off jumpers: for bit0 it's the bit4 (1-5, 2-6, 3-7)
    
    ' NOTE: I'm not using LATB for output (as usual) to avoid a lot of
    ' "Movlb N" bank instructions. The RMW is not an issue in this case 
    ' because only one PORTB (LATB) bit is altering at a time (writing
    ' PORTB writes LATB, only reading is different). But, take care with
    '   the outputs, have to avoid any high capacitive load of the pins.
     
    Device = 16F1826 ' 18-pin PIC, enhanced 8-bit core 
    Declare Xtal = 8
    Declare Reminders OFF
    Declare Optimiser_Level 2
    On_Hardware_Interrupt GoTo ITrut
    
    Dim runnerMs   As Dword ' incremented by TMR2 interrupt at every 1 ms
    Dim currentMs  As Dword ' to store (capture) the current runnerMs
    
    ' each PulsedPin (max. four (bitno = 0,1,2 or 3) has two own variables:
    Dim prevtoggMs[4] As Dword  ' to store toggling time (in ms)
    Dim wantedMs[4]   As Word   ' wanted ON/OFF time (in ms)
    
     ' PulsedPin parameters:
    Dim tOn   As Word ' HIGH (ON, logical 1) part of the pulse (in ms)
    Dim tOff  As Word ' LOW (OFF, logical 0) part in ms
    Dim bitno As Byte ' output bit number (0..3), must be different
    
    ' switchable pulse sequence (this routine is doing everything :-)
    $define PulsedPin(p1,p2,p3) bitno = p1 '
                                tOn   = p2 '
                                tOff  = p3 : GoSub Pulsed_Pin
    ' parameter values: p1=0-3 (bit no), p2=1-65535 (ms), p3=1-65535 (ms)
    
    ' The pulse period is max. 131 (65.5+65.5) secs, due of the 16-bit tOn, tOff.
    
    ' NOTE: the timing's accuracy is equal to the clock accuracy.
    '       Its precision (deviation from the nominal value) may not exceed
    '       0.3 ms ie the max. main loop time, using 4 active outputs as now.
    '        (the asm-optimized version's loop time is only 150 us)
    '       To get a better precision use a higher (eg 32 MHz) clock.
    
    $define BASIC_ONLY ' if not defined, Pulsed_Pin is asm-optimized (see below)
    ' if defined: 244 code, 43 ram; if not (ie asm-optimized): 184,35
    
    ' --------
    
    ' program starts here, with (internal) all_digital settings
    
      GoSub HW_Init ' also Timer2 is configured
      GoSub Zeroing ' reset some variables
    
      While 1=1 ' infinite loop,  appr 300 (asm: 150) us
    
        PulsedPin(0, 55,  45) ' time depends on the tOn and tOff but max 75 us
        PulsedPin(1, 150, 50)
        PulsedPin(2, 60, 140)
        PulsedPin(3, 350, 50)
    
      Wend
    
    ' -------- subroutines:
    
    ITrut: ' Timer2 ISR, runs every 1 ms. This is the "heart" of the program.
    Context Save
     PIR1bits_TMR2IF = 0 ' clear IT flag
     Inc runnerMs ' measures the time from the start (dword: max 49.7 days,
     ' then this "timer" wraps around and goes to zero). Hovewer, thanks to
     ' the used unsigned long substractions, also after that it's working well.
    Context Restore
    
    HW_Init:
      ' bank 1:
      OPTION_REGbits_NOT_WPUEN = 0 ' pullups ON
      PIE1bits_TMR2IE = 1 ' enable Timer2 IT
      TRISB = 0xF0        ' bit 4..7 are inputs
      ' bank 0:
      PORTB  = 0xF0       ' 1 for bit 4..7 (inputs), 0 for bit 0..3 (outputs)
      PIR1bits_TMR2IF = 0 ' clear TMR2 IT flag
      ' configure Timer2: 
      PR2 = 249           ' Timer2 Match value (period: 1 ms at 8 MHz)
      T2CON = 0b00111100  ' 1:8 postscaler, 1:1 prescaler, TMR2ON_bit = 1
    
      INTCONbits_PEIE = 1 ' Enable periferial ITs (like TMR2 match)
      INTCONbits_GIE = 1  ' Enable global ITs
    Return
    
    Zeroing:
     ' starting state of all the four pulses will be HIGH (for "tOn" ms)
     prevtoggMs[0] = 0
     prevtoggMs[1] = 0
     prevtoggMs[2] = 0
     prevtoggMs[3] = 0
     wantedMs[0] = 0
     wantedMs[1] = 0
     runnerMs = 0
     ' all the variables fit in bank 0, so:
     FSR0H = 0
     FSR1H = 0
    Return 
    
    ' the Arduino-like millis(), using direct update (no return value)
    Refresh_currentMs:
      INTCONbits_PEIE = 0 ' disable TMR2 IT to avoid disrupting update
      Nop ' needed because the above BCF is also disruptable (RMW)
      currentMs = runnerMs
      INTCONbits_PEIE = 1 ' re-enable TMR2 IT (using GIE_bit is problematic)
    Return
    
    ' ---------- two versions of the Pulsed_Pin subroutine:
    
    $ifdef BASIC_ONLY ' 244 code, 43 ram (asm-optimized: 184,35)
    
     ' in this case two additional variables are required:
     Dim inpMask As Byte 
     Dim outMask As Byte 
     ' and it is using 10 system variable bytes
    
     Pulsed_Pin: 
        outMask = 1 << bitno
        ' examine the appropriate jumper (for bit0 the bit4; 1-5, 2-6, 3-7)
        inpMask = outMask << 4 ' higher nybble
        If (inpMask & Port) = 0 Then
           ' if the jumper is closed ie 0 then output is zeroed:
           Port = Port & ~outMask
           Return ' end of function
        EndIf
        GoSub Refresh_currentMs
        ' the wantedMs time elapsed?
        If (currentMs - prevtoggMs[bitno]) >= wantedMs[bitno] Then 
           ' if the output is HIGH at this moment then it 
              ' will be LOW for tOff ms (and vice versa)
           If Port & outMask <> 0 Then tOn = tOff
           Port = Port ^ outMask ' toggle output bit (xor)
           wantedMs[bitno] = tOn ' and store wantedMs for the next call(s)
           prevtoggMs[bitno] = currentMs ' actualize and store prevtoggMs
        EndIf
     Return ' end of Pulsed_Pin (basic-only)
    
    ' ---------
    
    $else ' asm-optimized: 184 code, 35 ram (basic-only: 244,43)
    
     ' one additional variable, to avoid using system variable(s):
     Dim elapsedMs  As Dword ' elapsed time (in ms) from the last toggling 
    
     $define outMask bitno ' after set FSRs, bitno is reused (no new var)
    
     ' the code takes advantage of the Moviw/Movwi k[FSRn] instruction:
     '   this does not change the FSR so it needs to be set only once.
    
     Pulsed_Pin:
      ' calculate FSR pointers (not alter later, FSR0H and FSR1H are zero): 
      Lslf bitno,W  
      Movwf FSR0L
      Lslf WREG ' prevtoggMs is dword
      Addlw prevtoggMs
      Movwf FSR1L   ' FSR1 points to prevtoggMs[bitno], first byte
      Movlw wantedMs
      Addwf FSR0L,F ' FSR0 points to wantedMs[bitno], first byte
    
      ' bitno = 1 << bitno (calculate outMask)
      Incf bitno,W
      Clrf bitno ' original bitno value is lost (later not needed)
      STATUSbits_C = 1
     bLoop:
      Rlf bitno,F
      Decfsz WREG
        Bra bLoop
      ' now bitno = outMask !! (see the above outMask define)
    
      ' examine the appropriate jumper (for bit0 the bit4; 1-5, 2-6, 3-7)
       'if (Port & Swap(outMask)) = 0
      Swapf outMask,W ' change 4-bit nybbles to get input mask, to W !
      Andwf Port,W  ' if W = 0 now then Z = 1
      If STATUSbits_Z = 1 Then  ' if the jumper is closed ie 0 then
        ' output is zeroed:
         'Port = Port & ~outMask
        Comf outMask,W : Andwf Port,F 
        Return ' end of function
      EndIf
      GoSub Refresh_currentMs
      ' calculate elapsed time after the previous (the last) toggle:
       'elapsedMs (dword) = currentMs - prevtoggMs[original bitno]
      Moviw 0[FSR1]
      Subwf currentMs,W
      Movwf elapsedMs
      Moviw 1[FSR1]       ' FSR1 points to prevtoggMs[orig.bitno]
      Subwfb currentMsH,W
      Movwf elapsedMsH
      Moviw 2[FSR1]
      Subwfb currentMsHH,W
      Movwf elapsedMsHH
      Moviw 3[FSR1]
      Subwfb currentMsHHH,W
      Movwf elapsedMsHHH
      ' the wantedMs time elapsed?
       'if elapsedMs < wantedMs[orig.bitno] then return else toggle:
    '  movf elapsedMsHHH,W  (it is already in W)
      Iorwf elapsedMsHH,W ' wantedMs is only a 16-bit var, so
      Btfss STATUSbits_Z  ' if the higher word of elapsedMs is nonzero then:
         Bra toggling ' certainly not smaller than wantedMs, toggle needed
       ' compare lower word of elapsedMs:   
      Moviw 1[FSR0]   ' FSR0 points to wantedMs[original bitno]
      Subwf elapsedMsH,W
      Btfss STATUSbits_C
         Return  ' smaller yet, wait for the next call
      Btfss STATUSbits_Z
         Bra toggling ' not smaller
      Moviw 0[FSR0]
      Subwf elapsedMs,W
      Btfss STATUSbits_C
         Return ' smaller (nothing to do)
    
     toggling:
      ' if the output is HIGH at this moment then it 
      ' will be LOW for tOff ms (and vice versa)
    
       'if Port & outMask <> 0 Then tOn = tOff 
      Movf outMask,W : Andwf Port,W
      If STATUSbits_Z = 0 Then tOn = tOff
      ' toggle output bit (xor):
       'Port = Port ^ outMask
      Movf outMask,W : Xorwf Port,F 
       'wantedMs[orig.bitno] = tOn: store new wantedMs for the next call(s):
      Movf tOn,W
      Movwi 0[FSR0]
      Movf tOnH,W
      Movwi 1[FSR0]
       'prevtoggMs[orig.bitno] = currentMs: actualize and store prevtoggMs:
      Movf currentMs,W
      Movwi 0[FSR1]
      Movf currentMsH,W
      Movwi 1[FSR1]
      Movf currentMsHH,W
      Movwi 2[FSR1]
      Movf currentMsHHH,W
      Movwi 3[FSR1]
     Return ' end of Pulsed_Pin (asm-optimized)
    
    $endif ' BASIC_ONLY or asm-optimized Pulsed_Pin
    
    ' ------- end of program
    The Proteus simulation (the circuit) is very simple: only the PIC and
    four on/off switches are needed and an oscilloscope shows the signals:
    PICpulses_DSN.jpg

    It works (50ms/div):
    50ms_div.jpg

    Greetings
    Istvan

  2. #2
    Administrator John Drew's Avatar
    Join Date
    Feb 2002
    Posts
    2,524
    Thumbs Up
    Received: 100
    Given: 29
    Total Downloaded
    2.52 GB

    0 Not allowed!

    Default Re: Generating pulsing signals using Arduino millis()-like method

    Useful code IstvanK. How about creating an article on the WIKI as it's easily lost here on the forum?
    John

  3. #3
    Junior Member IstvanK's Avatar
    Join Date
    Nov 2015
    Posts
    6
    Thumbs Up
    Received: 9
    Given: 1
    Total Downloaded
    97.14 MB

    0 Not allowed!

    Default Re: Generating pulsing signals using Arduino millis()-like method

    Quote Originally Posted by John Drew View Post
    Useful code IstvanK.
    Thanks ..

    How about creating an article on the WIKI as it's easily lost here on the forum?
    Sorry, but I'm still waiting for this because I still cannot post (upload) a syntax colourized code.
    What's the trick?
    Istvan

  4. #4
    Administrator John Drew's Avatar
    Join Date
    Feb 2002
    Posts
    2,524
    Thumbs Up
    Received: 100
    Given: 29
    Total Downloaded
    2.52 GB

    0 Not allowed!

    Default Re: Generating pulsing signals using Arduino millis()-like method

    I'll get back to you. On my phone at present and won't be able to access my computer until tomorrow.
    John

  5. #5
    Administrator John Drew's Avatar
    Join Date
    Feb 2002
    Posts
    2,524
    Thumbs Up
    Received: 100
    Given: 29
    Total Downloaded
    2.52 GB

    0 Not allowed!

    Default Re: Generating pulsing signals using Arduino millis()-like method

    Hmm, you're right. You can add a zipped file with the colour but not just insert a colour file.
    You can go through a post with no colour and add colour using highlight with the mouse and then use the appropriate edit button.
    I couldn't find a method other than the one described.
    Other may be able to help.
    Irrespective of the colour issue your program would be very useful for people to access later - hence the WIKI article idea.
    Lester is the guru when it comes to the forum. He may be able to advise.
    Best wishes
    John

  6. #6
    Administrator-01 Lester's Avatar
    Join Date
    Jan 2002
    Posts
    1,668
    Thumbs Up
    Received: 62
    Given: 4
    Total Downloaded
    779.04 MB

    0 Not allowed!

    Default Re: Generating pulsing signals using Arduino millis()-like method

    OK, i'm looking at this, i''get back to you if i can implement a subset of GeSHi - it looks like a good solution to this requirement.
    Generic Syntax Highlighter

    Lester Wilson
    ---------------------------------
    Crownhill Associates Limited
    www.crownhill.co.uk
    Tel: +44 1353 749990
    Fax: +44 1353 749991
    lester@crownhill.co.uk
    ----------------------------------

  7. #7
    Administrator-01 Lester's Avatar
    Join Date
    Jan 2002
    Posts
    1,668
    Thumbs Up
    Received: 62
    Given: 4
    Total Downloaded
    779.04 MB

    0 Not allowed!

    Default Re: Generating pulsing signals using Arduino millis()-like method

    I have installed GeSHi

    for more info, look in the website/forum issues section
    Lester Wilson
    ---------------------------------
    Crownhill Associates Limited
    www.crownhill.co.uk
    Tel: +44 1353 749990
    Fax: +44 1353 749991
    lester@crownhill.co.uk
    ----------------------------------

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

     

Similar Threads

  1. Replies: 7
    Last Post: 17th November 2015, 10:42
  2. Software SPI with the bit banging method
    By AlbertoFS in forum WIKI Discussion
    Replies: 8
    Last Post: 3rd November 2015, 11:25
  3. 18F4550 - Encryption: Blowfish method.
    By wirecut in forum Proton Plus Compiler v3
    Replies: 0
    Last Post: 18th May 2012, 14:18
  4. Best Optocoupler method
    By pic-ignorant in forum The Lounge
    Replies: 15
    Last Post: 7th May 2011, 15:44
  5. Generating a checksum
    By SimonGie in forum GPS
    Replies: 21
    Last Post: 27th August 2009, 13:50

Members who have read this thread since 11th September 2018, 04:46 : 0

Actions :  (Set Date)  (Clear Date)

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

Tags for this Thread

Posting Permissions

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