Even voorstellen, mijn naam is Jurgen en als ik wat tijd kan vinden speel ik wat met microcontrollers en lees ik wat mee op CO :-).
Nu zou ik een thermometer willen maken met een DS18B20, een PIC16F690 en 3 7-segment displays.
ASM code is geschreven, maar wat blijkt, ik kan er langs geen kanten een correcte temperatuur opkrijgen. De data dat ik uitlees springt van 18°C naar 151°C naar 20°C,... Ik zit al meer dan een week vanalles te proberen en heb ik al 10 keer de datasheet van voor naar achter gelezen, maar ik kan het maar niet vinden. Voor zover ik kan zien zit ik juist met de timing, de pic draait op de 8Mc interne klok (deze heb ik ook nagezien met een blokgolf op de scoop)

Kan er iemand met een frisse geest eens de code nalezen of die iets kan vinden?

PS, de sensor is met een pull-up van 4K7 op PORTA,5 aangesloten en heeft geen parasitaire voeding.
De code was iets te groot om hier te posten, maar je kan ze hier downloaden : http://users.telenet.be/saskia-jurgen/CO/test2.asm

Alvast bedankt!

Even een gedachte spinsel van mijn kant. Zit het niet in de aansturing van de diplays perongeluk? Als je (ruwe) data eens doorstuurd via de uart naar je PC. Dan weet iig of je de communicatie met DS1820 goed gaat.

Nee, ik denk het niet, want als ik de variabelen zelf invul komt dit wel correct op het display.
Ik kan trouwens niet meer aan de uart, die pinnen zijn al bezet...

Zo te zien maak je de DS18 pin nergens laag bij output. Dat moet natuurlijk wel, anders is de status onbepaald. (Hangt af van of de input op dat moment toevallig hoog of laag is...)
Na een BCF TRISDS18 moet je een BCF DS18 geven...

