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.

DS18B20 Digital Thermometer + PIC + Assembly display flicker issue

Status
Not open for further replies.
Hello everyone.

Back in May I started a Digital Thermometer Project using the Dallas 18B20 sensor and a PIC16F268A using assembly language.

Firstly thanks to Mike K8LH, Pommie, Nigel Goodwin, and Dougy for their immense help throughout.

I am revisiting this project because I never 100% completed it.
After what I though was finishing it, I realized when the temp hit roughly 40c, the program froze.
I have managed to fix that bug and have tested it to its full range. Works perfectly from -55 to 127.

The issue I have is display flicker.
It is the slightest random shimmer over the LED display.
Just enough for the human Persistence of Vision to pick up.

Project Background:
Digital Thermometer using DS18B20 12-bit mode (.1 degree resolution)
Display is LED 4 digit 7 segment.
Program simply gathers data from Temp Sensor and
Uses Timer 2 interrupt to refresh LED display.


Pommie helped me out with a little routine that would wait for the interrupt to finish before the time crucial communication started.
This was only because disabling and re-enabling interrupts wasn't working for some reason.
But now it is after many changes, and I would like to continue using disable and re-enable interrupt instructions to prevent the interrupt during communication.

What I am asking is for fresh eyes to look over the program to try to lower the ratio of time that interrupts are disabled to stop the display flickering.
Basically, I have a Working program, but it needs code optimization.
Any tips???

Here is the ASM (to big to wrap in code tags)
DS18B20 Digital Temperature Sensor.asm

Schematic:
http://www.jakeselectronics.net/projects_digitaltemperaturesensor.php

Breadboard:
http://www.jakeselectronics.net/projects_digitaltemperaturesensor.php

edit: project finished, amended links to finished project
 
Last edited:
Make sure you're refreshing at least 50 times a second (the whole display not per segment) plus blank the display before switching to the next digit.
 
If I'm not mistaken his current refresh rate is around 500-hz (four displays updated at 500-usec intervals)...
 
It just dawned on me... I have a few ideas which will see interrupts disabled for a minimal amount of time. I will try later when I get home from work.

Note, the timer 2 setup may show a certain refresh/interrupt rate, but because interrupts are disabled for probably about 1/5 of the time, the refresh rate is effected.

I will post my results tonight...
 
Na Na Na 1/3 of the time isn't spent in the interrupt routine. It's the fact that I am preventing the interrupt executing often enough due to interrupts being disabled too long.
I'm pretty sure I have a fix, but can't test till tonight....
 
It looks like you're disabling interrupts for the duration of the 1000 usec OneWire reset. That's too long for your 500-usec interrupts. You should probably only disable interrupts for the 60-usec "read sense" portion of the Reset function.

You might consider using a 2-msec interrupt interval. That leaves more time between interrupts to handle the Reset and it would only reduce your display refresh rate down to 125-Hz (riciprocol of 8-usecs = 125-Hz) which is still fast enough to avoid flicker.

Regards...
 
Ok lets concenrate on the Reset routine.

Looking at the timing diagram and timing table...
So given the interrupt is 43uS long, theroretically, can't the interrupt be enabled for the whole thing? Providing the interrupt doesnt change the state of the DQ line??

ds18b20-reset-timing-diagram-jpg.47168

Code:
DS18B20_RESET  ; This routine Resets the DS18B20
      ;  BCF     INTCON, GIE             ; Disable Global Interrupts
        CALL    DQ_LL                   ; Force the DQ Line to Logic Low
        MOVLW   (D'480'-5)/5            ; Hold Low, Reset Pulse
        CALL    DELAY                   ; 
        CALL    DQ_HIZ                  ; Release DQ Line
        MOVLW   (D'60'-5)/5             ; Wait min 60uS after DQ released
        CALL    DELAY                   ; 
        BTFSC   PORTA, 4                ; Test for 'Presence Pulse'
        GOTO    DS18B20_RESET           ; If not present, Reset
        MOVLW   (D'420'-5)/5            ; Minimum wait of 480uS (60+420) 
        CALL    DELAY                   ; 
      ;  BSF     INTCON, GIE             ; Enable Global Interrupts
        RETURN                          ;

For full listing click here: DS18B20 Digital Temperature Sensor.asm
 

Attachments

  • DS18B20 Reset Timing Diagram.jpg
    DS18B20 Reset Timing Diagram.jpg
    75.7 KB · Views: 4,632
  • DS18B20 Timing Table.jpg
    DS18B20 Timing Table.jpg
    197.4 KB · Views: 955
.... So given the interrupt is 43uS long, theoretically, can't the interrupt be enabled for the whole thing? Providing the interrupt doesnt change the state of the DQ line??

