PIC16F877 + DHT22

Anonym: Já tedy nevím, ale ten výpočet mi nějak nesedí :
3 276 800 / 32 = 102 400
8-bitový timer je 256 => 102 400 /256 = 400 Hz => 0,0025 s = 2,5ms

Ledaže by jeden tik timeru přišel až po 4 taktech systemových hodin.

Pokud je jeden tik timeru = 1 tik systémových hodin, pak předděličku 110 => 1:128
3 276 800 / 128 = 25 600
25 600/256 = 100 Hz.

Ale tak to přesně je, v těchto malých PICech je všechno fosc/4, i pro časovač

Aha - tak to pak jo.

Jinak teda když už jsme nakousli časomíru, tak to ještě doplním: S tou původní frekvencí co jsem psal prve by to šlo taky, ale muselo by se to vydělit až na jedničku, což je (fosc/4) / 2^20, takže by na to nestačil TMR0 s předděličkou (a nebo stačil, ale dostali bychom 16Hz který bysme si museli ještě podělit sami v rutině přerušení, tj. započítat jen každou 16. obsluhu). Jinak pak je ještě vhodná frekvence krystalu např. 4.096MHz, kde by stačilo stejně jako u těch 3.2768MHz a 6.5536 MHz krystalu jen podělit 1x nějakou vhodnou mocninou 2 a pak už jsme na desítkových počtech, protože to po tom prvním dělení tou mocninou vychází už kulatý.

S klasickýma frekvencema jako 4MHz apod to nikdy nevychází pořádně a musí se připočítávat korekce, protože to nejde bezezbytku dělit dvěma. Teď jsou tedy Cčkaři chytřejší v tom jak to vlastně funguje (a jak to dělají assembleristi) a můžou to klidně dělat stejně a na DelayNěco se vykašlat, když budou chtít (možná tím ušetří nějaký místo v paměti programu).

Myslel jsem samozřejmě mocniny dvou, ne dvojku jako takovou.

Omlouvám se, tento týden na to nemám moc času, stihl jsem jenom zkusit koupené krystaly a funguje to do 8 MHz a pak to začíná blbnou, vynechává to každej druhej byte na displeji. Ale vypadá to, že ten problém byl v tom, že to nestíhalo, už to čte častěji, jen se mi zdá, že v blbejch místech, viz příloha.
333.rar (8.09 KB)

Jestli tam máš kód, který jsi naposled označil jako aktuální, pak čte v pořádku. LEDku invertuješ jenom před čekáním na náběžnou hranu, takže takhle jak to máš je to OK. Okamžik čtení bitu tam “označený” nemáš, to bys musel LEDku invertovat ještě jednou hned po __delay_us(35), abys viděl, ve kterém místě to fyzicky bit čte, ale podle toho, co jsem viděl, tak to už stíhá bez problémů. Před náběžnou hranu se dostane včas a s dostatečnou rezervou…

Nevím jak to myslíš že to má OK, ale vzhledem k tomu že ten sensor má významy těch bitů definovaný trochu jinak než jsme zvyklí z DS18B20, tak by ten kód asi měl ještě upravit.

Jde o to, že bude muset měřit délky pulsů toho signálu z čidla, protože jednak jsou významy dle datasheetu takové, že krátká log.1 = významově „databit je v nule” a dlouhá log.1 = „databit je v jedničce”, a druhak každý to čidlo může mít v rámci nějakých výrobních odchylek tu komunikaci různě rychlou, takže z toho plyne, že nějaký __delay_ms(35); apod napevno v tom kódu v podstatě nemá co dělat, protože i kdyby to náhodou nějak na tomhle čidle rozchodil, tak po jeho výměně se mu ta komunikace stejně zase rozsype. Navíc z toho datagramu jde vidět, že to ani nedočetl do konce (po 16 pulsech mu to přestalo togglovat - dobře, beru, asi ho teplota nezajímá, ale: 1. na konci tý komunikace je nějakej checksum 2. nevím jak čidlo reaguje na přerušení komunikace, podle toho datagramu to vypadá že si vysílá vesele dál, na což je případně potřeba myslet před zahájením dalšího čtení).

Algoritmus čtení z čidla je v mbed knihovně kterou jsem sem už linkoval, a to i včetně měření délky pulsů. Je to v podstatě nejjednodušší způsob jak to udělat (je to jen pár podmínek), nevím proč si to z toho nechce vzít a radši se moří s něčím, co z principu fungovat nebude. Další možnej způsob by byl že by si to pokaždý odměřil např. čítačem/časovačem (když píšu „odměřil” tak myslím hardwarově, takže žádný delay), ale to by musel přepojit vstupy a použít CCP modul.

