Forum: Mikrocontroller und Digitale Elektronik AtMega8 - Funktioniert das so?


von Nico (Gast)


Angehängte Dateien:

Lesenswert?

Hallo!

Ich möchte mir für eine Vitrine mit Pflanzen eine Anzeige basteln, die 
wesentliche Eigenschaften anzeigt (Luftfeuchte, Bodenfeuchte, 
Temperatur, Helligkeit). Dazu wollte ich den Zustand der resistiven 
Sensoren über einen AtMega8 auf Bargraphs anzeigen. Das ist dann 
zugleich mein "Debüt" mit µCs.
Ich habe auch schon Schaltplan und Programm fertig und mit Proteus Isis 
simuliert. Scheint alles zu laufen.
Da ich die Bauteile bestellen muss und nicht zweimal Porto bezahlen 
will, wäre es schön, wenn sich jemand das ganze mal ansehen und einen 
Kommentar abgeben könnte.
Zum Schaltplan im Anhang:
Ich bin mir nicht wirklich sicher, ob Proteus die Schaltzeichen für die 
Bargraphs kennt. Jedenfalls sollen das die Dinger ganz rechts sein.
Unten links sind die resistiven Sensoren als Potentiometer angedeutet.
Der ISP soll an die COM-Schnittstelle des Computers angeschlossen 
werden.
Das ganze funktioniert über Multiplexing. Port D und zwei Pins von Port 
C geben die Daten aus und 4 Pins von Port B schalten die entsprechenden 
Transistoren.
Ich denke, der Rest erklärt sich von alleine.
Und jetzt der Quelltext (zwei Anhänge gibt es hier nicht, oder?):
1
#include <avr/io.h>
2
#include <math.h>
3
4
// Anzahl der LEDs
5
volatile unsigned char LFeuchte;
6
volatile unsigned char BFeuchte;
7
volatile unsigned char Licht;
8
volatile unsigned char Temp;
9
10
volatile unsigned char count;
11
volatile unsigned char count2;
12
13
void Zeige(unsigned int LED, int n)
14
{
15
  if(n<0) n=0;
16
  PORTB=0x0;
17
  PORTD=0x0;
18
  PORTC=0x0;
19
  if(n>=1) PORTD |= 0x1;
20
  if(n>=2) PORTD |= 0x2;
21
  if(n>=3) PORTD |= 0x4;
22
  if(n>=4) PORTD |= 0x8;
23
  if(n>=5) PORTD |= 0x10;
24
  if(n>=6) PORTD |= 0x20;
25
  if(n>=7) PORTD |= 0x40;
26
  if(n>=8) PORTD |= 0x80;
27
  if(n>=9) PORTC |= 0x10;
28
  if(n>=10) PORTC |= 0x20;
29
  PORTB=LED;
30
}
31
32
void ActivateNext()
33
{
34
  switch(PORTB)
35
  {
36
    case 0x40: case 0x00:
37
      Zeige(0x01,LFeuchte);
38
      break;
39
    case 0x01:
40
      Zeige(0x02,BFeuchte);
41
      break;
42
    case 0x02:
43
      Zeige(0x04,Licht);
44
      break;
45
    case 0x04:
46
      Zeige(0x40,Temp);
47
      break;
48
  }
49
}
50
51
void Messen()
52
{
53
  volatile unsigned int U;
54
  ADMUX = 0x00;
55
  ADCSRA |= (1<<ADSC); //Single-Conversion
56
  while (ADCSRA & (1<<ADSC)); // Auf Abschluss warten
57
  U=ADCL;
58
  U+=(ADCH<<8);
59
  //SHS-A2
60
  if (U<=174) LFeuchte=0; //<50%
61
  if (U<=250 && U>174) LFeuchte=1; //50 - 55%
62
  if (U<=345 && U>250) LFeuchte=2; //55 - 60%
63
  if (U<=455 && U>345) LFeuchte=3; //60 - 65%
64
  if (U<=571 && U>455) LFeuchte=4; //65 - 70%
65
  if (U<=681 && U>571) LFeuchte=5; //70 - 75%
66
  if (U<=776 && U>681) LFeuchte=6; //75 - 80%
67
  if (U<=851 && U>776) LFeuchte=7; //80 - 85%
68
  if (U<=907 && U>851) LFeuchte=8; //85 - 90%
69
  if (U<=946 && U>907) LFeuchte=9; //90 - 95%
70
  if (U>=946) LFeuchte=10; //>95%
71
72
  ADMUX = 0x01;
73
  ADCSRA |= (1<<ADSC); //Single-Conversion
74
  while (ADCSRA & (1<<ADSC)); // Auf Abschluss warten
75
  U=ADCL;
76
  U+=(ADCH<<8);
77
  if (U>877) BFeuchte=0; //60 kR
78
  if (U<=877 && U>866) BFeuchte=1; //60-55 kR
79
  if (U<=866 && U>853) BFeuchte=2; //55-50 kR
80
  if (U<=853 && U>837) BFeuchte=3;
81
  if (U<=837 && U>818) BFeuchte=4;
82
  if (U<=818 && U>796) BFeuchte=5;
83
  if (U<=796 && U>767) BFeuchte=6;
84
  if (U<=767 && U>731) BFeuchte=7;
85
  if (U<=731 && U>682) BFeuchte=8;
86
  if (U<=682 && U>614) BFeuchte=9;
87
  if (U<=614) BFeuchte=10;
88
  
89
90
  ADMUX = 0x02;
91
  ADCSRA |= (1<<ADSC); //Single-Conversion
92
  while (ADCSRA & (1<<ADSC)); // Auf Abschluss warten
93
  U=ADCL;
94
  U+=(ADCH<<8);
95
  //Die folgenden Werte sind noch nicht angepasst
96
  if (U>877) Licht=0;
97
  if (U<=877 && U>866) Licht=1;
98
  if (U<=866 && U>853) Licht=2;
99
  if (U<=853 && U>837) Licht=3;
100
  if (U<=837 && U>818) Licht=4;
101
  if (U<=818 && U>796) Licht=5;
102
  if (U<=796 && U>767) Licht=6;
103
  if (U<=767 && U>731) Licht=7;
104
  if (U<=731 && U>682) Licht=8;
105
  if (U<=682 && U>614) Licht=9;
106
  if (U<=614) Licht=10;
107
108
  ADMUX = 0x03;
109
  ADCSRA |= (1<<ADSC); //Single-Conversion
110
  while (ADCSRA & (1<<ADSC)); // Auf Abschluss warten
111
  U=ADCL;
112
  U+=(ADCH<<8);
113
  if (U>630) Temp=0; //kleiner 15 Grad
114
  if (U<=630 && U>619) Temp=1; // 15 bis 16 Grad
115
  if (U<=619 && U>608) Temp=2; // 16 bis 17 Grad
116
  if (U<=608 && U>597) Temp=3; // 17 bis 18 Grad
117
  if (U<=597 && U>585) Temp=4; // 18 bis 19 Grad
118
  if (U<=585 && U>574) Temp=5; // 19 bis 20 Grad
119
  if (U<=574 && U>562) Temp=6; // 20 bis 21 Grad
120
  if (U<=562 && U>551) Temp=7; // 21 bis 22 Grad
121
  if (U<=551 && U>539) Temp=8; // 22 bis 23 Grad
122
  if (U<=539 && U>528) Temp=9; // 23 bis 24 Grad
123
  if (U<=528) Temp=10; // über 24 Grad
124
}
125
126
int main (void) {  
127
  DDRD  = 0xff;
128
  DDRB = 0x47; //01000111
129
  DDRC = 0x30; //00110000
130
  ADCSRA = 0xc7; //11000111, ADC aktivieren
131
132
  TCCR0 = (1<<CS00)|(1<<CS02);    //Prescaler 1024
133
 
134
  while(1) 
135
  {
136
    if(TCNT0 == 0xff) // alle 1.024 ms
137
    {
138
      count++;
139
      if(count==4) //getestet mit count == 50
140
      {
141
        count2++;
142
        ActivateNext();
143
        count = 0;
144
      }
145
      if(count2==200) //getestet mit count2 == 1
146
      {
147
        Messen();
148
        count2=0;
149
      }
150
    }
151
  }                         
152
153
  return 0;                 
154
}
Also in der Hauptschleife werden zum einen die Anzeigen aktualisiert 
(ca. 60 Hz pro Anzeige). Und zum anderen werden in regelmäßigen 
Abständen (ca. 1 s) neue Messungen durchgeführt.
Da bei der Simulation die CPU ziemlich belastet wird, habe ich nicht mit 
voller Geschwindigkeit getestet, sondern mit den in den Kommentaren 
angegebenen Werten ("getestet mit...").
Vielleicht findet ja jemand ein paar Minuten Zeit, sich die ganze Sache 
mal anzusehen.
Danke schonmal im Voraus.