Yes, I think that should work... I did not disable interrupts in the OwReset routine in my very old DS18B20 + 7-Segment project from years ago...
 
Yes, I think that should work... I did not disable interrupts in the OwReset routine in my very old DS18B20 + 7-Segment project from years ago...

Well, I tried it. It works for a couple of seconds, then freezes.

Mike do you still have your old program? Is there any chance you could PM it, or post it, so I can compare our programs. It may give me some idea's on where to alter my program
 
Mike!
I found it!

Look at your old post.
https://www.electro-tech-online.com...r-7-seg-multiplexing-issue.107446/#post885171

I dont know why, I thought I changed that ages ago...
If fact i did, but I changed it back to try something and forgot about it.
Anyway changed the 1 to a 0 and it now works.
Flawlessly :D

Code:
  ; Refresh display
        CLRF    PORTB                   ; Blank the display
        MOVF    PORTA, W                ; MOVE PORTA's current state to W
        ANDLW   B'111[COLOR="red"]0[/COLOR]0000'             ; Clear ONLY Column Select Bits & leave upper nibble unchanged
        IORWF   COLSEL, W               ; Inclusive OR above with COLSEL register
        MOVWF   PORTA                   ; Leave upper nibble of PORTA unchanged & select new Column
 
Could I suggest that you get rid of all the goto $+ lines and replace them with labels.
I.E.
Code:
		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
		[COLOR="black"][COLOR="red"]goto	$+2[/COLOR][/COLOR]		; NOT 0, skip next instruction
		[COLOR="red"]goto	$+7[/COLOR]		; 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
		[COLOR="red"]goto	$-D'4'[/COLOR]		; NOT 0, GOTO here - 4 instructions
		incfsz	TENS,F		; IS 0, Increment TENS register skip if 0
		[COLOR="red"]goto	$-D'7'[/COLOR]		; GOTO here - 7 instructions & reset the ONES register to D'246'
		incf	HUNS,F		; TENS overflowed, Increment HUNS
		[COLOR="red"]goto	$-D'10'[/COLOR]		; GOTO here - 10 instructions & reset the ONES and TENS registers to D'246'

One of these could be wrong and causing the crash but I have no way of knowing where you intended it to jump to.

Mike.
 
Could I suggest that you get rid of all the goto $+ lines and replace them with labels.
Ok, but before i do that, becasue I know the whole BIN_TO_DEC routine is working properly Ill show you this.

The program works with no noticable flicker (after changing a few things.)

This is the reset routine.
When the BCF and BSF INTCON,GIE instructions are present, like below. the program runs perfectly.
But as soonas I remove them the program runs for say 5-20 seconds then freezes (display 1 digit on the display IE what ever was last in the ISR)

Code:
DS18B20_RESET  ; This routine Resets the DS18B20
        [COLOR="sienna"]BCF     INTCON, GIE[/COLOR]             ; Disable Global Interrupts
        CALL    DQ_LL                   ; Force the DQ Line to Logic Low
        MOVLW   (D'480'-5)/5            ; Reset pulse must be held a minimum of 480uS
        CALL    DELAY                   ; 
        CALL    DQ_HIZ                  ; Release DQ Line
        MOVLW   (D'60'-5)/5             ; Wait for recovery
        CALL    DELAY                   ; 
        BTFSC   PORTA, 4                ; Test for 'Presence Pulse'
        GOTO    DS18B20_RESET           ; If not present, Reset
        [COLOR="sienna"]BSF     INTCON, GIE[/COLOR]             ; Enable Global Interrupts
        MOVLW   (D'420'-5)/5            ; Must wait a minmum of 480uS from when DQ line is released before moving on
        CALL    DELAY                   ; 
        RETURN                          ;

Seen as though the program is working without flicker its ok.
But its bugging me that the reset routine has to be prevented from getting interrupted when it shouldn't.
Looking at the timing diagram, it shouldn't matter that the 43uS ISR interrupts it, anywhere.
Its like the ISR does something to the DQ line.

Ill start changing those GOTO $-X instrutions.
Do you recomend lables NO matter what, or is say GOTO $-1 ok

full program: DS18B20 Digital Temperature Sensor.asm
 
A couple suggestions, if I may?

(1) You're not really using "request sense" capability in your program so why not trim the reset routine to something like the one I suggested long ago. Basically put out a '0' for 500-usecs, release the DQ line, then delay the last 500-usecs.

(2) Have you counted how many stack levels you're using? The routines Pommie and I came up with don't use "calls" to routines to set the OneWire pin hi or lo. The Maxim/Dallas examples don't use "calls" either. There may be a good reason for this (like only 4 stack levels available on 16F' devices).

