1. Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
    Dismiss Notice

PIC16F628A-Temp sensor-7 Seg Multiplexing issue :(

Discussion in 'Microcontrollers' started by jakeselectronics, May 19, 2010.

  1. jakeselectronics

    jakeselectronics Member

    Joined:
    May 2, 2009
    Messages:
    401
    Likes:
    4
    Location:
    Macedon Ranges, Australia
    Definitly!!!
    But right now it's almost 1030pm and I've got to be up at 530 for work, so I'll do it as soon as I get home and post my findings here.

    This time difference sucks.
     
  2. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,637
    Likes:
    109
    Location:
    Michigan, USA
    Hi again Jake,

    Just spotted another potential problem in your code in your bin2dec routine. The ISR is looking for values of 0..11 in the HUNS, TENS, and ONES variables to use as an index for the segment data table. Your bin2dec routine places values outside that range in the TENS and ONES variables so if an interrupt occurs while your main program is executing the bin2dec routine the segment data lookup in the ISR could fail with an out-of-range index value in the TENS or ONES variable.

    Regards, Mike
     
    Last edited: Jun 6, 2010
  3. jakeselectronics

    jakeselectronics Member

    Joined:
    May 2, 2009
    Messages:
    401
    Likes:
    4
    Location:
    Macedon Ranges, Australia
    I already spotted this while getting everything else but the DS18B20 comms routines working.
    To work around that issue I inserted a disable interrupt instuction at the start of the BCD2DEC routine and I re-enable the interrupts beofre returning..
    Code (text):
    BIN_TO_DEC  ; This routine converts an 8-bit number to Decimal and stores the answer in 3 GPR's; HUNS, TENS & ONES
      ; HUNS holds amount of hundreds (i.e. 0000 0010 = 2x100), TENS holds amount of tens (i.e. 0000 0010 = 2x10) & ONES holds amount of ones (i.e. 0000 0101 = 5x1)
            BCF     INTCON, GIE             ; Disable Interrupts
            INCF    TEMPHI                  ; Preload TEMPHI + 1
            CLRF    HUNS                    ; HUNS = 0000 0000
     
            MOVLW   D'246'                  ; MOVE Decimal'246' to W
            MOVWF   TENS                    ; TENS GPR = 1111 0101
            MOVWF   ONES                    ; ONES GPR = 1111 0101
            DECFSZ  TEMPHI, F               ; Decement TEMPHI register
            GOTO    $+2                     ; NOT 0, skip next instruction
            GOTO    $+7                     ; IS 0, TEMPHI = 0000 0000, skip next 6 instructions and calculate how many tens and hundreds
            INCFSZ  ONES, F                 ; Increment ONES register, skip if 0
            GOTO    $-D'4'                  ; NOT 0, GOTO here - 4 instructions
            INCFSZ  TENS, F                 ; IS 0, Increment TENS register skip if 0
            GOTO    $-D'7'                  ; GOTO here - 7 instructions & reset the ONES register to D'246'
            INCF    HUNS, F                 ; TENS overflowed, Increment HUNS
            GOTO    $-D'10'                 ; GOTO here - 10 instructions & reset the ONES and TENS registers to D'246'
     
            SUBWF   TENS, F                 ; W still holds D'246 so subract it from TENS register to determine how many 'TENS'
            SUBWF   ONES, F                 ; W still holds D'246 so subract it from ONES register to determine how many 'ONES'
     
      ; TENTHS = Fraction * 10 / 16 (Pommies routine to convert 4 bit number wher each bit represents 0.625 degrees, into rounded deciaml number)
            MOVLW   B'00001111'             ;
            ANDWF   TEMPLO,F                ;
            MOVF    TEMPLO,W                ;
            ADDWF   TEMPLO,F                ; *2, C=0
            RLF     TEMPLO,F                ; *4, C=0
            ADDWF   TEMPLO,F                ; *5, C=0
            RLF     TEMPLO,F                ; *10
            MOVLW   B'00001000'             ;
            ADDWF   TEMPLO,F                ; Rounding
            SWAPF   TEMPLO,W                ; Pseudo divide by 16
            ANDLW   B'00001111'             ;
            MOVWF   TENTHS                  ;
     
      ; Leading zero suppression & minus (-) sign if Temperature Negative
            MOVF    HUNS, W                 ; Does HUNS equal 1 or 2? MOVF instruction affects Z bit of STATUS register
            BTFSC   STATUS, Z               ; Test Z bit of STATUS register to see if HUNS = 0000 0000
            MOVLW   B'00001010'             ; Jump Pointer for blank arrangement
     
            BTFSC   SCRATCHPAD_BYTE1, 7     ; Is Temperature Negative?
            MOVLW   B'00001011'             ; YES, Jump Pointer for - arrangement
            MOVWF   HUNS                    ;
     
            BTFSS   STATUS, Z               ; Test Z bit of STATUS register to see if HUNS = 0000 0000
            GOTO    $+5                     ; HUNS is not, therefore do not blank TENS
            MOVF    TENS, W                 ; Does TENS equal 0?
            BTFSC   STATUS, Z               ; Test Z bit of STATUS register to see if last instruction = 0000 0000
            MOVLW   B'00001010'             ; Jump Pointer for blank arrangement
            MOVWF   TENS                    ;
     
            BSF     INTCON, GIE             ; Disable Interrupts
     
            GOTO    GET_TEMP
     
    And as for Pommies error spot, I have amended that by clearing the latch everytime before making the pin an output, and have also changed the instruction in the ISR to that one Mike(K8LH) suggested.
    (ANDLW B'11100000')
    but still, nothing.

    I am 99% sure now that the error lies within the DS18B20 communiction routines...

    .... the latest version: DS18B20 Digital Thermometer ASM WITH colour scheme
     
    Last edited: Jun 6, 2010
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,022
    Likes:
    317
    Location:
    Brisbane Australia

    I cant see any reason your code isn't working. Are you sure all the connections to the DS and the pullup are correct.

    Can you try testing for the presence pulse. Change your reset to be,
    Code (text):

    DS18B20_RESET               ; RESET
            bcf PORTA,4     ;
            bsf STATUS,RP0  ; }
            bcf TRISA,4     ; } DQ LOW
            bcf STATUS,RP0  ; }
                 
            movlw   (d'500'-8)/4    ;delay 500uS
            call    DELAY       ; CALL Delay: 500 cycle delay including CALL/GOTO & RETURN. Send Reset Pulse
            movlw   (d'60'-8)/4 ;wait 60uS
            bcf STATUS,C   
            btfsc   PORTA,4     ;read presence pulse
            bsf STATUS,C        ;and move to carry
            movlw   D'123'      ; Move Decimal 123 to W register
            goto    DELAY       ; GOTO Delay: 500 cycle delay including CALL/GOTO & RETURN. Wait MIN 480uS for DS18B20 & return with DQ line High Z
     
    and test the carry in your main code.

    Can I also suggest you change all the timings to the (nn-8)/4 to make it easier to read and please get rid of all the goto $+nn lines and use labels instead. The use of goto $+nn is a bad habit to get into and will cause bugs in the future.

    If you're still having problems, I have a 16f88 on a breadboard that I can hook up a DS to and try you code.

    Mike.
     
    • Like Like x 1
  6. jakeselectronics

    jakeselectronics Member

    Joined:
    May 2, 2009
    Messages:
    401
    Likes:
    4
    Location:
    Macedon Ranges, Australia
    I have just now pulled my old DS OW.routine out and inserted it into the program, and it works. It is verrrrrry long and messy and i really like your and mike's version. plus the refresh rate of the display due to placement of dis/enable interrupt instructions is bad. I can almost see each digit turn on and off. I want to use this much compressed ow routine.
    This tells me it is definitly the DS one wire routine that is not working.

    And I like the (d'500'-8)/4 lines... I didn;t even know you could use brackets like that.
    I will change them.

    I'm not disagreeing, but why is it a bad habbit and how does it cause bugs?
    I will happily change my ways if using lables is a proven much better way. In essence, doesn't a GOTO 'LABLE', just complie down to a GOTO $+/-n?

    Let me try a few things first and I will let you know how i go.
    Because my old code is working, and this new one isn't I want to go through them thoroughly and compare them first, to see If I can work it out.

    I will post later.
    Thanks Pommie!
     
  7. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,022
    Likes:
    317
    Location:
    Brisbane Australia
    As read and write slots only take 60uS, to read/write a complete byte is only 500uS. You interrupt occurs every 1000uS and so inserting a sleep instruction before reading/writing a byte will ensure the routine doesn't get interrupted. The sleep instruction will wait until the interrupt occurs.

    Mike.
     
    Last edited: Jun 7, 2010
  8. jakeselectronics

    jakeselectronics Member

    Joined:
    May 2, 2009
    Messages:
    401
    Likes:
    4
    Location:
    Macedon Ranges, Australia
    EDIT: don't worry

    but I may have found my problem....
    Ill post soon

    :D:D:D:D
     
    Last edited: Jun 8, 2010
  9. jakeselectronics

    jakeselectronics Member

    Joined:
    May 2, 2009
    Messages:
    401
    Likes:
    4
    Location:
    Macedon Ranges, Australia
    Hey guys,

    So I slowly worked through my old (working) OW routines and converted them to resemble the nicely layed out and compress version, in doing so I found an, if not THE, issue that has caused me so much grief.
    BUT, I don't know how to fix it.
    I will do my best to explain.
    In reference to the assembly source file (the link is below in my signature because I'm sick of finding then adding the link to nearly every post)....

    My problem lies with enabling and disabling interrupts in the OW routines.
    On lines 189 and 215 of my code (in the GET_TEMP routine) you'll see i have 2 instructions, 'disable interrupts' and 'enable interrupts'.
    Also on line 275 in the DELAY routine i have an 'enable interrupts' routine commented out.
    The interrupt only has a small window of code in which it can be triggered due to the disabling of interrupts for the whole OW routine, therefore the display is flicking randomly and each digit has a different brightness to the other.
    This code is working though. I am getting the temperature from the sensor which means the timing is right, and the temp is being displayed which means the display driver is alright.

    What I want to now do is get rid of lines 189 and 215, and un-comment the 'enable interrupts' instruction on line 275 as part of the DELAY routine so that the interrupts are disabled for a minimum amount of time, i.e. only during OW communication.
    But when I do this, weird things happen.
    sometimes a random digit, sometimes nothing...

    I'm getting closer and have narrowed it down to this,
    Pommie, if you still have that 88 on a Breadboard I would love for you to test this code an to see whats happening with your own eyes.

    as I said the assembly code is in the signature and I have added the schematic for the 628a i am using.

    Jake.
     

    Attached Files:

  10. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,637
    Likes:
    109
    Location:
    Michigan, USA
    Hi Jake,

    When you get a chance can you remove the "request sense" lines that Pommie had you add to the DS18B20_RESET subroutine and tell us if that makes any difference?

    Cheerful regards, Mike
     
    Last edited: Jun 9, 2010
  11. jakeselectronics

    jakeselectronics Member

    Joined:
    May 2, 2009
    Messages:
    401
    Likes:
    4
    Location:
    Macedon Ranges, Australia
    Removed them.
    ( and by removed, I commented out lines 224 & 225)
    No difference.
    Commented out the dis/enable interrupt instructions in the GET_TEMP routine, and un-commented the enable interrupt instruction in the delay routine....
    No difference

    Why would that effect anything?
     
  12. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,637
    Likes:
    109
    Location:
    Michigan, USA
    Sorry! Just a hunch.

    Why have you commented out the "Read Slot" code (lines 199-201)?

    Can you try the attached program (remove the ".TXT" suffix)?
     

    Attached Files:

    Last edited: Jun 9, 2010
  13. jakeselectronics

    jakeselectronics Member

    Joined:
    May 2, 2009
    Messages:
    401
    Likes:
    4
    Location:
    Macedon Ranges, Australia
    Hi Mike.
    Um, It was causing the display to refresh once every second or so. (you could see each digit turn on then off)
    So I was just leaving it out until the other problem was fixed.

    I tried your hex file.
    Nothing happend.
    The display didn't light up with anything.
     
  14. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,022
    Likes:
    317
    Location:
    Brisbane Australia
    Can I make a suggestion. Don't disable the interrupts but make sure the OW routines can't be interrupted by doing,

    Add a flag to the ISR,
    Code (text):

            SWAPF   W_ISR, W                ; Undo previous SWAPF and restore W register
            BCF     PIR1, TMR2IF            ; Clear TMR2 interrupt flag
            [COLOR="red"]BSF     Flags,0[/COLOR]
            RETFIE                          ; RETurn From IntErrupt
     
    And add a wait subroutine,
    Code (text):

    WaitISR     bcf Flags,0
    W_ISR_Loop  btfss   Flags,0
            goto    W_ISR_Loop
            return
     
    And call the subroutine before any read/write to the OW device.

    You will have to replace the read slots (after convert) with a suitable delay.

    Let us know what happens.

    Mike.
     
    Last edited: Jun 10, 2010
    • Like Like x 1
  15. jakeselectronics

    jakeselectronics Member

    Joined:
    May 2, 2009
    Messages:
    401
    Likes:
    4
    Location:
    Macedon Ranges, Australia
    Pommie, your idea worked.

    It seems to be working flawlessly.

    Once again, the updated (and working) assebler file is linked in my signature.

    I still would really like to know though why the previous way didn't work.
    I thought that was exactly what we were doing by using a 'BCF INTCON, GIE' at the start of a OW comms routine. Like below. (then a BSF INTCON, GIE as the last instruction (before the return) in the DELAY routine to re-enable ints)
    Code (text):
    DS18B20_WRITE_BIT  ; WRITE BIT  - WORKS
            BCF     INTCON, GIE             ;
            CALL    DQ_LL                   ;
            BTFSS   STATUS, C               ;
            GOTO    $+2                     ;
            CALL    DQ_HIZ                  ;
            MOVLW   (D'60'-8)/4             ;
            GOTO    DELAY                   ;
    So this is whats working.
    Code (text):
    DS18B20_WRITE_BIT  ; WRITE BIT  - WORKS
            CALL    WAIT_ISR
       ;     BCF     INTCON, GIE             ;
            CALL    DQ_LL                   ;
            BTFSS   STATUS, C               ;
            GOTO    $+2                     ;
            CALL    DQ_HIZ                  ;
            MOVLW   (D'60'-8)/4             ;
            GOTO    DELAY                   ;
    I'm stumpted.

    At least its working. Finally.
     
    Last edited: Jun 14, 2010
  16. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,022
    Likes:
    317
    Location:
    Brisbane Australia
    The reason the display was flickering was because it was being halted every now and again therefore giving some digits more time than others. The code above waits until an interrupt has happened and then runs the OW code. The interrupts occur every 1000uS and a read/write to the OW device takes 500uS so, the OW routines don't get interrupted and the interrupt doesn't get delayed.

    Why disabling interrupts didn't work I have no idea. Probably a timing issue that we didn't spot.

    Mike.
     
  17. jakeselectronics

    jakeselectronics Member

    Joined:
    May 2, 2009
    Messages:
    401
    Likes:
    4
    Location:
    Macedon Ranges, Australia
    I totally understand that.

    But disabling interrupts during OW comms routines then re-enabling at the end didn't even work.
    I got the flickering display after I disabled interrupts for the whole GET_TEMP routine and re-enabled at the end.

    anyway, another thing thats wierd is that I dont have a delay yet after the CONVERT T routine and it still works. Even though a reset happens not long after..
     
  18. jakeselectronics

    jakeselectronics Member

    Joined:
    May 2, 2009
    Messages:
    401
    Likes:
    4
    Location:
    Macedon Ranges, Australia
    Pommie, Back in post 64 you said/recomended this:

    Code (text):
    The use of goto $+nn is a bad habit to get into and will cause bugs in the future.
     
    Can I ask why?

    Doesn't a 'GOTO LABLE' instruction compile down to a $+nn anyway?
     
  19. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,022
    Likes:
    317
    Location:
    Brisbane Australia
    When you insert new code or rem out an instruction it is easy to miss changing the $+nn. A label does it automatically. Also, experienced programmers never use it and so can't follow your code to help debug it.

    Mike.
     
    • Like Like x 1
  20. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,022
    Likes:
    317
    Location:
    Brisbane Australia
    Can you try something else. Change the call to WaitISR to a sleep instruction and see if that works.

    I'm just curious to see if that solution works as well.

    Mike.
     
  21. jakeselectronics

    jakeselectronics Member

    Joined:
    May 2, 2009
    Messages:
    401
    Likes:
    4
    Location:
    Macedon Ranges, Australia
    So just so I understand, doing this;
    Code (text):
    DS18B20_WRITE_BIT  ; WRITE BIT  - WORKS
        ;    CALL    WAIT_ISR
            SLEEP
            CALL    DQ_LL                   ;
            BTFSS   STATUS, C               ;
            GOTO    $+2                     ;
            CALL    DQ_HIZ                  ;
            MOVLW   (D'60'-8)/4             ;
            GOTO    DELAY                   ;
    Should cause the WRITE_BIT routine to wait until the interrupt is complete to execute.
    Immediately after the interrupt, the read/write is carried out.
    ???

    So I changed all the 'CALL WAIT_ISR' instructions, to a SLEEP instruction and nothing happend. Display is blank.
     

Share This Page