Tomu měření délky pulzů bych se chcel zatím vyhnot a vrátit se k tomu až třeba později.
Ano, nedočetl jsem to dokonce, vyčítal jsem jenom první dva byte, tak proto je to jenom u vlhkosti.

Anonym: Tak to jsi asi nečetl datasheet toho DHT22.

Tam je jasně napsáno, že :
Host start signal min. 0,8ms, max. 200ms
Bus master release min. 20us, max. 200us
Response low je dlouhý min. 75us, max. 85us
Response high je dlouhý min. 75us, max. 85us
0 má pulz dlouhý min. 22us, max. 30us
1 má pulz dlouhý min. 68us, max. 75us.
Odstup mezi bitama (low) min. 48us, max. 55us.
Senzor release (low) min. 48us, max. 55us.

Tudíž po 35us od náběžné hrany je na drátu buď log. 0 = bit 0 nebo log. 1 = bit 1. Nikde jsem nepsal o tom, že je to stejné jako DS18B20 a nevím, kde jsi na tuhle pitomost přišel. Není potřeba nic měřit - prostě najít náběžnou hranu, počkat 35-60us a přečíst pin => mám bit. Pokud je v datasheetu nějaká maximální hodnota, tak jí musí splňovat (toleranci tam má). Pokud ne, je to zmetek a nemá cenu se s ním zabývat. Pokud čidlo nedodrží parametry v čase, není důvod se domnívat, že bude měřit v tolerancích napsaných v datasheetu.

A to, že četl jenom 2 byty jsem si všimnul, nicméně je to celkem jedno - prostě přečetl vlhkost a na zbytek se vykašlal - to ještě neznamená, že mu to nechodí.

B0sc0: Měřit délku pulzu nemusíš. Stačí dát _delay_us(35) … Co bych ale udělal, to jsou timeouty při čekání na nějakou hranu - a to nejenom při čtení dat, ale i při kontrole response pulzu. Může se Ti stát, že ztratíš bit (jak jsi viděl, tak na 2 MHz jsi je ztrácel běžně), zlomí se drátek k čidlu nebo ho odpojíš a pak ti to tu zamrzne. Je potřeba, abys třeba po 1 ms ukončil čekání a vrátit zpátky chybu …

Netvrdil jsem nikde že jsi o něm něco psal (o DS18B20), mluvím o něm a srovnávám s ním proto, že DHT-22 používá něco, co je jakože ‘1-wire’, ovšem to „jakože” je v tomto případě hodně důležité, protože oproti skutečnému 1-wire je tu dost rozdílů (jako např. že u skutečnýho 1-wire to probíhá tak, že shodím úroveň do nuly a přepnu na vstup, a čidlo mi tu nulu buď prodlouží nebo neprodlouží, ale měřím vždy ve stejném místě, protože datasheet přesně definuje kde mám měřit a konunikaci řídím vždy já, kdežto tady to tak nejde).

Je hezký že jsi tu vypsal časová rozmezí jednotlivých impulsů, ale tím jsi jen potvrdil co jsem psal, protože ty rozestupy jsou v různých místech komunikace prostě různý (myslím u různých čidel, nespoléhal bych moc na to že nula bude vždy max. 28µs a víc ani pikosekunda). Jinými slovy, musí ho zajímat vždy náběžná hrana každého pulsu (neříkám že nezajímá) a od ní nejlíp měřit, ale on píše že měřit nechce - „včil babo raď”.

Navíc teda jak jsi psal prve, ať si ten toggling aspoň dá za ten delay, ať teda vidíme kde skutečně testujeme, jinak to tam máme k ničemu.

Nebo ještě jinými slovy - podívej se pořádně na ten datagram: Má testovat jedničky a testuje nuly - jasně, má toggling ještě před delay, ale to by měl být mimo o 35µs cca, ale on je mimo na začátku asi o 120µs a dál se ten rozdíl ještě zvětšuje, tak jak můžeš napsat že to má ok? Ať to togglí po delay a změří to znova, pak můžem mudrovat dál.

Už od rána se těším až to zkusím dát za delay, večer dám vědět :slight_smile:

Jak víš, že testuje nuly ? Myslím, že by ses měl pořádně podívat Ty. První dva dlouhé pulzy jsou 80us dlouhé. Odstup od sestupné hrany k jeho toggle NENÍ 120us, ale nějakých 32-33us. On totiž dílek, tedy těch 50us, je od jedné dlouhé čáry ke druhé. Ty krátké čárky jsou po 10us. V tomhle datagramu se nemůžeš dívat na to, kde je toggle, resp. jak daleko je od té které hrany - tady je to úplně jedno, protože :

  1. udělá toggle
  2. čeká na náběžnou hranu (to je while smyčka, ne přesně daný delay)
  3. počká 35us (to je přesně daný delay)
  4. přečte si stav pinu
  5. případě, že je pin high, tak počká na low (opět while smyčka)

