So - schon wieder ich. Nachdem die Chipkarte funktioniert, kann ich den nächsten Punkt meiner 'ToDo Liste' angehen. Ich habe mir ein Sample von Sensirion SHT11 (Temp und Feuchtemesser) besorgt und möchte diesen nun ansteuern. Mit dem C Beispiel der App Notes hab ich nun das Programm geschrieben und es funktionert schon gar nicht schlecht. Des Sensor antwortet. Leider lese ich nur schwachsinnige Werte aus. Bei jedem Auslesen kommen andere 'Integer' Werte raus. Bei den fertigen Floatwerten kommen immer noch teilweise Buchstaben mit ... Lese ich das Statusregister aus, so zeigt mein LCD konstant -13 an (obwohl ich beim Auslesen den Wert in ein UNSIGNED char schreibe). Die Integerwerte, die ausgegeben werden, sind immer die selben (z.B. 255,200,-864,1554,2827,...) Jemand ne Idee, woran das liegen kann (denn ich denke, die Kommunikation funktioniert schon, da das Statusregister immer gleich ist)? (Quelltext is im Attachment) Ich bin für jede Hilfe dankbar! Mike PS. Mega8 und CodeVision
Ich hab es gerade geschafft, richtige Werte auszulesen, aber mein Programm ist nicht so flexibel und vollständig wie dein. Wenn du trotzdem Interesse hast, dann melde dich nochmal. P.S. Ich hab auch mit CodeVision gearbeitet.
Hallo, bevor sich jemand fragt, warum ich den Thread wieder aus dem Archiv geholt habe: Ich habe ein Problem mit meinem SHT11 (am Atmega16), dass scheinbar identisch ist mit dem von Mike. Auch auf meinem Display kommen sehr merkwürdige Werte an: Die Temperatur ist immer 0, die Feuchte-Werte wiederholen sich regelmäßig (4224, -28544, 4224, usw.). Auch ich habe den Sensirion-C-Code verwendet und ihn an den nötigen Stellen angepasst. Weiß jemand Rat, woran es liegen könnte? Gruß Christoph
Hi, ich habe den sensor anfang dieses jahres an einem pic betrieben... habe allerdings das ganze in assembler geschrieben einschließlich der umrechnung der werte die vom sensor kommen... vielleicht liegt es an der implementierung der formeln. der sensor gibt 12 bit werte bei luftfeuchte und 8 bit werte bei temperatur zurück. dieser wert muss zuvor in einer quadratischen gleichung in eine luftfeuchte umgerechnet werden. datenblatt.. ich habe das zuvor etwas von einem char gelesen. char sind meiner meinung nach 8bit signed nur 7....lang... weiß ja nicht wie tief ihr da drin steckt... dennis
Hallo, also ich habe heute Nachmittag mein Problem gefunden. Im Herstellercode ist meines Erachtens ein Fehler, der dazu führt, dass LSB und MSB vertauscht werden. Statt *(p_value) = sensor_read_byte(ACK); //read the first byte (MSB) *(p_value+1) = sensor_read_byte(ACK); //read the second byte (LSB) in der measure-Routine habe ich jetzt *(p_value+1) = sensor_read_byte(ACK); //read the first byte (MSB) *(p_value) = sensor_read_byte(ACK); //read the second byte (LSB) geschrieben und siehe da, es funktioniert wunderbar. Da ich bislang nicht viel in Richtung Mikrocontroller gemacht habe bzw. noch garnichts mit Zeigern, ist mir das erst relativ spät aufgefallen. Gruß Christoph
Das hängt davon ab, ob die Darstellung von 16-bit-Werten big-endian oder little-endian ist. Das könnte von Prozessor zu Prozessor (Familie) und von Compiler yu Compiler verschieden sein. Das Beispiel ist für den GCC geschrieben, ihr verwendet CodeVison. Ob es daran liegt - eine Vermutung.
@Profi: Ja, das wäre eine logische Erklärung. Das Beispiel ist allerdings für Keil geschrieben, ich benutze GCC.
Hi! Soweit ich weiß wird der AVR als little-endian behandelt, das sollte aber unabhängig vom Compiler sein. Ein Anhaltspunkt könnten die X, Y, Z Register bieten. $1a ist das low-Byte des x-Registers $1b ist das high Byte des y-Register Davon ausgehend wird der 16 Bit Wert 0xAABB im Speicher in der Reihenfolge 0xBB 0xAA abgelegt. Daher sollte man vorsichtig sein wenn man versucht Zahlen durch direktes Ablegen im Speicher zu erzeugen. Besser wäre etwas in der Art *(p_value) = ((((unsigned int) sensor_read_byte(ACK))<<8 )& 0xFF00); *(p_value) += (((unsigned int) sensor_read_byte(ACK)) & 0xFF); Wobei p_value vom Typ unsigned int * sein muß; Das sollte funktionieren egal ob big oder little endian. Gruß Dirk
Hi, habe auch ne Problem mit dem SHT15 Sensor. Hab mir schon die ganzen Quelcodes hier durchgelesen, aber leider will meiner nicht. Es wir immer nur 0 für temp und humi angezeigt ! hab schon mindestends 100 mal den code verändert und kontrolliert, komme einfach nicht auf die Lösung. Vielleicht findet einer von euch etwas... Benutzte Winavr mit Atmega8 @ 8Mhz Gruß Jan H. PS: Habe den original Sensirion Code benutzt und umgeschrieben, teileweise auch von anderen Codes etwas übernommen.
PullUp auf PortB4? OT-Vorschlag: for (i=0x80;i>0;i/=2) //shift bit for masking kürzer: for (i=0x80;i;i/=2) //shift bit for masking wobei i Kurzform von i!=0 ist
was meinst du mit Pullup auf PortB4 ? hab ne 10k von Data port auf Vcc muss ich da noch was verändern ? oder den Widerstand weglaßen ?
Ja, den meine ich. Bei längerer Leitung könnten 10k zu viel sein, versuche mal 1 .. 5k.
Hab mir mal den Code von Mike angeschaut und auch auf meinen ATmega 16 angepasst. Aber er zeigt mir nur starre Werte an. In der ersten Zeile steht 16384 und in der dritten Zeile -13107. Kann mir jemand sagen ob das jetz Adress Werte sind oder ob das die Werte für Temp und Humi sind aber nicht richtig dargestellt bzw gewandelt? Hat sonst jemand diesen Code ausprobiert und funktionsfähig hinbekommen?
Jetz hab wieder was geändert und hab jetz für Temp -40 und für Humi 0 stehen. Hab auch das versucht was Christoph vorgeschlagen hat mit dem ändern des einlesens des MSB und LSB aber bringt bei mir keinen fortschritt. Kann mir jemand helfen ich poste nochmal meinen Code.
Ich hatte auch so ein merkwürdiges Phänomen. Bei mir ist es aber tatsächlich daran gelegen, dass ich am Steckboard den 100nF Kondensator nicht bestückt habe...
hast du dir schonmalden Samplecode bei Sensirion angeschaut? http://www.sensirion.com/images/getFile?id=95 Werner
Den Code hab ich mir angeschaut kann man ja mit meinem vergleichen das fast der gleiche wie Mike seiner und entspricht dem von Sensirion.
@Thomas P wenn du das Problem auch hattest kannst du doch mal meinen code mit deinem vergleichen und sagen ob da irgendwas fehlt oder nich.
na super dann kannste ja über meinen code schauen und sagen ob der i.O. ist oder ob ich doch noch nen hardware problem hab
>na super dann kannste ja über meinen code schauen und sagen ob der i.O. >ist Da sind zuviele Kommentare drin... >oder ob ich doch noch nen hardware problem hab Schaun mer mal...
zu viele ich hab noch keinen gesehn der sich über kommentare beschwert hat. is doch meistens das gegenteil. aber wär nett wenn des machen würdest!
Hallo Steffen, Hast du beim Atmega16 das Jtag disabled? Jtag ist per default angeschaltet und damit gehen einige Portpins nicht so, wie gewünscht. Falls du kein oszi hast kannst doch auch das Timing mit Schleifen so verlangsamen, dass du mit einem Multimeter die Daten- und Clockleitung messen kannst. Hast überhaupt ne Anzeigeänderung, wenn du das ganze ohne Sensor ablaufen lässt?
Wie schalte ich den JTAG aus obwohl ich denke das der aus is. Ich hab nochmal den ganzen Code überprüft, er ist haargenau der gleiche wie ich ihn hab, ausser halt die Port Pins. Ne hab keine Anzeigenänderung, is halt doof man weis nie ob der Sensor die Adresse verstanden hat oder nich erst ma ergebnis.
So JTAG is aus. Also liegts daran nicht. Sind die 100nF Kondensatoren Pflicht an der GND und VCC Leitung? Ich hab auch nur einen Pull-Up Widerstand an der Datenleitung dran reicht das auch aus?
Dann schliesse statt des Sensors erstmal ne LED an, dann schauste ob (mit delays im Code) ob das gewünschte Bitmuster überhaupt am Sensor ankommt. Wenn die LED schon nicht so blinkt, wie sie sollte, kann man weitersehen. Natürlich 2 LEDs, eine bei Clock und eine bei Data. Ja, der 100nF ist Pflicht.
char s_write_byte(unsigned char value) { unsigned char i,error=0; DDRC = 0b00000011; // DATA Ausgang for (i=0x80;i>0;i/=2) //shift bit for masking { if (i & value) DATA_OUT=1; //masking value with i , write to SENSI-BUS else DATA_OUT=0; delay_us(2); SCK=1; //clk for SENSI-BUS delay_us(5); //pulswith approx. 5 us SCK=0; } DATA_OUT=0; DDRC = 0b00000010; // DATA Eingang !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! SCK=1; //clk #9 for ack delay_us(2); error=DATA_IN; //check ack (DATA will be pulled down by SHT11) delay_us(2); SCK=0; return error; //error=1 in case of no acknowledge } wieso DDRC = 0b00000010; // Data Eingang also die Datenleitung stellst du hier ja wohl auf Ausgang, aber den Clock auf Eingang, zuminsdest danach: #define DATA_OUT PORTC.1 #define DATA_IN PINC.1 #define SCK PORTC.0 Ich hab jetzt aber keine Zeit den ganzen Code durchzugehen. Gruß Volker
Gute Frage ist es eigentlich nötig immer die Datenrichtung neu festzulegen? Bei dem Sample Code ist das ja gar nicht oder is das bei Keil ganz anders?
bei nem 8051 kann man nicht zwischen Ein- und Ausgang umschalten, zumindest hat der kein Datenrichtungsregister. Wenn man einen Port als Eingang benutzen will, schreibt man einfach eine 1 drauf, die dann extern nach Gnd gezogen werden kann. Bei deinem Atmega musst du das sehr wohl immer zur richtigen Zeit machen. Gruß Volker
In deinen ganzen Funktionen stellt du nicht die Daten- sondern immer die Clockleitung von Ausgang auf Eingang bzw. umgekehrt um. Du mußt aber die Datenleitung umstellen, Clock sollte immer auf Ausgang liegen. Gruß Volker
#define DATA PORTC.1 #define SCK PORTC.0 char s_write_byte(unsigned char value) { unsigned char i,error=0; DDRC = 0b00000010; // DATA Ausgang Ja aber Clock steht nun auf Eingang, also falsch. Dasselbe hier: char s_read_byte(unsigned char ack) { unsigned char i,val=0; DDRC = 0b00000000; // DATA Eingang ... Am besten du gehst alle den kompletten Code nochmals durch, und machst dann den vorgeschlagenen Test mit Leuchtdioden. Gruß Volker
DDRC = 0b00000011; // DATA Ausgang, Clock Ausgang DDRC = 0b00000001; // DATA Eingang, Clock Ausgang Volker
Ja entschuldige das hab ich inzwischen auch gemerkt und geändert. Hab das ganze mal mitm Oszi durchgemessen und festgestellt das die Clock Leitung alle 260ns einen Takt bekommt und die Datenleitung alle 20µs. Das kann ja nich sein die Datenleitung sollte doch nur dann einen High pegel haben wenn man sie entsprechend anspricht. Ich versteh es nich.
DATA=0; DDRC = 0b00000001; // DATA Eingang SCK=1; //clk #9 for ack delay_us(2); error=DATA; //check ack (DATA will be pulled down by SHT11) Beim Einlesen darst du nicht über DATA (Portc) gehen sonder über Pinc, welches du ab einer gewissen Version rausgenommen hast. Also ist bei dir error immer 0. Ob die 2us dem Sensor reichen, weiss ich grad nicht. Vielleicht solltest du dich erstmal mit den Portfunktionen des ATMega vetraut machen, also DDR, PORT, PIN, Pullup... Ansonsten Step by Step, also erstmal schauen, ob der Sensor die überhaupt ein ACK gibt. Muss jetzt leider weg, vielleicht später nochmal. Volker
Und sag nicht, dass du den Code, den du zuletzt gepostet hast ohne Fehler kompilieren hast können. error=DATA_IN; //check ack (DATA will be pulled down by SHT11) Wo ist denn DATA_in überhaupt defeniert. In einem deiner ersten Codes wars noch drin. #define DATA_IN PINC.1 Also wieder reinnehmen und den Eingang über DATA_IN einlesen. Volker
So hab dieses Stück Code nochmal durchs Oszi gejagt und der Sensor zieht nicht wie im Datenblatt angegeben alleine die Datenleitung auf Low wenn das Byte übertragen wurde. Heißt da jetz Sensor kaputt oder zu hoher Pull-Up Widerstand oder sollte ich besser den internen des Controllers nehmen? while(1) { s_transstart(); if(error!=0) { s_connectionreset(); //in case of an error: connection reset lcd_clear(); lcd_gotoxy(0,0); lcd_putsf("Error"); } s_write_byte(MEASURE_HUMI); char s_write_byte(unsigned char value) { unsigned char i,error=0; for (i=0x80;i>0;i/=2) //shift bit for masking { if (i & value) DATA=1; //masking value with i , write to SENSI-BUS else DATA=0; SCK=1; //clk for SENSI-BUS #asm("nop\nop\nop"); //pulswith approx. 5 us SCK=0; } DATA=1; SCK=1; error=DATA; SCK=0; /*if (DATA==0) { SCK=1; //clk #9 for ack #asm("nop"); //check ack (DATA will be pulled down by SHT11) SCK=0; } else error=DATA;*/ return error; //error=1 in case of no acknowledge }
Wo ist deine Datenrichtungsumschaltung (Eingang, Ausgang) geblieben? Auch liest du noch immer nicht über Pin ein. siehe hier: error=DATA; Versuche doch mal umzusetzen, was ich gestern schrieb, so wird das jedenfalls nichts.
Das damnit nix zu tun. Er gibt mir ja Fehler zurück weil der Sensor die Leitung selber nich auf Low zieht. Selbst wenn ich die Datenrichtung festlege, was ich auch festeingestellt habe // Port C initialization // Func0=Out Func1=Out Func2=In Func3=In Func4=In Func5=In Func6=In // State0=0 State1=P State2=T State3=T State4=T State5=T State6=T PORTC=0x02; DDRC=0x03; klappt es nicht. Da wo der Sensor was machen soll, passiert nichts. Solang der die Leitung nicht selber auf Low zieht geht gar nichts mehr.
1. Ich habe mir den Thread nicht komplett durchgelesen. 2. Der SHT11 arbeitet mit einem I²C-kompatiblen Bus (physical layer). Das bedeutet für die Datenleitung, dass sie zwischen GND und Hochohmig umgeschaltet wird. Für den H-Pegel sorgt ein entsprechender Pull-Up-Widerstand. Auf die gleiche Art kann man mit der Clock-Leitung umgehen. Das Umschalten zwischen den beiden Pegeln auf der Datenleitung geschieht durch umschalten des Datenrichtungsregisters (DDRC). Dabei sollte der PORTC beim Datenleitungsbit auf 0 (GND) geschaltet sein. Ergo: Durch die Steuerung per DDR muß man die Bit-Richtung der Datenleitung invertieren. Wenn dort eine "1" hineinschreibt, wird auf Ausgang geschaltet. Dieser liegt aber auch GND. Schreibt man eine "0" ins DDR, wird der Ausgang in den hochohmigen Zustand geschaltet (durch den Pull-Up auf H-Pegel). Um dann noch vom SHT11 die Daten empfangen zu können, muß man ins DDR eine "0" schreiben. Meine SHT11-Routine (IAR-C) wird euch nichts bringen, da der Sensor über eine andere Art am Controller hängt. Also: ändere die Bitrichtung, und du solltest mehr Erfolg haben.
Er gibt mir ja Fehler zurück weil der Sensor die Leitung selber nich auf Low zieht. Selbst wenn ich die Datenrichtung festlege, was ich auch festeingestellt habe Wer gibt dir nen Fehler zurück? Etwa die Funktion s_write_byte? Die wird die immer einen Fehler zurückliefern so wie das konfiguriert ist. DATA=1; SCK=1; error=DATA; ergo folgt error=1, da kann der Sensor machen was er will. Das muss so sein: 1. Port auf Eingang umschalten (ist nun durch extrenen Pullup high) error=DATA_IN; (vorher definiert #define DATA_IN PORTC.1)
@Rahul, der Trollige
>Der SHT11 arbeitet mit einem I²C-kompatiblen Bus (physical layer).
Genau DAS steht NICHT im Datenblatt, sondern das Gegenteil. Nur weil der
einen Open Drain Datenausgang hat, ist der noch lange nicht auch nur
annähernd I2C kompatibel. Vom logischen Protokoll mal ganz zu schweigen.
MfG
Falk
>Genau DAS steht NICHT im Datenblatt, sondern das Gegenteil. Stimmt... Punkt 2.2 ABER (aus der FAQ): "5. Is your bi-directional 2-wire interface compatible with I2C ? No it is not. The difference is in the start/stop sequence (transition start with SHTxx) and how the SHTxx humidity sensor signals the end of a measurement. SHTxx should not share a I2C bus with I2C components. However sharing of the SKC line and using a dedicated DATA line for the SHTxx humidity sensor will work well." Es wird das gleiche Problem wie beim TWI sein... http://www.sensirion.com/en/02_sensors/03_humidity/02_faq/08_faq.htm >Vom logischen Protokoll mal ganz zu schweigen. logisches Protokoll != physical layer, oder?
>Er gibt mir ja Fehler zurück weil der Sensor die >Leitung selber nich auf Low zieht. Selbst wenn ich die Datenrichtung >festlege, was ich auch festeingestellt habe Der arme kleine Sensor soll gegen die Push-pull-Endstufe des AVR anstinken? Das wird er (bzw. sein Ausgangstreiber) nicht besonders mögen.
@Rahul, der Trollige hast schon recht mit deiner Umschaltung zwischen High und Low über das DDR-Register, ich habe es bei meinen Routinen genauso gemacht. Das ganze geht aber auch so, wie Steffen das probiert, allerdings muss er verstehen, dass er einen Portpin nicht über PORTx sondern über PINx einliest. MfG Volker
"Der arme kleine Sensor soll gegen die Push-pull-Endstufe des AVR anstinken? Das wird er (bzw. sein Ausgangstreiber) nicht besonders mögen". Deshalb muß er ja bevor er einliest auf Eingang umschalten.
>Deshalb muß er ja bevor er einliest auf Eingang umschalten.
Oder er lässt es gleich...
So siehts jetz aus und der Sensor macht eigenständig ein Pull Down. Aber er sollte dann doch in den Messzustand gehen für ein paar ms laut Datenblatt. Er tut das aber nur für ein paar us. Muss ich denn noch was beachten.? #define DATA_OUT PORTC.1 #define DATA_IN PINC.1 #define SCK PORTC.0 char s_write_byte(unsigned char value) { unsigned char i,error=0; for (i=0x80;i>0;i/=2) //shift bit for masking { if (i & value) DATA_OUT=1; //masking value with i , write to SENSI-BUS else DATA_OUT=0; SCK=1; //clk for SENSI-BUS #asm("nop\nop\nop"); //pulswith approx. 5 us SCK=0; } DDRC=0x01; SCK=1; error=DATA_IN; SCK=0; return error; //error=1 in case of no acknowledge }
Nun ja, die s_write_byte funktion scheint ja nun zu funktionieren. Was für einen Befehl schreibst du zum Sensor? Wie geht es nach der Schreibfunktion im Programm weiter? Woher weißt du, dass der Sensor nur für ein paar us im Messzustand ist? Übrigens hier noch eine kurze Erklärung, weshalb die Methode, von Rahul dem trolligen eigentlich die bessere ist. SCK=0; } DDRC=0x01; SCK=1; Angenommen das letzte Bit, das du an den Sensor schreibst ist eine 1, der Controller-Port steht noch auf Ausgang, dann kommt SCK=0. Nun will der Sensor die Datenleitung auf 0 ziehen, also Kurzschluss, der erst aufgehoben wird, nachdem der Port auf Eingang umgeschaltet wurde. Wenn der Sensor also extrem schnell ist, könnte dies zu Problemen führen. Volker
Den Befehl gebe ich dem Sensor den führt er auch aus. MEASURE_TEMP 0x03 //000 0001 1 Dann steht aber im Datenblatt, das der Sensor für eine 12bit Messung 55ms braucht. D.h. die DATA Leitung ist solange auf High und die SCK Leitung auf Low. Wenn ich aber am Oszi das darstelle ist nach ein paar us Schluss.
Ist sichergestellt, dass der Port während der Messung auf Eingang steht? Falls das Programm vor Beendigung der Messung den Port wieder auf Ausgang stellen sollte, gehts natürlich schief. Volker
@Steffen Bienert habe glaube ich das gleich Problem wie du mit einem sht-75, kannst du mir sagen woran es bei Dir lag? Danke :-)
oben und im Datenblatt steht folgende Zeile: #asm("nop\nop\nop"); //pulswith approx. 5 us Ich habe nun von C keine Ahnung, aber das sieht mir danach aus, als ob 3 NOPs generiert werden, also 3 Takte, wobei die Clockfrequenz nicht angegeben ist oder ich diese übersehen habe. Wie kommt man nun mit 3 Clockzyklen auf 5 µs? Was ist da richtig? Ich verwende ATMega32 mit 8 Mhz Takt und Assembler. mfg
Dear Steffen Bienert and Volker , Would you please provide me the final code! I unfortunately don't understand german so I couldn't follow the discussion! Thanks
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.