Forum: Compiler & IDEs RC Schalter Problem oder Fehler


von Mister S. (misterslb)


Lesenswert?

Guten Tag

Der Code ist für eine Fernsteuerung gedacht mit attiny13.

Das Problem: ich würde gerne den Code als Schalter benützen verstehe 
aber nicht wie. Der Knüppel nach unten Led1 und Led2 sind an(nicht gut), 
Knüppel mitte keine Led an (Gut so) und Knüppel oben Led1 an (gut). Wie 
kann ich den Code ändern das nur Led1 (oben) und nur Led2 (unten) 
leuchten.





1
/*
2
 * AVR_Schalter_Attiny13a_nachbau.c
3
 *
4
 * Created: 01.01.2002 00:59:52
5
 *  Author: Q
6
 */ 
7
8
9
/************************************************************************************/
10
// Schalterfunktionalität an einem Empfänger- RC- Ausgang
11
//
12
//  -> erprobt mit ATtiny13
13
//
14
// Version: 0.2
15
//
16
// Datum: 01.02.2010
17
//
18
// Hardware bei ATtiny13 (Taktfrequenz (4,8Mhz, CKDIV8 Vorteiler Fuse gesetzt -> 600kHz):
19
// R/C-Kanal an PB1 (INT0)
20
// Schalt-LED1 an PB3
21
// Schalt-LED2 an PB4
22
23
24
/************************************************************************************/
25
// Compiler- Warnungen
26
27
#ifndef F_CPU
28
#warning "F_CPU not defined"
29
#define F_CPU 600000UL
30
#endif
31
32
/************************************************************************************/
33
// Libraries
34
35
#include <avr/io.h>
36
#include <avr/interrupt.h>
37
#include <avr/wdt.h>    // für Watchdog- Funktionen
38
#include <stdint.h>
39
40
41
/************************************************************************************/
42
// Pin- Belegung
43
44
#define RC_KanalEingang    PINB  // Eingangssignal R/C- Empfänger
45
#define RC_KanalPin      PINB1  // Pin für Eingangssignal R/C- Empfänger
46
47
48
49
/************************************************************************************/
50
// Variablen
51
52
static volatile uint8_t Reading;  // Bit- Merker zur Sperrung der Hauptroutine während der erneuten Wertermittlung
53
// Merker Flanke
54
55
56
static volatile uint8_t RCvalue;  // empfangener Wert von R/C- Empfänger -> wird von Timer runtergezählt
57
58
/************************************************************************************/
59
//Header
60
61
void RC_Read();
62
void RC_Error();
63
64
/************************************************************************************/
65
// Interruptroutinen
66
67
/* ISR für INT0 - R/C-Signal mit Timer lesen */
68
ISR(INT0_vect)
69
{
70
  RC_Read();
71
}
72
73
74
/************************************************************************************/
75
// Hauptprogramm
76
77
int main(void)
78
{
79
  DDRB |= (1<<PB3); //LED1
80
  
81
  DDRB |= (1<<PB4); //LED2
82
  
83
  PORTB |= (1<<PB1);
84
  
85
  
86
87
88
  // Initialisierung Interrupteingang INT0
89
  MCUCR |= (1<<ISC00);  // Interrupt wird bei jedem Pegelwechsel an INT0 ausgelöst
90
  GIMSK |= (1<<INT0);    // Interrupt INT0 aktivieren
91
92
  // Initialisierung Timer0
93
  TIMSK0 |= (1<<TOIE0);  // Timer0 Interrupt aktivieren
94
  
95
  // Initialisierung Watchdog auf 500ms, bedingt #include <avr/wdt.h>
96
  wdt_enable(WDTO_500MS);
97
98
  
99
  
100
  
101
  // globale Interrupptfreigabe
102
  sei();
103
104
  /***********************************************************************************/
105
  while(1)
106
  {
107
    // Watchdog zurücksetzen
108
    wdt_reset();
109
110
    
111
    
112
    {
113
      
114
      
115
      // LED- Ausgänge schalten, je Timer- Wert -> erprobt mit ATmega8
116
      
117
      
118
      
119
      if (RCvalue > 160)
120
      {
121
        PORTB &= ~(1<<PB3); //LED1 an
122
        
123
      }
124
          
125
      else
126
      {
127
        PORTB |= (1<<PB3);
128
      }
129
      
130
      
131
      
132
      if ((RCvalue > 100))
133
      {
134
        PORTB &= ~(1<<PB4); //LED2 an
135
      }
136
      
137
      else
138
      {
139
        PORTB |= (1<<PB4);
140
      }
141
    
142
      
143
          
144
          
145
      
146
  
147
      
148
149
    }
150
  }
151
}
152
153
/***********************************************************************************/
154
155
// ISR für INT0 - R/C-Signal mit Timer lesen
156
void RC_Read()
157
{
158
  // Timer starten mit steigender Flanke
159
  if(Reading == 0)
160
  {
161
    TCCR0B |= (1<<CS01);  // Start Timer0 mit Vorteiler 8
162
    Reading = 1;    // Merker Flanke setzten
163
  }
164
  
165
  // Timer stoppen mit fallender Flanke
166
  else
167
  {
168
    TCCR0B = 0x00;    // Stop Timer0
169
    RCvalue = TCNT0;  // Wert von Timer lesen
170
    TCNT0 = 0x00;    // neuen Startwert für Timer laden
171
    Reading = 0;    // Merker Flanke setzten
172
  }
173
174
  
175
}

