Forum: Mikrocontroller und Digitale Elektronik Bitte um Tipps - Attiny 13 + LM35 Temperatursteuerung


von Thomas M. (Gast)


Lesenswert?

Hallo,

mein aktuelles Projekt ist eine Temperatursteuerung mit einem Attiny, 
einem LM35 und anschließendes aktivieren eines Lüfters sobald die 
Temperatur von 60°C überschritten wurde.
Der Lüfter soll dabei nur 2 States können - on und off. Dieser ist 
aktuell noch gar nicht angeschlossen, mir geht es rein um das 
Ausgangssignal des Attiny13.

Mein Code sieht aktuell so aus:

Problem ist, dass ich stets nur 5V als Ausgangssignal bekomme, hat 
jemand einen Tipp für mich?
1
# define F_CPU 7000000UL // 7MHz
2
3
#include <avr/io.h>
4
#include <util/delay.h>
5
6
7
void adc_init_temp()
8
{
9
  ADMUX = (1<<REFS0) | (1 << MUX1) | (0 << MUX0) | (1 << ADLAR); //  1,1V als Referenz, PB4 für ADC, 8bit Register ADCH
10
  ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(0<<ADPS0); // ADC enable + division factor = 64 -> 7MHz/200kHz = 35 bis 7MHz/50kHz=140
11
}
12
13
14
int adc_read(void)
15
{
16
  ADCSRA |= (1<<ADSC); // erstmal "1" einlesen
17
  while(ADCSRA & (1<<ADSC)); // korrekt einlesen
18
  return (ADCH); // ADC zurückgeben
19
}
20
21
int main(void)
22
{
23
  adc_init_temp();  
24
  while(1)
25
    {
26
    if (adc_read() >560)
27
    PORTB |= (1<<PB3);
28
    else 
29
    PORTB &=~ (1<<PB3);
30
    
31
    //ADCSRA &= ~(1<<ADEN); /falls ich 2 ADC-Kanäle mit unterschiedlichen Parametern initialisiere, muss ich bei jedem Wechsel beim Einlesen, diesen Befehl nutzen - korrekt?
32
     }
33
}

von Thomas M. (Gast)


Lesenswert?

Entschuldigung - näheres zu meiner Schaltung:

der LM35 ist lediglich an + und - sowie am mittleren PIN an PB4 
angeschlossen, ADC hab ich auf diesem PIN aktiviert.
Das Ausgangssignal wird an PB3 erwartet.
Die 560 in der If-Schleife habe ich berechnet mit 60°=~0,6V, 1,1V 
Referenzspannung: (0,6*1024)/1,1V

Die Schaltung muss mitnichten eine hohe Genauigkeit haben, mir reichts 
auf +-5°C genau.

Beste Grüße
Thomas

von Edi R. (Gast)


Lesenswert?

Thomas M. schrieb:
> Problem ist, dass ich stets nur 5V als Ausgangssignal bekomme, hat
> jemand einen Tipp für mich?
1
  return (ADCH); // ADC zurückgeben
2
3
...
4
5
    if (adc_read() >560)

Das klappt nicht. Mit ADCH bekommst Du nur ein Byte zurück, das hat 
einen Wertebereich von 0..255 und ist deshalb immer kleiner als 560.

von Draco (Gast)


Lesenswert?

Thomas M. schrieb:
> mir geht es rein um das
> Ausgangssignal des Attiny13.

Ok..

Thomas M. schrieb:
> Problem ist, dass ich stets nur 5V als Ausgangssignal bekomme, hat
> jemand einen Tipp für mich?

Ok...

Was erwartest du?! Die bekommst "nur" fünf Volt auf den Portpins 
herraus. Ein TTL Pegel halt. Du wolltest deinen Lüfter wohl direkt an 
den Tiny hängen?!

von Edi R. (Gast)


Lesenswert?

Er meint vermutlich, dass er nur HIGH bekommt, also dass der Ausgang nie 
LOW wird.

von Thomas M. (Gast)


Lesenswert?

Das ist ein wertvoller Hinweis, vielen Dank!
Wobei dann sollte doch 255 < 560 sein und PB3 dauerhaft ausgeschaltet 
sein oder?

von Edi R. (Gast)


Lesenswert?

Thomas M. schrieb:
> Wobei dann sollte doch 255 < 560 sein und PB3 dauerhaft ausgeschaltet
> sein oder?

Das stimmt allerdings. Hast Du den Ausgang überhaupt als Ausgang 
konfiguriert?

