PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [ERLEDIGT] LM75 Auswerten und Temperatur über terminal ausgeben?



Ferdinand
21.05.2011, 11:36
Hallo
Ich möchte einen LM75 Auswerten und Temperatur über terminal ausgeben nur scheiter das ein wenig.

2 pullup widerstände 10K von SDA, SCL jeweils auf +5V. Die, A0, A1, A2 jeweils direkt auf GND
und einen 100nF an VCC und GND. Ein gesetzt Wirt ein ATmega644 mit 8MHz auf einem STK500

Das Programm.:

MAIN




#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <util/delay.h>
#include "uart.h"
#include "i2c.h"

int main (void) {

USART_Init( UBRR_VAL ) ;


uart_puts ("\033[2J");

uart_puts ("\033[32m");


uart_puts ("Hallo Welt\r\n") ;

uart_putc ( 0x01);

uart_puts ("\r\nHallo Welt 2 ") ;

_delay_ms(10000);




TWI_init(FAKTOR, TEILER);
unsigned int temperatur;
char s[7];

while(1)
{

uart_puts ("\033[2J");

temperatur = TWI_empf(ADRESSE_R);

uart_puts ("\r\nTemperatur ") ;
uart_puts( utoa( temperatur, s, 10 ) );
//uart_putc ( temperatur);
uart_puts (" C \r\n") ;

_delay_ms(1000);

}

}

uart.h



/*
UART-Init:
Berechnung des Wertes für das Baudratenregister
aus Taktrate und gewünschter Baudrate
*/

#ifndef F_CPU

#warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 8000000"
#define F_CPU 8000000UL // Systemtakt in Hz - Definition als unsigned long beachten
// Ohne ergeben sich unten Fehler in der Berechnung
#endif

#define BAUD 9600UL // Baudrate

// Berechnungen
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) // clever runden
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1))) // Reale Baudrate
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.

#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
#error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch!
#endif





void USART_Init( unsigned int baud )
{
/* Set baud rate */
UBRR0H = (unsigned char)(baud>>8);
UBRR0L = (unsigned char)baud;
/* Enable receiver and transmitter */
UCSR0B = (1<<RXEN0)|(1<<TXEN0);
/* Set frame format: 8data, 1stop bit */
UCSR0C = 3<<UCSZ00;
}

/* ATmega16 */
int uart_putc(unsigned char c)
{
while (!(UCSR0A & (1<<UDRE0))) /* warten bis Senden moeglich */
{
}

UDR0 = c; /* sende Zeichen */
return 0;
}

/* puts ist unabhaengig vom Controllertyp */
void uart_puts (char *s)
{
while (*s)
{ /* so lange *s != '\0' also ungleich dem "String-Endezeichen" */
uart_putc(*s);
s++;
}
}

void uart_cls (void)
{
int x;

for(x=0;x <= 20;x++ )
{
uart_puts ("\r\n") ;

}
}

i2c.h





#define TAKT 8000000UL
#define ADRESSE_R 0b10010001 //Lesen
#define ADRESSE_W 0b10010000 //Schreiben
#define FAKTOR 32
#define TEILER 1

void TWI_init(unsigned char faktor, unsigned char teiler)
{
TWBR = faktor;
TWSR = teiler;
}

void TWI_send(unsigned char adres, unsigned char daten)
{
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
loop_until_bit_is_set(TWCR, TWINT);
TWDR = adres;
TWCR = (1<<TWINT)|(1<<TWEN);
loop_until_bit_is_set(TWCR, TWINT);
TWDR = daten;
TWCR = (1<<TWINT)|(1<<TWEN);
loop_until_bit_is_set(TWCR, TWINT);
TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN);
}

unsigned int TWI_empf(unsigned char adres)
{
unsigned char dat1, dat2;
unsigned int daten;
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
loop_until_bit_is_set(TWCR, TWINT);
TWDR = adres;
TWCR = (1<<TWINT)|(1<<TWEN);
loop_until_bit_is_set(TWCR, TWINT);
TWCR = (1<<TWINT)|(1<<TWEN);
loop_until_bit_is_set(TWCR, TWINT);
dat1 = TWDR ;
TWCR = (1<<TWINT)|(1<<TWEA)|(1<<TWEN);

TWCR = (1<<TWINT)|(1<<TWEN);
loop_until_bit_is_set(TWCR, TWINT);
dat2 = TWDR ;

loop_until_bit_is_set(TWCR, TWINT);
TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN);

