PDA

View Full Version : Serial Comms and Crystals



Scampy
- 23rd March 2015, 14:03
Hi Guys and Gals

Some years ago, with the help of DT and Henrik I worked on a 4 channel thermostat project which I'm now looking at upgrading to incorporate some new sensors and options. One of the problems that I'm still trying to resolve is the serial communications.

I've used PIC Multi Calc to give me the settings and defines for the serial port settings on both cases. I've also written a PC application in Liberty Basic to read and update the settings, but also tried communications by sending the commands via the terminal in MCS.

OK - I'm using an 18F4580 with an OSC val of 48 in both cases. Inserting a 12Mhz crystal in the development board with the USART settings to


'DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
'DEFINE HSER_TXSTA 20h ' Enable transmit, BRGH = 0
'DEFINE HSER_CLROERR 1 ' Clear overflow automatically
'DEFINE HSER_SPBRG 25 ' 115200 Baud @ 48MHz, 0.16%
'SPBRGH = 0
'BAUDCON.3 = 1 ' Enable 16 bit baudrate generator


Compile and load into the PIC and launch the application, which first checks the comm ports available and then scans for a response from the PIC by sending a "C" to the PIC which then responds with "R" and then on confirmation that it found the controller launches the application and sends "R again which instructs the PIC to send the data stream. This works fine when the 12 Mhz crystal is in place. I can also launch the serial monitor in MCS and replicate receiving the data stream.

But as I really wanted to use a 20 Mhz crystal as it make other processes run faster which in a PID thermostat is my preference, I get "no controller found" when the PIC is polled from the application. In the serial monitor it registers connection with the com port (I'm using a USB/ Serial module from Mikroelectronika) but again fails to respond to the manual TX codes. Here's the revised USART settings that the multicalc application gives


DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
DEFINE HSER_SPBRG 25 ' 115200 Baud @ 0.16%
DEFINE HSER_CLROERR 1 ' Clear overflow automatically

RCSTA = $90 ' Enable serial port & continuous receive
TXSTA = $24 ' Enable transmit, BRGH = 1
SPBRG = 25 ' 115200 Baud @ 0.16%


Now I'm assuming that the reason it works with the 12 Mhz xtal is that the 48 OSC value is divisible by 4 to equal the crystal value. Where as using the 20 Mhz xtal, the OSC value is not directly divisible. So I changed the OSC value to 40, recalculated the USART settings for a 40 OSC and tried that, but to no avail.

Any suggestions on how to get this working with a 20 Mhz xtal

HenrikOlsson
- 23rd March 2015, 19:01
Hi,
The fact that you're using a 12MHz x-tal and DEFINE OSC 48 tells me that you're using the PLL in the chip to increase the frequency from 12 to 48MHz. This by itself seems a bit strange since the maximum operating frequency of the 18F4580 is 40MHz so if you really ARE running at 48MHz you're operating the chip outside of it specifications.

Dropping in a 20MHz x-tal instead of the 12MHz means the PIC is trying to run at 80MHz - twice as fast as it's maximum rated speed.

If it really does use a 12MHz x-tal with the PLL enabled - thus running at 48MHz - and it's doing it reliably then that is as fast as you're going to get.

If it's actually running at 12MHz then what you want is to drop in a 10MHz x-tal and enable the PLL. Then you DEFINE OSC 40.

Please remember that DEFINE OSC never ever changes the speed which the PIC runs at. It only informs the compiler what speed YOU intend to run the PIC at.

/Henrik.

Scampy
- 23rd March 2015, 21:06
Cheers Henrik,

10Mhz xtal, OSC set to 40 with HS PPL in the config and it works fine. I thought I was possibly on the right track, but didn't realise that I was in effect overclocking the PIC using the 12 and 20 Mhz crystals.

Now to look for a cheap I2C humidity sensor. The DTH11 that I was playing with uses pause statements which slow the rest of the code down.

Demon
- 23rd March 2015, 22:15
...

Now to look for a cheap I2C humidity sensor. The DTH11 that I was playing with uses pause statements which slow the rest of the code down.

Don't you mean "you" use PAUSE in your code? (I'm not familiar with that sensor)

You could use DT INT instead to generate an interval.

Robert

Scampy
- 23rd March 2015, 23:41
The code does include DT's INT file.

I've found an indepth data sheet which states that each two way communication process should take 4ms, so why it seems that the code runs slow might of been down to the use of the wrong crystals ??