von Markus F. (mfro)


Lesenswert?

Größer als 160 ist auch größer als 100. Gell?

Da fehlt noch ein bißchen was.

von STK500-Besitzer (Gast)


Lesenswert?

Wenn dein Messwert >100 ist KANN LED2 leuchten.
Aber nur,  wenn er nicht auch >160 ist.

von Fred (Gast)


Lesenswert?

Sollte wohl statt

if ((RCvalue > 100))

eher

if (RCvalue < 140)

heißen.

von Fred (Gast)


Lesenswert?

vielleicht hieß das auch vorher:

if ((RCvalue > 100) && RCvalue < 140)

????

wenn kein Signal anliegt liegt der Wert unter 100.
Mittelstellung wäre 150. Also zwischen unterer Position 100 und
fast Mittlestellung 140 soll die LED2 leuchten.

von Mister S. (misterslb)


Lesenswert?

Guten Abend

Habe das Problem oben gelöst jetzt habe aber gemerkt das ich 2 Timer 
brauche, für das verwende ich jetzt einen atMega8. Der 1 Timer 
funktioniert mit int0 aber der 2 Timer mit int1 funktioniert nicht.

Kann man überhaupt 2 Timer mit Interrupt benutzen?????

Vielen Vielen Dank für die Hilfe.

PEACE
1
// ISR für INT0 - R/C-Signal mit Timer lesen
2
void RC_Read()
3
{
4
  // Timer starten mit steigender Flanke
5
  if(Reading == 0)
6
  {
7
    TCCR0 |= (1<<CS01);  // Start Timer0 mit Vorteiler 8
8
    Reading = 1;    // Merker Flanke setzten
9
  }
10
  
11
  // Timer stoppen mit fallender Flanke
12
  else
13
  {
14
    TCCR0 = 0x00;    // Stop Timer0
15
    RCvalue = TCNT0;  // Wert von Timer lesen
16
    TCNT0 = 0x00;    // neuen Startwert für Timer laden
17
    Reading = 0;    // Merker Flanke setzten
18
  }
19
20
  Error = 0;      // Error- Merker zurücksetzen
21
}
22
23
//into1
24
void RC_Reada()
25
{
26
  // Timer starten mit steigender Flanke
27
  if(Readinga == 0)
28
  {
29
    TCCR2 |= (1<<CS01);  // Start Timer0 mit Vorteiler 8
30
    Readinga = 1;    // Merker Flanke setzten
31
  }
32
  
33
  // Timer stoppen mit fallender Flanke
34
  else
35
  {
36
    TCCR2 = 0x00;    // Stop Timer0
37
    RCvaluea = TCNT2;  // Wert von Timer lesen
38
    TCNT2 = 0x00;    // neuen Startwert für Timer laden
39
    Readinga = 0;    // Merker Flanke setzten
40
  }
41
42
  Errora = 0;      // Error- Merker zurücksetzen
43
}
44
45
46
// ISR für Timer0 - Fehlerhandling Timeroverflow
47
void RC_Error()
48
{
49
  TCCR0 = 0x00;      // Stop Timer0
50
  RCvalue = 0;      // Wert für Ausgänge annehmen
51
  TCNT0 = 0x00;      // neuen Startwert für Timer zurücksetzen
52
  Reading = 0;      // Merker Flanke setzten
53
  Error = 1;        // Error- Merker setzen
54
}
55
56
// ISR für Timer1 - Fehlerhandling Timeroverflow
57
void RC_Errora()
58
{
59
  TCCR2 = 0x00;      // Stop Timer2
60
  RCvaluea = 0;      // Wert für Ausgänge annehmen
61
  TCNT2 = 0x00;      // neuen Startwert für Timer zurücksetzen
62
  Readinga = 0;      // Merker Flanke setzten
63
  Errora = 1;        // Error- Merker setzen
64
}