daten = dat1 | (dat2 << 8);

return daten;
}



Terminal Ausgabe





Hallo Welt

Hallo Welt 2

Temperatur 12568 C
Temperatur 65303 C
Temperatur 65303 C
Temperatur 12568 C
Temperatur 12568 C
Temperatur 65303 C
Temperatur 12568 C
Temperatur 65303 C
Temperatur 65303 C
Temperatur 12568 C
Temperatur 12568 C
Temperatur 65303 C

Ich möchte das er mir so ein wert "26.5C" anzeigt.
Was mach ich falsch?

Danke

by Ferdinand

crowdy
24.05.2011, 21:52
Es geht nur um die Ausgabe? Hast du es schon mal mit dtostrf(); probiert? Kenn mich damit nicht so aus, aber die Werte müssten doch irgendwie in °C umgerechnet werden, oder nicht?
mfg

PicNick
25.05.2011, 08:59
Das Beispiel ist zwar mit Bascom, aber man sieht, wie der LM75 gestrickt ist

http://www.rn-wissen.de/index.php/Sensorarten#Temperatur-Sensor_LM75

Ferdinand
26.05.2011, 22:35
hi

ich habs verstanden.

nur wen ich das 1. beit als char sende dan kommt so was "Temperatur -> C" und kein zahlen wert ?

Ferdinand
28.05.2011, 10:12
Hi

Hier habe ich mein Ergebnis:


"i2c.h"



#define TAKT 8000000UL
#define ADRESSE_R 0b10010001 //Lesen
#define ADRESSE_W 0b10010000 //Schreiben
#define FAKTOR 32
#define TEILER 1

void TWI_init(unsigned char faktor, unsigned char teiler)
{
TWBR = faktor;
TWSR = teiler;
}

void TWI_send(unsigned char adres, unsigned char daten)
{
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
loop_until_bit_is_set(TWCR, TWINT);
TWDR = adres;
TWCR = (1<<TWINT)|(1<<TWEN);
loop_until_bit_is_set(TWCR, TWINT);
TWDR = daten;
TWCR = (1<<TWINT)|(1<<TWEN);
loop_until_bit_is_set(TWCR, TWINT);
TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN);
}


char dat1, dat2;

char TWI_empf(unsigned char adres)
{

TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
loop_until_bit_is_set(TWCR, TWINT);
TWDR = adres;
TWCR = (1<<TWINT)|(1<<TWEN);
loop_until_bit_is_set(TWCR, TWINT);
TWCR = (1<<TWINT)|(1<<TWEN);
loop_until_bit_is_set(TWCR, TWINT);
dat1 = TWDR ;
TWCR = (1<<TWINT)|(1<<TWEA)|(1<<TWEN);

TWCR = (1<<TWINT)|(1<<TWEN);
loop_until_bit_is_set(TWCR, TWINT);
dat2 = TWDR ;

loop_until_bit_is_set(TWCR, TWINT);
TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN);

return dat1;
}

und die MAIN:




#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <util/delay.h>
#include "uart.h"
#include "i2c.h"

int main (void) {

USART_Init( UBRR_VAL ) ;

uart_puts ("\033[2J");
uart_puts ("\033[32m");
uart_puts ("Hallo Welt\r\n") ;
uart_putc ( 0x01);
uart_puts ("\r\nHallo Welt 2 ") ;

_delay_ms(10000);

TWI_init(FAKTOR, TEILER);
char temperatur;
char einer;
char zehner;
char c = 248;

while(1)
{

uart_puts ("\033[2J");

temperatur = TWI_empf(ADRESSE_R);
einer = ( temperatur % 10 ) + 48;
zehner = ( temperatur / 10 ) + 48;


if (dat2 >= 0b10000000)
{
uart_puts ("\r\nTemperatur ") ;
uart_putc (zehner);
uart_putc (einer);
uart_puts (",5 ");
uart_putc (c);
uart_puts ("C \r\n") ;

}

else
{
uart_puts ("\r\nTemperatur ") ;
uart_putc (zehner);
uart_putc (einer);
uart_puts (",0 ");
uart_putc (c);
uart_puts ("C \r\n") ;

}
_delay_ms(1000);

}
}
Das Problem war das mein terminal Ales in ascii interpretiert hat also auch die werte die von dem LM75 kommen man muste diesen wert erst um Rechnen so das Er dem ascii Code entspricht und ich auch mein gewünschten dezimal werte bekomme.