Tím smyčka končí a jde na 1) nebo po 8. bitu vrátí hodnotu. Všimni si, že toggle dělá PŘED ČEKÁNÍM na náběžnou hranu, takže toggle = vstup do smyčky, následuje náběžná hrana a 35us po ní čte pin, jenže ve kterém je to místě nezjistíš, protože tam toggle NENÍ !!!. Místo, kde čte si můžeš jenom odpočítat a říct “tady někde se čte pin”. Ten high impulz pro 0 trvá cca 25us, pro 1 trvá asi 68us. Z toho plyne, že číst by měl cca 1 čárku za sestupnou hranou nuly, v případě jedničky zcela bezpečně cca v polovině pulzu.

Než něco napíšeš, měl by sis především pořádně prohlídnout program, projít datasheet, zkontrolovat, jestli jsi v datagramu pochopil správně dílky a pak to ještě jednou zkontrolovat.

Nech si ty osobní invektivy, jo (myslím tu poslední větu)? Od toho tu nejsme, abysme si nadávali. Už jsem tu jednou psal že z toho záznamu z pseudoanalyzéru nejsem moc chytrej.

Jo, to vím taky že nemá značku tam kde ji má mít. Když se něco ladí, tak se značky (jo, to je ten toggling) dělají proto, abysme viděli, ne proto aby se něco dopočítávalo, dělat značku před čekací smyčkou tedy jaksi postrádá význam.

Počkám až to změní a s čím pak přijde.

OK - připouštím, že jsem tu poslední větu trošku přehnal, nicméně - pokud datagramu 100% nerozumíš, tak se nemá smysl hádat do bezvědomí. Totéž platí u datasheetů a vlastně úplně u všeho…

V tom případě mi vysvětli, k čemu ty datasheety jsou ? Když vezmu datasheet třeba ke stabilizátoru 7805, tak se tam dočtu, že výstupní napětí je :
min. 4,8V, typ. 5V, max. 5,2V => 5V ±0,2V

To znamená, že je tam tedy kolik ? 2-48V (případně nějaké jiné) nebo 4,8-5,2V ? Úplně to samé platí pro časy uvedené v datasheetu DHT22. 0 je 22-30us a přes to vlak nejede.

To je jen tvůj pocit, že tomu nerozumím. Taky mám různé pocity, ale jelikož jsem se nepřišel hádat, nechávám je stranou.

Máš pravdu v tom že výrobce neuvádí rozsahy parametrů pro nic za nic, ale myslel jsem to tak, že rozhodně není optimální pohybovat se na jejich hranicích (35µs je taková hranice, střed je jinde když si trochu započítáš. Chápu že kód má nějakou režii, a tu bych právě pro zajímavost rád viděl na tom záznamu*), ale spíš myslet dopředu a připravit se na víc eventualit (včetně např. vadného čidla, jak jsi správně podotkl s těmi timeouty, nebo třeba rušení na lince apod). K tomu jako jeden z prostředků mimochodem slouží i ten kontrolní součet co čidlo posílá na konci, jistě to nemusím probírat dopodrobna (stejně tak jako nekritizuju jeho nevyužití v kódu, to je jeho rozhodnutí jestli součet využije nebo ne, a jeho případná rizika. Já jen zmiňuju že tu ta možnost je, nemá to žádný emocionální ani jiný podtext, takže bych byl nerad, kdyby si ho tam někdo svévolně dosazoval).

Rozhodně nemůžeš popřít že jednoduchá úprava kódu za účelem zpřehlednění záznamu je krok dopředu (a předtím jsem hovořil právě jen a pouze o tom, jak ten záznam vypadá - vím proč tak vypadá, nemusíš mi to vysvětlovat), cílem teď je aby vypadal líp a víc tak vypovídal o tom, co se přesně děje. Pak totiž zřejmě vyplavou na povrch další věci, které teď nejsou moc dobře vidět.


Nevím co umožňuje ten PK analyzér, ale jestli to dobře chápu* tak stejně máme malou vzorkovací frekvenci, jeden systick toho PICu je 500ns aktuálně.

**Neplést si zdvořilost s blbostí prosím, a to obecně všude, ne jen tady… Děkuji.

Tak jsem dal ten toogle hned za to čekání a podle mě to tak má být.
Mělo by to být 0000000101101001 což je 361/10=36,1% to by snad mohla být vlhkost v pokoji.
Ale na GLCD mi to zobrazuje hodnotu 257 a nebo 256, ještě jsem ji nedělil 10.
Což mě napadá, že že 256 je vlastně první byte posunutý o 8 doleva ale nevím, proč tam je jako druhý byte 0 a nebo 0.