Arco, ik had goede hoop dat dit inderdaad het probleem was, maar ik krijg nog steeds dezelfde vreemde waardes... ;(
Nog een idee? Ik ben er zeker van dat het iets simpel is waar ik steeds maar over kijk...

@kombucha De pull up gaat inderdaad naar de plus.

Nieuwe versie met de tip van Arco staat online op dezelfde locatie.

Mischien nog een aanvulling, als ik gewoon het scratchpad uitlees krijg ik wel mooi 85 terug, dus dat gedeelte zou moeten werken...
Wat het natuurlijk nog vreemder maakt...

Ik heb helaas geen 18B20, anders kon ik het uitproberen. (Heb alleen een 18S20)

Nog een update, heb net een nieuwe sensor gehaald, en probleem blijft bestaan...
Nog iets waar het niet aan ligt denk ik dan maar...

Even een kickje, mischien zien jullie er wat meer in als ik enkel de routines verantwoordelijk voor de communicatie hier post?

Eerst de hoofdlus :


main

	banksel	INTCON				
	bcf 	INTCON,T0IE			;Interupts negeren
	bcf 	STATUS,RP0
	call	ClearDigit
	call	GetTemp				;Haal temperatuur op van DS18
	call	Cond_Data			;Verwerk 2 bytes naar 3 getallen BCD
	banksel	INTCON				;Interupts terug toelaten
	bsf 	INTCON,T0IE
	bcf 	STATUS,RP0	
	call	Delay1s				;2Seconden wachten
	call	Delay1s	
	
	goto	main				;Terug naar begin

Dan de hoofdroutine die voor de communicatie :


GetTemp	

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;		goto	DEBUG		  ;Spring direct naar scratchpad lezen (85 terug)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

		call	DS_Reset				;Reset DS18		

		bcf 	STATUS,RP0
		movlw	0xCC					;Skip ROM 
		movwf	DS_Data_L			
		call	DS_Out					;0xCC naar DS18
		movlw	0x44					;Convert T
		movwf	DS_Data_L
		call	DS_Out					;0x44 naar DS18
		banksel	TRISA
		bsf 	TRISDS18				;DQ hoog
		bcf 	STATUS,RP0
		call	Wait_Temp				;Wacht tot temperatuur 
		btfss	DS_Data_L,0				;conversie klaar is
		goto	$-2
DEBUG
		call	DS_Reset				;Reset DS18
		movlw	0xCC					;Skip ROM
		movwf	DS_Data_L
		call	DS_Out					;0xCC naar DS18
		movlw	0xBE					;Read Scratchpad
		movwf	DS_Data_L
		call	DS_Out					;0xBE naar DS18
		call	DS_IN					;Haal data op van DS18
		banksel	TRISA
		bsf 	TRISDS18				;DQ hoog
		bcf 	STATUS,RP0
		RETURN

Deze reset de DS18


DS_Reset
		banksel	TRISA
		bcf 	TRISDS18				;DQ laag voor 500µS
		banksel	PORTA
		bcf 	DS18
		movlw	d'100'					;Delay500µs
		movwf	d1
		call	Delay
		decfsz	d1
		goto	$-2
		banksel	TRISA
		bsf 	TRISDS18				;DQ hoog
		bcf 	STATUS,RP0
		movlw	d'20'					;Delay100µs
		movwf	d1
		call	Delay
		decfsz	d1
		goto	$-2
		banksel	PORTA				
		btfss	DS18					;Test op presence puls na 100µS, 
		goto	$-1					;en wacht daarna nog 400µS
		movlw	d'80'					;Delay400µs
		movwf	d1
		call	Delay
		decfsz	d1
		goto	$-2
		bcf 	STATUS,RP0
		RETURN

Deze wacht tot de sensor klaar is met de temperatuur conversie (ja ik kan gewoon 750mS wachten maar deze routine is een spinsel uit het foutzoeken)


Wait_Temp
		
		bcf 	STATUS,RP0				
		clrf	DS_Data_L				;Clear DS_Data_L
		banksel	TRISA
		bcf 	TRISDS18				;DQ laag voor 4µS
		banksel	PORTA
		bcf 	DS18
		call	Delay
		bsf 	TRISDS18				;DQ terug hoog
		call	Delay					
		call	Delay					
		banksel	PORTA
		btfsc	DS18					;Controleer na 8µS als DQ laag is
								;(temp conversie klaar)
		bsf 	DS_Data_L,0				;Zet een vlag
		movlw	d'12'					;Delay60µs
		movwf	d1
		call	Delay					;Wacht nog 60µS tot einde Read time slot
		decfsz	d1
		goto	$-2
		RETURN

Deze verstuurt een byte naar de sensor


DS_Out
		movlw	0x08					;8 bits versturen
		movwf	Teller1
DS_Out_1
		btfsc	DS_Data_L,0				;Test als de bit die klaarstaat 0 of 1 is
		goto	$+3
		call	DS_Out_LO				;Bij 0, spring naar DS_Out_LO
		goto	$+2
		call	DS_Out_HI				;Bij 1, spring naar DS_Out_HI
		rrf 	DS_Data_L,f
		decfsz	Teller1,f				;decrease teller, bij teller=0 spring verder
		goto	DS_Out_1			
		banksel	TRISA
		bsf 	TRISDS18				;DQ terug hoog
		bcf 	STATUS,RP0
		RETURN

DS_Out_LO
		banksel	TRISA
		bcf 	TRISDS18				;DQ laag voor 70µS
		banksel	PORTA
		bcf 	DS18
		movlw	d'14'					;Delay70µs
		movwf	d1
		call	Delay
		decfsz	d1
		goto	$-2
		banksel	TRISA
		bsf 	TRISDS18				;DQ terug hoog, en wacht nog 4µS				
		call	Delay					;Delay4µs
		bcf 	STATUS,RP0
		RETURN

DS_Out_HI
		
		banksel	TRISA
		bcf 	TRISDS18
		banksel	PORTA
		bcf 	DS18					;DQ laag voor 8µS
		call	Delay					;Delay8µs
		call	Delay
		banksel	TRISA
		bsf 	TRISDS18				;DQ terug hoog, en wacht nog 60µS 
		bcf 	STATUS,RP0				;tot einde write slot
		movlw	d'12'					;Delay60µs
		movwf	d1
		call	Delay
		decfsz	d1
		goto	$-2
		bcf 	STATUS,RP0
		RETURN

Deze ontvangt 2 bytes van de sensor


DS_IN
		bcf 	STATUS,RP0			
		clrf	DS_Data_L				;Wis variabelen
		clrf	DS_Data_H
		movlw	d'16'					;16 bits inlezen
		movwf	Teller1
		
DS_IN_1
		bcf 	STATUS,C				
		rrf 	DS_Data_L,f				;Roteer Data_L naar rechts
		bcf 	STATUS,C
		rrf 	DS_Data_H,f				;Roteer Data_H naar rechts
		btfsc	STATUS,C				;Bij carry, zet bit bij Data_L
		bsf 	DS_Data_L,7
		banksel	TRISA
		bcf 	TRISDS18				;DQ laag voor 4µS
		banksel	PORTA
		bcf 	DS18
		call	Delay					;Delay4µs
		banksel	TRISA
		bsf 	TRISDS18				;DQ terug hoog
		call	Delay					;Delay8µs
		call	Delay
		banksel	PORTA	
		btfsc	DS18					;Test na 8µS of er een bit klaarstaat
		bsf 	DS_Data_H,7				;Bij 1, zet bij Data_H, en wacht nog 
								;60µS tot einde Read slot
		movlw	d'12'					;Delay60µs
		movwf	d1
		call	Delay
		decfsz	d1
		goto	$-2
		decfsz	Teller1					;Decrease Teller, bij 0 spring verder
		goto	DS_IN_1
		call	DS_Reset				;Na 2 bytes gelezen, afbreken door Reset
		RETURN

Deze zet de ontvangen data om in 3 bytes BCD, de tienden worden momenteel gebruikt om hondertallen te tellen.


Cond_Data
		
		bcf 	STATUS,RP0	
		clrf	Tientallen				;Variabelen resetten
		clrf	Eenheden
		clrf	Tienden
		
		swapf	DS_Data_L				;Nibbles van Data_L omwisselen
		btfsc	DS_Data_H,0				;Relevante bits van Data_H verplaatsen
		bsf 	DS_Data_L,4
		btfsc	DS_Data_H,1
		bsf 	DS_Data_L,5
		btfsc	DS_Data_H,2
		bsf 	DS_Data_L,6
		bcf 	DS_Data_L,7
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Test op hondertallen;;;;;;;;;DEBUG;;;;;;;;;;;;;;;;;;;;;;
		movlw	d'100'					
		subwf	DS_Data_L,f				;Zet de hondertallen in tienden
		btfss	STATUS,C
		goto	$+3
		incf	Tienden
		goto	$-4
		addwf	DS_Data_L,f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;	
		movlw	d'10'					;Tientallen Tellen
		subwf	DS_Data_L,f
		btfss	STATUS,C
		goto	$+3
		incf	Tientallen
		goto	$-4
		addwf	DS_Data_L,f
		movlw	d'1'					;Eenheden Tellen
		subwf	DS_Data_L,f
		btfss	STATUS,C
		goto	$+3
		incf	Eenheden
		goto	$-4
		movlw	d'10'					;Test op meer dan 9 in variabelen	
		subwf	Tientallen,w				;bij meer dan 9 zet E op display
		btfss	STATUS,C
		goto	$+3
		movlw	d'10'
		movwf	Tientallen
		movlw	d'10'
		subwf	Eenheden,w
		btfss	STATUS,C
		goto	$+3
		movlw	d'10'
		movwf	Eenheden
		movlw	d'10'
		subwf	Tienden,w
		btfss	STATUS,C
		goto	$+3
		movlw	d'10'
		movwf	Tienden
		bcf 	STATUS,RP0		

		RETURN

Het zal wel iets onnozels zijn waar ik blijf over kijken, maar ik hoop er op dat er iemand me op mijn fout kan wijzen. (Ik zal hem eeuwig dankbaar zijn :-) )

