PDA

View Full Version : Trouble with LCD 2x8 and sequential display of values



fratello
- 17th February 2012, 18:41
Hello !
I try to build one volt/termometer with 16F684 and 2x8 characters display. I wrote the code, all works ...fine, the "IN" temperature is shown for 8 seconds, the "OUT" temperature for next 8 seconds, and so on, and so on (the voltage is on second line permanent)....
BUT : sometimes, the value of temperature "jump" to "0.0 'C", especially when the temperature decreases ?! I really don't understand why :( . I made many changes in "pause", in "Define LCD_COMMANDUS 2000" and "Define LCD_DATAUS 50" , I added/removed " WaitLoop1: While not DQ1 : Wend" , but without results...
Any clue ? Thanks in advance !
This is "the big part" of my code :

Main :
Gosub Get_Vbatt ' make a new measure
TmpW = Vbatt * Vfs ' AD * 20480
TmpW = Div32 1024 '(AD * 20480) / 1024
Gosub char_batt
LcdOut $FE, $c0, symb ," ", dec TmpW dig 4,dec TmpW dig 3,",",dec TmpW dig 2, " V"

Gosub StartTimer
While seconds =< 8
Part1:
' Start temp.conv.Sensor1
OWOut DQ1, 1, [$CC, $44]
OWOut DQ1, 1, [$CC, $BE]
OWIn DQ1, 2, [temperature1.byte0, temperature1.byte1]

If Temperature1.15 then
Temperature1= ~Temperature1 +1
Twist1 = 1
Endif

Dummy1 = 625 * Temperature1
TempC1 = DIV32 10
TempC1 = (Temperature1 & $7FF) >> 4
Float1 = ((Temperature1.Lowbyte & $0F ) * 25 )>>2
Temperature1 = TempC1*100 + Float1

If Twist1 then
V1= 10000 - Temperature1
Twist1 = 0
else
V1= 10000 + Temperature1
EndIf

If V1 >= 10000 then
Temperature1=V1-10000
else
Temperature1=10000-V1
EndIf

GoSub SelectSign
If (temperature1/100) =>10 then
LcdOut $FE, $80, "I:", Sign1, DEC (Temperature1 / 100), ".", DEC Temperature1 dig 1, 0
else
LcdOut $FE, $80, "I:", Sign1, $14, DEC (Temperature1 / 100), ".", DEC Temperature1 dig 1, 0
Endif
Pause 500
Wend
'================================================= ================================================== ================
While seconds >= 9 and seconds =< 17
Part2 :
' Start temp.conv.Sensor1
OWOut DQ2, 1, [$CC, $44]
OWOut DQ2, 1, [$CC, $BE]
OWIn DQ2, 2, [temperature2.byte0, temperature2.byte1]

If Temperature2.15 then
Temperature2= ~Temperature2 +1
Twist2 = 1
Endif

Dummy2 = 625 * Temperature2
TempC2 = DIV32 10
TempC2 = (Temperature2 & $7FF) >> 4
Float2 = ((Temperature2.Lowbyte & $0F ) * 25 )>>2
Temperature2 = TempC2*100 + Float2

If Twist2 then
V2= 10000 - Temperature2
Twist2 = 0
else
V2= 10000 + Temperature2
EndIf

If V2 >= 10000 then
Temperature2=V2-10000
else
Temperature2=10000-V2
EndIf

GoSub SelectSign
If (temperature2/100) =>10 then
LcdOut $FE, $80, "O:", Sign2, DEC (Temperature2 / 100), ".", DEC Temperature2 dig 1, 0
else
LcdOut $FE, $80, "O:", Sign2, $14, DEC (Temperature2 / 100), ".", DEC Temperature2 dig 1, 0
Endif
Pause 500
Wend
Gosub ResetTime
Goto Main

I have in code "include elapsed.bas" of course...The internal osc is set to 4 MHz.

fratello
- 18th February 2012, 06:28
Even in Proteus I see this trouble, if "Out" temperature decreases verry fast ...
(Just remove final extension of files)

fratello
- 19th February 2012, 12:50
...or another way to display sequential values of temperature(s), while - on second line- display the voltage ?!
Have someone another ideea ? Thanks !

