Mittwoch, 19. Juni 2013, 01:25 UTC+2

Sie sind nicht angemeldet.

  • Anmelden
  • Registrieren

Lieber Besucher, herzlich willkommen bei: LedStyles.de. Falls dies Ihr erster Besuch auf dieser Seite ist, lesen Sie sich bitte die Hilfe durch. Dort wird Ihnen die Bedienung dieser Seite näher erläutert. Darüber hinaus sollten Sie sich registrieren, um alle Funktionen dieser Seite nutzen zu können. Benutzen Sie das Registrierungsformular, um sich zu registrieren oder informieren Sie sich ausführlich über den Registrierungsvorgang. Falls Sie sich bereits zu einem früheren Zeitpunkt registriert haben, können Sie sich hier anmelden.

Organized

LedStyles Newbie

21

Donnerstag, 19. April 2012, 19:58

Kann die Funktionen jetzt nutzen...

Aber entweder ist die Bibliothek fehlerhaft, oder ich zu blöd. Der Compiler meckert wegen der Konstante "DDC7" herum, die kennt er nicht, steht aber so im Quelltext der Bib.? Habe es mal spaßeshalber in 7 geändert, dann kann ich es kompilieren, linken und überspielen, aber hier das nächste Problem: So wie ich dachte, man müsse die Temperatur aus dem LM75 auslesen, klappt es wohl nicht.

Er hat ja 9 bit.
0 0000 0000

Das MSB gibt an, ob die Temperatur positiv oder negativ ist. Das LSB gibt an, ob die Nachkommastelle 5 oder 0 ist (also *,5 oder *,0). Das ist mir aber egal, von daher könnte ich das Byte einfach um einen nach rechts verschieben und gut ist.

Wie lese ich das aber jetzt aus? Ich habe 2 mal die Lese-Methode aufgerufen, das erste mal habe ich den Rückgabewert (Aufruf mit ACK) verworfen, da darin ja nur angegeben ist, ob die Temperatur positiv oder negativ ist. Beim zweiten Auslesen (NAK) habe ich dann die Temperatur eingelesen und um einen nach rechts geshiftet.