Basically connection is via a single pin. This pin is kept high by pull up resistor. To get data, the PIC needs to make the pin go low for a minimum of 18ms then hight again and waits 20-40us for the response. The sensor then sends a response by taking the pin low for 80us and then back up high for a further 80us and then sends the data, which is a 40bit stream of high pulses with a duration of 20-28us to represent a 0 or 70us for a 1. Each pulse is preceded by a low pulse of 50us, with a final 50us low at the end of the data stream.

I've seen examples using pulseIN command, with pause xxUS to trick the sensor into sending data, but don't know if interrupts could be used here ?

here's the data sheet http://www.micropik.com/PDF/dht11.pdf

richard
- 24th March 2015, 01:57
dht11/dht22
http://www.picbasic.co.uk/forum/showthread.php?t=19800

Charlie
- 24th March 2015, 02:53
You could use an HIH 4030. It outputs a voltage that you read with the ADC - as fast as you like.

Scampy
- 24th March 2015, 10:18
dht11/dht22
http://www.picbasic.co.uk/forum/showthread.php?t=19800

Thanks for the link. It states that it was for a 64mhz clock speed. Any idea what I need to change to make it run at 40 mhz ?

richard
- 24th March 2015, 10:45
this should be close


if ((tmr6 <75)||(tmr6>85))then goto badread
would become

if ((tmr6 <45)||(tmr6>55))then goto badread

and

if ((tmr6>20)&&(tmr6<80)) then ' noise ?
if (tmr6 >50 ) then

would become