Regards, Mike
 
Mike I'll try anyhing.

Regarding number 1.
I am currently running this:
Code:
DS18B20_RESET  ; This routine Resets the DS18B20
        CALL    DQ_LL                   ; Force the DQ Line to Logic Low
        MOVLW   (D'500'-5)/5            ; Reset pulse must be held a minimum of 480uS
        CALL    DELAY                   ; 
        CALL    DQ_HIZ                  ; Release DQ Line
        MOVLW   (D'500'-5)/5             ; Wait for recovery
        CALL    DELAY                   ; 
        RETURN                          ;
It seems to be working alright.
But I wanted to use this program as a base, and expand it. To add another sensor and use more of the DS18B20's commands.

and regarding number 2.
Im pretty sure th 16F628A im using has an 8 level deep stack.
"All PIC® microcontrollers employ an advanced RISC architecture. The PIC16F627A/628A/648A have enhanced core features, an eight-level deep stack, and multiple internal and .........." (taken from the data sheet)

...But the most I counted was 4.

Well its been a few minutes, and the above reset routine seems to have not stuffed it.
which makes me even more confused as to why this wont work:
Code:
DS18B20_RESET  ; This routine Resets the DS18B20
    ;    BCF     INTCON, GIE             ; Disable Global Interrupts
        CALL    DQ_LL                   ; Force the DQ Line to Logic Low
        MOVLW   (D'480'-5)/5            ; Reset pulse must be held a minimum of 480uS
        CALL    DELAY                   ; 
        CALL    DQ_HIZ                  ; Release DQ Line
        MOVLW   (D'60'-5)/5             ; Wait for recovery
        CALL    DELAY                   ; 
        BTFSC   PORTA, 4                ; Test for 'Presence Pulse'
        GOTO    DS18B20_RESET           ; If not present, Reset
    ;    BSF     INTCON, GIE             ; Enable Global Interrupts
        MOVLW   (D'420'-5)/5            ; Must wait a minmum of 480uS from when DQ line is released before moving on
        CALL    DELAY                   ; 
        RETURN                          ;
 
Sorry, I meant 8 stacks...

Can you describe "just froze"?

I can't find the old 4-digit DS18B20 software. Sorry. It was long ago and used a 16F648A on a solderless breadboard with Charlieplexed displays. I ran it for a couple weeks and dismantled it.

I've still got the example I wrote for your other thread. Is that the one you wanted? It's untested...
 
Last edited:
Pictures tell more than words....

Works fine for a few mintues...
p1000477-jpg.47207
Then...
p1000478-jpg.47208

And its not always the right most digit.. Its any one of the 4. It like the interrupt stops getting triggered.
That or the program goes into a undesired loop.
 

Attachments

  • P1000477.JPG
    P1000477.JPG
    155.9 KB · Views: 3,405
  • P1000478.JPG
    P1000478.JPG
    151.1 KB · Views: 3,333
I think I've found your problem.
Code:
		movf	F_ISR,W		; MOVE F_ISR to W
		movwf	FSR		; Restore FSR
		movf	P_ISR,W		; MOVE P_ISR to W
		movwf	PCLATH		; Restore PCLATH
		swapf	S_ISR,W		; Undo previous SWAPF, place result in W
		movwf	STATUS		; Restore STATUS
		swapf	W_ISR,F		; Use SWAPF instruction so status bits don't change
		swapf	W_ISR,W		; Undo previous SWAPF and restore W register
[COLOR="black"][COLOR="red"]		bcf	PIR1,TMR2IF	; Clear TMR2 interrupt flag        [/COLOR][/COLOR]
		bsf	FLAGS,0		; Set ISR Complete Flag to indicate ISR has just been executed
		retfie			; Return From Interrupt
When you switch to bank 1 to change the tris the bcf PIR1,TMR2IF will clear the PIE1 register instead of the PIR1 register.

Change it to,
Code:
[COLOR="red"]		bcf	PIR1,TMR2IF	; Clear TMR2 interrupt flag        [/COLOR]
		movf	F_ISR,W		; MOVE F_ISR to W
		movwf	FSR		; Restore FSR
		movf	P_ISR,W		; MOVE P_ISR to W
		movwf	PCLATH		; Restore PCLATH
		swapf	S_ISR,W		; Undo previous SWAPF, place result in W
		movwf	STATUS		; Restore STATUS
		swapf	W_ISR,F		; Use SWAPF instruction so status bits don't change
		swapf	W_ISR,W		; Undo previous SWAPF and restore W register
		retfie			; Return From Interrupt
And all will be well.:D

Mike.
 
Last edited:
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top