Hallo,
ich bin neu hier und möchte mich kurz vorstellen. Mein Name ist Heiko,
ich komme aus der schönen(?) Sprottenstadt Kiel. Elektronik bzw.
Elektrik verwende ich in meinem Hobby Modellbau, weswegen da auch der
Schwerpunkt liegt. Hauptsächlich Lichtsteuerungen für Raumschiffe und
Steuermodule für meine RC-Modelle. Angefangen habe ich da mit der
Arduino-Umgebung, was auch ganz gut klappte und die Scheu vor den
"nackten" AVRs nahm (Stichwort Fuses). Irgendwann war mir das aber
zuviel Gekrücke, vor allem wenn ich einfachere Sachen nur mit Attinys
machen wollte. Daher erfolgte vor kurzem der Sprung auf die "echte"
AVR-Umgebung (Atmel Studio 6.2, AVRISP MkII, etc.).
Nun zu meinem Problem: Ich versuche über einen Attiny85 zwei Signale
eines Empfängers einzulesen und entsprechend weiterzuverarbeiten. Im
ersten Anlauf will ich nur das empfangene Signal eines Kanals zum testen
ausgeben, wenn das vernünftig funktioniert geht es weiter.
Kern sind die beiden Timer. Timer0 läuft im CTC-Modus und erhöht alle
8µs einige Zähler um 1. Timer1 ist nur dafür da, alle 20ms die
Signalausgabe neu zu starten (habe ich auch nur dank dieses Treads zum
laufen bekommen: Beitrag "ATtiny25, TimerCounter1, CTC-Mode: Bug?").
Der Signalstart alle 20ms funktioniert auch tadellos, nur das
auszugebende Signal klappt gar nicht. Wenn kein Empfänger angeschlossen
ist, soll der Start- bzw. letzte gültige Wert zwischen 1000-2000µs
ausgegeben werden. Stattdessem wandert das Signal förmlich, beginnend
bei ca. 3200µs langsam runter auf 2000µs und dann wieder von vorne. Kann
ich auf meinem Spielzeug-Taschen-Oszi richtig schön beobachten.
Ich bin da jetzt langsam etwas ratlos, kaue schon seit einigen Tagen
daran herum. Die Suche ergab leider nicht so furchtbar viel (mal mit
PC-Interrupt, mal ohne, oft nur ein Kanal, etc.), auch wenn das Thema
"Servosignal" offenbar ganze Seiten füllt.
1 | #include <avr/interrupt.h>
|
2 | #include <avr/io.h>
|
3 |
|
4 | #define pin_benedini PB0 // Anschluss für Benedini-Modul
|
5 | #define pin_drehgeber PB1 // Anschlüss für Poti-Geber vom Empfänger
|
6 | #define pin_taster PB2 // Anschluss für Tast-Geber vom Empfänger
|
7 | #define pin_led PB4 // Anschluss für Status-LED
|
8 |
|
9 | volatile uint16_t zeit = 0; // aktuelle Ausgabedauer für Benedini-Modul
|
10 | volatile uint16_t zeit_empfaenger[2] = {188, 188}; // Signaldauer der empfangenen Empfängersignale
|
11 | uint16_t zeit_ausgabe[2] = {188, 188}; // auszugebende Signaldauer für Benedini und LED
|
12 | uint8_t pin_empfaenger[2] = {pin_taster, pin_drehgeber};
|
13 | uint8_t pinb_alt = 0; // Zustand von PINB vor Änderung von PORTB
|
14 |
|
15 | int main(void)
|
16 | {
|
17 | DDRB |= ((1 << pin_benedini) | (1 << pin_led)); // Benedini und LEd als Ausgang definieren
|
18 |
|
19 | TCCR0A |= (1 << WGM01); // CTC-Mode aktiviert
|
20 | TCCR0B |= (1 << CS00); // Prescaler = 1
|
21 | OCR0A = 63; // 8µs
|
22 | TIMSK |= (1 << OCIE0A); // Interrupt aktivieren
|
23 |
|
24 | TCCR1 |= ((1 << CS13) | (1 << CS11) | (1 << CS10) | (1 << PWM1A) | (1 << CTC1)); // Prescaler für Timer1 = 1024; CTC aktiviert
|
25 | OCR1C = 154; // 19840µs Periodendauer = 20ms für Servosignal
|
26 | TIMSK |= (1 << TOIE1); // Interrupt aktivieren
|
27 |
|
28 | sei(); // globale Interrupts aktivieren
|
29 |
|
30 | while(1)
|
31 | {
|
32 | for(uint8_t i = 0; i < 2; i++){
|
33 | if(PINB & (1 << pin_empfaenger[i]) && !(pinb_alt & (1 << pin_empfaenger[i]))){ // steigender Pegel, Zeitmessung wird gestartet
|
34 | zeit_empfaenger[i] = 0;
|
35 | pinb_alt |= (1 << pin_empfaenger[i]);
|
36 | }
|
37 |
|
38 | if(!(PINB & (1 << pin_empfaenger[i])) && pinb_alt & (1 << pin_empfaenger[i])){ // fallender Pegel, Zeitmessung wird beendet
|
39 | if(zeit_empfaenger[i] >= 109 && zeit_empfaenger[i] <= 266){ // Zeitdauer ist gültig, als Ausgangsdauer festlegen
|
40 | zeit_ausgabe[i] = zeit_empfaenger[i];
|
41 | }
|
42 | pinb_alt &= ~(1 << pin_empfaenger[i]);
|
43 | }
|
44 |
|
45 | }
|
46 |
|
47 | if(zeit > zeit_ausgabe[0] && PINB & (1 << pin_led)){ // Wenn Dauer der Ausgabe >= geplante Signallänge, Signal abschalten
|
48 | cli();
|
49 | PORTB &= ~((1 << pin_led) | (1 << pin_benedini));
|
50 | sei();
|
51 | }
|
52 | }
|
53 | }
|
54 |
|
55 | ISR(TIMER0_COMPA_vect){
|
56 | zeit++;
|
57 | zeit_empfaenger[0]++;
|
58 | zeit_empfaenger[1]++;
|
59 | }
|
60 |
|
61 | ISR(TIMER1_OVF_vect){
|
62 | PORTB |= ((1 << pin_led) | (1 << pin_benedini)); // Alle 20ms die Signalausgabe neu starten
|
63 | zeit = 0;
|
64 | }
|
Heiko