Guten Nachmittag, Ich Arbeite immer noch an mein Temperaturmessgerät. Nun bin ich dabei ein Alarm für die Sensoren ein zu führen, denn man einstellen kann. Das Problem ist der Wert(in °C) soll im EEPROM(Externer Chip) gespeichert werden. Bis jetzt habe ich nur ein uint8_t gespeichert, im EEPROM. Wenn ich die vorhandene Funktion für writeEEPROM(adresse, uint8_t data) abändere auf Float so das ein Float geschrieben wird anstatt ein uint8_t. Und ich das nachdem schreiben wieder auslese kommt nur die ganz Zahl als Float zurück also so: writeEEPROM_Float(22, 21.92f); //21.92f schreiben Wenn ich dann mit readEEPROM_Float(22) das ganze wieder auslese und zum USART sende dann kommt nur 21.00 zurück. Kann das vielleicht an der Adressierung liegen? Denn ich schreibe ja die EEPROM Adresse und 0xFF. Mfg Felix.
Wie soll denn ein float in ein Byte passen?
Könnte das daran liegen, dass Dein float 32bit umfasst, Du aber nur ein Byte in den eeprom schreibst? Ich sehe in Deiner Funktion jedenfalls nur einen einzigen Daten-Schreibzugriff.
1 | void writeEEPROM_Float(unsigned int eepromaddress, float data) { |
2 | i2c_start(I2C_Device_Address + I2C_WRITE); |
3 | i2c_write(eepromaddress & 0xFF); |
4 | i2c_write(data); |
5 | i2c_stop(); |
6 | _delay_ms(5); |
7 | }
|
i2c_write(data) schickt nur ein einziges Byte Deines floats. Wie ist denn diese Routine definiert und gibt Dir der Compiler keine Warnung, weil die Typen nicht passen? Gruß, Stefan
Felix N. schrieb: > uint8_t. Und ich das nachdem schreiben wieder auslese kommt nur die ganz > Zahl als Float zurück also so: > > writeEEPROM_Float(22, 21.92f); //21.92f schreiben Schmeiss Float raus, schreibe zwei uint8_t stattdessen, also 21 und 92. Schneller und braucht weniger Platz.
Marc V. schrieb: > Schmeiss Float raus, schreibe zwei uint8_t stattdessen, also > 21 und 92. > Schneller und braucht weniger Platz. Hi. Dieses Idee hat ich auch schon aber, aus einem Float zwei int's zu machen da bin ich immer hängen geblieben. Wie mache ich dem am besten draus 2 Ints?
Wie ist bei Dir i2c_write(data) definiert? Ev. gibt es eine ähnliche Routine, die mehrere Bytes über i2c überträgt. Die wäre das Mittel der Wahl. Z.B.: i2c_writeBlock(uint8_t *pBlock, int dataSize);
1 | void writeEEPROM_Float(unsigned int eepromaddress, float data) { |
2 | i2c_start(I2C_Device_Address + I2C_WRITE); |
3 | i2c_write(eepromaddress & 0xFF); |
4 | i2c_writeBlock((uint8_t*) &data, sizeof(data)); |
5 | i2c_stop(); |
6 | _delay_ms(5); |
7 | }
|
Gruß, Stefan
Felix N. schrieb: > Hi. Dieses Idee hat ich auch schon aber, aus einem Float zwei int's zu > machen da bin ich immer hängen geblieben. Wie mache ich dem am besten > draus 2 Ints? Wie bist du überhaupt beim Float gelandet ? Soviel ich weiss, sendet kein Sensor einen Float als Wert raus ?
Stefan K. schrieb: > Wie ist bei Dir i2c_write(data) definiert? > Ev. gibt es eine ähnliche Routine, die mehrere Bytes über i2c überträgt. > Die wäre das Mittel der Wahl. So sieht die Methode aus:
1 | unsigned char i2c_write(unsigned char data) { |
2 | uint8_t twst; |
3 | |
4 | TWDR = data; |
5 | TWCR = (1<<TWINT) | (1<<TWEN); |
6 | |
7 | while(!(TWCR & (1<<TWINT))); |
8 | |
9 | twst = TW_STATUS & 0xF8; |
10 | if(twst != TW_MT_DATA_ACK) return 1; |
11 | return 0; |
12 | }
|
Marc V. schrieb: > Wie bist du überhaupt beim Float gelandet ? > Soviel ich weiss, sendet kein Sensor einen Float als Wert raus ?
1 | float readTemperatureAnalog(uint8_t channel) { |
2 | float temp = readADC(channel); //Read from ADC |
3 | |
4 | float mV = (temp / 1023.0) * 5000; //Convert to mV with 5 V Ref |
5 | float offSet = mV - 700; // subtract 700 |
6 | float celsius = offSet / 10; // Divide 10 for °C |
7 | |
8 | return celsius; |
9 | |
10 | }
|
Damit schickst Du mehrere Bytes an den I2C:
1 | void i2c_writeBlock(unsigned char *pBlock, int dataSize) |
2 | {
|
3 | int i; |
4 | for (i=0; i<dataSize; i++) |
5 | {
|
6 | i2c_write(*(pBlock+i)); |
7 | }
|
8 | }
|
9 | |
10 | void i2c_readBlockNak(unsigned char *pBlock, int dataSize) |
11 | {
|
12 | int i; |
13 | for (i=0; i<dataSize; i++) |
14 | {
|
15 | *(pBlock+i) = i2c_readNak(); |
16 | }
|
17 | }
|
.. in Deinem Programm (writeEEPROM_Float und readEEPROM_Float):
1 | float floatData; |
2 | ...
|
3 | i2c_writeBlock((unsigned char*) &floatData, sizeof(data)); |
4 | ...
|
5 | i2c_readBlockNak((unsigned char*) &floatData, sizeof(data)); |
6 | ...
|
Alles aus dem Stegreif geschrieben und ungetestet! Gruß, Stefan
:
Bearbeitet durch User
Felix N. schrieb: > float readTemperatureAnalog(uint8_t channel) { > float temp = readADC(channel); //Read from ADC > > float mV = (temp / 1023.0) * 5000; //Convert to mV with 5 V Ref > float offSet = mV - 700; // subtract 700 > float celsius = offSet / 10; // Divide 10 for °C > > return celsius; > > } Wenn es um AVR geht, dann ist laut ATMEL ADC = Vin * 1024 / Vref, also ist Vin = Vref * ADC / 1024 oder 5000 * ADC / 1024 mit 5V Vref wobei 0x00 = GND und 0x3FF = Vref - LSB Auflösung ist somit 4,887mV oder ungefähr 204 Werte pro Volt. Das ist genau genug, ADC ist auch nicht 100% genau. Um die ganze Rechnerei mit Float zu sparen, kannst du mit Long etwa so rechnen: uint8_t Ganz = ADC / 204; long lk = ((ADC % 204) * 1000) / 204; uint8_t Dez = lk / 10; Wie kommst du auf deine Berechnung mit Offset und so ?
Marc V. schrieb: > Wie kommst du auf deine Berechnung mit Offset und so ? Ich nutze denn LM35 aus Sensor. Dieser gibt bei 0 °C 0 mV aus und bei 150 °C 1500 mV um aber bis -55 Grad zu messen braucht er eine negative Spannung. Da man diese aber nicht mit dem ADC messen kann. Habe ich an Ground eine 0,7 Volt angeschlossen mit einer 1N914 und ein 1k Ohm Widerstand. So kann ich auch im plus Bereich negative Temperaturen messen. Die 700 Offset sind also bei -33 Grad gibt der LM35 ein mV von 370 mV aus. -330 + 700 = 370 mV. Also -330 Entsprechen -33 Grad bei Full Range. Durch die Modifikation liegt die Spannung bei -33 Grad nicht bei -330 mV sondern bei +370 mV. Sonst kann ich keine negativen Temps messen.
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.