Als je de interrupt routine uit de startpost gebruikt, moet je wel de w_temp en status_temp in shared memory zetten en niet in bank 0.
Gebruik bij jumps ook eens labels in je code; dan is het tenminste enigszins begrijpelijk.
(Op gebruik van het '$+' en '$-' directive zou eigenlijk straf moeten staan. Je krijgt er onvermijdelijk fouten door, en is zeer onoverzichtelijk...)

bij een vaste voeding hoef
je volgens mij niet op de presence puls te wachten
en kun je dat gewoon schrappen.
( bij mij ging het spul in een loop lopen )

ik denk overigens niet dat het invloed heeft op jou probleem
maar je weet nooit
sk

@Arco Ik w-temp & status_temp op 0x70 & 0x71 geplaatst (shared memory als ik de datasheet juist interpreteer) en heb nog steeds hetzelfde effect |:-(
Ivm met de labels, ik dacht dat dit de gebruikelijke manier was om over en weer te springen, omdat er anders een warboel aan labels ontstaat... Moet ik mijn code eens aanpassen ter betere lezing...?

@Burner Wat bedoel je met 'bij mij ging het spul in een loop lopen'? Wacht je gewoon een tijdje na het resetten om verder te gaan met de communicatie?

Ivm met de labels, ik dacht dat dit de gebruikelijke manier was om over en weer te springen, omdat er anders een warboel aan labels ontstaat...

Nee, het is nu juist een warboel. Als er staat 'goto $-5' moet je eerst gaan rekenen, terwijl 'goto mijn_label' meteen duidelijk is. Zeker als je je code na een jaar of zo terug ziet om iets aan te wijzigen, heb je alleen al een halve dag nodig om te begrijpen wat er precies allemaal gebeurt...

Helemaal in de problemen kom je als je een extra instructie toevoegt, en vergeet de sprong aan te passen. Dat is meestal goed voor een paar uurtjes genoeglijk zoeken naar de oorzaak van het ineens niet meer werken...

@Burner Wat bedoel je met 'bij mij ging het spul in een loop lopen'? Wacht je gewoon een tijdje na het resetten om verder te gaan met de communicatie?

het bleef maar wachten op een presence puls, die maar niet kwam..

het bleef maar wachten op een presence puls, die maar niet kwam..

Nooit eindeloze loops gebruiken, altijd een time-out inbouwen...

Eindelijk nog eens tijd gevonden om wat met de hobby bezig te zijn, en :
Probleem gevonden!

Heb de boel eens op een breadboard gemaakt met een andere PIC, die ik kon debuggen met mijn elektuur ICD2 kloon, en de fout kwam al na 2 minuten bovendrijven!

Het probleem zat hem hier :


Cond_Data
		
		bcf 	STATUS,RP0	
		clrf	Tientallen				;Variabelen resetten
		clrf	Eenheden
		clrf	Tienden
		
		swapf	DS_Data_L				;Nibbles van Data_L omwisselen
		btfsc	DS_Data_H,0				;Relevante bits van Data_H verplaatsen
		bsf 	DS_Data_L,4
		btfsc	DS_Data_H,1
		bsf 	DS_Data_L,5
		btfsc	DS_Data_H,2
		bsf 	DS_Data_L,6
		bcf 	DS_Data_L,7

............

Ik had bij mijn eerste test van de communicatie de bits van de getallen na de komma genegeerd, met het idee 'dat komt straks wel, eerst de gehele getallen', met als gevolg dat na het wisselen van de nibbles van de low byte ik had vergeten de bits van de tienden te wissen, en zodoende een volledig verkeerde waarde op het display kreeg! |:-(

Zoals bij mijn eerste vermoeden dus een stomme fout waar ik maar bleef overkijken!
Positief punt is wel dat de code verantwoordelijk voor de communicatie wel blijkbaar direct juist was!

Toch bedankt aan diegenen die wat tijd in mijn geklooi hebben gestopt!