In temp steht dann aber ein Wert drin, der sich nicht ändert. Blöderweise weiß ich halt auch nicht, welcher da drin steht :( Aber zumindest nicht die Temperatur, sonst würde er sich ja ändern.

Quellcode

1
2
3
4
5
6
7
8
9
10
i2c_master_init();
	
while (1) {
	// Temperatur holen
	i2c_master_start();
	i2c_master_read(0);
	temp = i2c_master_read(1);
	i2c_master_stop();
	temp >>= 1;
	[...]
  • Zum Seitenanfang

maveric00

LedStyles Praktikant

22

Donnerstag, 19. April 2012, 20:41

Hallo,

der I2C-Bus funktioniert etwas anders, als Du es hier versuchst: Der Master schreibt die Adresse des Bauteils, welches er ansprechen möchte auf den Bus und liest dann entweder Daten vom Bus oder schreibt einen Befehl auf den Bus.

Diese Adresse setzt sich beim LM75 aus einem Herstellerteil, einem LM75-Teil und dem R/~W-Teil zusammen, die miteinander oder-verknüpft sind. Der Herstellerteil ist 0b1001 (<<4),der LM75-Teil hat 3 Bit (<<1), je nachdem, wie die Pins 5,6 und 7 mit Ground oder mit VCC verbunden sind. Welche Jumperstellung welchem Wert entspricht ist mir nicht ganz klar (bei einer flüchtigen Suche habe ich auch Hinweise gefunden, dass das Datenblatt die vertauscht hat). Deswegen einfach alle Jumper offen lassen und beide Werte ausprobieren, wenn es mit dem ersten nicht klappt. Das letzte Bit ist eine 1 für Lesen und eine 0 für schreiben. Damit muss als erstes Byte ein 0b1001xxx1 geschickt werden, mit xxx = 000 oder 111.

Somit muss Deine Code-Sequenz etwa so aussehen:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
i2c_master_init();
	
while (1) {
	// Temperatur holen
	i2c_master_start();
	i2c_master_write(145); // Adresse senden, entspricht 0b10010001, alternativ 159 fuer 0b10011111
	temp = i2c_master_read(0); // mit ACK, den Wert merken
	temp2 = i2c_master_read(1); // mit NACK, den wert kann man verwerfen, wenn das LSB nicht interessiert
	i2c_master_stop();
	// temp >>= 1;   <-- dies ist nicht notwendig, da nur das high-byte der Temperatur verwendet wird 
	[...]


Das Datenblatt für den LM75 findest Du unter anderem hier. Dort ist auch auf Seite 11 die Bitsequenz dargestellt, die zum Lesen der Temperatur gesendet werden muss.

Das ist jetzt natürlich rein theoretisch, ich hoffe, dass es funktioniert...

Schöne Grüße,
Martin
  • Zum Seitenanfang

maveric00

LedStyles Praktikant

23

Donnerstag, 19. April 2012, 20:47

Hallo,

noch was vergessen... Diese Sequenz:

Quellcode

1
2
3
4
5
6
#define I2C_DDR			DDRC					// Register für die I2C Kommunikation
#define I2C_DDR_REG_BIT	DDC7					//
#define I2C_PORT		PORTC					// I2C Port definition

#define SCL				PC6						// Port B Pin 1
#define SDA				PC7						// Port B Pin 2


muss an das myAVR-Board angepasst werden, je nachdem an welchem Pin SCL und SDA hängen. Dabei muss die Pin-Nummer von SDA sowohl bei SDA als auch bei I2C_DDR_REG_BIT gesetzt werden (also hier nicht die 7 wie oben geschrieben, sondern entweder die 3 oder 4, die Zuordnung geht aus Deinem Posting nicht ganz eindeutig hervor).

Schöne Grüße
Martin
  • Zum Seitenanfang

Organized

LedStyles Newbie

24

Donnerstag, 19. April 2012, 21:08

SDA: Port C, Pin 3
SCL: Port C, Pin 4

Konfiguration:

Quellcode

1
2
3
4
5
6
7
8
9
#define I2C_DDR			DDRC					// Register für die I2C Kommunikation
#define I2C_DDR_REG_BIT	DDC3						//
#define I2C_PORT		PORTC					// I2C Port definition

#define SCL				PC4
#define SDA				PC3

#define SDA_LESE_PIN 	PINC
#define SDA_LESE_BIT 	SDA


Temperatur holen:

Quellcode

1
2
3
4
5
i2c_master_start();
i2c_master_write(TEMP_ADDR); // TEMP_ADDR = 0b10010001
temp = i2c_master_read(0);
temp2 = i2c_master_read(1);
i2c_master_stop();


Funzt nicht! :(
  • Zum Seitenanfang

maveric00

LedStyles Praktikant

25

Donnerstag, 19. April 2012, 22:10

Hallo,

wenn es mit dem anderen Wert auch nicht funktioniert (10011111), dann wäre mein nächster Schritt, mit zwei Low Current LEDs (+ Vorwiderstände, dann reicht allerdings der integrierte Pullup für SDA nicht mehr aus, und es muss ein externer Pullup in Größe von ~2-4 kOhm eingeplant werden) oder (etwas schwieriger, da der Takt bei nur einem Messgerät nicht sichtbar ist) mit einem Multimeter oder einem Oszilloskop SCL und SDA (bzw. nur SDA) anzusehen, ob die Bitfolge dem Datenblatt entspricht (möglichst direkt am LM75). Dazu kann man die delay definitionen alle auf _delay_ms(1000) setzen, dann wird das schön langsam herausgetaktet. Hab' ich mal so gemacht, als ich eine I2C-Routine entwickelt habe, die 8 I2C-Busse gleichzeitig bedienen konnte. Der Source davon nützt Dir allerdings nicht wirklich etwas, da ich bisher auch keinen Fehler in den verlinkten Routinen entdeckt habe.

Alternativ kann man auch zwei LEDs mit Vorwiderständen an zwei andere Ausgänge hängen, die SDA und SCL-Definitionen entsprechend anpassen und dann zumindest die Daten des Masters überprüfen (der Slave, da nicht vorhanden, liefert dann immer eine 1 zurück). Allerdings fließt dann bei SDA nur zwischen 0.1 und 0.3 mA, was eventuell etwas wenig ist, um eine LED zum leuchten zu bringen. Auch hier kann dann ein externer Pullup in der Größenordnung 300-500 Ohm helfen (bei "normalen" LEDs, die werden dann zwar mit deutlich unter 20 mA betrieben, dafür grillt man den AVR aber auch nicht) .

Wird aber beides sehr eng bis morgen, über das Wochenende könnte es aber klappen (wenn Du entweder Multimeter oder LEDs und Widerstände hast).

Da ich weder die Hardware habe, noch die myAVR-Seite aktuell die Dokumente 'rausrückt, kann ich nicht mehr viel weiter raten. Ich drücke aber beide Daumen...

Schöne Grüße,
Martin
  • Zum Seitenanfang

Organized

LedStyles Newbie

26

Dienstag, 24. April 2012, 10:56

Hi

Ich besorge mir heute den LM335 und einen passenden Widerstand von 2,5kOhm. Ist vllt. nicht so genau, aber das ist mir jetzt ziemlich egal. Abgabe ist jetzt endgültig am Donnerstag (die gesamte Klasse bekommt nichts gebacken weil der Lehrer einfach nichts erklärt bzw. es selbst nicht kann :D).

Quellcode

1
2
3
4
5
6
7
8
9
O 5V
|
R 2,5kOhm
|
|-- 10mV/K
|
LM335
|
O GND


Funktioniert so doch, oder?

Wie ist das mit dem Analog-Digital-Converter des Atmega8? Der kann doch von 0V bis 5V in 10bit-Auflösung umwandeln oder?

EDIT: Habe gerade gelesen, dass er von 0V bis VREF umwandeln kann. Am einfachsten benutze ich dann die interne VREF (2,56V) und schalte einfach zwischen "10mV/K" (bei 0° = 273K * 10mV = 2,73V) und ADC zwei Dioden (also Spannungsabfall 1,5V etwa) oder? Dann kann ich ja bis (2,73V - 1,5V) / 10mV = 123°C messen, ohne VREF zu verändern, oder?

Gruß,
Andy

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Organized« (24. April 2012, 11:04)

  • Zum Seitenanfang

Kanwas

Bronze LedStyler

Beiträge: 3 196

Wohnort: 5....

27

Dienstag, 24. April 2012, 11:24

Du kannst auch die Versorgungsspannung als Referenz nehmen. Das sind dann deine 5V. Das hat dann auch den Vorteil, dass Versorgungsspannungsschwankungen den Messwert nicht verfälschen.
Mir persönlich gefällt die ADC Routine von mikrocontroller.net ganz gut ;)
Sämtliche Angaben ohne Gewähr und ohne Anspruch auf Vollständigkeit!
  • Zum Seitenanfang

Organized

LedStyles Newbie

28

Dienstag, 24. April 2012, 14:42

Also einfach 5V (die auch am Vcc anliegen) an den AREF-Pin packen? Muss ich dann noch was an den Fusebits ändern, oder erkennt der das automatisch? Nicht, dass ich da einen Kurzschluss produziere.

Auszug aus Datenblatt:

Zitat

If the user has a fixed voltage source connected to the AREF pin, the user may not use the other reference voltage options in the application, as they will be shorted to the external voltage. If no external voltage is applied to the AREF pin, the user may switch between AVCC and 2.56V as reference selection. The first ADC conversion result after switching reference voltage source may be inaccurate, and the user is advised to discard this result.


Unterstrichen: Also muss ich irgendwas ändern? Oder darf ich im Programmablauf kein bestimmtes Bit in einem Register setzen?

Fett: Oder muss ich gar nichts an AREF anschließen? Da steht ja, dass man zwischen Vcc und 2,56V wählen kann. EDIT: Ist es richtig, wenn ich Vcc als Referenzspannung haben möchte, dass ich dann das Bit REFS0 in ADMUX setzen muss? REFS1 bleibt dann auf 0. Muss ich dann noch einen Kondensator zwischenschalten (100nF)?

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »Organized« (24. April 2012, 14:50)

  • Zum Seitenanfang

Kanwas

Bronze LedStyler

Beiträge: 3 196

Wohnort: 5....

29

Dienstag, 24. April 2012, 15:03

Im Datenblatt ist ein Schaltbild zur Eingangsstufe des ADC.

Du hast im Grunde drei Möglichkeiten. Du nutzt die interne Referenz, du nutzt AVcc als Referenz oder du nutzt eine beliebige Spannung an Aref als Referenz.
AVcc als Referenz hat für mich den Nachteil, dass die Spannung nicht direkt am ADC anliegt.
Wenn du den Eingang Aref als Referenz nutzt liegt der direkt am ADC an. Dann kannst du allerdings die beiden anderen Referenzen nicht mehr nutzen.

Die Einstellungen dazu werden im ADMUX Register gemacht.

Und immer an eine Entstörung der der Eingänge AVcc und Aref denken. Auch dazu gibt es ein Schaltbild im Datenblatt.
Sämtliche Angaben ohne Gewähr und ohne Anspruch auf Vollständigkeit!
  • Zum Seitenanfang

Organized

LedStyles Newbie

30

Dienstag, 24. April 2012, 15:15

Habe gerade mal die Platine des myAVR untersucht, da scheint AVcc schon entstört an Vcc zu hängen. Also kein großer Aufwand für mich :)

Danke! Setze mich jetzt in die Karre und fahr zu Conrad nach Dortmund (für 4 Bauteile! Yey -.-)
  • Zum Seitenanfang

Organized

LedStyles Newbie

31

Dienstag, 24. April 2012, 20:07

Kann der LM335 kaputt gehen, wenn man ihn falsch anschließt? Hatte den +-Pin von ihm an 5V, dürfte ein Kurzschluss gewesen sein und er jetzt ist er hinüber, oder? Habe glücklicherweise 2 Stück gekauft...

Programmierung sieht bisher so aus:
http://pastebin.com/p73rtAe2

Kann ich die Messungen irgendwie bremsen? Das flackert jetzt ordentlich hin und her (das tut es hoffentlich nicht mehr, wenn ich den LM335 getauscht habe). Prescaler ist schon auf 128, oder bezieht sich das nur auf die Frequenz des Messwerks? Wenn ja, was ist da optimal?
  • Zum Seitenanfang

Kanwas

Bronze LedStyler

Beiträge: 3 196

Wohnort: 5....

32

Mittwoch, 25. April 2012, 08:32

Schau dir mal die ADC Routine auf mikrocontroller.net an. Da werden 256 Messungen zusammengefasst. Dadurch wird die Messung genauer. Mache ich eigentlich immer so.
Sämtliche Angaben ohne Gewähr und ohne Anspruch auf Vollständigkeit!
  • Zum Seitenanfang

Organized

LedStyles Newbie

33

Mittwoch, 25. April 2012, 11:48

Wo finde ich die? 8| Habe jetzt schon viel danach gesucht, aber leider finde ich keinen Artikel, Forumsbeitrag, o.ä. darüber.

Aber sehr gute Neuigkeiten: Habe den anderen IC angelötet (diesmal richtig) und mit einem Voltmeter gemessen - 3,05V! Also etwa 31°C. Kann ich den IC in Wasser halten? Dann könnte ich es genau kalibrieren: Glas mit Wasser, IC und normales Termometer rein. Dann so lange am Poti spielen, bis die Werte überein stimmen. Aber das wäre erst das Feintuning - erstmal muss die Software richtig laufen.
  • Zum Seitenanfang

Pesi

Golden LedStyler

Beiträge: 7 582

Wohnort: 6980 Mulholland Drive

Beruf: Mischling

34

Mittwoch, 25. April 2012, 13:41

Guckst Du hier - der ganze Artikel über den ADC ist recht interessant (da werden auch die ganzen relevanten Register beschrieben etc.), ebenso wie das gesamte Tutorial...
It's only light - but we like it!

Da es sich in letzter Zeit häuft: Ich beantworte keine PNs mit Fragen, die sich auch im Forum beantworten lassen!
Insbesondere solche von Mitgliedern mit 0 Beiträgen, die dann meist auch noch Sachen fragen, die bereits im entsprechenden Thread beantwortet wurden.
Ich bin keine private Bastler-Hotline, technische Tipps etc. sollen möglichst vielen Lesern im Forum helfen!
  • Zum Seitenanfang

Organized

LedStyles Newbie

35

Mittwoch, 25. April 2012, 13:45

Und was bringt mir das jetzt? Assembler ist für mich genau so kryptisch wie Hieroglyphen, damit kann ich nichts anfangen. Zudem ich ja sowieso in C programmiere. :(
  • Zum Seitenanfang

Pesi

Golden LedStyler

Beiträge: 7 582

Wohnort: 6980 Mulholland Drive

Beruf: Mischling

36

Mittwoch, 25. April 2012, 13:53

Assembler ist für mich genau so kryptisch wie Hieroglyphen, damit kann ich nichts anfangen.
:D ?(

Lies' Dir doch einfach die *Beschreibung* durch wie's gemacht wird, und die *Kommentare* im asm-Code (der ist ja zum Glück gut kommentiert) - geht ja nicht um die Sprache, sondern um's Prinzip, und das kannst Du dann ja in C "nachbauen"...

oder geht's hier um C&P-Programmierung..? - da kann ich bei C wiederum leider nix beitragen...
It's only light - but we like it!

Da es sich in letzter Zeit häuft: Ich beantworte keine PNs mit Fragen, die sich auch im Forum beantworten lassen!
Insbesondere solche von Mitgliedern mit 0 Beiträgen, die dann meist auch noch Sachen fragen, die bereits im entsprechenden Thread beantwortet wurden.
Ich bin keine private Bastler-Hotline, technische Tipps etc. sollen möglichst vielen Lesern im Forum helfen!
  • Zum Seitenanfang

Kanwas

Bronze LedStyler

Beiträge: 3 196

Wohnort: 5....

37

Mittwoch, 25. April 2012, 14:00

Alternativ stößt man mit ein bisschen Eigeninitiative auf das GCC-Tutorial. Welches den selben Stoff in C aufbereitet ^^

Manchmal ist ein Blick über den eigenen Tellerrand auch nicht verkehrt. Inline ASM ermöglicht manchmal Dinge . . .
Sämtliche Angaben ohne Gewähr und ohne Anspruch auf Vollständigkeit!
  • Zum Seitenanfang

Organized

LedStyles Newbie

38

Mittwoch, 25. April 2012, 15:02

Also, ich habe mal versucht, das in C umzusetzen.

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// ADC gemittelt auslesen
uint16_t readADC()
{
	uint16_t erg;
	uint8_t adlow, adhigh, tmp = 0, tmp1 = 0, tmp2 = 0, tmp3 = 0, messungen = 0, quit = 0;
	
	while (quit != 1) {
		ADCSRA |= (1 << ADSC); // ADC starten
		while (ADCSRA & (1 << ADSC)); // Warten, bis beendet
		
		adlow = ADCL;
		adhigh = ADCH;
		
		asm volatile ("add %[tmp1], %[adlow]" : [tmp1] "+r" (tmp1), [adlow] "+r" (adlow));
		asm volatile ("adc %[tmp2], %[adhigh]" : [tmp2] "+r" (tmp2), [adhigh] "+r" (adhigh));
		asm volatile ("adc %[tmp3], %[tmp1]" : [tmp3] "+r" (tmp3), [tmp1] "+r" (tmp1));
		
		messungen++;
		if (messungen == 255) // bei 256 Durchläufen
			quit = 1;		  // abbrechen
	}
	
	if (tmp1 > 128) { // wenn größer als 128 muss aufgerundet werden
		// Die folgenden beiden Zeilen erzeugen einen Fehler, deshalb erst mal weg gelassen
		//asm volatile ("subi %[tmp2], low(-1)" : [tmp2] "+r" (tmp2));
		//asm volatile ("sbci %[tmp3], high(-1)" : [tmp3] "+r" (tmp3));
	}
	
	adlow = tmp2;
	adhigh = tmp3;
	
	return adlow | (adhigh << 8);
}


Leider kommen da nur ganz lustige Sachen heraus, die LED blinkt wild vor sich hin. Sprich, das Ergebnis ist nicht mal im Ansatz konstant (obwohl die Temperatur gleich bleibt).
  • Zum Seitenanfang

Organized

LedStyles Newbie

39

Mittwoch, 25. April 2012, 15:36

Ok, sorry, ich bin doof.

In nativem C ist es einfacher als in einem C-Assembler-Mix.

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
uint16_t readADC()
{
	uint32_t sum = 0;
	uint16_t i = 0;
	uint8_t adlow, adhigh;
	
	for (i = 0; i <= 255; i++) {
		ADCSRA |= (1 << ADSC); // ADC starten
		while (ADCSRA & (1 << ADSC)); // Warten, bis beendet
		
		adlow = ADCL;
		adhigh = ADCH;
		
		sum += ADCL + (ADCH << 8);
	}
	
	return (uint16_t) (sum >> 8);
}


So funzt es!

Danke an Alle - ich werde demnächst ein Tutorial dazu schreiben bzw. meine Dokumentation veröffentlichen :)
  • Zum Seitenanfang

Mirfaelltkeinerein

LedStyles Experte

Beiträge: 1 453

Wohnort: Südwesten

Beruf: Ja

40

Mittwoch, 25. April 2012, 17:41

Kann ich den IC in Wasser halten? Dann könnte ich es genau kalibrieren: Glas mit Wasser, IC und normales Termometer rein. Dann so lange am Poti spielen, bis die Werte überein stimmen.
Falls das noch interessant ist: Den IC direkt in Wasser zu tauchen ist keine gute Idee, aber man kann den in einen Schlauch (nicht zu großer Durchmesser, Schrumpfschlauch eignet sich hervorragend) stecken, den Schlauch umklappen, so dass die die beiden Enden nebeneinander liegen und der Sensor dicht am Knick. Die Schlauchenden mit etwas Draht oder einem Kabelbinder zusammentüddeln, damit damit der Schlauch nicht wieder aufklappt und das Ganze dann in das Wasserglas stellen. Die Schlauchenden natürlich über der Wasseroberfläche. So ist das Ganze erstmal wasserdicht oder zumindest wassergeschützt und die thermische Kopplung eigentlich auch ausreichend. Außerdem kann man den Schlauch nachher wieder verwenden.
There are only 10 types of people: those who understand binary and those who don't.
  • Zum Seitenanfang