Nico

von Michael U. (amiga)


Lesenswert?

Hallo,

hab nur kurz auf den Schaltplan geschaut...

Wenn die Bargraphs grüne LED haben, dürfte der LED-Strom bei mindestens 
20mA liegen. Dann überschreitest Du die maximal zulässigen 200mA des 
Mega8.

Die 100n an den Spannugsanschlüssen zwischen VCC/GND und AVCC/AGND 
fehlen.
AREF gehört über 100n an GND, nicht an AVCC.

AVCC sollte über eine Drossel entkoppelt werden wenn man den ADC 
benutzt.

An den ADC-Eingängen sind vermutlich auch noch ca. 100n Kondensatoren 
gegen GND als Tiefpass gegen Störungen auf den Leitungen zu den Sensoren 
nötig.

Was sind das für Sensoren? Speziell Luftfeuchte als Widerstandssensor 
kenne ich im Moment nicht.

C3 würde ich eher 220-470µ nehmen, die LEDs erzeugen merkliche 
Lastwechsel, hängt aber auch vom Netzteil ab.

Q1 am Reset gibt einen netten Verstärker für Störungen ab wenn nichts 
angeschlossen ist. Besser noch 47-100n am Reset gegen GND.

Gruß aus Berlin
Michael

von Nico (Gast)


