Bitte um Tipps - Attiny 13 + LM35 Temperatursteuerung

Gast #4215004
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
}
Gast #4215020
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
Gast #4215030
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.
Gast #4215047
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?
Gast #4215069
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
}
Gast #4215074
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.
Gast #4215145
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?
Gast #4215186
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)")

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren