PIC16F877 + DHT22

Tady jde třeba, jestli by jste nepoužili jiné datové typy, atd.
Data ze snímače lezou, to už jsem kontroloval.

Nejde o to jestli lezou, ale jaká a jak přesně lezou… Sry, ale prinscreen z analyzéru je prostě víc, než „Data ze snímače lezou, to už jsem kontroloval.”, pak až můžem navázat se čtením a odpovídat na dotazy (a taky až uvedeš co to máš za kompilátor - SDCC, XC8 nebo něco jiného?). Obecně první prostě musí být z čeho vyjít, aby to nebyla ztráta času pro všechny strany, jen tvrzení nestačí.

Ok, omlouvám se. V příloze je prinscreen, jenom teda z PICkit2. Další kdyžtak udělám. Kompiler používám HI-TEC C PRO.

200us/dílek, to asi opravdu budeš muset přidat lepší. Jinak v datasheetu toho „zázraku” píšou že je to DS18B20 + přidanej senzor vlhkosti, takže 1-wire, takže by ti asi dost pomohl datasheet přímo od toho DS18B20 (pokud se ho číňani drželi aspoň trochu), tam je popsaný jak má vypadat 1-wire (možná tak vypadá, ale podle toho co jsi přiložil to fakt nepoznám).

Jinak teda říkám narovinu dopředu že nejsem céčkač, takže odchytávání vstupu v Cčku bude výzva trochu víc než v ASM (ale analyzér bude potřeba tak či onak, bez něj se sériové komunikace ladí hodně těžko, takže do budoucna si určitě pořiď od soudruhů saleae klon pokud nemáš, stojí to dvě stovky a práce to za ty prachy nadělá až až).

A na tuhle ptákovinu jsi přišel jak ? Datasheet od DHT11 tu mám před sebou a nic takového tam není. Je tam ale celkem dobře popsáno, jak spustit přenos, jak dlouhý má pulz být a jak vypadají bity, které DHT11 vrací a jak data intepretovat. Je to tam popsáno dost detailně.

Odpověď se skrývá pod heslem „On ale nemá DHT-11” a googlovským výsledkem hledání „k čínskýmu pajcu čínskej datasheet” (a navíc to nic nemění na tom, že si to navzorkoval s malým rozlišením :wink: )

Je to děláný PICkit2kou, ale objednám z eBay lepší a budou lepší snímky :slight_smile:

Nebo si z práce půjčím oscilo, to bude nejrychlejší :slight_smile:

B0sc0: Logický analyzátor se Ti hodí (osciloskop je v tomhle případě poněkud těžkopádný, pokud nemáš k dispozici paměťový), nicméně tentokrát bych řekl, že Tvůj PICkit2 to zvládnul. Trochu jsem pohledal a DHT22 posílá data sice stejným způsobem jako DHT11, ale rozkódovat je musíš trošku jinak. Pokud jsem dobře počítal a simulační software nekecá, tak jsi z čidla dostal 02 01 00 E4 E7 (kontrolní součet tam sice nemáš zachycený celý, ale je to nižších 8 bitů součtu bytů na pozicích 0-3). První 2 byty jsou 10xvlhkost, druhé 2 byty jsou 10xteplota. 0x0201 je 513 => 513/10 = 51,3%, teplota je 0x00E4 = 228 => 228/10 = 22,8°C.

Záporná hodnota není kódovaná “klasicky”, ale hodnota je doplněná jedničkou na bitu 15 :
0x00E4 = 228 => 22,8°C
0x80E4 = -228 => -22,8°C

Díky Balů, ten saleae analzátor jsem již objednal. Ty hodnoty sedí, ale nevím proč mi je nechce stonožka načíst a zobrazit. :-/

A nemůže být chyba tady ?

unsigned char teplota = (T_byte1 << 8 )| T_byte2; unsigned char vlhkost = (RH_byte1 << 8 )| RH_byte2;

Jestli se nepletu, tak unsigned char má 8 bitů. Neměl bys tam mít unsigned int místo unsigned char ?

unsigned int teplota = (T_byte1 << 8 )| T_byte2; unsigned int vlhkost = (RH_byte1 << 8 )| RH_byte2;

To je přesně to, k čemu jsem myslel, že se vyjádříte. Až příjdu z práce, tak se na to mrknu. Díky
Ten princip toho přenosu je celkem jednoduchej, tak nechápu, že to nechodí :slight_smile:

To je tak, když si neprojdu pořádně program a hledám problém tam, kde evidentně není … Jsem zvědavý, jestli je to ono.

A navíc by, jestli se dobře dívám, měly být ty proměnné volatile , nebo ne?

Tak jsem zkusil dát

unsigned int teplota;
unsigned int vlhkost;

a pokaždé mi to vyčte něco jiného, udělal jsem x opakování a vyčtlo mi to:
Teplota: 4112;-32704;32704;20496;3084;-28664;12296;-32704;-12272
Vlhkost: 8224;8192;4096;1154;4240;4112;128;4176