Lesenswert?

Danke, fürs Ansehen.
1
Wenn die Bargraphs grüne LED haben, dürfte der LED-Strom bei mindestens
2
20mA liegen. Dann überschreitest Du die maximal zulässigen 200mA des
3
Mega8.
Ich weiß jetzt gar nicht mehr, warum ich bei den Bargraphs 100R 
Vorwiderstand genommen habe. Wenn ich da 500R nehme, wären das ja 
I=U/R=5 V / 500 R=10 mA. Wären insgesamt höchstens hundert mA. Wäre das 
dann zu verkraften?
1
Die 100n an den Spannugsanschlüssen zwischen VCC/GND und AVCC/AGND
2
fehlen.
Da hatte ich eigentlich die Kondensatoren oben links vor und hinter dem 
Spannungswandler vorgesehen. Reichen die nicht aus oder müssen woanders 
noch welche hin?
1
AREF gehört über 100n an GND, nicht an AVCC.
Also lieber die interne Referenzspannung benutzen?
1
An den ADC-Eingängen sind vermutlich auch noch ca. 100n Kondensatoren
2
gegen GND als Tiefpass gegen Störungen auf den Leitungen zu den Sensoren
3
nötig.
Gut. Das werde ich noch einbauen.
1
Was sind das für Sensoren? Speziell Luftfeuchte als Widerstandssensor
2
kenne ich im Moment nicht.
Bei Conrad gibt es da zum Beispiel den SHS A2, den ich verwenden will.
1
C3 würde ich eher 220-470µ nehmen, die LEDs erzeugen merkliche
2
Lastwechsel, hängt aber auch vom Netzteil ab.
Gut. Werde ich auch noch ändern. Gibt es ein Problem, wenn eine Batterie 
genutzt werden soll?
1
Q1 am Reset gibt einen netten Verstärker für Störungen ab wenn nichts
2
angeschlossen ist. Besser noch 47-100n am Reset gegen GND.
Ändere ich auch noch.

Danke für die Mühe.

Nico

von holger (Gast)


Lesenswert?