if ((tmr6>12)&&(tmr6<50 then ' noise ?
if (tmr6 >31 ) then

Scampy
- 24th March 2015, 12:41
Richard, thanks for the suggestions.

I'm in the process of editing the code (to reflect the pins I'm using and that I don't have a serial LCD), and came up with an error, presumably as I'm using 2.60 version rather than PBP 3 related to tmr6 and t6con statements. Any ideas

richard
- 24th March 2015, 20:19
pic 18F4580 has no timer6 try using tmr2 or rework the timer counts for timer3 with a 8:1 prescale

Scampy
- 24th March 2015, 22:19
Richard,

need some additional help. The following code compiled, but displayed RH 0.0 and tmr 0 on the LCD. I changed the values for badread and noise as suggested, but still have the same result. As mentioned I'm using a 10 mhz crystal with HS_ppl enabled to run the pic at 40 Mhz. Could you point me in the right direction as to what I'm doing wrong ?



; config settings 18F4580, 10mhz crystal HSPPL

ASM
__CONFIG _CONFIG1H, _OSC_HSPLL_1H
__CONFIG _CONFIG2L, _PWRT_ON_2L
__CONFIG _CONFIG2H, _WDT_ON_2H & _WDTPS_512_2H
__CONFIG _CONFIG3H, _PBADEN_OFF_3H
__CONFIG _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L
ENDASM

DEFINE OSC 40
ADCON1 = $0F
clear
INCLUDE "alldigital.pbp"
CMCON = 7
TRISA = %11001111

DEFINE LCD_DREG PORTB ' LCD Data port
DEFINE LCD_DBIT 0 ' starting Data bit (0 or 4)
DEFINE LCD_EREG PORTB ' LCD Enable port
DEFINE LCD_EBIT 5 ' Enable bit (on EasyPIC 5 LCD)
DEFINE LCD_RSREG PORTB ' LCD Register Select port
DEFINE LCD_RSBIT 4 ' Register Select bit (on EasyPIC 5 LCD)
DEFINE LCD_BITS 4 ' LCD bus size (4 or 8 bits)
DEFINE LCD_LINES 4 ' number of lines on LCD
DEFINE LCD_COMMANDUS 2000 ' Command delay time in us
DEFINE LCD_DATAUS 50 ' Data delay time in us

ASM
hum = _dht+3
tempa = _dht+1
ENDASM

T1CON = %00000001 ; free-running, 1:1 prescaler

dht_data var PORTA.1
dht_dir var TRISA.1
dht var byte[5]

tempa var word EXT
bits var byte
crc var byte
hum var word EXT

main:
gosub read_dht
LCDOut $FE,$94,"rh ",#hum/10,".",dec1 hum//10
pause 4000
goto main

read_dht:
for bits=4 to 0 step-1
dht[bits]=0
next

tmr2=0
dht_dir=0
dht_data=0
pauseus 1000 'start it up
dht_data=1
pauseus 30
dht_dir=1
pauseus 40 'wait till middle of response pulse window
if ( dht_data)then goto badread 'no response then give up
while (!dht_data)
wend
t2con=6
while ( dht_data)
wend
t2con=0
if ((tmr2 <75)||(tmr2>85))then goto badread ' confirm presence ?
for bits =39 to 0 step -1
tmr2=0
while (!dht_data)
wend
t2con=6
while ( dht_data)
wend
t2con=0
if ((tmr2>20)&&(tmr2<80)) then ' noise ?
if (tmr2 >50 ) then
dht.0[bits] = 1
endif

else
goto badread ' noise ?
endif
next
crc=0
for bits=1 to 4
crc=crc+ dht[bits]

next
if crc != dht[0] then goto badcrc 'crc

return

badread:
LCDOut $FE,$94 +8,"tmr6 ",#tmr2
for bits=4 to 0 step-1
dht[bits]=0
next
return
badcrc:
for bits=4 to 0 step-1
LCDOut $FE,$94 +16,hex dht[bits],","
next
return

richard
- 24th March 2015, 23:22
you did not make the changes I suggested

; config settings 18F4580, 10mhz crystal HSPPL

ASM
__CONFIG _CONFIG1H, _OSC_HSPLL_1H
__CONFIG _CONFIG2L, _PWRT_ON_2L
__CONFIG _CONFIG2H, _WDT_ON_2H & _WDTPS_512_2H
__CONFIG _CONFIG3H, _PBADEN_OFF_3H
__CONFIG _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L
ENDASM

DEFINE OSC 40
ADCON1 = $0F
clear
INCLUDE "alldigital.pbp"
CMCON = 7
TRISA = %11001111

DEFINE LCD_DREG PORTB ' LCD Data port
DEFINE LCD_DBIT 0 ' starting Data bit (0 or 4)
DEFINE LCD_EREG PORTB ' LCD Enable port
DEFINE LCD_EBIT 5 ' Enable bit (on EasyPIC 5 LCD)
DEFINE LCD_RSREG PORTB ' LCD Register Select port
DEFINE LCD_RSBIT 4 ' Register Select bit (on EasyPIC 5 LCD)
DEFINE LCD_BITS 4 ' LCD bus size (4 or 8 bits)
DEFINE LCD_LINES 4 ' number of lines on LCD
DEFINE LCD_COMMANDUS 2000 ' Command delay time in us
DEFINE LCD_DATAUS 50 ' Data delay time in us

ASM
hum = _dht+3
tempa = _dht+1
ENDASM

T1CON = %00000001 ; free-running, 1:1 prescaler

dht_data var PORTA.1
dht_dir var TRISA.1
dht var byte[5]

tempa var word EXT
bits var byte
crc var byte
hum var word EXT

main:
gosub read_dht
LCDOut $FE,$94,"rh ",#hum/10,".",dec1 hum//10
pause 4000
goto main

read_dht:
for bits=4 to 0 step-1
dht[bits]=0
next

tmr2=0
dht_dir=0
dht_data=0
pauseus 1000 'start it up
dht_data=1
pauseus 30
dht_dir=1
pauseus 40 'wait till middle of response pulse window
if ( dht_data)then goto badread 'no response then give up
while (!dht_data)
wend
t2con=6
while ( dht_data)
wend
t2con=0
if ((tmr2 <45)||(tmr2>55))then goto badread ' confirm presence ?
for bits =39 to 0 step -1
tmr2=0
while (!dht_data)
wend
t2con=6
while ( dht_data)
wend
t2con=0
if ((tmr2>12)&&(tmr2<50)) then ' noise ?
if (tmr2 >31 ) then
dht.0[bits] = 1
endif

else
goto badread ' noise ?
endif
next
crc=0
for bits=1 to 4
crc=crc+ dht[bits]

next
if crc != dht[0] then goto badcrc 'crc

return

badread:
LCDOut $FE,$94 +8,"tmr6 ",#tmr2
for bits=4 to 0 step-1
dht[bits]=0
next
return
badcrc:
for bits=4 to 0 step-1
LCDOut $FE,$94 +16,hex dht[bits],","
next
return

richard
- 24th March 2015, 23:40
if you don't have a oscilloscope or logic analyser add some more diagnostics to the program





; config settings 18F4580, 10mhz crystal HSPPL

ASM
__CONFIG _CONFIG1H, _OSC_HSPLL_1H
__CONFIG _CONFIG2L, _PWRT_ON_2L
__CONFIG _CONFIG2H, _WDT_ON_2H & _WDTPS_512_2H
__CONFIG _CONFIG3H, _PBADEN_OFF_3H
__CONFIG _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L
ENDASM

DEFINE OSC 40
ADCON1 = $0F
clear
INCLUDE "alldigital.pbp"
CMCON = 7
TRISA = %11001111

DEFINE LCD_DREG PORTB ' LCD Data port
DEFINE LCD_DBIT 0 ' starting Data bit (0 or 4)
DEFINE LCD_EREG PORTB ' LCD Enable port
DEFINE LCD_EBIT 5 ' Enable bit (on EasyPIC 5 LCD)
DEFINE LCD_RSREG PORTB ' LCD Register Select port
DEFINE LCD_RSBIT 4 ' Register Select bit (on EasyPIC 5 LCD)
DEFINE LCD_BITS 4 ' LCD bus size (4 or 8 bits)
DEFINE LCD_LINES 4 ' number of lines on LCD
DEFINE LCD_COMMANDUS 2000 ' Command delay time in us
DEFINE LCD_DATAUS 50 ' Data delay time in us

ASM
hum = _dht+3
tempa = _dht+1
ENDASM

T1CON = %00000001 ; free-running, 1:1 prescaler

dht_data var PORTA.1
dht_dir var TRISA.1
dht var byte[5]

tempa var word EXT
bits var byte
crc var byte
hum var word EXT

main:
gosub read_dht
LCDOut $FE,$94,"rh ",#hum/10,".",dec1 hum//10
pause 4000
goto main

read_dht:
for bits=4 to 0 step-1
dht[bits]=0
next

tmr2=0
dht_dir=0
dht_data=0
pauseus 1000 'start it up
dht_data=1
pauseus 30
dht_dir=1
pauseus 40 'wait till middle of response pulse window
if ( dht_data)then goto badresponce 'no response then give up
while (!dht_data)
wend
t2con=6
while ( dht_data)
wend
t2con=0
if ((tmr2 <45)||(tmr2>55))then goto badpresence ' confirm presence ?
for bits =39 to 0 step -1
tmr2=0
while (!dht_data)
wend
t2con=6
while ( dht_data)
wend
t2con=0
if ((tmr2>12)&&(tmr2<50)) then ' noise ?
if (tmr2 >31 ) then
dht.0[bits] = 1
endif

else
goto badread ' noise ?
endif
next
crc=0
for bits=1 to 4
crc=crc+ dht[bits]

next
if crc != dht[0] then goto badcrc 'crc

return

badread:
LCDOut $FE,$94 +8,"tmr2 ",#tmr2

next
return
badcrc:
for bits=4 to 0 step-1
LCDOut $FE,$94 +16,hex dht[bits],","
pause 5000
next
return
badresponse:
LCDOut $FE,$94 +8,"nr "
return

badpresence:
LCDOut $FE,$94 +8,"pr",#tmr2
return

Scampy
- 25th March 2015, 00:22
you did not make the changes I suggested


I changed the values for badread and noise as suggested, but still have the same result.

Sorry Richard, I must of confused you by posting the code with the values in the original code.

I'll take a look at your suggested code tomorrow and let you know - cheers for your help

EDIT - loaded the code as is and the LCD displays rh 0.0 nr
I assume that it's not getting a response from the sensor ? I have checked the connections and they appear correct (+ve to 5v, GND to ground, and signal to PORT A pin 1) this is connected via a header to the EasyPIC5 board with the 10K pull up resistors enabled (also tried without) I have a Hantek PC scope which I can use to test. I'm guessing I should see pin A1 going from high to low for the initial handshake between PIC and sensor ??

richard
- 25th March 2015, 02:08
expected dht response to start signal

Scampy
- 25th March 2015, 12:49
OK seems to of been a hardware issue. Replaced the sensor and now get a value on the lcd. The program is giving a reading of 870.4 - how would I turn this into a percentage

Tabsoft
- 25th March 2015, 15:19
Just to get a sense of the raw data collected, perhaps you can change your "main" subroutine to the follow and post the results output on the LCD?



main:
gosub read_dht
'LCDOut $FE,$94,"rh ",#hum/10,".",dec1 hum//10
lcdout $FE, $94, hex2 dht(0), " ", hex2 dht(1), " ",hex2 dht(2), " ", hex2 dht(3), " ", hex2 dht(4)
pause 4000
goto main

Scampy
- 25th March 2015, 19:35
LCDOut $FE,$94,"rh ",#hum/10,".",dec1 hum//10 this gives a value of 870.4

lcdout $FE, $94, hex2 dht(0), " ", hex2 dht(1), " ",hex2 dht(2), " ", hex2 dht(3), " ", hex2 dht(4) produces 38 00 16 00 22

Scampy
- 25th March 2015, 19:52
In one of the other examples I've tested it has the following statement

humid=dht[31]*128+dht[30]*64+dht[29]*32+dht[28]*16+dht[27]*8+dht[26]*4+dht[25]*2+dht[24]*1

Using
lcdout $FE,$C0,"Humidity = ",#humid,"% " gives the humidity as a percentage.

Just trying to apply this to Richards code to get the same result

Tabsoft
- 25th March 2015, 20:22
Not using the DHT11 sensor, what is the temperature around your test rig?

Tabsoft
- 25th March 2015, 21:02
As I read the datasheet for the DHT11 a few of things jump out.
1. The resolution for the Humidity is 1%
2. The resolution for the Temperature is 1 degC.

The datastream is 40 bits long.
8bit integral RH data + 8bit decimal RH data + 8bit integral T data + 8bit decimal T data + 8bit check sum.
The algorithm you are implementing stores the bitstream into the dht array like this.
dht[4] = integral RH data
dht[3] = decimal RH data
dht[2] = integral T data
dht[1] = decimal T data
dht[0] = checksum

So the Hex data values you showed earlier "38 00 16 00 22" should be this
dht[0] = checksum = $38 (56 decimal) $00 + $16 + $00 + $22
dht[1] = decimal T data = $00 (this is the decimal portion of the Temperature, which will always be 0)
dht[2] = integral T data = $16 (22 decimal)
dht[3] = decimal RH data = 00 (this is the decimal portion of the Humidty, which will always be 0)
dht[4] = integral RH data = $22 (34 decimal)

I believe you do not need to perform any calculations to convert the RH data to a percentage.
That is what is giving you the strange results.
The calculation "#hum/10" is taking the hum variable and dividing it by 10.
The issue as I see it is that using the hum variable is not necessary and giving you the incorrect values.
PBP treats word variables as Little Endian numbers meaning the low order byte is stored first then the high order byte.
So when hum = _dht+3 and hum is declared as a word, PBP is looking at dht[3] & dht[4] as the word variable hum.
This would be $00 $22, but since we are looking at Little Endian numbers PBP will use dht[4] as the high byte and dht[3] as the low byte.
This makes hum = $2200 (8704 dec), which will result in 870 decimal when you divide 8704 by 10 and a result of 4 with 8704 // 10.
Making your output equal 870.4 as you say.

For the RH percentage you simply need to display the value in dht[4], something like this.
lcdout $FE, $94, dec dht[4], "%"
You do not need the ".",dec1 stuff since the DHT11 does not report a decimal place for RH or Temperature because of the resolution of the sensor.

As for the Temperature, if you are going to just use it as a Celsius number, there is no need for any calculation or conversion either.
Just simply display the value in dht[2]. E.g. lcdout $FE, $94, dec dht[2].

Hope this helps.

richard
- 25th March 2015, 21:04
looks like the dht11 only has a 8 bit range for rh an t so the display needs to be
LCDOut $FE,$94,"rh ",#hum/100
or
LCDOut $FE,$94,"rh ",#dht[4]

my fault I stopped reading the dht11 data sheet when I saw the 40 bit timings were the same as a dht22 , I have no dht11 to test with

richard
- 25th March 2015, 21:11
just an observation but the fineoffset wh1081 weather station that I have uses a dht11 and its readings vary greatly from those of the dht22 right next to it . somehow I think the dht11 is not very accurate

Tabsoft
- 25th March 2015, 21:43
Richard,

I don't think #hum/100 will give the correct result.
Since I. This example hum=8704 ($2200), 8704/100=87 ($57).

The correct result should be 34 ($22).
He just needs to use dht[4]
Or
To use a division calculation with hum it should be #hum/256.
This will right shift 8704 ($2200) 8 bits resulting in 34 ($22).
:)

Scampy
- 25th March 2015, 21:46
Guys thanks for your continued input.

using the #hum/100 gives 87% as the value, which to me seems rather humid, especially when the indoor humidity according to my maplins weather station says it's 51%. As a comparison I tried the following code which uses the pause and pulsein statements to read the chip



ASM
__CONFIG _CONFIG1H, _OSC_HS_1H
__CONFIG _CONFIG2L, _PWRT_ON_2L
__CONFIG _CONFIG2H, _WDT_ON_2H & _WDTPS_512_2H
__CONFIG _CONFIG3H, _MCLRE_ON_3H & _LPT1OSC_OFF_3H & _PBADEN_OFF_3H
__CONFIG _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L
ENDASM


'************************************************* ******************************
' LCD (20 x 4) set up
'************************************************* ******************************

DEFINE LCD_DREG PORTB ' LCD Data port
DEFINE LCD_DBIT 0 ' starting Data bit (0 or 4)
DEFINE LCD_EREG PORTB ' LCD Enable port
DEFINE LCD_EBIT 5 ' Enable bit (on EasyPIC 5 LCD)
DEFINE LCD_RSREG PORTB ' LCD Register Select port
DEFINE LCD_RSBIT 4 ' Register Select bit (on EasyPIC 5 LCD)
DEFINE LCD_BITS 4 ' LCD bus size (4 or 8 bits)
DEFINE LCD_LINES 4 ' number of lines on LCD
DEFINE LCD_COMMANDUS 2000 ' Command delay time in us
DEFINE LCD_DATAUS 50 ' Data delay time in us

'************************************************* ******************************
' Defines Statements
'************************************************* ******************************

DEFINE OSC 20 ' 18F4520 / 18F2520, 20mhz crystal
ADCON1 = $0F
clear

'************************************************* ******************************
'Analog and Comparator settings
'************************************************* ******************************

ADCON0 = %00000000 'AD converter module disabled
ADCON1 = %00001111 'All Digital
ADCON2 = %00000000
CMCON = 7 'Disable Comparators

'************************************************* ******************************
'Port and Register settings (interrupts)
'************************************************* ******************************

TRISA = %00010111
TRISB = %00000011
T0CON = %11000111

T1CON = %00000001 ; free-running, 1:1 prescaler
TMR1H = %11111111
TMR1L = %11111011


'************************************************* ******************************

LCDOUT $FE,1:FLAGS=0:PAUSE 250:LCDOUT $FE,1:PAUSE 250 ' Initialize LCD

'************************************************* ******************************

dht var byte[32]
humidite var byte
haut var byte
bas var byte
temp var byte
x var byte
dht11 var portA.1

'************************************************* ******************************
start:
TRISA.1 = 0 '
high dht11
pause 2000 ' wait 2 sec
low dht11 : pause 18' send 20ms low
high dht11 : pauseus 30 ' send 40us hi
TRISA.1 = 0
PulsIn PORTA.1, 1, haut
if haut < 15 then goto start
for x = 31 to 0 step-1
PulsIn PORTA.1, 1, dht[x] ' 1
next x
For x = 31 to 0 step-1
if dht(x)>=9 and dht(x)<=21 then dht(x)=0 'if pulsewidth between 20 and 40uS then read as '0'
if dht(x)>=29 and dht(x)<=41 then dht(x)=1 'if pulsewidth between 60 and 80uS then read as '1'
next x
humidite=dht[31]*128+dht[30]*64+dht[29]*32+dht[28]*16+dht[27]*8+dht[26]*4+dht[25]*2+dht[24]*1
temp=dht[15]*128+ dht[14]*64+dht[13]*32+dht[12]*16+dht[11]*8+dht[10]*4+dht[9]*2+dht[8]*1
lcdout $FE,1
lcdout $FE,$C0,"Humidite = ",#humidite,"% "
lcdout $FE,$80,"Temperature = ",#temp,$DF,"C"
goto start


This gives 174c in our living room, with the humidity fluctuating between three values of 24%, 144% and 152%. Clearly there is something wrong with the hardware. I'm using a new solderless breadboard so I'll look at hard wiring the sensor and see if that helps, even though the connections between the Easypic board and sensor are next to each other

Scampy
- 25th March 2015, 21:52
Richard,

I don't think #hum/100 will give the correct result.
Since I. This example hum=8704 ($2200), 8704/100=87 ($57).

The correct result should be 34 ($22).
He just needs to use dht[4]
Or
To use a division calculation with hum it should be #hum/256.
This will right shift 8704 ($2200) 8 bits resulting in 34 ($22).
:)

