Hallo Zusammen! Ich habe das MyAVR-Board MK3 und will damit einen SHT11 ansteuern umd auslesen. Ich bin ein Anfänger in Sachen µCs und habe nun verschiede C-codes probiert, doch es funktioniert nicht. Mit dem Oszi habe ich die Funktion überprüft, der Sensor gibt auch ein ACK und irgendwas zurück, aber es ist halt Blödsinn! Kann es sein, dass der Atmega2560 zu schnell ist und der Sensor damit nicht klarkommt? Der ATmega läuft mit 16 MHz. Auch habe ich den Sensor an einem relativ langen, ca. 50 cm, Kabel, könnte dies Probleme bereiten? Vielen Dnk schon mal für Eure Hilfe! MfG Konrad
Pullup an der Datenleitung vergessen? Ansonsten sagt die Kristallkugel, dass du einen Fehler in Zeile 42 deines Programms hast.
Konrad Bethmann schrieb: > Kann es sein, dass der Atmega2560 zu schnell ist und der Sensor damit > nicht klarkommt? Du musst den I²C halt langsam genug betreiben. Standard-I²C benutzt 100 kHz Taktrate, “fast” benutzt 400 kHz. Im Zweifel lieber erstmal mit 100 kHz rangehen. Ich habe schon erfolgreich mehr als einen SHT-21 an ATmega128RFA1 betrieben, die ebenfalls mit 16 MHz laufen. Die Länge des Busses ist bei I²C auch nicht so kritisch. Das ist ja keine Hochfrequenz. Denk dran, den Bus hat Philips so konzipiert, dass man damit die Bedienelemente innerhalb eines Fernsehgeräts anschließen kann. Die liegen auch nicht alle auf 10 cm beieinander.
:
Bearbeitet durch Moderator
Jörg Wunsch schrieb: > Du musst den I²C halt langsam genug betreiben. Standard-I²C benutzt > 100 kHz Taktrate, “fast” benutzt 400 kHz. Im Zweifel lieber erstmal > mit 100 kHz rangehen. Der SHT11 hat kein I2C. Ist aber ähnlich.
Jörg Wunsch schrieb: > Die Länge des Busses Ich betreibe einige SHT11 an 5m abgeschirmter Mikrofonleitung, also richtig viel Kapazitätsbelag. Das geht zuverlässig, allerdings nicht mit 100kHz Takt. Der Sensor ist recht unkritisch im Handling.
A. K. schrieb: > Der SHT11 hat kein I2C. Ja, hatte ich so dunkel in Erinnerung. Daher hat's auch keinen Sinn, meinen SHT-21-Code zu posten. > Ist aber ähnlich. Eben, insofern unterscheiden sie sich elektrisch nicht viel. Man kann halt nur nicht das TWI-Modul zur Ansteuerung nehmen, sondern muss es „zu Fuß“ implementieren.
Danke an Alle für die schnellen Antworten! Ich werde mal heute Abend ein Bild machen, aber ich habe Den Widerstand und den Kondensator richtig angeschlossen! Ich hänge einfach mal den Quellcode mit an, vielleicht ist der Fehler dort versteckt! Danke schon mal im Voraus! LG Konrad P.s.: Ich habe eine RAR-Datei angehangen und alle Datein noch mal so, kann sein, das einige das RAR nicht öffnen können Die Haupt datei ist : LCD_BOARD.c, die Unterprogramme liegen in SHT_TEST.c, und MK3_2560_LCD.h ist für das Display, nur zur Erklärung!
Meinen Code gibts hier, die Urfassung ohne T-Kompensation: Beitrag "Sensirion SHT11 Code"
:
Bearbeitet durch User
Danke A.K., deine code habe ich mir auch schon angesehen, da ich aber absoluter Änfänger bin, konnte ich nicht recht was mit anfangen, wäre super, wenn du mir einenen lauffähigen code geben könntest, also mit Main. Ich weiss, es klingt doof, doch ich plage mich nun schon recht lange damit rum und komme auf keinen Grünen Zweig, dass mir die Lust bald vergeht! LG Konrad
Konrad Bethmann schrieb: > wenn du mir einenen lauffähigen code geben könntest, also mit Main. Sinnlos, da konfigurationabhängig. PS: Die Messroutine ist in Beitrag "Re: Sensirion SHT11 Code" Wann das auch nicht reicht, dann fang man mit dem üblichen Beispiel einer blinkenden LED an.
:
Bearbeitet durch User
Hi A. K.! Alles klar, dann werde ich mich mal mit der Messroutine auseinandersetzen. Die Konfiguration einstellen und auch ne LED blinken lassen, dass klappt schon. Soweit bin ich dann doch! Was mir gerade aufgefallen ist, ich sollte vielleicht die Compillerwarnungen nicht ganz ignorieren, das hilft bestimmt! LG Konrad
Konrad Bethmann schrieb: > ich sollte vielleicht die Compillerwarnungen nicht ganz ignorieren, das > hilft bestimmt! Das ist immer eine gute Idee. Man kann natürlich gelegentlich auch mal eine Warnung in Kauf nehmen, aber nur, nachdem man sich gründlich vergewissert hat, dass sie für eine konkrete Situation tatsächlich bedeutungslos ist. In der Regel fährt man mit einer “zero warnings policy” immer noch am besten.
Ich habe bissel was geändert und nun keineWarnungen mehr, aber leider auch den Sensor nicht da, um ihn auszuprobieren, werde heute Abend berichten! LG Konrad
Hi Zusammen! Auf den Rat von A.K. hin habre ich seinen Code genommen und mir ein Programm zum Auslesen des SHT11 gebastelt, aber es passiert immer noch nichts. Vielleicht könnte ja der ein oder andere mit Erfahrung mal über das Programm schauen und vielleicht findet er ja den Fehler. Ich hänge auch mal die Source datei von A.K. mit an, damit ihr wisst von welchen Unterfunktionen die rede ist. Ich denke, dass die Ergebnisse in der Variable "v" gespeichter werden und deshalb wollte ich sie mir auf dem Display anzeigen lassen, aber da kommt entweder eine 0 oder, wenn ich v vorher initialisiere eben die Zahl, mit der ich initialisiert habe, keine Ahnung, wo mein Fehler liegt. Vielen Dank schon mal fürs ansehen!! VG Konrad P.s.: Das Display funktioniert, also da kann es keine Probleme geben! Hier der Code:
1 | #define F_CPU 16000000UL
|
2 | #include <avr/io.h> |
3 | #include "config.h" |
4 | #include "sht11.h" |
5 | #include <util/delay.h> |
6 | #include <stdint.h> |
7 | #include "MK3_2560_LCD.h" |
8 | int16_t feuchte_messen(void) |
9 | {
|
10 | sht11_start_humid(); |
11 | while (!sht11_ready()); |
12 | return sht11_result_humid(); |
13 | }
|
14 | int16_t v; |
15 | |
16 | |
17 | int main(void) |
18 | {
|
19 | |
20 | MK3_INIT_LCD(); // init des LCD |
21 | MK3_LCD_CLEAR(); // LCD loeschen |
22 | MK3_LCD_LIGHT(1); // beleuchtung einschalten |
23 | MK3_LCD_PRINT_STRING("test"); |
24 | |
25 | DDRD =0xFF; |
26 | PORTD =0x00; |
27 | |
28 | while(1) |
29 | {
|
30 | |
31 | MK3_LCD_PRINT_UINT(v); |
32 | _delay_ms(1000); |
33 | } return 0; |
34 | }
|
:
Bearbeitet durch User
Beim Code im Anhang nützt es garantiert nix, den Takt nach <delay.h> zu definieren. Und der direkt gepostete Code ruft die Messung nicht auf. Es fehlt die Hardware-Beschreibung, also Schaltbild und Foto, sowie und dein config.h.
:
Bearbeitet durch User
-und wo in der main(while)-Schleife führtst du die Funktion feuchte_messen(void); aus?
Sorry, natürlich habe ich in der Main while-schleife das Unterprogramm "feuchte_messen()" drin, da ist mir ein Fehler beim kopieren passiert die config.h hänge ich mit an Tut mir leid, dass ich nicht gleich alles vollständig hatte! VG Konrad
Hi zusammen! Leider kann ich gerade keinen Schaltplan erstellen und auch kein Foto machen. Der SHT11 ist wie im Datenblatt verdrahtet, sprich 100 nF-Kondensator zwischen GND und Vcc, sowie ein Widerstand, 10 k, zwischen DATA und Vcc und dann halt an das MK3-Board, die Leitungen sind nun auch kürzer, ca 10 cm, es sollte alles passen, aber es tut sich nichts! Danke für die Hilfe im _Voraus! VG Konrad
hi zusammen! Nun habe ich doch noch ein bild der Sensorbeschaltung machen können, aber laut datenblatt dürfte das so passen! hat jemand zeit gefunden, mal in den code zu schauen, ob es da einen fehler gibt? Danke noch mal!VG Konrad
Hallo Konrad, was mir auf die Schnelle aufgefallen ist, dass das toggeln der Clock-leitung mit 2u recht kurz ist. Laut Datenblatt ist typisch 0,1 Mhz angegeben. Versuche als mal alle Delays auf 10u hochzusetzen. Kannst Du Dir die Clock und Data mit einem Ozi oder Logikanalyser ansehen? Gruß Thomas
Thomas E. schrieb: > Laut Datenblatt ist typisch 0,1 Mhz angegeben. In meinem Exemplar des Datasheets sind es bis 10MHz ab 4,5V, bis 1MHz darunter.
:
Bearbeitet durch User
mein Datenblatt ist schon älter von 2008. Max ist dort mit 5Mhz angegeben, typisch aber mit 0,1 Mhz bei 5V. Schaden kann es jedenfalls nicht, die Clock mal zu senken. Gruß Thomas
Thomas E. schrieb: > mein Datenblatt ist schon älter von 2008. Interessant. Da hat sich wohl nicht nur das Datasheet geändert. Meine Datasheet war bisher die V3 von 2007. Ein "typ" Wert steht dort nicht drin. "Data sheet valid for SHTxx-V4 and SHTxx-V3" In der aktuellen völlig anders gestalteten V5 des Datasheets steht nun "Reference to V3 sensors eliminated."
:
Bearbeitet durch User
Konrad Bethmann schrieb: > Nun habe ich doch noch ein bild der Sensorbeschaltung machen können, > aber laut datenblatt dürfte das so passen! Dem Bild lässt sich die Beschaltung nicht wirklich entnehmen. Beispielsweise wo der Widerstand dran hängt, und mit welchen Pins vom Controller der Sensor verdrahtet ist.
Hi! Ich werde mal versuchen, die Taktrate zu senken, vielleicht hilft es. Der Widerstand ist an DATA und an Vcc. Data und CLOCK sind an PORT D, DATA PD7 und CLOCK PD4. GND und Vcc sind an der Spannungsversorgung des MK3-Boards, mi U = 4,9V Das sollte also alles passen. VG Konrad
Konrad Bethmann schrieb: > Ich werde mal versuchen, die Taktrate zu senken, vielleicht hilft es. _delay_us(5) statt _delay_us(2) schadet sicher auch nicht. Und mach ein _delay_ms(11) vor die Initialisierung.
:
Bearbeitet durch User
Nun habe ich das Delay raufgesetzt und auch vor der Initialisierung eins gemacht, es ändert sich rein gar nichts, was mich echt nervt!! Vielleicht lege ich das Teil erstmal zur Seite und sehe morgen oder übermorgen weiter, heute wird das glaube nichts mehr! VG Konrad
Guten Morgen zusammen! Nun habe ich nochmals bissel am Code gefeilt und es passiert trotzdem nichts!! Leider habe ich auch gerade kein Oszi zur hand, was mich ärgert! Hier kommt mal der CODE, vielleicht hat ja einer ne Idee VG Konrad p.s.: er wurde problemlos compiliert!
1 | #define F_CPU 16000000
|
2 | #define sht_port DDRB // Richtungsregister definieren
|
3 | #define sht_o PORTB // Ausgangsport definieren
|
4 | #define sht_i PINB // Eingangsport definieren
|
5 | #define data PB0 // Datenleitung zum Sensor
|
6 | #define clk PB1 // Steuerleitung zum Sensor
|
7 | #include <avr\io.h> |
8 | #include <stdint.h> |
9 | #include <avr/io.h> |
10 | #include <util/delay.h> |
11 | #include "MK3_2560_LCD.h" |
12 | |
13 | //Konstanten
|
14 | #define status_schreiben 0x06
|
15 | #define status_lesen 0x07
|
16 | #define messung_temp 0x03
|
17 | #define messung_feuchte 0x05
|
18 | #define Ack 1
|
19 | #define noAck 0
|
20 | //-----------------Unterprogramme------------------------------------------------------------
|
21 | |
22 | void delay(void) // Delay für Syncronisation |
23 | {
|
24 | _delay_us(5); |
25 | }
|
26 | |
27 | void data_hi(void) // 1 an DATA |
28 | {
|
29 | sht_o |= (1<<data); |
30 | }
|
31 | |
32 | void data_lo(void) // 0 an DATA |
33 | {
|
34 | sht_o &=~(1<<data); |
35 | }
|
36 | |
37 | void clk_hi(void) // 1 an clk |
38 | {
|
39 | sht_o |= (1<<clk); |
40 | }
|
41 | |
42 | void clk_lo(void) // 0 an clk |
43 | {
|
44 | sht_o &=~(1<<clk); |
45 | }
|
46 | |
47 | // Startsequenz
|
48 | |
49 | void start(void) |
50 | {
|
51 | sht_port = 0xFF; |
52 | data_hi(); delay(); |
53 | clk_lo(); delay(); |
54 | clk_hi(); delay(); |
55 | data_lo(); delay(); |
56 | clk_lo(); delay(); |
57 | clk_hi(); delay(); |
58 | data_hi(); delay(); |
59 | clk_lo(); delay(); |
60 | }
|
61 | |
62 | // Sensorreset
|
63 | void reset(void) |
64 | {
|
65 | sht_port = 0xFF; |
66 | char i; |
67 | data_hi(); delay(); |
68 | clk_hi(); delay(); |
69 | for (i=0;i<9;i++) // 9 Taktzyklen |
70 | {
|
71 | clk_hi(); delay(); |
72 | clk_lo(); delay(); |
73 | }
|
74 | start(); // Startsequenz |
75 | }
|
76 | |
77 | // Statusregister schreiben
|
78 | |
79 | char sht_schreiben(char cWert) |
80 | {
|
81 | char i; |
82 | char cFehler; |
83 | |
84 | for(i=0x80;i>0;i/=2) // Mit einer Schleife jedes einzelne Bit des... |
85 | {
|
86 | if (i & cWert) data_hi(); // ...zu uebergebenden Bytes maskieren und das |
87 | else data_lo(); // Ergebnis auf die DATA-Leitung geben |
88 | // Anschliessend einen Taktimpuls erzeugen
|
89 | clk_hi(); delay(); // Taktimpuls |
90 | clk_lo(); delay(); |
91 | }
|
92 | data_hi(); delay(); |
93 | clk_hi(); delay(); // steigende Flanke der Takt-Leitung |
94 | sht_port &=~(1<<data); // DATA-Pin auf Eingang umschalten |
95 | cFehler = PINB; // DATA einlesen und in fehler sichern |
96 | clk_lo() ; // fallende Flanke der Takt-Leitung |
97 | sht_port |=(1<<data); // DATA-Pin auf Ausgang zurueckschalten |
98 | return(cFehler); |
99 | }
|
100 | |
101 | // Statusregister lesen
|
102 | |
103 | char sht_lesen(char cAck) |
104 | {
|
105 | char i; |
106 | char cWert = 0; |
107 | |
108 | data_hi(); delay(); |
109 | sht_port &=~(1<<data); // DATA-Pin auf Eingang umschalten |
110 | for(i=0x80;i>0;i/=2) // Mit einer Schleife das 8-Bit Datenwort |
111 | // bitweise einlesen
|
112 | {
|
113 | clk_hi(); delay(); |
114 | if (PINB) cWert = (cWert | i); |
115 | clk_lo(); delay(); |
116 | }
|
117 | sht_port |=(1<<data); // DATA-Pin auf Ausgang zurueckschalten |
118 | data_hi(); delay(); // Bestaetigung (Acknowledge) senden |
119 | clk_hi(); delay(); |
120 | |
121 | clk_lo(); delay(); |
122 | data_hi(); delay(); |
123 | return (cWert); |
124 | }
|
125 | |
126 | //Temperaturmessung
|
127 | |
128 | char temp(int iTemperatur) |
129 | {
|
130 | char cFehler = 0; |
131 | unsigned int i; |
132 | char cTemperaturHigh; |
133 | char cTemperaturLow; |
134 | |
135 | int iTemperaturLin; |
136 | |
137 | // Schritt 1: Temperaturmessung
|
138 | // Schritt 1.1: Startbedingung erzeugen
|
139 | start(); |
140 | // Schritt 1.2: Anweisung zur Temperaturmessung
|
141 | cFehler += sht_schreiben(messung_temp); |
142 | // Schritt 1.3: Auf Messergebnis warten
|
143 | sht_port &=~(1<<data); // DATA-Leitung auf Eingang umschalten |
144 | for (i=0;i<65535;i++) if (PINB == 0){ delay();} |
145 | if (PINB) cFehler += 1; // Time-out! -> Fehlerflag setzen |
146 | sht_port |=(1<<data); // DATA-Leitung auf Ausgang umschalten |
147 | // Schritt 1.4: High-Byte vom Sensor lesen und in cTemperaturHigh sichern
|
148 | cTemperaturHigh = sht_lesen(Ack); |
149 | // Schritt 1.5: Low-Byte vom Sensor lesen und in cTemperaturLow sichern
|
150 | cTemperaturLow = sht_lesen(noAck); |
151 | |
152 | // Schritt 3: Temperatur berechnen
|
153 | iTemperaturLin = (int)(256 * cTemperaturHigh); |
154 | iTemperaturLin = iTemperaturLin + cTemperaturLow; |
155 | |
156 | // Schritt 4: Temperatur linearisieren
|
157 | iTemperaturLin = (int)(iTemperaturLin / 10); |
158 | iTemperaturLin = iTemperaturLin - 400; |
159 | |
160 | // Schritt 8: Temperatur- und Feuchtewert dem aufrufenden Programm uebergeben
|
161 | iTemperatur = iTemperaturLin; |
162 | |
163 | // Schritt 9 Rueckgabewert (hier: cFehler)
|
164 | return (cFehler); |
165 | }
|
166 | |
167 | int main (void) |
168 | {
|
169 | |
170 | int iTemperatur; |
171 | |
172 | |
173 | |
174 | MK3_INIT_LCD(); // init des LCD |
175 | |
176 | MK3_LCD_CLEAR(); // LCD loeschen |
177 | MK3_LCD_LIGHT(true); // beleuchtung einschalten |
178 | |
179 | |
180 | while (1) |
181 | {
|
182 | iTemperatur =0; |
183 | sht_port = 0xFF; |
184 | temp( iTemperatur); |
185 | _delay_ms(500); |
186 | MK3_LCD_SETCURSOR(0,32); |
187 | MK3_LCD_PRINT_STRING("Temperatur"); |
188 | |
189 | MK3_LCD_SETCURSOR(0,48); |
190 | MK3_LCD_PRINT_STRING("Feuchte"); |
191 | //iTemperatur = 12;
|
192 | MK3_LCD_SETCURSOR(20,16); |
193 | MK3_LCD_PRINT_UINT(iTemperatur); |
194 | _delay_ms(500); |
195 | |
196 | }
|
197 | return 0; |
198 | }
|
199 | //-----------------------------------------------------------------------------
|
:
Bearbeitet durch Moderator
Konrad Bethmann schrieb: > #define sht_port DDRB // Richtungsregister definieren > #define sht_o PORTB // Ausgangsport definieren > #define sht_i PINB // Eingangsport definieren > #define data PB0 // Datenleitung zum Sensor > #define clk PB1 // Steuerleitung zum Sensor Konrad Bethmann schrieb: > Data und CLOCK sind an PORT D, DATA PD7 und CLOCK PD4. Also was nun? Port D/4+7 oder Port B/0+1? Konrad Bethmann schrieb: > void data_lo(void) // 0 an DATA > { > sht_o &=~(1<<data); > } Bedenke, dass die DATA Leitung als open drain angesteuert werden sollte. Also einmalig PORTx.y=0 setzen und dann nur noch über DDRx.y steuern, mit 0=high/input und 1=low. Beachte, dass der Sensor nach Powerup und Reset-Befehl ein Weilchen nicht ansprechbar ist.
:
Bearbeitet durch User
Entschuldige A.k., ich hatte einen neuen Code geschrieben und da war die Portbelegung anders, also an Port B und nicht D. Danke für deinen Hinweis mit der DATALeitung! VG Konrad
Wenn du dich am Beispielcode von Sensiron orientieren solltest: Die Ports vom dort m.W. verwendeten 8051 sind von Haus aus open drain.
Guten Abend zusammen! Da ich diese Woche nicht mehr AN EIN VERNÜNFTIGES oSZI KOMME; WERDE ICH WOHL ERST mONTAG WIEDER MICH DEM sENSOR WIDMEN1! Zufälligerweise hatte ich noch eine NI-Karte da, doch die kann nur 100k S/s damit konnte ich nichts richtiges anfangen! Also, am Mo gehts weiter, muss doch irgendwann mal klappen! VG Konrad
Hi zusammen! Nun habe ich zwei sht11 ausprobiert, nichts rührt sich! Gibt es irgendeine möglichkeit, mit der ich testen kann, ob die Sensoren noch funktionieren? VG Konrad
Das hier
1 | ...
|
2 | for(i=0x80;i>0;i/=2) // Mit einer Schleife das 8-Bit Datenwort |
3 | // bitweise einlesen
|
4 | {
|
5 | clk_hi(); delay(); |
6 | if (PINB) cWert = (cWert | i); |
7 | ...
|
ist mir in der Lesroutine etwas zu progressiv. Den kompletten PINB zu benutzen, dürfte recht sicher nicht zielführend sein. Ausserdem: Wieso steht da PINB direkt im Code und nicht sht_i?
1 | ...
|
2 | for(i=0x80;i>0;i/=2) // Mit einer Schleife das 8-Bit Datenwort |
3 | // bitweise einlesen
|
4 | {
|
5 | clk_hi(); delay(); |
6 | if (sht_i & (1<<data)) cWert = (cWert | i); |
7 | ...
|
weiter hab ich dann nicht mehr geschaut. Insbesondere hab ich nicht überprüft, ob die Reihenfolge der Pinbewegungen Sinn ergeben und/oder mit den Vorgaben vom Sensor übereinstimmen.
:
Bearbeitet durch User
Ausserdem wäre drauf hinzuweisen, dass char i; for(i=0x80;i>0;i/=2) mit Sicherheit nicht die gewünschte Wirkung hat, wenn man bedenkt, dass der char Typ ein Vorzeichen hat und GCC deshalb die Schleife komplett entfernt.
A. K. schrieb: > Ausserdem wäre drauf hinzuweisen, dass > char i; > for(i=0x80;i>0;i/=2) > mit Sicherheit nicht die gewünschte Wirkung hat, wenn man bedenkt, dass > der char Typ ein Vorzeichen hat und GCC deshalb die Schleife komplett > entfernt. Ja, darüber wollte ich schon (fast) schreiben. Aber der Code ist so grauslich formatiert, dass ich mir den nicht weiter antun will. Übrigens kommt das PINB Problem auch noch an anderen Stellen im Code vor.
Hallo zusammen! Dankefür die schnellen Antworten, ich habe nun die Änderungen eingebaut und den Code auch (hoffentlich) besser formatiert. Aber es brachte leider gar nichts. Vielleicht könnt ihr ja nochmal drübersehen. Nun habe ich zwar im Code die ganzen Displaysachen rausgenommen, doch ich habe die Funktion des Sensors mit dem Oszi kontrolliert und er gibt nichts zurück!
1 | #define F_CPU 16000000
|
2 | #define sht_o PORTB // Ausgangsport definieren
|
3 | #define sht_i PINB // Eingangsport definieren
|
4 | #define data PB0 // Datenleitung zum Sensor
|
5 | #define clk PB1 // Steuerleitung zum Sensor
|
6 | #include <avr\io.h> |
7 | #include <stdint.h> |
8 | #include <avr/io.h> |
9 | #include <util/delay.h> |
10 | |
11 | |
12 | //Konstanten
|
13 | #define status_schreiben 0x06
|
14 | #define status_lesen 0x07
|
15 | #define messung_temp 0x03
|
16 | #define messung_feuchte 0x05
|
17 | #define Ack 1
|
18 | #define noAck 0
|
19 | //-----------------Unterprogramme------------------------------------------------------------
|
20 | |
21 | void delay(void) // Delay für Syncronisation |
22 | {
|
23 | _delay_us(5); |
24 | }
|
25 | |
26 | void data_lo(void) // 0 an DATA |
27 | {
|
28 | sht_i |= (1<<data); |
29 | }
|
30 | |
31 | void data_hi(void) // 1 an DATA |
32 | {
|
33 | sht_i &=~(1<<data); |
34 | }
|
35 | |
36 | void clk_hi(void) // 1 an clk |
37 | {
|
38 | sht_o |= (1<<clk); |
39 | }
|
40 | |
41 | void clk_lo(void) // 0 an clk |
42 | {
|
43 | sht_o &=~(1<<clk); |
44 | }
|
45 | |
46 | // Startsequenz
|
47 | |
48 | void start(void) |
49 | {
|
50 | |
51 | data_hi(); delay(); |
52 | clk_lo(); delay(); |
53 | clk_hi(); delay(); |
54 | data_lo(); delay(); |
55 | clk_lo(); delay(); |
56 | clk_hi(); delay(); |
57 | data_hi(); delay(); |
58 | clk_lo(); delay(); |
59 | }
|
60 | |
61 | // Sensorreset
|
62 | void reset(void) |
63 | {
|
64 | |
65 | char i; |
66 | data_hi(); delay(); |
67 | clk_hi(); delay(); |
68 | for (i=0;i<9;i++) // 9 Taktzyklen |
69 | {
|
70 | clk_hi(); delay(); |
71 | clk_lo(); delay(); |
72 | }
|
73 | start(); // Startsequenz |
74 | }
|
75 | |
76 | // Statusregister schreiben
|
77 | |
78 | char sht_schreiben(char cWert) |
79 | {
|
80 | unsigned int i; |
81 | char cFehler; |
82 | |
83 | for(i=0x80;i>0;i/=2) // Mit einer Schleife jedes einzelne Bit des... |
84 | {
|
85 | if (i & cWert) data_hi(); // ...zu uebergebenden Bytes maskieren und das |
86 | else data_lo(); // Ergebnis auf die DATA-Leitung geben |
87 | // Anschliessend einen Taktimpuls erzeugen
|
88 | clk_hi(); delay(); // Taktimpuls |
89 | clk_lo(); delay(); |
90 | }
|
91 | data_hi(); delay(); |
92 | clk_hi(); delay(); // steigende Flanke der Takt-Leitung |
93 | sht_i |=(1<<data); // DATA-Pin auf Eingang umschalten |
94 | cFehler = sht_i; // DATA einlesen und in fehler sichern |
95 | clk_lo() ; // fallende Flanke der Takt-Leitung |
96 | sht_i &=~(1<<data); // DATA-Pin auf Ausgang zurueckschalten |
97 | return(cFehler); |
98 | }
|
99 | |
100 | // Statusregister lesen
|
101 | |
102 | char sht_lesen(char cAck) |
103 | {
|
104 | unsigned int i; |
105 | char cWert = 0; |
106 | |
107 | data_hi(); delay(); |
108 | sht_i &=~(1<<data); // DATA-Pin auf Eingang umschalten |
109 | for(i=0x80;i>0;i/=2) // Mit einer Schleife das 8-Bit Datenwort |
110 | // bitweise einlesen
|
111 | {
|
112 | clk_hi(); delay(); |
113 | if (sht_i & (1<<data)) cWert = (cWert | i); |
114 | clk_lo(); delay(); |
115 | }
|
116 | sht_i |=(1<<data); // DATA-Pin auf Ausgang zurueckschalten |
117 | data_hi(); delay(); // Bestaetigung (Acknowledge) senden |
118 | clk_hi(); delay(); |
119 | |
120 | clk_lo(); delay(); |
121 | data_hi(); delay(); |
122 | return (cWert); |
123 | }
|
124 | |
125 | //Temperaturmessung
|
126 | |
127 | char temp(int iTemperatur) |
128 | {
|
129 | char cFehler = 0; |
130 | unsigned int i; |
131 | char cTemperaturHigh; |
132 | char cTemperaturLow; |
133 | |
134 | int iTemperaturLin; |
135 | |
136 | |
137 | |
138 | start(); |
139 | |
140 | cFehler += sht_schreiben(messung_temp); |
141 | |
142 | sht_i &=~(1<<data); // DATA-Leitung auf Eingang umschalten |
143 | for (i=0;i<65535;i++) if (sht_i == 0){ delay();} |
144 | if (sht_i) cFehler += 1; // Time-out! -> Fehlerflag setzen |
145 | sht_i |=(1<<data); // DATA-Leitung auf Ausgang umschalten |
146 | cTemperaturHigh = sht_lesen(Ack); |
147 | cTemperaturLow = sht_lesen(noAck); |
148 | iTemperaturLin = (int)(256 * cTemperaturHigh); |
149 | iTemperaturLin = iTemperaturLin + cTemperaturLow; |
150 | iTemperaturLin = (int)(iTemperaturLin / 10); |
151 | iTemperaturLin = iTemperaturLin - 400; |
152 | iTemperatur = iTemperaturLin; |
153 | |
154 | return (cFehler); |
155 | }
|
156 | |
157 | int main (void) |
158 | {
|
159 | sht_o =0x00; |
160 | int iTemperatur; |
161 | |
162 | while (1) |
163 | {
|
164 | iTemperatur =0; |
165 | temp( iTemperatur); |
166 | _delay_ms(500); |
167 | }
|
168 | return 0; |
169 | }
|
:
Bearbeitet durch User
Die Textformatierung sah in meinem Editor viel besser aus, sorry dafür! Und auch sorry, wenn ich zusehr damit rumnerve, ich würde den Sensor nur gern zum Laufen bringen
Konrad Bethmann schrieb: > Die Textformatierung sah in meinem Editor viel besser aus, sorry dafür! Das ist meistens so, wenn man TABs verwendet. Und als Anhang statt inline hätte sich das auch nicht schlecht gemacht.
Der 'char ist beim gcc signed' Fehler ist immer noch drinnen. Merke: WEnn du mit Bytes hantierst, dann nimmst du nicht den Datentyp 'char' sondern entweder 'unsigned char' oder 'uint8_t'. Du fährst am besten, wenn du dir angewöhnst, dass es 3(!) kleine Datentypen gibt. * "signed char" bzw. "int8_t" Die nimmst du für alles, wofür du nur kleine Zahlen brauchst, die aber mit Vorzeichen. Also zb wird eine WOhnraumtemperatur wohl selten größer als +127 bzw. kleiner als -128° Celsius sein. Ein int8_t wäre also passend, wenn keine Kommastellen gebraucht werden, aber negative Zahlen möglich sein sollen. * "unsigned char" bzw. "uint8_t" Die nimmst du immer dann, wenn du kleine Zahlen ohne Vorzeichenerweiterung brauchst. Genau das ist der Datentyp der Wahl wenn man mit Bytes hantiert. Denn hier will man keine Sonderbahandlung eines Bits als Vorzeichenbit haben. Ansonsten natürlich für alles, was nicht negativ werden kann. Zb die Anzahl an Schweissgeräten im Lager einen kleinen Schlosserei wird eher selten negativ sein und wohl auch selten größer als 255. * "char" Reine 'char' benutzt du nur dann, wenn du Textverarbeitung machst. Da kannst du es dem Compiler überlassen, ob er einen char als signed char oder als unsigned char implementiert. Aber auch nur da! In allen anderen Fällen überlässt du es nicht dem Compilerbauer sondern benutzt explizit entweder signed oder unsigned
:
Bearbeitet durch User
Und Programm erst mal abspecken. Du hast Probleme mit der Kommunikation? Dann interessiert die Auswertung erst mal überhaupt nicht. Was dich interssiert ist, dass du 1 Byte zum Sensor schickst und vom Sensor 1 Byte (oder mehrere) als Antwort kriegst. Alles andere in deinem Programm ist erst mal nur überflüssiger Ballast, der selbst wieder Fehler enthalten kann.
Ich glaube ehrlich gesagt nicht, dass das hier
1 | for (i=0;i<65535;i++) if (sht_i == 0){ delay();} |
in deinem Editor besser aussieht. Abgesehen davon, dass es immer noch falsch ist. PINB durch sht_i zu ersetzen löst nicht das Problem, dass du immer noch den kompletten Port einliest und nicht nur den einen interessierenden Pin.
Ich hab jetzt das Datenblatt des SHT nicht studiert. Darf man eigentlich das Timing der Ansteuerung beliebig langsam machen? Wenn ja, dann würde ich das mal empfehlen.
Es hat sich eingebürgert, den Namen von Präprozessordefinitionen gross zu schreiben. Wenns nicht grad das Äquivalent einer Funktion ist. So ist beispielsweise dein "data" für geübte Leser von C Quellcode ziemlich irritierend.
Karl Heinz schrieb: > Darf man eigentlich > das Timing der Ansteuerung beliebig langsam machen? Ja. > Wenn ja, dann würde ich das mal empfehlen. Und dabei zusehen. Apropos Timing, zum ca. dritten Mal: Der SHT ist ein Morgenmuffel. Wie viele seiner Anwender auch, darf er anfangs erst einmal ein Weilchen nicht angesprochen werden.
:
Bearbeitet durch User
Karl Heinz schrieb: > Was dich interssiert ist, dass du 1 Byte zum > Sensor schickst und vom Sensor 1 Byte (oder mehrere) als Antwort > kriegst. Oder zunächst einmal das ACK Bit der grob an I2C orientierten Kommunikation.
Konrad Bethmann schrieb: > void data_lo(void) // 0 an DATA > { > sht_i |= (1<<data); > } > > void data_hi(void) // 1 an DATA > { > sht_i &=~(1<<data); Um einen Ausgang zu steuern muss man den Eingang verändern? Wäre nicht sht_o der geeignetere Kandidat?
Georg G. schrieb: > Um einen Ausgang zu steuern muss man den Eingang verändern? > Wäre nicht sht_o der geeignetere Kandidat? Weder noch. Beitrag "Re: SHT11 an ATmega2560 Es funktioniert nicht"
In einigen der gängigen Libs wird entgegen dem Datenblatt nicht Open Drain genommen sondern "hart" angesteuert. Wenn man den Takt entsprechend steuert, geht das prima. Über den Eingang geht es definitiv aber nicht.
Georg G. schrieb: > In einigen der gängigen Libs wird entgegen dem Datenblatt nicht Open > Drain genommen sondern "hart" angesteuert. Bei 8051 Ports ist das auch nicht wirklich "hart". Um den Pullup kommt man auch dann nicht herum und falsch bleibt auch dann falsch, wenn es funktioniert. Es geht auch nur um die Datenleitung. Die Taktleitung ist unidirektional.
:
Bearbeitet durch User
Der TO verwendet einen ATMega. Und auch die Libs, auf die ich mich beziehe, sind für ATMega. Glaub mir einfach, es funktioniert hervorragend. Der SHT11 wird nur bei passendem Taktpegel niederohmig. Du hast alle Zeit der Welt, den Ausgang umzuschalten.
Und wo liegt der Vorteil? Man muss dann Richtungs- und Ausgaberegister steuern. In der open drain Version hingegen nur die Richtung.
:
Bearbeitet durch User
Hi Zusammen! Vielen Dank nochmal für die Hinweise! Ich habe nun den Verdacht, dass der Sensor kaputt ist, da ich den Befehl für die Temperaturmessung gesendet habe, Oszi sei dank, konnte ich es auch "ansehen". Aber es fehlt die Bestätigung des Sensors, das der Befehl gültig war. Es kann sein, dass ich ihn vorhin beim anschliessen verkehrt gepolt habe, das nimmt er mir bestimmt übel, schöner Mist! Einen Sensor habe ich noch, mal sehen, ob es damit klappt! VG Konrad
So wie es aussieht ist auch dieser Sensor hin, zumindet kommt keine Bestätigung, dass der Befehl gültig ist. Schade!!
Hi! Anscheinend ist auch ein weitere Sensor kaputt, er gibt keine Bestätigung, wenn ich ihm ein Komando sende! Ich warte erstmal, bis ich neue Sensoren bekomme und sehe dann weiter! VG Konrad
Wie wahrscheinlich ist es, dass drei Sensoren mit demselben Fehler kaputt sind? Ist da nicht wahrscheinlicher, dass die Ansprache inkorrekt ist?
hi Dirk! Ja, es ist nicht sehr wahrscheinlich, aber ich denke mal, zwei Sensoren sind durch meinen Dummheit kaputt gegangen, da ich sie verkehrt gepolt angeschlossen habe, bei einem habe ich es auch gerochen, also eigene Dummheit!! VG Konrad
Es gibt doch diese DHT22 oder auch die DHT11 Sensoren, die sind nicht so fummelig. DHT11: 10 Stück für EUR 9,28 ... oder Preisvorschlag :-) http://www.ebay.de/itm/10pcs-DHT11-Humidity-Sensor-Temperature-Sensor-Digital-Output-for-Arduino-DE-/231238598923 DHT11 mit Befestigungsplatine: 1,47 Euro http://www.ebay.de/itm/DHT11-Digitale-Temperatur-Und-Feuchte-Sensor-Modul-Temperatursensor-Kabel-/390794837948 DHT22 (3.3V): 1 Stück für 2,93 Euro, aber dafür genauer. http://www.ebay.de/itm/DHT22-AM2302-Digital-Temperature-and-Humidity-Sensor-Replace-SHT11-SHT15-/140786274816
Hi zusammen! Als ich mir noch makl alles angesehen habe, auch meine Osziaufzeichnungen, fiel mir auf, dass ein Hight an DATA nur knapp 2V sind, der Sensor braucht aber laut Datenblatt min. 80%Vdd was in meinem Fall 3,84 V sind, die aber nicht anliegen. Kann es sein, dass dadurch nichts passiert, klingt mir sehr logisch! Ich habe extra noch mal nachgesehen, es ist auch ein 10k Widerstand, der zwischen DATA und Vdd hängt, wie im Datenblatt angegeben! Die meisten hier nehmen auch die 10 K, und es funktioniert, nun verstehe ich den Fehler erst recht nicht! Viele Grüße Konrad
Konrad Bethmann schrieb: > Als ich mir noch makl alles angesehen habe, auch meine > Osziaufzeichnungen, fiel mir auf, dass ein Hight an DATA nur knapp 2V > sind Ohne Sensor ?
Doch mit sensor am µC, ich habe das schon vorher mal beobachtet, aber nichts dabei gedacht, nun sehe ich das etwas anders!
Wenn keine Kommunikation läuft, dann sollte auf der DATA Leitung über den Pullup-Widerstand die volle Versorgungsspannung anliegen. Wenn das nicht der Fall ist, dann ist was faul. Egal ob das 10K sind oder weniger, die Leitung ist muss offen sein. Bei einem defekten Sensor ist an dieser Stelle natürlich alles möglich. Wenn die 2V aber auch ohne Sensor zu messen sind, dann hast du ein gänzlich anderes Problem.
:
Bearbeitet durch User
Hi zusammen! Welch Wunder, nun funktioniert es doch irgendwie, zumindest sieht es so aus, dass der Sensor meinen Befehl akzeptiert und was misst. Er legt die Datenleitung nach dem Befahl kurz auf Low und dann wieder higth. Nun dauert es ne Weile und dann wird die Datenleitung wieder low. Habe ich das Datenblatt richtig verstanden, dass ich nach dem Low auf der Datenleitung (nach der Messung) Wieder pulse auf die SCL-Leitung geben muss und bit für bit die Messwerte auslesen kann? VG Konrad
Ist die DHT22 Software nicht zu den DHT11 / SHT11 kompatibel ? http://moretosprojects.blogspot.de/2014/01/dht22-blocking-library-for-avr.html Sie funktioniert bei mir wunderbar. Man kann aber nur maximal alle 2 Sekunden einen neuen Wert bekommen, steht jedenfalls so im Datenblatt. Im DHT22 ist ein 4k7 Ohm Widerstand von Vcc nach Data schon integriert.
Anscheinend funktioniert der Sensor wirklich, denn wenn ich den Befehl zur Feuchtemessung gebe, ist die Datenleitun viel eher wieder auf low, als wenn ich den Temperaturbefehl sende. Nach dem ich einige Leute bestimmt zur Verzweiflung getrieben habe, wofür ich mich entschuldige, ist das Fazit des Ganzen, nicht einfach Blind fremden Code zu übernehmen, sonsdern selbst was tun! Danke trotzdem für die Hilfe und wenn ich auch richtige Daten habe(z.B. Temperaturwerte), dann werde ich mich wieder melden! VG Konrad
In dem DHT22 Code von dem Brasilianer kann man das mit den Zeiten wunderschön sehen, der Code ist übersichtlich und hat mir sehr geholfen. Ich hatte damals auch Probleme damit, zum einen weil mir eine Interruptroutine immer während des Lesevorganges reingesprungen ist und ein anderes mal weil ich + und Data vertauscht hatte.
Guten morgen zusammen! Evtl. Können mir die C-Profis noch mal helfen! Nachdem ich nun Hoffnung habe, dass der Sensor tut, was er tun soll, komme ich nicht weiter. Laut datenblatt legt der SHT11 während einer Messung DATA auf higth und wenn die Messung beendet ist zurück auf low. Nun wollte ich mit folgender Schleife warten, bis wieder Low ist und dann weitermachen, doch es klappt nicht und ich erkenne den Fehler nicht! for (a=0;a<65035;a++) { if (!(PIND & (1 << data))) {break;} else {_delay_us(6);} } // Byteeinlessen ... Wie gesagt, nichts passiert! VG Konrad @Mike Danke für deine Hinweise, bin noch nicht dazugekommen, mir den Code richtig anzusehen!
Warum nimmst du nicht erst einmal eine erprobte Lib und änderst dann nach deinen Vorlieben? Hier eine simple Leseroutine (die den Port nicht Open Drain macht, aber dennoch funktioniert). Die Messung mit Warteschleife:
1 | /*---------------------------------------------------------------------------*/
|
2 | static uint8_t measure(uint8_t *p_value, uint8_t *p_checksum, uint8_t mode) { |
3 | |
4 | uint8_t error = 0; |
5 | uint8_t ack = 1; |
6 | uint16_t i; |
7 | |
8 | transmission_start(); |
9 | error = write_byte(mode); |
10 | #ifdef DEBUG
|
11 | lcd_puts_P("CMD-Write: "); |
12 | if (error) { |
13 | lcd_puts_P("ERROR "); |
14 | }
|
15 | else { |
16 | lcd_puts_P("OK "); |
17 | }
|
18 | #endif
|
19 | _delay_ms(1); |
20 | |
21 | /* wait until sensor has finished measurement or timeout */
|
22 | for (i = 0; (i < SHT11_MEASURE_TIMEOUT) && (!error); i++) { |
23 | ack = SHT11_READ_DATA; |
24 | if (!ack) { |
25 | break; |
26 | }
|
27 | _delay_ms(1); |
28 | }
|
29 | |
30 | error += ack; |
31 | #ifdef DEBUG
|
32 | if (error) { |
33 | lcd_puts_P("Timeout "); |
34 | }
|
35 | else { |
36 | lcd_puts_P("Execute OK "); |
37 | }
|
38 | #endif
|
39 | /* read MSB */
|
40 | *(p_value + 1) = read_byte(SHT11_ACK); |
41 | /* read LSB */
|
42 | *(p_value) = read_byte(SHT11_ACK); |
43 | /* read checksum */
|
44 | *p_checksum = read_byte(SHT11_NO_ACK); |
45 | |
46 | return (!error); |
47 | }
|
Und die Byte-Lese-Routine
1 | /*---------------------------------------------------------------------------*/
|
2 | static uint8_t read_byte(uint8_t ack) { |
3 | |
4 | uint8_t i; |
5 | uint8_t value = 0; |
6 | |
7 | SHT11_DATA_IN; |
8 | _delay_us(MINI_DELAY); |
9 | |
10 | /* read value bit by bit */
|
11 | for (i = 0; i < 8; i++) { |
12 | value = value << 1; |
13 | SHT11_SCK_HIGH; |
14 | _delay_us(MINI_DELAY); |
15 | if (SHT11_READ_DATA) { |
16 | /* increase data by one when DATA is high */
|
17 | value++; |
18 | }
|
19 | SHT11_SCK_LOW; |
20 | _delay_us(IF_SPEED); |
21 | }
|
22 | |
23 | /* send ack if necessary */
|
24 | SHT11_DATA_OUT; |
25 | |
26 | if (ack) { |
27 | SHT11_DATA_LOW; |
28 | _delay_us(IF_SPEED); |
29 | }
|
30 | else { |
31 | SHT11_DATA_HIGH; |
32 | _delay_us(IF_SPEED); |
33 | }
|
34 | |
35 | clk_signal(); |
36 | |
37 | /* release data line */
|
38 | SHT11_DATA_IN; |
39 | |
40 | return(value); |
41 | }
|
:
Bearbeitet durch Moderator
Hallo Georg! Danke dir. Ich habe schon einige Libs probiert und nie hat was funktioniert, deshalb habe ich aus den verschiedenen Versionen selbst was zusammen gesetzt, ohne viel Gedöns, aber es klappt nicht so wie ich das will, ich werde wohl noch mal was tun müssen! VG Konrad
Hallo Zusammen! Nun läuft es wunderbar!!! Ich habe den Code von A.K. genommen und es klappt! Ich habe einen ziemlich dummen Fehler gemacht, aber es funktionier und hatte nichts mit dem Auslesen des Sensors zu tun!! Vielen Dank noch mal an alle, aUCH WENN ES VERMEIDBAR GEWESEN WÄRE; SO HABE ICH ZUMINDEST VIEL GELERN; DAS IST MIR AUCH WICHTIG! VG Konrad
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.