Das geht so auf http://www.torsten-horn.de/techdocs/ascii.htm kan man erkennen das Stele 48 mit 0 beginnt und stelle 57 mit 9 endet, also musste ich meinen wert erst mal unterteilen um die einer zu erhalten teilt man durch 10 und merkt sich den Rest das geht mit "%10" Dan verschiebt man den wert um 48 stellen nach hinten also +48 und erhält das gewünschte ascii Zeichen, um die zehner zu erhalten, teilt man das ganze durch /10 und verschiebt das Ergebnis um 48 stellen also wider +48 jetzt nur noch nacheinander ausgeben und fertig.

THX

by Ferdinand

kremsy
01.06.2012, 21:53
Hallo,

ich weiß der Thread ist schon sehr alt.
Habe deinen code für mein Projekt übernommen, dazu ne frage, gibt es eine Möglichkeit auch die Kommastelle anzuzeigen?

Ferdinand
02.06.2012, 08:50
Hi

Welche Komma Stele?
Also die von dem LM75, das habe ich so gelöst:




if (dat2 >= 0b10000000)

{
uart_puts ("\r\nTemperatur ");
uart_putc (zehner);
uart_putc (einer);
uart_puts (",5 ");
uart_putc (c);
uart_puts ("C \r\n");

}

else
{

uart_puts ("\r\nTemperatur ");
uart_putc (zehner);
uart_putc (einer);
uart_puts (",0 ");
uart_putc (c);
uart_puts ("C \r\n");
}


viel erfolg!!!

kremsy
02.06.2012, 19:48
Danke sehr, habs einfach durch 32 geteilt erstmal, damit hab ich so halbwegs die kommastellen.

Hast du eigentlich auch mal mit dem LM76 gearbeitet? Muss das Programm jetzt so umschreiben dass es auch für LM76 funzt.

kremsy
02.06.2012, 20:48
Beim Auslesen der Temperatur des LM75 hängt sich der Prozessor auf, wenn ein Signal über USART reinkommt, versteh das nicht wirklich.

Usart funktioniert Problemlos wenn ich die Zeile auskommentiere:

// temperatur = TWI_empf(ADRESSE_R);
wenn ich sie drinlasse, hängt sich der Prozessor ab und zu auf, wenn über USART etwas empfangen wird während diesen Befehls.

Ist sehr strange, habt ihr da eine Idee?

Programm:
#define F_CPU 16000000UL //Takt 16MHz

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <util/twi.h>
#include "i2c.h"

/* Programm Libs */
#include "defines.h"


volatile uint8_t IRFlag;
volatile uint8_t IR_zaehl=0;
volatile uint8_t RxData;