Dividing hum by 256 gives a reading of 35 on the LCD. The values for dht(1) to (5) are 39 00 16 00 23

I'm still not satisfied the sensor is working right, and this is the second one I've tried

Scampy
- 25th March 2015, 22:07
Hummm

Well I've now soldered the wires direct to the sensor, and plugged the wires directly into the header on the EasyPIC5 board.

Dht(0) - 4 now reads 38 00 19 00 1F with a hum/256 value of 34.

whilst this seems to of resolved the issues with the breadboard, 34% humidity seems rather low, and quite a gap from the 50% shown on the weatherstation

richard
- 25th March 2015, 22:08
brain fade due to lack of coffee divide 256 is of course correct

attached the blue is a dht11 the red a dht22 in the same room

Tabsoft
- 25th March 2015, 22:10
As Richard has stated, the DHT11 doesn't seem to be too accurate in his experience.

As far as your readings go 39 00 16 23

This is 35% RH and 22c Temp.

Just use dht[4] for RH and dht[2] for Temp.

Scampy
- 25th March 2015, 23:23
Thanks guys - I'll look at getting a DH22 as I need something more precise given that this will be monitoring the humidity in my snakes enclosure.

Tabsoft
- 27th March 2015, 00:39
Hi Richard,

I was wondering if you could help me understand your use of Timer2 in this project during the read loop for the 40 bits from the DHT11.