Pro to spojení byte používám

	vlhkost = (RH_byte1 << 8 )| RH_byte2; 

Což si myslím, že by mělo fungovat.
Když dám zobrazit na druhém řádku číslo měření a na 6. vlhkost tak tam mám těch 257 nebo 256.
Pokud tam k přidám zobrazení jednotlivých byte vlhkosti na 4. a 5. řádek, tak mi to z nějákého důvodu na číslu měření napíše 8225, na vlhkosti 8224 a na těch jednotlivých byte vlhkosti - Byte1 0 a na Byte2 0 nebo 1ku.
Nechápu proč, číslo měření by mělo jít od nuly nahoru a ne v prvním cyklu hned na 8225.

Myslím,že tak jak jsem to popsal, tak to nemůže nikdo pochopit. Pro jistotu tu dám zase kód při kterým to vypisuje pouze číslo měření a vlhkost.

[code]// DHT22 knihovna
unsigned char Check;

void StartSignal()
{
TRISA = 0b00000000; //PORTA je výstup
RA0 = 0; //RA0 jde do 0 = startovacísignál
__delay_ms(18);//18
RA0 = 1; //RA0 se vrací do 1
__delay_us(30);
TRISA = 0b11111111; //PORTA je vstupní
}

void CheckResponse()
{
Check = 0;
__delay_us(40);
if (RA0 == 0)
{
__delay_us(80);//80
if (RA0 == 1)
Check = 1;
__delay_us(40);//40
}
}
int ReadData()
{
int i=0, j;
for(j = 0; j < 8; j++)
{
i = 0;
while(RA0 == 0); //Čeká dokud je RA0 v 0
__delay_us(35);//30 hranice mezi log 0 a log 1
RC6 = ~RC6;
if(RA0 == 1) //Zkouší, zda je RA0 po uplynulé době v 1 čí 0
{
i|= (1 << (7 - j)); //Nastaví bit do 1
while(RA0 == 1); //Čeká dokud je RA0 v 1
}
}
return i;
}

void main(void)
{
PSPIE = 0;
PSPMODE = 0;
ADCON1 = 7;
TRISA = 0b00000000;
TRISB = 0b00000000;
TRISC = 0b00000000;
TRISD = 0b00000000;

   GLCD_Init(); 
   __delay_ms(100); 
   GLCD_ClrScr(); 

   int i = 0; 
   char text1[16]; 
   char text2[16];
   char text3[16]; 
   char text4[16]; 
   char text5[16];
   char text6[20]; 

   GLCD_ClrScr(); 
       
     int T_byte1, T_byte2, RH_byte1, RH_byte2; 
 int Temp, RH, Sum ; 

   TRISA = 0b00000000;    //RA0 jako vstup 
   TRISC = 0b00000000; 
	int a = 0; 

  unsigned int teplota =  0;
  unsigned int vlhkost =  0;

while(1) 
{     
  RH_byte1 = 0; 
  RH_byte2 = 0; 
  T_byte1 = 0; 
  T_byte2 = 0; 
  teplota = 0; 
  vlhkost = 0;       



	StartSignal(); 
	CheckResponse();

	RH_byte1 = ReadData(); 
	RH_byte2 = ReadData(); 
    //T_byte1 = ReadData(); 
    //T_byte2 = ReadData(); 
    //Sum = ReadData(); 

vlhkost = (RH_byte1 << 8 )| RH_byte2; 

	GLCD_ClrScr(); 

  sprintf(text5,"Mereni: %d                ",a); 
  GLCD_text(0, 1,text5 );
  /*sprintf(text1,"Byte 1: %d               ",RH_byte1); 
  GLCD_text(0, 3,text1 ); 
  sprintf(text2,"Byte 2: %d               ",RH_byte2); 
  GLCD_text(0, 4,text2 ); */

  sprintf(text6,"Vlhkost:%d             ",vlhkost); 
  GLCD_text(0, 5,text6 );

a++;

  RC7 = 1; 
  __delay_ms(500); 
  RC7 = 0; 
  __delay_ms(500); 

}//end while(1)
}//end main [/code]

Se divím, že jste mě ještě neposlali někam :slight_smile:

To je to co už jsem jednou psal - vyčteš 16 bitů, čidlo si vesele posílá dál, ale ty nepočkáš až „dokecá” a hned to tam pošleš znova, takže pak odchytáváš blbosti.

Aha kecám, máš na konci dvě půlsekundy, ty jsem přehlídnul.

Dej asi i ten záznam radši, jestli máš…