Darrel Taylor
- 19th February 2012, 19:02
... BUT : sometimes, the value of temperature "jump" to "0.0 'C", ...
I have in code "include elapsed.bas" ...

1-Wire and interrupts don't get along very well together.
1-Wire has some pretty strict timing requirements, and interrupts like to mess that up.

You can get good readings, but you have to plan on bad data occasionally.
Which means verifying the CRC, and checking for all 0's in the packet. The CRC will pass (incorrectly) with all 0's
You can use the CRC routines from Tom Estes ... http://www.picbasic.co.uk/forum/showthread.php?t=1672
If the CRC fails, just go back and read the temperature again, no need to do another conversion.

That of course means you need to read the sensor as a Packet, instead of individual variables.

You also need to wait for the conversion to complete, either by PAUSE'ING the required amount of time, or polling the busy bit.
Currently, you are not waiting at all after a conversion command.

fratello
- 19th February 2012, 19:24
Thank You for support !
...it's another way to do this ?
I don't think I have enough space for adding something like CRC routines in my code (using 16F684)...

ScaleRobotics
- 19th February 2012, 19:44
How about just throw away values that are outside of expected ranges? Like take a running average, and if the temp is way off, disregard it. That way, it can still be 0 deg C, but only if its close to the average temp.

fratello
- 20th February 2012, 06:37
Thank you all for support !
Since the "timming" it's not so important , I made this change :


' Start temp.conv.Sensor1
OWOut DQ1, 1, [$CC, $44]
OWOut DQ1, 1, [$CC, $BE]
OWIn DQ1, 2, [temperature1.byte0, temperature1.byte1]
Pause 800 ; because DS18B20 need 750 ms for conversion
If Temperature1.15 then
Temperature1= ~Temperature1 +1
Twist1 = 1
Endif
...

...and the display works fine now...despite the decrease of speed in display the changes of temperatures.