In this section of code.....
" t2con=6
while ( dht_data)
wend
t2con=0
if ((tmr2>12)&&(tmr2<50)) then ' noise ?
if (tmr2 >31 ) then
dht.0[bits] = 1
endif
else
goto badread ' noise ?
endif"

I see that Timer2 is turned on with the Prescaler set to 16.
Then after the data line drops to 0, Timer2 is stopped.

Then the TMR2 register is tested for its count value.
If the count is less than 12 or greater than 50, then it's a bad read.
Otherwise if the count is greater than 31 and less than 50 the bit is a 1.
Is this correct?

If the Fosc is 40Mhz and Timer2 counts at Fosc/4 and the Timer2 Prescaler is 16.
Then
Would the test "((tmr2>12)&&(tmr2<50))" equate to
If count is greater than 19.2us and less than 80us?

And then would the test "(tmr2 >31 )" equate to
If count is greater than 49.6us?

Which I think the test logic would translate to...
If the count is less than 19.2us or greater than 80us then it's a bad read.
Otherwise if the count is greater than 49.6us and less than 80us the bit is a 1.

I think this is right, but please let me know if not.
Just trying to understand how it is implemented.

Thanks

richard
- 27th March 2015, 01:44
Which I think the test logic would translate to...
If the count is less than 19.2us or greater than 80us then it's a bad read.
Otherwise if the count is greater than 49.6us and less than 80us the bit is a 1.