Nevím, proč je u teploty sem tam záporná hodnota, když by to mělo být unsigned. Hodnoty nejsou děleny 10.

Se mi zdá, že to čte jak se mu chce, zkusím si pohrát se zpožděním u rozpoznávání 0 a 1.

Pak ještě zkusim

volatile

Upravil jsem si program, aby mi vypisoval i číslo měření, protože sem tam se mi to sekne a nedostane se to ani do while(1) a kolikrát to přestane i měřit.

Když tam dám u teploty a vlhkosti

volatile unsigned int

tak mi to vypíše hned při prvním měření u hodnot měření, teploty a vlhkosti 8224 a tu to vypíše vždycky při dalších měřeních.

Můj program teď vypadá takto

[code]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
}
}

char ReadData()
{
char i, j;
for(j = 0; j < 8; j++)
{
while(RA0 == 0); //Čeká dokud je RA0 v 0
__delay_us(40);//30 hranice mezi log 0 a log 1
if(RA0 == 0) //Zkouší, zda je RA0 po uplynulé době v 1 čí 0
i&= ~(1<<(7 - j)); //Znuluje bit
else
{
i|= (1 << (7 - j)); //Nastaví bit do 1
while(RA0 == 1); //Čeká dokud je RA0 v 1
break;
}
}
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(); 

   unsigned int i = 0; 
   char text1[16]; 
   char text2[16];
   char text3[16]; 

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

   TRISA = 0b00000000;    //RA0 jako vstup 
   TRISC = 0b00000000; 
	int a =0;
   __delay_ms(1000); 

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

  sprintf(text3,"Mereni: %d                ",a); 
  GLCD_text(0, 2,text3 ); 
  sprintf(text1,"Teplota: %d^C            ",teplota); 
  GLCD_text(0, 4,text1 ); 
  sprintf(text2,"Vlhkost: %d `            ",vlhkost); 
  GLCD_text(0, 6,text2 ); 

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

while(1) 
{ 
	StartSignal(); 
	CheckResponse(); 

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

	teplota = (T_byte1  << 8 )| T_byte2; 
	vlhkost = (RH_byte1 << 8 )| RH_byte2; 

	GLCD_ClrScr(); 

  sprintf(text3,"Mereni: %d                ",a); 
  GLCD_text(0, 2,text3 ); 
  sprintf(text1,"Teplota: %d^C            ",teplota); 
  GLCD_text(0, 4,text1 ); 
  sprintf(text2,"Vlhkost: %d `            ",vlhkost); 
  GLCD_text(0, 6,text2 ); 
	a++;

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

  RH_byte1 = 0; 
  RH_byte2 = 0; 
  T_byte1 = 0; 
  T_byte2 = 0; 
  teplota = 0; 
  vlhkost = 0; 

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

Tak mě napadá, jestli v tý funkci ReadData :

  1. Není ten break v cyklu for tak nějak navíc ? Jakmile se break provede, ukončí se cyklus for bez ohledu na j - vyhoď ho.
  2. Když před cyklem for dáš i=0, tak Ti stačí podmínka

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 }

mozna je chyba nekde v prevodu ale zameril bych se nejdrive na vycteni konstantni hodnoty z cidla,takze bych to hodil na LA , pripojit tam jeste vystup z picu a ten bych togloval pri cteni toho cidla aby bylo jasny kdy se cte stav toho cidla…

Tak teď mi to z nějákýho důvodu nechce nic načíst.

Ten break; je tak fakt asi navíc, když se ne to teď dívám, tak by to mělo být asi takto

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

Togloval nevíc co znamená, ale tipnul bych si, že to má hodit puls, když to načte něco. Je to tak

Toglovat : Já bych řekl, že to MiloPS3 myslel tak, že do ReadData dáš něco ve stylu

Rozsviť LEDku smyčka for Zhasni LEDku return i

Tím, že jsi vyhodil ten break se Ti

          while(RA0 == 1); //Čeká dokud je RA0 v 1

provede vždy. Proto Ti to nečte. Chybí Ti tam závorky.

Tohle by mělo fungovat :

int ReadData() { int i, j; i = 0; //Znuluje všechny bity for(j = 7; j >= 0; j--) { while(RA0 == 0); //Čeká dokud je RA0 v 0 __delay_us(30);//30 hranice mezi log 0 a log 1 if(RA0 == 1) //Zkouší, zda je RA0 po uplynulé době v 1 čí 0 { i|= (1 << j); //Nastaví bit do 1 while(RA0 == 1); //Čeká dokud je RA0 v 1 } } return i; }

Ne,pokud by dal do cteni cekaci smysku navic tak by to asi nefungovalo.
Hned za if(RA0 == 1) { das treba RAB0=toggle
Nevim jestly to tvuj prekladac zna tuhle funkci pokud ne treba nasimulovat,
Pin RB0 se bude stridave nenit 0101… udelati to jakoby hodiny,podle toho pak poznas kdy ctes ten stav toho cidla, to co prectes programem ti musi sedet s tim co odectes v LA