>Gut. Werde ich auch noch ändern. Gibt es ein Problem, wenn eine Batterie
>genutzt werden soll?

Eine 9V Blockbatterie? Jo, dann läuft das ganze
vieleicht 10 Minuten.

von roman (Gast)


Lesenswert?

irgendwie begreiff ich nicht wiso alle die led's direkt vom avr 
treiben... meine ein uln dazwischen kostet nix und entlastat die 
schaltung... zudem hat man die möglichkeit den strom so zu variieren wie 
man möchte...

von Michael U. (amiga)


Lesenswert?

Hallo,

Nico wrote:

> Ich weiß jetzt gar nicht mehr, warum ich bei den Bargraphs 100R
> Vorwiderstand genommen habe. Wenn ich da 500R nehme, wären das ja
> I=U/R=5 V / 500 R=10 mA. Wären insgesamt höchstens hundert mA. Wäre das
> dann zu verkraften?
Deine Rechnung stimmt nicht. I = (5V - Uled - Ul_out)/R
Uled steht in deren Datenblatt, bei roten ca. 1,6V, bei grünen ca. 2V.
Ul_out ist die Spannung am AVR-Pin bei L-Pegel und dem fließenden Strom.
Gibt es im AVR-Datenblatt Diagramme zu. Bei 10mA wohl um 0,2V.

Umgestellt zum Widerstand also 5V - 2V - 0,2V = 2,8V / 10mA = 280 Ohm.
Allerdings machst Du ja einen 1:4 Multiplex, also sollte der Strom schon 
höher sein, er fließt ja nur 1/4 der Zeit und die LED sind evtl. zu 
dunkel.

Der Maximalstrom eines Portpins ist zwar 40mA, allerdings darf der Strom 
über Vcc bzw. GND des AVR 200mA nicht übersteigen (Datenblatt).

> Da hatte ich eigentlich die Kondensatoren oben links vor und hinter dem
> Spannungswandler vorgesehen. Reichen die nicht aus oder müssen woanders
> noch welche hin?
Siehe Stützkondensatoren/Abblockkondensatoren oder wie es auch gerade 
heißt. Alle ICs müssen dicht an ihren Vcc/GND-Anschlüssen einen 100n 
Kondensator bekommen.
Beim Umschalten treten im ns-Bereich Stromspitzen auf, die von diesen 
Kondensatoren gepuffert werden sollen. Da jeder mm Leiterbahn/Draht eine 
kleine Induktivität darstellt, verlieren die ihre Wirkung, wenn sie zu 
weite weg sind.
>
>
1
AREF gehört über 100n an GND, nicht an AVCC.
> Also lieber die interne Referenzspannung benutzen?
Nein. Man kann auch AVCC als Referenz intern einschalten. Wenn aber AREF 
an AVCC angeschlossen ist und Du programmierst dann die interne 
Referenzspannug, dann liegt die an dem Pin. Ob das den FET, der die 
2,56V dann gegen die 5V schalten soll, so gefällt?

>
1
Was sind das für Sensoren? Speziell Luftfeuchte als
2
> Widerstandssensor
3
> kenne ich im Moment nicht.
> Bei Conrad gibt es da zum Beispiel den SHS A2, den ich verwenden will.

Naja, das ist ein Betauungssensor, ob man den sinnvoll zur relativen 
Feuchtemessung nutzen kann?
Ich kenne sowas aus alten Camcordern, wenn da Kondeswasser auftrat, weil 
man von kalten ins warme gekommen ist, dann haben die das Einschalten 
verhindert, damit das Band nicht an der Kopftrommel kleben bleibt.

>
1
C3 würde ich eher 220-470µ nehmen, die LEDs erzeugen merkliche
2
> Lastwechsel, hängt aber auch vom Netzteil ab.
> Gut. Werde ich auch noch ändern. Gibt es ein Problem, wenn eine Batterie
> genutzt werden soll?
Nein, macht keine Probleme, im Gegenteil.

Gruß aus Berlin
Michael

von Klaus (Gast)


Lesenswert?

Für Feuchtigkeits- und Temperatur messungen empfehle ich den Sensor 
SHT11 der Firmal Sensirion.

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.