that's it although a '0' is 26-28uS and a 1 is 70us according to the data sheet I have added some tolerance (this helps if interrupts are involved) if the count is outside this range then its not right and the process is abandoned , this test is not strictly necessary and could be omitted

the 1/0 test is basically centered in between the 1 and the 0 times ie 50 is halfway between 30 and 70 once again to add some tolerance . if less than halfway its a 0 otherwise a 1


there is some risk in this method in that hangs are possible if the dht responds in an unforseen manner . in my production version the tmrx int is enabled and if it is triggered then the process is also aborted to recover from such a sensor hang .

Scampy
- 28th March 2015, 19:54
Tabsoft / Richard,

I've incorporated the code below into my main program and whilst it runs fine, it does flash up a fair few "bad read" errors. Is there anything I could tweak to reduce these occurancies



read_dht:
for bits=4 to 0 step-1
dht[bits]=0
next

tmr2=0
dht_dir=0
dht_data=0
pause 18 'start it up
dht_data=1
pauseus 30
dht_dir=1
pauseus 40 'wait till middle of response pulse window
if ( dht_data)then goto badresponse 'no response then give up
while (!dht_data)
wend
t2con=6
while ( dht_data)
wend
t2con=0
if ((tmr2 <45)||(tmr2>55))then goto badpresence ' confirm presence ?
for bits =39 to 0 step -1
tmr2=0
while (!dht_data)
wend
t2con=6
while ( dht_data)
wend
t2con=0
if ((tmr2>12)&&(tmr2<50)) then ' noise ?
if (tmr2 >31 ) then
dht.0[bits] = 1