Was mir noch aufgefallen ist:
1
# define F_CPU 7000000UL // 7MHz
Der ATtiny13 hat einen internen Oszillator mit 9,6 MHz, mit der 
standardmäßig eingeschalteten Teilung durch 8 kommt man auf 1,2 MHz. Mit 
dem eingebauten Taktgenerator kommt man aber nicht auf 7 MHz. Hast Du 
wirklich eine externe 7-MHz-Taktquelle?

von Thomas M. (Gast)


Lesenswert?

Danke Edi, Tipps hab ich mal verarbeitet:
Allerdings bekomme ich jetzt dauerhaft von 25-80°C 47mV aus PB3.

1
# define F_CPU 1200000UL // 1,2MHz
2
3
#include <avr/io.h>
4
#include <util/delay.h>
5
6
7
void adc_init_temp()
8
{
9
  ADMUX = (0<<REFS0) | (1 << MUX1) | (0 << MUX0) | (1 << ADLAR); //  5V als Referenz, PB4 für ADC, 8bit Register ADCH
10
  ADCSRA = (1<<ADEN)|(0<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); // ADC enable + division factor = 8 -> 1,2MHz/200kHz = 6 bis 1,2MHz/50kHz=24
11
}
12
13
14
int adc_read(void)
15
{
16
  ADCSRA |= (1<<ADSC); // erstmal "1" einlesen
17
  while(ADCSRA & (1<<ADSC)); // korrekt einlesen
18
  return (ADCH); // ADC zurückgeben
19
}
20
21
int main(void)
22
{
23
  adc_init_temp();
24
  DDRB |= (1 << PB3);
25
  while(1)
26
  {
27
    if (adc_read() >123)//123 < 255 bei 5V Referenz
28
    PORTB |= (1<<PB3);
29
    else
30
    PORTB &=~ (1<<PB3);
31
  }
32
}

von Draco (Gast)


Lesenswert?

Uff... ja das kann sein

Edi R. schrieb:
> Er meint vermutlich, dass er nur HIGH bekommt, also dass der Ausgang nie
> LOW wird.

Uff achso...

Das "müsste" zwar so gehen:

Thomas M. schrieb:
> ADMUX = (1<<REFS0) | (1 << MUX1) | (0 << MUX0) | (1 << ADLAR);
1
ADMUX |= (1<<REFS0) | (1<<MUX1) | (1<<ADLAR);

Da sieht man beim überfliegen die gesetzten Bits besser.

Dann versuche mal im FreeRunning Mode dies hier zum warten:
1
while(!ADCSRA&(1<<ADIF));
2
      ADCSRA|=(1<<ADIF);

Desweiteren würde ich dir dringend raten, den Freeruning Mode links 
liegen zu lassen - sondern nimm den ADC Interrupt.

von MaWin (Gast)


Lesenswert?

Thomas M. schrieb:
> Allerdings bekomme ich jetzt dauerhaft von 25-80°C 47mV aus PB3.

Dein 123 Schaltwert schaltet auch erst bei 240 GradC.

Nimm mal lieber wieder deine 1.1V Referenz statt der 5V.

Niemand hat davon geredet, daß du sie umstellen sollst.

von Thomas (Gast)


Lesenswert?

Ich werde das Programm nachher gleich verbessern, danke für die Tipps!

Welchen Fehler mache ich in meiner Rechnung für den ADC Wert? 10mV/C = 
0,6V bei 60 Grad C, laut Formel rechne ich doch die 0,6V * 1024 / U_ref?

von Draco (Gast)


Lesenswert?

Thomas schrieb:
> laut Formel rechne ich doch die 0,6V * 1024 / U_ref?

Du nutzt nur 8Bit... also:

0,6V * 256 / 1,1V = (irgendwas bei) 139 (Kein Rechner parat :D )

bei den jetzt eingestellten 5V Ref im letzten Posting:

0,6V * 256 / 5,0V = ~30

von Edi R. (Gast)


Lesenswert?

Der Fehler in der Formel ist, dass Du nicht durch 1024 teilen darfst, 
sondern durch 256, weil Du nur ein Byte verwendest.

Ich würde folgendes ändern:
1) Referenzspannung nicht VCC, sondern 1,1 V ("ADMUX = (1<<REFS0)...")
2) Right-Aligning (ADLAR) auf 0 belassen ("... (0 << ADLAR) ...")
3) alle 10 bit des ADC verwenden ("return (ADC); // ADC zurückgeben")
4) wieder 560 als Limit einsetzen ("if (adc_read() >560)")

von Edi R. (Gast)


Lesenswert?

ich meine natürlich:
2) Left-Aligning (ADLAR) auf 0 belassen..

("ADLAR" heißt ja "ADC Left Align Result")

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
Noch kein Account? Hier anmelden.