Sari la conținut
ELFORUM - Forumul electronistilor

Interfata pentru senzor DHT11


vili_topor

Postări Recomandate

Incerc sa imi umplu timpul si sa fac ceva util, asa ca am inceput sa lucrez la un proiect cu PIC 16F628A pentru interfatarea unui senzor temperatura/umiditate DTH11. Am cumparat 4 senzori, nici unul nu da raspuns la secventa de "trezire" initiata de PIC.

Pun codul dupa ce am taiat tot din el, lasand numai secventa de initiere a comuniacrii cu senzorul. Voi atasa si datasheet senzor. Poate ma ajuta cineva care a lucrat cu asa ceva sau a intampinat problema. Am sapat pe net, totul pare OK, numai ca nu functioneaza.

Se aprinde LED pe RB3 in bucla MILISECUNDA si se stinge dupa ce iese din bucla, semn ca PIC-ul pune linia de date LOW. Apoi aceasta ramane tot timpul HIGH prin rezistenta de pull-up, senzorul nu o pune LOW si ramane in bucla detestare a liniei pentru aparitia statusului LOW(portiunea de cod BOLD)

PROCESSOR 16F628A
    ;interfata cu 16F628A pentru modul digital temperatura/umiditate DTH11
    ;se foloseste oscilator extern, quartz de 4 Mhz
    #include "p16f628a.inc"
    __CONFIG _FOSC_XT & _WDTE_OFF & _PWRTE_OFF & _MCLRE_OFF & _BOREN_OFF & _LVP_OFF & _CPD_OFF & _CP_OFF
    CBlock 0x20
    multiplicare;folosit la setarea delay de forma multiplicare x micosecunda, etc
    timp1;folosit la secunda
    timp2;folosit la secunda
    timp3;folosit la secunda;
    timp4;folosit la milisecunda
    timp5;folosit la milisecunda
    timp7;folosit la microsecunda
    grade
    zecimeGrade
    umiditate
    zecimeUmiditate
    paritate
    cifra1
    cifra2
    cifra3
    cifra4
    temporar;stochez cate 8 biti din sirul de date transmis de senzor apoi il copii in variabila corespunzatoare(grade, umiditate, etc)
    contor;folosit in bucla de stocare a bitilor in temporar
    setVariabila;alege in care din variabile este copiat temporar
    endc
    
    org 0000
    goto main
    
    org 0004;intreruperi
    return;daca apare o intrerupere accidentala, se duce inapoi 
    ;goto loop;se intoarce in bucla dupa o intrerupere
    
    main
    movlw 41;pentru calculul secundei
    movwf timp1;
    movlw 156
    movwf timp2;
    movlw 50;
    movwf timp3;
    movlw b'11111110';cifra zero
    movwf cifra1
    movwf cifra2
    movwf cifra3
    movwf cifra4
    movlw 8
    movwf contor;contor folosit la numarul de rotatii rlf temporar pt a sesiza cand au fost opt rotatii.
    clrf PORTB
    bsf STATUS, RP0
    movlw b'00000000';{PORTB setat pentru OUTPUT
    movwf TRISB
    bcf STATUS, RP0
    call secunda;pentru stabilizarea alimentarii circuitelor
  
    clrf T2CON;pregateste TMR2
    clrf TMR2
    citire;initiaza o citire a senzorului
    clrf temporar;se reseteaza in vederea stocarii sirului de biti
    ;linia de date este intre RB0 si pinul DATA al modului DHT11
    ;linia este pull-up printr-o rezistenta de 4.7 Kohm
    bcf PORTB, RB0; se pune RB0 low pentru 20 milisecunde
    call milisecunda
    bsf STATUS, RP0
    movlw b'00000001';se pune RB0 pe input, restul pe output
    movwf TRISB
    bcf STATUS, RP0
    btfsc PORTB, RB0;verifica daca RB0 e HIGH prin rezistenta de pull-up si stinge ledul pe RB3
    BCF PORTB, 3
    
    ;DE AICI NU MAI FUNCTIONEAZA
    
    ;se citeste raspunsul senzorului, care trebuie sa puna RB0 pe low 80  microsec apoi pe high 80 microsec. 
    btfsc PORTB, RB0;ramane in bucla cat timp linia de date e HIGH prin rezistenta de pull-up. Cand linia e comandata low de senzor executa urmatoarele linii
    goto $-1

    bsf PORTB, 1;aprinde ledul pe RB1, pentru a arata ca linia a trecut in LOW
    btfss PORTB, RB0;ramane in bucla cat linia de date e LOW prin comanda data de senzor. Cand senzorul nu mai comanda LOW, linia trece HIGH prin rezistenta de pull-up
    goto $-1
    bsf PORTB, 2;aprinde eldul pe RB2 pentru a semnala ca linia de date a trecut in HIGH
   
    loop
    goto loop
   
    
    secunda
    decfsz timp1, 1
    goto faza2
    movlw 41;initializeaza timp1 pentru 1 secunda timp1=41. Se creste la 80 pa a avea aporx 2 sec intarziere
    movwf timp1
    return
    
    faza2
    decfsz timp2, 1
    goto faza3
    movlw 156;initializeaza timp2
    movwf timp2
    goto secunda
    
    faza3
    movlw 50;initializeaza timp3
    movwf timp3
    decfsz timp3, 1
    goto $-1
    goto faza2
    
    ;goto faza2
    
    milisecunda;20100 instructiuni, adica 20,1 milisecunde
    btfss PORTB, RB0
    bsf PORTB, 3;semnaleasa ca RB0 e LOW in urmatoarele 20 milisecunde
    movlw 33
    movwf timp4
    faza4
    decfsz timp4, 1
    goto faza5
    return
    faza5
    movlw 200
    movwf timp5
    decfsz timp5, 1
    goto $-1
    goto faza4
    
    
    microsecunda;la frecventa de 4 mhz , o instructiune pt o microsecunda.
    decfsz multiplicare, 1
    goto microsecunda
    return
    
    
    
    
    end
 

DHT11 senzor temperatura si umiditate.pdf

Editat de vili_topor
Pentru o mai buna intelegere a problemei
Link spre comentariu
  • Răspunsuri 9
  • Creat
  • Ultimul Răspuns

Top autori în acest subiect

  • vili_topor

    5

  • cimitavita

    4

  • XAN77

    1

Top autori în acest subiect

Imagini postate

senzorul nu da valori exacte pentru duratele bit 1 si bit 0. Valorile pentru bit 1 si bit 0 variaza in anumite limite, chiar la acelasi senzor. Daca faci programul pentru valori exacte ale duratelor bit 1 si bit 0 o sa obtii numai erori. In plus, intre octetii cititi  de la senzor, trebuie sa mai lasi o pauza de 80 - 120us, pentru-ca interfata senzorului sa aiba timp sa puna la iesire urmatorul octet.

Bit 0: Tlow_low_sgn = 50 us (48-55us),  TH0_high_sgn = 26 us (22-30us)

Bit 1: Tlow_low_sgn = 50 us (48-55us),  TH1_high_sgn = 70 us (68-75us).

AM2302 grafic bus signal's.jpg

Link spre comentariu

Multumesc de raspuns...insa nu am ajuns la citirea datelor, probabil abia acolo incepe distractia. Dupa ce PIC pune linia LOW pentru mai mult de 18 milisecunde si pinul de la linia de date intra in starea INPUT, ar trebui ca senzorul sa puna linia LOW pentru 80 microsecunde, apoi sa o elibereze pentru alte 80 microsecunde(linia HIGH prin rezistenta de pull-up)ca raspuns la semnalul PIC-ului. Nu se intampla chestia asta, nu pune linia pe zero logic...deci nu se pune problema datelor atata timp cat senzorul "doarme".

Vad ca timing-ul este altul decat in datasheet-ul atasat de mine. Voi incerca sa ma ghidez...Mai am o nelamurire. Din grafic reiese ca PIC pune linia 1 logic dupa maximum 20 milisecunde. Cum o face, efectiv? Din status OUTPUT pune pinul liniei la 5V sau intra in status INPUT si elibereaza linia, aceasta fiind HIGH prin rezistenta de pull-up? Ca pe net am vazut sfaturi si asa, si asa si nu stiu cum e corect. Mie nu mi-a functionat in nici un mod(folosind graficul de timing din datasheet DHT11).

Link spre comentariu

de unde 18ms?  Linia date trebuie pusa low pentru 1ms adica 1000us. Apoi este trecuta in 1 pentru maxim 200us. In astea 200us senzorul trebuie sa raspunda punand linia de date la masa.

Link spre comentariu

La AM2302 si DHT22 este 1 milisecunda insa la DHT11 in datasheet scrie ca trebuie sa fie low cel putin 18 milisecunde... Aveti datasheet DHT11 atasat in primul post

Link spre comentariu

Da ai mult timp de umplut dacă faci în limbaj de asamblare. Nu te-ai gândit să te orientezi spre un limbaj cu ajutorul căruia să ajungi mai repede la rezultatul dorit? Posibil compilatorul să aibă exemple în el cu acel senzor iar de nu, găsești pe net o librărie pentru el, fie pentru PIC sau Arduino și o adaptezi.

Link spre comentariu

x_dadu Daca stii electronica, mai ales digitala, tocmai ca in limbaj de asamblare e cel mai usor de facut si se pierde si cel mai putin timp. Pentru DHT22 mi-a luat vreo 4 ore sa scriu programul. Mai mult timp am pierdut cu documentatia ca sa vad exact cum merge DHT22.

 

Am testat cateva zeci de DHT22 si am gasit cativa care mergeau bine, dar care tineau linia de date low un pic mai mult decat este scris in datasheet si din cauza asta nu mergeau pe Arduino.

La senzori 1-wire ar trebui ca intreruperile sa fie oprite complet iar calculul temporizarilor sa fie facute pe durata instructiunilor si numarul lor.

Din cauza ca PIC-urile vechi nu aveau intructiuni jr conditie, am trecut pe atmega si 8051.

Trebuie neaparat sa faci programul ca sa accepte variatii. De pilda, pentru 50us, programul trebuie sa accepte 48 - 52us sau chiar 46 - 54us. E foarte greu sa gasesti un senzor digital care sa dea date exact ca in datasheet.

 

AM2302_sensor.asm

Link spre comentariu

Am ales limbaj de asanblare pentru ca chiar vreau sa inteleg ce se intampla in spatele unei functii. In codul postat nu ma folosesc de intreruperi sau de timer-e ci doar de bucle care testeaza o conditie si atungi cand este indeplinita, trece mai departe. Am verificat prin LED punerea liniei low de catre PIC si eliberarea ei dupa 20 milisecunde(ledul aprins pe perioada de 20 milisecunde(evident, abia se aprinde ca se si stinge din cauza inertiilor). Testul e realizat prin verificarea conditiei liniei de date si aprinderea/stingerea ledului de pe pinul 4(RB3) al portului B. Dupa care, senzorul ar trebui sa puna linia low pentru un timp. Prin BTFSC PORTB, RB0, urmat de GOTO $-1 testez cand senzorul pune linia din high in low, deci nu conteaza interavlul de timp cat este linia high . Am ales aceasta solutie tocmai din temerea ca nu toti senzorii lucreaza fix dupa timingul din datasheet. Daca linia este low, se sare instructiunea GOTO si se aprinde ledul de pe RB1, pentru a vizualiza indeplinirea conditiei. Ei, asta nu se intampla, ceea ce ma face sa cred ca linia ramane high. De ce oare? Ori secventa de start este gresita ca timpi low/high(desi am testat variante diverse), ori senzorul defect..Dar am testat patru...Poate din cauza ca linia e pull-up atat prin rezistenta externa cat si prin cea de pull-up intern? Din datasheet am inteles ca la o linie de conectare dintre PIC si senzor mai lunga de 20 m e necesara scaderea rezistentei de pull-up extern(din cauza rezistentei liniei, ce se inseriaza)ceea ce presupune ca e necesar un anume curent minim pentru a tine senzorul pull-up.

 

Link spre comentariu

in locul senzorului pune un led de la Vcc la iesirea uC si mareste pauzele de 100 ori, inasa fel ca pauza de 18ms sa devina 1,8 secunde. Vezi daca ledul sta aprins 1,8 secunde si daca microcontrolerul trece pe urma pe intrare si citeste high pe acea intrare. Asta se poate vedea aprinzand un al doilea led daca intrarea e high.  Trebuie sa pui si cate o rezistenta de 0,5 - 1K in serie cu ledurile respective altfel o sa distrugi iesirile.

Link spre comentariu

Multumesc de sfat, am sa incerc si asa. Insa intre timp am mai citit documentatia PIC 16F628A si la TRISB/PORTB am gasit o precizare legata de comportament atipic in conditiile in care se scrie la PORTB iar portul are setati pini si pe OUTPUT si pe INPUT(cazul meu, cand aveam input pentru RB0 unde era linia de date si OUTPUT pe ceilalti pini). Inserez: 5.3 I/O Programming Considerations
5.3.1 BIDIRECTIONAL I/O PORTS
Any instruction that writes, operates internally as a read
followed by a write operation. The BCF and BSF instructions,
for example, read the register into the CPU,
execute the bit operation and write the result back to
the register. Caution must be used when these instructions
are applied to a port with both inputs and outputs
defined. For example, a BSF operation on bit5 of
PORTB will cause all eight bits of PORTB to be read
into the CPU. Then the BSF operation takes place on
bit5 and PORTB is written to the output latches. If
another bit of PORTB is used as a bidirectional I/O pin
(e.g., bit 0) and is defined as an input at this time, the
input signal present on the pin itself would be read into
the CPU and rewritten to the data latch of this particular
pin, overwriting the previous content. As long as the pin
stays in the Input mode, no problem occurs. However,
if bit 0 is switched into Output mode later on, the content
of the data latch may now be unknown.

Asa ca am lasat pe portul B numai linia de date la RB0, am dezactivat comparatoarele  si VREF pe PORTA(pinii 0-3) si am pus ledurile pe pinii 0, 1 si 2. Acum se aprind cele doua leduri care indica schimbarea starii liniei din HIGH in LOW si din LOW in HIGH ca raspuns dat de senzor la semnalul de start. Mai vad maine daca se comporta cum trebuie si pe secventa de date...Voi posta rezultatul. Multumesc de sprijin si o seara frumoasa.

Si inca o precizare: am schimbat rezistenta externa de pull-up din 4.7k in 5.1k. Daca in varianta de 4.7 aveam pe linia de date prin pull-up, in conditia de linie necomandata, in jur de 5 V, prin rezistenta de 5.1, cu linia de date necomandata, am cam 3.5 V. Asa de mare diferenta? Maine pun din nou rezistenta de 4.7 si vad ce se intampla, pt a fi sigur care a fost cauza blocajului(daca intr-adeavr am scapat de el...)

Editat de vili_topor
Precizari suplimentare
Link spre comentariu

Creează un cont sau autentifică-te pentru a adăuga comentariu

Trebuie să fi un membru pentru a putea lăsa un comentariu.

Creează un cont

Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!

Înregistrează un nou cont

Autentificare

Ai deja un cont? Autentifică-te aici.

Autentifică-te acum



×
×
  • Creează nouă...

Informații Importante

Am plasat cookie-uri pe dispozitivul tău pentru a îmbunătății navigarea pe acest site. Poți modifica setările cookie, altfel considerăm că ești de acord să continui.Termeni de Utilizare si Ghidări