Continue to Site

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.

  • 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.

PIC16F628A-Temp sensor-7 Seg Multiplexing issue :(

Status
Not open for further replies.
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.
 
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:
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
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:
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:
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:
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.
 
I cant see any reason your code isn't working.
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.

The use of goto $+nn is a bad habit to get into and will cause bugs in the future.
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?

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.
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!
 
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:
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.
 

Attachments

  • scan0001.jpg
    scan0001.jpg
    153.6 KB · Views: 162
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:
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?
 
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)?
 

Attachments

  • 16F648A DS18B20.HEX.TXT
    2.4 KB · Views: 182
Last edited:
Hi Mike.
Why have you commented out the "Read Slot" code (lines 199-201)?
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.

Can you try the attached program (remove the ".TXT" suffix)?
I tried your hex file.
Nothing happend.
The display didn't light up with anything.
 
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:
        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:
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:
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.
....but make sure the OW routines can't be interrupted....
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:
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:
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:
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.
 
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..
 
Pommie, Back in post 64 you said/recomended this:

Code:
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?
 
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.
 
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.
 
Can you try something else. Change the call to WaitISR to a sleep instruction and see if that works.

So just so I understand, doing this;
Code:
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.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top