main_-_Kopie.c


1
#define F_CPU 1000000            // int.Takt auf 1MHz gestellt
2
#include <avr/io.h>
3
#include <util/delay.h>
4
5
// Präprozessor Makros
6
#define OBER_BEREICH (int16_t)(11.8*1024/15)    // oberen Spg-Schwellwert definieren, Formel: OW.MBg*AL/MBg, wird vom Compiler nur ein mal berechnet
7
#define UNTER_BEREICH (int16_t)(10.8*1024/15)    // unteren Spg-Schwellwert definieren, Formel: UW.MBg*AL/MBg, wird vom Compiler nur ein mal berechnet
8
#define SET_BIT(port,mask) ((port) |= (1<<mask))  // Ausgangs-Port einschalten
9
#define CLR_BIT(port,mask) ((port) &= ~(1<<mask))  // Ausgangs-Port ausschalten
10
#define LED_HIGH (SET_BIT(PORTB,PB0)); (CLR_BIT(PORTB,PB1)); (CLR_BIT(PORTB,PB2))  // LED1 (Spg. Oberbereich) ein, Rest aus
11
#define LED_MID (CLR_BIT(PORTB,PB0)); (SET_BIT(PORTB,PB1)); (CLR_BIT(PORTB,PB2))  // LED2 (Spg. Mittelbereich) ein, Rest aus
12
#define LED_LOW (CLR_BIT(PORTB,PB0)); (CLR_BIT(PORTB,PB1)); (SET_BIT(PORTB,PB2))  // LED3 (Spg. Unterbereich) ein, Rest aus
13
#define BATT_ON (SET_BIT(PORTB,PB4))        // "Batterie"-Ausgang ein
14
#define BATT_OFF (CLR_BIT(PORTB,PB4))        // "Batterie"-Ausgang aus
15
16
void ADC_Init(void)                  // ADC initialisieren
17
{  
18
    //ADMUX = (0<<REFS1) | (1<<REFS0);      // AREF an PB0, internal Vref= off
19
  ADMUX = (0<<REFS1) | (0<<REFS0);        // AVcc als Referenz benutzen, unabhängig von AREF/PB0
20
    //ADMUX = (1<<REFS1) | (0<<REFS0);      // interne Referenzspannung 1,1V nutzen
21
22
    //ADCSRA = (0<<ADPS2) | (0<<ADPS1) | (1<<ADPS0);  // Frequenzvorteiler 2 // Multiplexer schnell, aber ungenau
23
    //ADCSRA = (0<<ADPS2) | (1<<ADPS1) | (0<<ADPS0);  // Frequenzvorteiler 4
24
  ADCSRA = (0<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);      // Frequenzvorteiler 8 // 1MHz/8=125kHz=8us
25
    //ADCSRA = (1<<ADPS2) | (0<<ADPS1) | (0<<ADPS0);  // Frequenzvorteiler 16
26
    //ADCSRA = (1<<ADPS2) | (0<<ADPS1) | (1<<ADPS0);  // Frequenzvorteiler 32
27
    //ADCSRA = (1<<ADPS2) | (1<<ADPS1) | (0<<ADPS0);  // Frequenzvorteiler 64
28
    //ADCSRA = (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);  // Frequenzvorteiler 128 // Multiplexer langsam, aber genau
29
30
  ADCSRA |= (1<<ADEN);              // ADC aktivieren
31
32
  // nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen,
33
  // man liest also einen Wert aus und verwirft diesen, um den ADC "warmlaufen zu lassen" (Quelle: FRANZIS-Buch)
34
  ADCSRA |= (1<<ADSC);              // eine Wandlung starten "single conversion"
35
36
  while (ADCSRA & (1<<ADSC));            // auf Ergenbnis warten
37
  // ADCW muss ein mal gelesen werden, sonst wird das Ergebnis der nächsten Wandlung nicht übernomen (Quelle: FRANZIS-Buch)
38
39
  (void) ADCW;                  // ADCW gibt den 10bit-Messwert (0-1023) zurück
40
}
41
42
uint16_t ADC_Read(uint8_t Eingang)          // ADC Einzelmessung
43
{
44
  ADMUX = (ADMUX & ~(0x1F)) | (Eingang & 0x1F);  // Eingangskanal wählen, ohne andere Bits zu beeinflußen
45
  ADCSRA |= (1<<ADSC);              // eine Wandlung starten "single conversion"
46
  while (ADCSRA & (1<<ADSC));            // auf Ergenbnis warten
47
  return ADCW;                  // ADCW gibt den 10bit-Messwert (0-1023) zurück
48
}
49
50
uint16_t ADC_Read_Avg(uint8_t Eingang, uint8_t Durchlauf)  // ADC Mehrfachmessung zur arithm. Mittelwertbbildung
51
{                              // zur Genauigkeitssteigerung
52
  uint32_t MesswSum = 0;
53
  
54
  for (uint8_t i = 0; i < Durchlauf; ++i)      // Durchläufe
55
  {
56
    MesswSum += ADC_Read(Eingang);        // Messwerte summieren
57
    //_delay_us(250);              // warte 250us, Intervall der Messwertauslesung, bei sehr verrauschtem Signal besser
58
  }
59
  return (uint16_t)(MesswSum / Durchlauf);    // Mittelwertbildung
60
}
61
62
void Warte(uint16_t WarteMS)
63
{
64
  while(WarteMS)                  // Wartezeit
65
  {
66
    WarteMS--;                  // runter zählen
67
    _delay_ms(1);                // 1ms
68
  }
69
}
70
71
void Led_Ein(uint8_t Led)              // LEDs auswählen
72
{
73
  static uint8_t LetztLed = 0xFF;          // 0xFF ... undefeniert // static ... Variable überlebt nach der Funktion
74
75
  if(LetztLed != Led)
76
  {
77
    switch(Led)
78
    {
79
      case 1: LED_HIGH; Led=1; break;      // LED/high ein, Rest aus
80
      case 2: LED_MID; Led=2; break;      // LED/mid ein, Rest aus + Mindest-Wartezeit [ms]
81
      default: LED_LOW; Led=3; break;      // sonst, LED/low ein, Rest aus
82
    }
83
    LetztLed=Led;
84
  }
85
}
86
87
int main(void)                    // Hauptprogramm
88
{
89
  DDRB &= ~(1<<PB5);                // Eingang PB5...Master_OFF, wenn 1
90
  DDRB = ((1<<PB4)|(1<<PB2)|(1<<PB1)|(1<<PB0));  // Ausgang PB4=Batt_ON, PB2=low, PB1=mid, PB0=high
91
92
  uint16_t MitWert;                // Mittelwert
93
  uint8_t Led=2;                  // LED auswahl
94
95
  //PORTB &= ~((1<<PB4)|(1<<PB2)|(1<<PB1)|(1<<PB0));  // Ausgangsvoreinstellung, PB0, PB1, PB2, PB4 = 0
96
  ADC_Init();                    // ADC initialize
97
98
  //while((PINB & (1<<PB5)) == 0)  //Klappt nicht // auf "0" prüfen
99
  //while(PINB & (1<<PB5))  //KLAPPT NICHT  // auf "1" prüfen        // Endlosschleife solang PB5 = 0
100
  while(0)
101
  {
102
    MitWert=ADC_Read_Avg(3,64);          // Mittelwert, (Eingangs-Kanal (3=ADC3), Mess-Durchläufe)
103
104
    if(MitWert>=OBER_BEREICH)          // oberer Messbereich
105
    {
106
      if(Led==3)                // von LED3 erst über LED2 nach LED1
107
      {
108
        Led_Ein(2);              // LED/mid ein, Rest aus + Mindest-Wartezeit
109
        Warte(2000);            // Mindest-Wartezeit [ms]
110
        BATT_ON;  //??? nur akt. wenn vorger low
111
        Led_Ein(1);              // LED/high ein, Rest aus
112
        Led=1;
113
      }
114
      else
115
      {
116
        Led_Ein(1);              // LED/high ein, Rest aus
117
        BATT_ON;
118
        Led=1;
119
      }
120
    }    
121
    else if(MitWert<=UNTER_BEREICH)        // unterer Messbereich
122
    {
123
      if(Led==1)                // von LED1 erst über LED2 nach LED3
124
      {
125
        Led_Ein(2);              // LED/mid ein, Rest aus + Mindest-Wartezeit
126
        Warte(2000);            // Mindest-Wartezeit [ms]
127
        BATT_OFF;  //??? nur akt. wenn vorger high
128
        Led_Ein(3);              // LED/low ein, Rest aus
129
        Led=3;                // LED/low ein, Rest aus
130
      }
131
      else
132
      {
133
        Led_Ein(3);              // LED/low ein, Rest aus
134
        BATT_OFF;
135
        Led=3;
136
      }
137
    }
138
    else                    // mittlerer Messbereich
139
    {
140
      Led_Ein(2);                // LED/mid ein, Rest aus + Mindest-Wartezeit
141
      Warte(2000);              // Mindest-Wartezeit [ms]
142
      Led=2;
143
    }    
144
    Warte(100);                  // [mSek], Wartezeit bis nächste Messwertauswertung
145
  }
146
}