endif

else
goto badread ' noise ?
endif
next
crc=0
for bits=1 to 4
crc=crc+ dht[bits]
next
if crc != dht[0] then goto badcrc 'crc

return

badread:
LCDOut $FE,$94 +8,"Bad read"
pause 1000
LCDOut $FE,$94 +8," "
' next
return
badcrc:
for bits=4 to 0 step-1
LCDOut $FE,$94 +16,hex dht[bits],","
pause 1000
next
return
badresponse:
LCDOut $FE,$94+8,"No Response"
return

badpresence:
LCDOut $FE,$d4,"pr",#tmr2
return

richard
- 28th March 2015, 20:39
does your program use interrupts ? if so how long does the isr take to execute ?
the tolerance here is 10uS + or - so an interrupt can easily cause the timing tolerance to be exceeded
possible solutions
1. disable interrupts during dht read
2. increase tolerance
3. ignore bad reading and retry
4. remove the noise test


t2con=0

if ((tmr2>12)&&(tmr2<50)) then ' noise ?
if (tmr2 >31 ) then
dht.0[bits] = 1

endif

else
goto badread ' noise ?

endif
5. use a faster chip

Tabsoft
- 30th March 2015, 04:44
To get a better understanding what is going on, why don't you make a small change for debugging.

Instead of this...