von Karl H. (kbuchegg)


Lesenswert?

Mister S. schrieb:
> Guten Abend
>
> Habe das Problem oben gelöst jetzt habe aber gemerkt das ich 2 Timer
> brauche,


Wozu?


Was du hättest merken sollem, das ist, dass das ständige Timer 
starten/stoppen unsinnig ist.

Wenn du für einen Fahrradfahrer die Rundenzeit stoppen sollst, dann kann 
man dafür selbst verständlich eine Stoppuhr nehmen. Man kann aber auch 
eine stink normale Uhr nehmen.
Man merkst sich, wenn der Fahrer über die Startlinie geht, zb um 
17:47:12 und wann er die Ziellinie passiert, zb um 17:53:15. Die 
Differenz, 00:06:03 (oder in Sekunden 363 Sekunden) ist die Laufzeit.

Genauso auch hier:

Kein Mensch muss hier ...

> // ISR für INT0 - R/C-Signal mit Timer lesen
> void RC_Read()
> {
>   // Timer starten mit steigender Flanke
>   if(Reading == 0)
>   {
>     TCCR0 |= (1<<CS01);  // Start Timer0 mit Vorteiler 8

... den Timer ständig starten ...

>     Reading = 1;    // Merker Flanke setzten
>   }
>
>   // Timer stoppen mit fallender Flanke
>   else
>   {
>     TCCR0 = 0x00;    // Stop Timer0
>     RCvalue = TCNT0;  // Wert von Timer lesen

... oder stoppen.

Es reicht völlig, wenn man sich den Zählerstand im Falle Reading==0 
merkt und hier dann ganz einfach die Differenz dazu nimmt. Schon hat man 
genau dieselbe Information.

ABER!

Da der Timer da ständig durchläuft und niemals gestoppt wird, können da 
auch 86 Interrupts die Werte von 86 RC-Kanälen auswerten, wenn du das 
willst.

> Kann man überhaupt 2 Timer mit Interrupt benutzen?????

Natürlich kann man. Du wirst halt mal wieder irgendwo in der Copy&Paste 
Programmierung etwas übernommen haben, was für den anderen Timer etwas 
anders funktioniert.
Aber wie gesagt: Mit ein wenig Überlegen ist das gar nicht notwendig. 1 
Timer reicht völlig aus. Und einfacher wird das Programm dann auch noch.

von Mister S. (misterslb)


Lesenswert?

Hallo

DAnke für den Tipp ein Timer reicht. Habe jetzt INT0 und INT1 mit 
Timer1, den Timer Starte und Stoppe ich immer noch versuche aber noch 
den Timer durchlaufen zu lassen.

Programm Funktioniert. DAnke für die Hilfe. Peace.

von Tom (Gast)


Lesenswert?

hi,
kannst du deinen code mal zeigen?

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.