1 |
|
2 | //Bibliotheken einbinden
|
3 | #define F_CPU 8000000
|
4 | #include <avr/eeprom.h>
|
5 | #include <avr/interrupt.h>
|
6 | #include <avr/io.h>
|
7 | #include "lcd-routines.h"
|
8 | #include <stdlib.h>
|
9 | #include <util/delay.h>
|
10 |
|
11 | //Variablendeklaration
|
12 | uint16_t eeunten EEMEM; //fuer EEPROM
|
13 | uint16_t unten; //fuer EEPROM
|
14 | uint16_t eeoben EEMEM; //fuer EEPROM
|
15 | uint16_t oben; //fuer EEPROM
|
16 | int flanke; //fuer PWM
|
17 | uint16_t flankeStart; //fuer PWM
|
18 | volatile uint16_t stick; //fuer Knueppelposition (volatile = Global gueltig)
|
19 | volatile uint8_t currentOverload; //fuer Stromsensor
|
20 | char Buffer[20]; //fuer LCD
|
21 | int lcdpwm; //fuer LCD
|
22 | float i; //fuer Rechnung
|
23 | float deltaStick; //fuer Rechnung
|
24 | int k; //fuer Rechnung
|
25 |
|
26 | ISR(TIMER1_CAPT_vect)
|
27 | {
|
28 | // Initialiserung fuer PWM einlesen vom Empfänger
|
29 | if (flanke==0)
|
30 | {
|
31 | flankeStart = ICR1;
|
32 | TCCR1B &= ~(1<<ICES1); // fallende Flanke zur Auswertung des ICP
|
33 | flanke = 1;
|
34 | }
|
35 | else
|
36 | {
|
37 | stick = ICR1 - flankeStart;
|
38 | flanke = 0;
|
39 | TCCR1B |= (1<<ICES1); // steigende Flanke zur Auswertung des ICP
|
40 | }
|
41 | TIFR = ( 1 << ICF1 );
|
42 | }
|
43 |
|
44 | ISR(ANA_COMP_vect)
|
45 | {
|
46 | //Intialisierung fuer Strommessung
|
47 | if bit_is_clear(ACSR, ACO)
|
48 | {
|
49 | currentOverload = 1;
|
50 | }
|
51 | else
|
52 | {
|
53 | currentOverload = 0;
|
54 | }
|
55 | }
|
56 |
|
57 | void PWM_Mosfet(void)
|
58 | {
|
59 | /*Initialisierung fuer PWM ausgeben an Mosfet Treiber
|
60 | PWM = Prozessorgeschwindigkeit / (Prescaler * 256)
|
61 | PWM = 8000000 / (8 * 256) = 3906,25Hz = 3,9kHz*/
|
62 | DDRD |= (1 << PD7); // Motor (OC2 => PD7) = Ausgang
|
63 | OCR2 = 0; // von 0 bis 255 einstellbar
|
64 | TCCR2 |= (1 << COM21); // normaler Modus (für invertierenden Modus | (1 << COM20))
|
65 | TCCR2 |= (1 << WGM21) | (1 << WGM20); // fast PWM
|
66 | TCCR2 |= (1 << CS21); // Prescaler Clock/8
|
67 | }
|
68 |
|
69 | void PWM_Empfaenger(void)
|
70 | {
|
71 | //Initialisierung fuer PWM einlesen vom Empfänger
|
72 | TCCR1B |= (1<<ICES1); // steigende Flanke zur Auswertung des ICP
|
73 | TCCR1B |= (1<<CS11) | (1<<CS10); //Quelle für Timer/Counter = CPU-Takt/64
|
74 | TIMSK |= (1<<TICIE1); //Capture Interrupt Enable
|
75 | DDRD &= ~(1<<PD6); // Impuls von Fernsteuerung (ICP1 => PD6) = Eingang
|
76 | PORTD |= (1<<PD6); //Pullup aktiviert
|
77 | }
|
78 |
|
79 | void Strommessung(void)
|
80 | {
|
81 | //Initialisierung fuer Strommessung
|
82 | ACSR |= (0 << ACD);
|
83 | ACSR |= (1 << ACBG); //interne Referenzspannung (1,3 Volt)
|
84 | ACSR |= (1 << ACI);
|
85 | ACSR |= (1 << ACIE);
|
86 | ACSR |= (0 << ACIC);
|
87 | ACSR |= (0 << ACIS1) | (0 << ACIS0);
|
88 | }
|
89 |
|
90 | void Knueppelweg(void)
|
91 | {
|
92 | //Initialisierung fuer Knueppelweg
|
93 | lcd_clear();
|
94 | lcd_string("Regler");
|
95 | lcd_setcursor( 0, 2);
|
96 | lcd_string("V2.0");
|
97 | _delay_ms(1000);
|
98 |
|
99 | //Werte ermitteln
|
100 | if(!(PINB & (1 << PB0)))
|
101 | {
|
102 | PORTB |= (1 << PB1);
|
103 | _delay_ms(1000);
|
104 | while(1) //fuer untere Knueppelposition
|
105 | {
|
106 | lcd_clear();
|
107 | lcd_string("down:");
|
108 | lcd_setcursor(0, 2);
|
109 | lcdpwm = stick * 8;
|
110 | itoa(lcdpwm, Buffer, 10);
|
111 | lcd_string(Buffer);
|
112 | _delay_ms(50);
|
113 | if(!(PINB & (1 << PB0)))
|
114 | {
|
115 | unten = stick;
|
116 | unten += 2; // Korrekturfaktor
|
117 | eeprom_write_word (&eeunten, unten); //schreiben
|
118 | lcd_clear();
|
119 | lcd_string("its:");
|
120 | lcd_setcursor(0, 2);
|
121 | itoa(unten, Buffer, 10);
|
122 | lcd_string(Buffer);
|
123 | _delay_ms(3000);
|
124 | break;
|
125 | }
|
126 | }
|
127 | _delay_ms(1000);
|
128 | while(1) //fuer obere Knueppelposition
|
129 | {
|
130 | lcd_clear();
|
131 | lcd_string("up:");
|
132 | lcd_setcursor(0, 2);
|
133 | lcdpwm = stick * 8;
|
134 | itoa(lcdpwm, Buffer, 10);
|
135 | lcd_string(Buffer);
|
136 | _delay_ms(50);
|
137 | if(!(PINB & (1 << PB0)))
|
138 | {
|
139 | oben = stick;
|
140 | oben -= 2; //Korrekturfaktor
|
141 | eeprom_write_word (&eeoben, oben); //schreiben
|
142 | lcd_clear();
|
143 | lcd_string("its:");
|
144 | lcd_setcursor(0, 2);
|
145 | itoa(oben, Buffer, 10);
|
146 | lcd_string(Buffer);
|
147 | _delay_ms(3000);
|
148 | PORTB &= ~(1 << PB1);
|
149 | break;
|
150 | }
|
151 | }
|
152 | }
|
153 | lcd_clear();
|
154 | }
|
155 |
|
156 | void WaitForUserReady(void)
|
157 | {
|
158 | //Kontrolliert ob der Knueppel beim ersten Start in der Nullposition ist
|
159 | while(stick != unten);
|
160 | PORTC |= (1 << PC0);
|
161 | }
|
162 |
|
163 | void Ein_Ausgaenge(void)
|
164 | {
|
165 | //Initialisierung fuer Ein-/Ausgaenge
|
166 | DDRB &= ~(1 << PB0); //Taster (PB0) = Eingang
|
167 | PORTB |= (1 << PB0); //Pullup
|
168 | DDRB |= (1 << PB1); //Gelbe LED (PC6) = Ausgang
|
169 | DDRC |= (1 << PC0); //SD/ Pin IR2184 Mosfet Treiber (PC0) = Ausgang
|
170 | }
|
171 |
|
172 | void ADC_Init(void)
|
173 | {
|
174 | //Initialisierung fuer Spannungsmessung
|
175 | uint16_t result;
|
176 |
|
177 | // interne Referenzspannung als Refernz für den ADC wählen:
|
178 | ADMUX = (1<<REFS1) | (1<<REFS0);
|
179 | ADCSRA = (1<<ADPS2) | (1<<ADPS1); // Frequenzvorteiler, Dummyreadout
|
180 | ADCSRA |= (1<<ADEN); // ADC aktivieren
|
181 | ADCSRA |= (1<<ADSC); // eine ADC-Wandlung
|
182 | while (ADCSRA & (1<<ADSC)) { // auf Abschluss der Konvertierung warten
|
183 | }
|
184 | result = ADCW;
|
185 | }
|
186 |
|
187 | uint16_t ADC_Read(uint8_t channel)
|
188 | {
|
189 | // Initialisierung fuer Spannungseinzelmessung
|
190 | ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F); //Kanal waehlen, ohne andere Bits zu beeinflußen
|
191 | ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion"
|
192 | while (ADCSRA & (1<<ADSC) ) { // auf Abschluss der Konvertierung warten
|
193 | }
|
194 | return ADCW;
|
195 | }
|
196 |
|
197 | int main (void)
|
198 | {
|
199 | lcd_init();
|
200 | lcd_clear();
|
201 |
|
202 | PWM_Mosfet();
|
203 | PWM_Empfaenger();
|
204 | Strommessung();
|
205 | sei(); //fuer ISR (gibt den Startschuss fuer Interrupt)
|
206 | Ein_Ausgaenge();
|
207 | Knueppelweg();
|
208 |
|
209 | currentOverload = 0;
|
210 |
|
211 | unten = eeprom_read_word (&eeunten); //EEPROM lesen
|
212 | oben = eeprom_read_word (&eeoben);
|
213 |
|
214 | WaitForUserReady();
|
215 |
|
216 | deltaStick = oben - unten; //Knueppelweg Vorberechnung
|
217 | deltaStick = 255 / deltaStick;
|
218 |
|
219 | ADC_Init(); //Spannungsmessung
|
220 | uint16_t spannung; //Spannungsmessung
|
221 |
|
222 | while(1)
|
223 | {
|
224 | if(currentOverload == 1)
|
225 | {
|
226 | PORTB |= (1 << PB1);
|
227 | k = 0;
|
228 | }
|
229 | else
|
230 | {
|
231 | PORTB &= ~(1 << PB1);
|
232 | i = stick - unten;
|
233 | i = i * deltaStick;
|
234 | k = i;
|
235 | if(stick >= oben)
|
236 | {
|
237 | k = 255;
|
238 | }
|
239 | if(stick <= unten)
|
240 | {
|
241 | k = 0;
|
242 | }
|
243 | OCR2 = k;
|
244 | spannung = ADC_Read(0);
|
245 | if (spannung <= 250)
|
246 | {
|
247 | break;
|
248 | }
|
249 | }
|
250 | }
|
251 | while(1)
|
252 | {
|
253 | OCR2 = 0;
|
254 | lcd_init();
|
255 | lcd_clear();
|
256 | lcd_string("Akku");
|
257 | lcd_setcursor( 0, 2);
|
258 | lcd_string("leer!");
|
259 | _delay_ms(1000);
|
260 | PORTC &= ~(1 << PC0);
|
261 | }
|
262 | return 0;
|
263 | }
|