for bits =39 to 0 step -1
tmr2=0
while (!dht_data)
wend
t2con=6
while ( dht_data)
wend
t2con=0
if ((tmr2>12)&&(tmr2<50)) then ' noise ?
if (tmr2 >31 ) then
dht.0[bits] = 1

endif

else
goto badread ' noise ?
endif
next


Do this instead...


for bits =39 to 0 step -1
tmr2=0
while (!dht_data)
wend
t2con=6
while ( dht_data)
wend
t2con=0
if tmr2 <= 12 then goto tooshort
if tmr2 => 50 then goto toolong
if (tmr2 >31 ) then
dht.0[bits] = 1
endif

next


Then create the 2 subs, tooshort and toolong and have each print a different error message.

falingtrea
- 30th March 2015, 19:12
TI and Silicon Labs have RH/Temperature devices with an I2C interface in the $5.00 single part range: Si7013, Si7020, Si7021 2%-4% accuracy TI HDC1000 and HDC1008 similar accuracy specification. Both are available at Digikey. Honeywell also has a device, HIH6130, but it is a bit more expensive, at $14.

Scampy
- 30th March 2015, 19:47
Guys, thanks for the additional replies,

@Tim, I'll check out those suggestions... cheers

richard
- 1st April 2015, 03:47
malcom
before you go too far down this track you might like to research some other devices or at least have a way to calibrate these things. I now have three sensors in the same room 2x dht22, 1 dht11. the dht 11 reads 60% the dht22's read 46.3 and 49.5 right now @19.6C (tis as close as they seem to get) . real hum is anyone's guess , the readings tend to converge @ around 20C but diverge wildly below 10C and above 30C. there is some info on the web about bedding these sensors in or "reforming them" . not sure how fussy reptiles are , I do know how fussy the cold blooded half of the human race is

Scampy
- 1st April 2015, 15:29
Richard,

Thanks for the suggestion. I've been having some issues and have to agree that these sensors are not really suitable where precision is required. I added tabsofts suggestion, and I got as many short errors as I did Longs... I've also got several not connected errors. I think I'll look at something that uses a standard communications interface such as those suggested by Tim.

The humidity requirements of the snakes I keep are not that critical, but this probe is intended to be used to monitor the humidity in the container containing eggs in an incubator, where the humidity needs to be kept at a set range so they don't dry out.

Charlie
- 2nd April 2015, 14:21
According to the datasheets, for the DHT22:
Operating range humidity 0-100%RH;
Accuracy humidity +-2%RH(Max +-5%RH);
Resolution or sensitivity humidity 0.1%RH;
Repeatability humidity +-1%RH;
Humidity hysteresis +-0.3%RH
Long-term Stability +-0.5%RH/year
DHT22 should be fine for your application.

AvionicsMaster1
- 2nd April 2015, 14:41
Just for my own edification what temp and humidity are you looking to maintain? Google implied both need to be tailored to type of snake egg.

Scampy
- 3rd April 2015, 15:58
Just for my own edification what temp and humidity are you looking to maintain? Google implied both need to be tailored to type of snake egg.

Royal Python eggs are typically incubated at 32c and 90% humidity