int main(void)
{
/* TIMER INIT */
SETBIT(TCCR0,CS00);// Prescaler von 1024 16MHz/1024 = 15,6kHz = 64us
SETBIT(TCCR0,CS02);
TCNT0 = 255; // Reload Wert 0-255 250*4us*8 = 8ms = 125Hz
SETBIT(TIMSK,TOIE0); // Timer IR Aktivieren

// DDRD=0xFB; //D0-D1 & D3-D7 as Output
// SETBIT(MCUCR,ISC01); //Fallende Flanke
// SETBIT(GICR,INT0); //Taster IR Aktivieren

sei(); //Globale IRs aktivieren

/* Lokale Variablen: */


/* Ports as Outputs: */
DDRA=0xFF;
DDRB=0xFF;
DDRC=0xFF;


uart_init();
//SETBIT(PORTB,1);

SETBIT(PORTA,3);//VCC für Temp

TWI_init(FAKTOR, TEILER);
unsigned char temperatur=0;
unsigned char komma=0;
char test=0;
while (1)
{

if(IRFlag == 1 && !((UCSRA & (1<<RXC))))
{
IRFlag=0;
SETBIT(PORTB,1);//LED
// temperatur = TWI_empf(ADRESSE_R);
komma=dat2;
CLEARBIT(PORTB,1);//LED
}

//if ( (UCSRA & (1<<RXC)) ) //Zeichen Empfangen?
else
{
RxData=uart_getc();
if(RxData=='R') //Relais Einschalten
{
// SETBIT(PORTB,1);//LED
SETBIT(PORTA,6);//Relais
uart_putc('R');
}
if(RxData=='S') //Relais Ausschalten
{
// CLEARBIT(PORTB,1);//LED
CLEARBIT(PORTA,6);//Relais
uart_putc('S');
}
if(RxData=='T') //Relais Ausschalten
{
if(temperatur)
uart_putc(temperatur);
}
if(RxData=='U') //Relais Ausschalten
{
if(komma)
uart_putc(komma);
}
RxData=0;
}

_delay_ms(20);

/*
uart_putc('f');
_delay_ms(1000);

uart_putc('A');
_delay_ms(1000);
uart_putc(uart_getc());*/
}

}




/* TIMER 0 IR HANDLER */
ISR( TIMER0_OVF_vect ) //Wenn Timer IR kommt Led ausschalten + IR Flag auf 1
{
IR_zaehl++;
if(IR_zaehl==160)
{
IRFlag=1;
IR_zaehl=0;
}
}


/* Taster 0 IR HANDLER */
ISR( INT0_vect )
{

}

kremsy
02.06.2012, 21:23
Aber es tritt auch nicht immer auf, sondern zufällig. Zurzeit tritt es gar nicht auf.

Ich mach mich mal an den LM76.

kremsy
02.06.2012, 22:01
ab jetzt mal einfach alle Bit-Warteschleifen gegen delay warteschleifen
getauscht.

char TWI_empf(unsigned char adres)
{

TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
//loop_until_bit_is_set(TWCR, TWINT);
_delay_ms(100);
TWDR = adres;
TWCR = (1<<TWINT)|(1<<TWEN);
//loop_until_bit_is_set(TWCR, TWINT);
_delay_ms(100);
TWCR = (1<<TWINT)|(1<<TWEN);
//loop_until_bit_is_set(TWCR, TWINT);
_delay_ms(100);
dat1 = TWDR ;
TWCR = (1<<TWINT)|(1<<TWEA)|(1<<TWEN);

TWCR = (1<<TWINT)|(1<<TWEN);
//loop_until_bit_is_set(TWCR, TWINT);
_delay_ms(100);
dat2 = TWDR ;

//loop_until_bit_is_set(TWCR, TWINT);
_delay_ms(100);
TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN);

return dat1;
}

kremsy
03.06.2012, 14:05
Hab Pullup von 5 auf 20kOhm geändert, scheint jetz zu funktionieren ;).

kremsy
03.06.2012, 14:41
So, nun zum Eigentlichen Problem der Kommastelle.

struct TEMPERATUR {
unsigned char temp;
unsigned char komma;
};


struct TEMPERATUR temp_sensor1,temp_sensor2,temp_sensor3;

Beim LM75 ists ganz einfach und funktioniert:

temp_sensor2.temp = TWI_empf(ADRESSE_SENSOR2_R); //Für LM75
temp_sensor2.komma= (dat2>>5)*10/8; //Für LM75

Datenblatt:
http://docs-europe.electrocomponents.com/webdocs/0b4c/0900766b80b4c8ed.pdf



Beim LM76 zeigts mir bei der Kommastelle immer 9 an:

temp_sensor1.temp = (TWI_empf(ADRESSE_SENSOR1_R)<<1)|((dat2>>7)); //für LM76
temp_sensor1.komma= (dat2>>3&0b00001111)*10/16; //für LM76

Datenblatt:
http://docs-europe.electrocomponents.com/webdocs/06ec/0900766b806ece4e.pdf

Vielleicht habt ihr ne idee, wo mein Denkfehler ist.

kremsy
03.06.2012, 21:25
Das Problem ist eigentlich dass D3-D6 beim LM76 immer High sind, ist da der Sensor Kaputt? Oder an was könnte dass liegen?