fratello
- 20th February 2012, 15:59
I rushed... still have, from time to time, "0.0 'c" on display, ONLY for sensor on DQ2 (out sensor) .... :( ....

gadelhas
- 20th February 2012, 16:02
I rushed... still have, from time to time, "0.0 'c" on display, ONLY for sensor on DQ2 (out sensor) .... :( ....
Why not you poll the busy bit, instead of the Pause 800 statment?

I don't know your application, but you can also disable interrupts before the 1-wire stuff, and then enable them again.

fratello
- 20th February 2012, 16:07
I don't know your application, but you can also disable interrupts before the 1-wire stuff, and then enable them again.
Thanks for help ! How can I make this ? The most part of code it's in post #1...

gadelhas
- 20th February 2012, 16:51
Thanks for help ! How can I make this ? The most part of code it's in post #1...

Can you put the code of your interrupts stuff, because i don't see it in the code of the post #1

fratello
- 20th February 2012, 18:06
I use just :
"Include "Elapsed.bas"" ; for counting seconds
without other interrupts...

gadelhas
- 20th February 2012, 19:10
I use just :
"Include "Elapsed.bas"" ; for counting seconds
without other interrupts...

I believe that Elapsed.bas uses Timer 1, maybe Darrel can correct me, if so, do this



@ INT_DISABLE TMR1_INT

'1 wire stuff

@ INT_ENABLE TMR1_INT


Probabily the acurracy of the elapsed.bas would be affected.

fratello
- 20th February 2012, 19:33
I think I made some mistakes ... :( ...

gadelhas
- 20th February 2012, 20:13
Can you attache the files? ( your code and elapsed.bas)

fratello
- 21st February 2012, 09:26
The code is in post #1 ; this is the "header" :

@ DEVICE PIC16F684, INTRC_OSC_NOCLKOUT, WDT_OFF, PWRT_ON, BOD_OFF, MCLR_ON, PROTECT_ON

DEFINE OSC 4

TRISA= %00010000
TRISC= %00110000

CMCON0 = %00000111 ' Disable analog comparators.
VRCON = %00000000 ' Disable Comparator Voltage Reference
ANSEL = %00010000 ' Set pin (AN2) to analog input, the rest to digital
ADCON0 = %10001101 ' Set up A/D converter - Right Just., VDD REF., CH 3, ON
ADCON1 = %00110000 ' Set up A/D Converter clock source to internal RC

DEFINE ADC_BITS 10
DEFINE ADC_CLOCK 3
DEFINE ADC_SAMPLEUS 50

DEFINE LCD_DREG PORTC ' LCD on port c
DEFINE LCD_DBIT 0 ' Data bits C0..C3
DEFINE LCD_RSREG PORTA ' RS on PORTA
DEFINE LCD_RSBIT 1 ' RS on A1
DEFINE LCD_EREG PORTA ' E on PORTA
DEFINE LCD_EBIT 2 ' E on A2
DEFINE LCD_BITS 4 ' LCD 4 bit mode
DEFINE LCD_LINES 2 ' 2 line LCD display
Define LCD_COMMANDUS 2000 ' Command Delay (uS)
Define LCD_DATAUS 50 ' Data Delay (uS)

Temperature1 Var Word
Temperature2 Var Word
TempC1 Var Word
TempC2 Var Word
Float1 Var Word
Float2 Var Word
Sign1 Var Byte
Sign2 Var Byte
DQ1 Var PORTC.5 ' OUT SENSOR
DQ2 Var PORTC.4 ' IN SENSOR


Twist1 Var Bit
Dummy1 Var Byte
V1 Var Word
Twist2 Var Bit
Dummy2 Var Byte
V2 Var Word
symb Var Byte

Vfs con 20480 ' 20,480v
K16 con 61441 ' coefficiente filtro 15/16
Vbatt Var Word ' Vbatt filtrato
TmpW Var Word
Acc_Vbatt Var Word ' accumulatore Vbatt filtrato * 16
batt Var Word

DS18B20_1_12bit CON %01111111 ' 750ms, 0.0625°C (default)
DS18B20_2_12bit CON %01111111 ' 750ms, 0.0625°C (default)

LCDOUT 254,64,4,10,4,0,0,0,0,0 ' Cust Char #0 ; http://www.darreltaylor.com/files/CustChar.htm
LCDOUT 254,72,10,31,17,17,17,17,31,0 ' Cust Char #1
LCDOUT 254,80,10,31,17,17,17,31,31,0 ' Cust Char #2
LCDOUT 254,88,10,31,17,17,31,31,31,0 ' Cust Char #3
LCDOUT 254,96,10,31,17,31,31,31,31,0 ' Cust Char #4
LCDOUT 254,104,10,31,31,31,31,31,31,0 ' Cust Char #5
LCDOUT 254,112,15,3,5,9,16,16,16,0 ' Cust Char #6
LCDOUT 254,120,1,1,1,18,20,24,30,0 ' Cust Char #7

include "Elapsed.bas"

Twist1 = 0
Twist2 = 0

Pause 5000
LcdOut $FE, $80," TERMO "
LcdOut $FE, $C0," VOLT "
PAUSE 3000
LCDOUT $FE, 1, $FE, $0C ' Clear display, cursor off
Pause 200

;Init Sensor 1
OWOUT DQ1, 1, [$CC, $4E, 0, 0, DS18B20_1_12bit]
OWOut DQ1, 1, [$CC, $48] ' Start temperature conversion
OWOut DQ1, 1, [$CC, $B8]
OWOut DQ1, 1, [$CC, $BE]
Pause 50
OWIn DQ1, 2, [temperature1.byte0, temperature1.byte1]
Pause 50
;Init Sensor 2
OWOUT DQ2, 1, [$CC, $4E, 0, 0, DS18B20_2_12bit]
OWOut DQ2, 1, [$CC, $48] ' Start temperature conversion
OWOut DQ2, 1, [$CC, $B8]
OWOut DQ2, 1, [$CC, $BE]
Pause 50
OWIn DQ2, 2, [temperature2.byte0, temperature2.byte1]
Pause 50

More about "Elapsed.bas" (credits to Mr.Darrel !) here : http://www.picbasic.co.uk/forum/showthread.php?t=3251&p=17473#post17473
Thanks again for support !

gadelhas
- 21st February 2012, 21:54
I copied your code, and i can not see that error, however, instead of the;



@ INT_DISABLE TMR1_INT

'1 wire stuff

@ INT_ENABLE TMR1_INT


try this;



T1CON.0 = 0 ; Turn OFF Timer1

'1 wire stuff

T1CON.0 = 1 ; Turn ON Timer1

fratello
- 22nd February 2012, 06:59
I tried this way, but...the timer stop counting (so, I can't display 5 sec. IN and 5 sec. OUT) and the reading of sensor(s) it's not continous....like in my "original" code :( ...
I want to read permanent the sensors (for sensing the variation of temperatures) and display the temperature, 5 seconds from first sensor, the next 5 seconds from second sensor, so on, so on ....
Otherwise I can write the code like this :
" display temperature 1
pause 5000
display temperature 2
pause 5000
goto loop "
which is not a good option ...

Darrel Taylor
- 22nd February 2012, 21:03
fratello,

Try this hex file.
It uses elapsed.bas, adds CRC checking and error correction, while only using 1375 WORDs.
Yours was 1871 WORDs, so it also saves ~500 WORDs (~1/4 of total memory.)

It should run on your .dsn, but the voltage will be off because I changed the circuit a little.

http://support.melabs.com/DT/DT18x20_Fratello.jpg

I didn't have your code, so the battery icon is different.

fratello
- 23rd February 2012, 06:30
Thank You so much ! I will try soon Your hardware ... I must (re) build the PCB.
In Proteus I have some messages ... It's something wrong ?
...and the temperature on display don't follow the variation of sensor(s)-the new temperature is on display NEXT time when the temperature is show !

Darrel Taylor
- 23rd February 2012, 16:29
Oh, OK.
I din't see that your's kept up with changes during each period.
I will fix that.

I wasn't seeing the ADC clock error, but I'll take a look.

fratello
- 23rd February 2012, 20:00
Thank You again for helping me !
The code for batterie is this :

LCDOUT 254,64,4,10,4,0,0,0,0,0 ' Cust Char #0 ; http://www.darreltaylor.com/files/CustChar.htm
LCDOUT 254,72,10,31,17,17,17,17,31,0 ' Cust Char #1
LCDOUT 254,80,10,31,17,17,17,31,31,0 ' Cust Char #2
LCDOUT 254,88,10,31,17,17,31,31,31,0 ' Cust Char #3
LCDOUT 254,96,10,31,17,31,31,31,31,0 ' Cust Char #4
LCDOUT 254,104,10,31,31,31,31,31,31,0 ' Cust Char #5
LCDOUT 254,112,15,3,5,9,16,16,16,0 ' Cust Char #6
LCDOUT 254,120,1,1,1,18,20,24,30,0 ' Cust Char #7

...post #16.

Darrel Taylor
- 24th February 2012, 07:47
Sorry, sometimes I get carried away ... :D


'************************************************* **************************
'* Name : DT18x20_Fratello.pbp
'* Author : Darrel Taylor
'* Date : 2/19/2012
'* Version : 1.1 (2/24/2012)
'* Target : 16F684 @ 4 mhz
'************************************************* **************************

DEFINE OSC 4
CLEAR
;----[Main Options]---------------------------------------------------------
TimeToShow CON 5 ; Seconds to show each temperature

;----[Battery Options]------------------------------------------------------
Res1 CON 20000 ; Top Resistor of Voltage Divider
Res2 CON 10000 ; Bottom Resistor of Divider
VDD CON 50 ; VDD voltage
MaxBat CON 140 ; 14.0V ; Batt indicator Max
MinBat CON 98 ; 9.8V ; Batt indicator Min

;----[DS1820 Options]----Value----Default-----------------------------------
DEFINE DS1820_DECIMALS 1 ; 1
DEFINE DS18B20_ONLY YES ; NO
DEFINE DS1820_VERIFYCRC YES ; NO
DEFINE DS1820_USETIMEOUT NO ; YES
MaxRetries CON 4
INCLUDE "DT18x20.pbp" ; Include DT18x20 module
; --- To get the include file, Register at http://darreltaylor.com/whatsup/

Inside VAR PORTC.5 ; Pin assigned to Inside Sensor
Outside VAR PORTC.4 ; Pin assigned to Outside Sensor

;----[Elapsed Timer]--------------------------------------------------------
INCLUDE "Elapsed.bas"
; --- To get the include file ... Go to ...
; --- http://www.pbpgroup.com/modules/wfsection/article.php?article
GOSUB ResetTime

;----[LCD definitions]------------------------------------------------------
DEFINE LCD_DREG PORTC ; LCD Data port
DEFINE LCD_DBIT 0 ; starting Data bit (0 or 4)
DEFINE LCD_EREG PORTA ; LCD Enable port
DEFINE LCD_EBIT 2 ; Enable bit
DEFINE LCD_RSREG PORTA ; LCD Register Select port
DEFINE LCD_RSBIT 1 ; Register Select bit
DEFINE LCD_BITS 4 ; LCD bus size (4 or 8 bits)
DEFINE LCD_LINES 2 ; number of lines on LCD
DEFINE LCD_COMMANDUS 2000 ; Command delay time in us
DEFINE LCD_DATAUS 50 ; Data delay time in us

;----[Analog options]-------------------------------------------------------
DEFINE ADC_BITS 10
DEFINE ADC_CLOCK 3
ADCON0.7=1 ; Right Justify A/D results

;----[Program Variables]----------------------------------------------------
BattLevel VAR BYTE ; 0 - 10, 0=Empty 10=Full
RawBattery VAR WORD
Volts VAR WORD
LastVolts VAR WORD : LastVolts=0
Sensor VAR BIT : Sensor=1
Char VAR BYTE
y VAR BYTE
Retries VAR BYTE
TempW VAR WORD
GIE VAR INTCON.7

;----[Initialization]-------------------------------------------------------
CMCON0=7 ; disable Comparators
ANSEL=0 ; All Digital
ADCON1=$30 ; ADC_CLOCK is FRC
LCDOUT $FE,1:PAUSE 250:LCDOUT $FE,1 ' Initialize LCD

LCDOUT " TERMO- ",$FE,$C0," VOLT "
GOSUB StartConversions ; get the first reading started
PAUSE 4000

GOSUB StartTimer ; Start the Elapsed Timer
Seconds=TimeToShow ; Force 1st display on start-up
SecondsChanged=1

;----[Main Program Loop]----------------------------------------------------
Main:
IF SecondsChanged THEN
SecondsChanged=0
IF Seconds !=0 AND Seconds != TimeToShow THEN GOSUB StartConversions
IF Seconds=TimeToShow THEN ; on each period
Seconds=0
Sensor=!Sensor ; Toggle sensors
LCDOUT $FE,$80
IF Sensor=0 THEN
LCDOUT "I: " ; Indicate Inside sensor
ELSE
LCDOUT "O: " ; Indicate Outside sensor
ENDIF
ENDIF
ENDIF
;---------------------------------
IF Sensor=0 THEN
@ DS1820_Select _Inside ; Select Inside DS18x20 pin
ELSE
@ DS1820_Select _Outside ; Select Outside DS18x20 pin
ENDIF
DS1820_Flags=0 ; clear flags before Stat
GIE=0 ; disable interrupts
@ DS1820_Stat ; get sensor status
GIE=1 ; enable interrupts
IF DS1820_Done THEN ; if conversion finished
@ DS1820_Read ; try to read the temp
Retries=0
RetryRead:
IF DS1820_Error=0 THEN ; if there were no errors
GOSUB TempToLCD ; display TempC
ELSE ;--- Error reading Sensor --------
IF Retries < MaxRetries THEN
Retries=Retries + 1
@ DS1820_Read ; try to read it again (no Conv)
GOTO RetryRead
ENDIF
LCDOUT $FE,$82,"Error "
ENDIF
ENDIF
GOSUB ReadVoltage
PAUSE 100
GOTO Main

;----[Start conversion on both sensors]-------------------------------------
StartConversions:
@ DS1820_Select _Inside ; Select Inside DS18x20 pin
@ DS1820_Convert ; start conversion
@ DS1820_Select _Outside ; Select Outside DS18x20 pin
@ DS1820_Convert ; start conversion
RETURN

;----[Display TempC on LCD]-------------------------------------------------
TempToLCD:
TempW=TempC
LCDOUT $FE,$82
IF ABS(TempW)/DS1820_DIG < 10 THEN LCDOUT " "
IF TempW.15 THEN
LCDOUT "-" ; if negative, display minus sign
ELSE
LCDOUT "+"
ENDIF
TempW=ABS(TempW) ; get the positive value
LCDOUT DEC TempW/DS1820_DIG ; Display the Integer portion
LCDOUT "." ; display decimal point
TempW=TempW//DS1820_DIG ; get decimal portion
LCDOUT DEC1 TempW DIG 0
IF ABS(TempC) < 1000 THEN
LCDOUT $DF
ENDIF
RETURN

;----[Read battery voltage]-------------------------------------------------
RT CON Res1 + Res2 ; Total Divider Resistance

ReadVoltage:
ADCIN 3, RawBattery
Volts=RawBattery * Rt
Volts=DIV32 Res2
Volts=Volts * VDD
Volts=DIV32 1023
IF Volts != LastVolts THEN
LastVolts=Volts
LCDOUT $FE,$C1
IF Volts/10 < 10 THEN LCDOUT " "
LCDOUT " ",DEC Volts/10,",",DEC1 Volts Dig 0," V"
IF Volts >= MaxBat THEN
BattLevel=12
ELSE
IF Volts <= MinBat THEN
BattLevel=0
ELSE
BattLevel=(Volts - MinBat +1) * 12 / (MaxBat - MinBat +1)
ENDIF
ENDIF
GOSUB ShowBattery
ENDIF
RETURN

;----[Show Battery Icon 0 - 12, 0=Empty 12=Full]--------------------------
ShowBattery:
lcdout $FE,$C0,1,$FE,$48,$0A,$1F
for y=4 to 1 step -1
if BattLevel >= (y * 3) then
Char=$1F
else
if BattLevel >= (y * 3 - 1) then
Char=$17
else
if BattLevel >= (y * 3 - 2) then
Char=$13
else
Char=$11
endif
endif
endif
lcdout Char
next y
lcdout $1F
return

fratello
- 24th February 2012, 07:59
A GREAT piece of code ! A VERRY GOOD EXAMPLE !!!
As usual, I'm speechless...Thank YOU, Mr. Darrel !
:applause:

fratello
- 24th February 2012, 08:25
Bad post, sorry...
but I can' compile the code : "Cannot open file (Include file "P16F684.inc" not found)" ?!

fratello
- 24th February 2012, 10:35
I am so sorry ... :( ....
What a dumb I am ...
Of course, Mr. Darrel have the answer : http://www.picbasic.co.uk/forum/showthread.php?t=8270&p=52195#post52195
Everything works just fine !

fratello
- 25th February 2012, 08:49
Everything works just fine ! Thanks again, Mr.Darrel !
One last (I hope :) ) request : Can this "lint" be removed ? I try to find another value for "LCDOUT $nn", but without good results ...
Thanks !

Darrel Taylor
- 25th February 2012, 19:34
Two ways ...

1) Add a 0 to the last LCDOUT ...
lcdout $1F,0


2) You can make the battery icon 1 pixel taller ...

ELSE
BattLevel = (Volts - MinBat +1) * 15 / (MaxBat - MinBat +1)
ENDIF
ENDIF
GOSUB ShowBattery
ENDIF
RETURN

;----[Show Battery Icon 0 - 15, 0=Empty 15=Full]--------------------------
ShowBattery:
lcdout $FE,$C0,1,$FE,$48,$0A,$1F
for y = 5 to 1 step -1
if BattLevel >= (y * 3) then
Char = $1F
else
if BattLevel >= (y * 3 - 1) then
Char = $17
else
if BattLevel >= (y * 3 - 2) then
Char = $13
else
Char = $11
endif
endif
endif
lcdout Char
next y
lcdout $1F
return

fratello
- 25th February 2012, 19:49
Just finish to write my own code, based on previous source (see post #1 ), it's good for me ...BUT ...
Of course, Mr.Darrel solution it's BETTER !
I owe with some thousands of e-beer :) ! Thanks again !

fratello
- 27th February 2012, 14:38
This is how my car-dashboard will be (this is beta version :) ) ...
The original is in the last picture.

gadelhas
- 27th February 2012, 14:51
Congratulations! Very good Job!!!