Attiny-Anfänger: Hilfe bei Tastensteuerung

Gast #3241675
Lesenswert?

Hallo zusammen!

Ich versuche gerade mir einen Treiber für meine LED Taschenlampe zu 
programmieren, allerdings habe ich da so meine Probleme. Ich habe 
bereits einen veröffentlichten Code an meine Bedürfnisse angepasst, 
welcher allerdings die Modi durch Unterbrechung der Spannungsversorgung 
realisiert. Da ich allerdings für mein aktuelles Projekt einen 
SMD-Taster verwenden muss, habe ich versucht mir was eigenes zu 
Stricken.

Vorab kurz die Funktionsweise:

Attiny wird über eine Taste gesteuert.
PWM wird für die Ansteuerung des "Leistungsteils" verwendet.
Durch das Drücken des Tasters sollen die Modi gewechselt werden.
Da die Stromquelle / Akku nicht physikalisch getrennt wird, soll der 
Attiny in den Power-Down Modus versetzt werden und so den Akkus nur 
minimal zu entleeren.

DIe Funktion hatte ich mir wie folgt vorgestellt:

in der main-Routine wird über case/switch ein Modus gewählt und verfällt 
hier in eine Dauerschleife.

In einer Interrupt-Routine wird der Taster abgefragt, bzw. die Routine 
ausgelöst sobald dieser aktiviert wird. Zusätzlich wird eine Flagge 
gesetzt, welche die Dauerschleife in der main-Routine unterbricht und in 
den nächsten Modus geht.

Als letzter Modus wird das PWM Signal zu 0 gesetzt und der Power-Down 
Modus aktiviert.

Der Attiny wird bei einem erneuten Tastsignal geweckt und fährt im 
Programm fort.

Zusätzlich wollte ich in der WatchDog-Routine eine Akkuüberwachung 
implementieren.
(Dies habe ich aus einem lauffähigen Code so entnommen)


Jetzt zu meinem Problem: Das einzige was funktioniert ist die PWM, ein 
Umschalten der Modi funktioniert nicht.

Ich denke ich habe irgendwo einen Verständnisfehler. Allerdings hab ich 
keine Ahnung wo.
Für Kritik und Anregungen bin ich gerne offen.

1
//LED Treiber mit Attiny13; PWM Ausgang für LED Steuerung PB1; Akkuüberwachung über ADC PB2; Taster auf PB3
2

3
//########################################################################################### MODE/PWM SETUP 
4

5
#define outpin 1  // PWM Ausgang PB1
6
#define PWM OCR0B  //PWM-value
7

8
#define adcpin 2    //ADC PIN !  PB2
9
#define adcchn 1  //ADC Kanal ! ADC1
10

11
#define tasterpin 3  //PCINT3
12

13
#define portinit() do{ DDRB=(1<<outpin); PORTB=0xff-(1<<outpin)-(1<<adcpin)-(1<<tasterpin);  }while(0)//Port deklarieren
14

15

16
#define F_CPU 4800000    //CPU: 4.8MHz  PWM: 9.4kHz       ####### use low fuse: 0x75  #######   
17
//#define BATTMON  125//enable battery monitoring with this threshold
18

19

20
//###########################################################################################
21

22
#include <avr/io.h>
23
#include <util/delay.h>
24
#include <avr/interrupt.h>
25
#include <avr/sleep.h>
26
#include <avr/eeprom.h>
27
#include <avr/pgmspace.h>
28
#include <avr/wdt.h>
29

30
#define byte uint8_t
31
#define word uint16_t
32

33
#define WDTIME 0b01000011  //125ms
34

35
#define sleepinit() do{ WDTCR=WDTIME; sei(); MCUCR=(MCUCR &~0b00111000)|0b00110000; }while(0) //WDT-int and Power Down-Sleep
36

37
#define SLEEP asm volatile ("SLEEP")
38

39
#define pwminit() do{ TCCR0A=0b00100001; TCCR0B=0b00000001; }while(0)  //chan A, phasePWM, clk/1  ->2.35kHz@1.2MHz
40

41
#define adcinit() do{ ADMUX =0b01100000|adcchn; ADCSRA=0b11000100; }while(0) //ref1.1V, left-adjust, ADC1/PB2; enable, start, clk/16
42
#define adcread() do{ ADCSRA|=64; while (ADCSRA&64); }while(0)
43
#define adcresult ADCH
44

45

46
#define ADCoff ADCSRA&=~(1<<7) //ADC off (enable=0);
47
#define ADCon  ADCSRA|=(1<<7)  //ADC on
48
#define ACoff  ACSR|=(1<<7)    //AC off (disable=1)
49
#define ACon   ACSR&=~(1<<7)   //AC on  (disable=0)
50

51

52
//______________________Taster entprellen_______________________________________________________________________________________________
53
/************************************************************************/
54
/*                                                                      */
55
/*                      Not so powerful Debouncing Example              */
56
/*                      No Interrupt needed                             */
57
/*                                                                      */
58
/*              Author: Peter Dannegger                                 */
59
/*                                                                      */
60
/************************************************************************/
61
// Target: ATtiny13
62
//http://www.mikrocontroller.net/attachment/highlight/67964
63

64
#define debounce( port, pin )            \
65
({                  \
66
  static uint8_t flag = 0;  /* new variable on every macro usage */  \
67
  uint8_t i = 0;              \
68
                  \
69
  if( flag ){      /* check for key release: */    \
70
    for(;;){      /* loop ... */        \
71
      if( !(port & 1<<pin) ){  /* ... until key pressed or ... */  \
72
  i = 0;      /* 0 = bounce */      \
73
  break;                \
74
      }                  \
75
      _delay_us( 98 );    /* * 256 = 25ms */      \
76
      if( --i == 0 ){    /* ... until key >25ms released */  \
77
  flag = 0;    /* clear press flag */      \
78
  i = 0;      /* 0 = key release debounced */    \
79
  break;                \
80
      }                  \
81
    }                  \
82
  }else{      /* else check for key press: */    \
83
    for(;;){      /* loop ... */        \
84
      if( (port & 1<<pin) ){  /* ... until key released or ... */  \
85
  i = 0;      /* 0 = bounce */      \
86
  break;                \
87
      }                  \
88
      _delay_us( 98 );    /* * 256 = 25ms */      \
89
      if( --i == 0 ){    /* ... until key >25ms pressed */  \
90
  flag = 1;    /* set press flag */      \
91
  i = 1;      /* 1 = key press debounced */    \
92
  break;                \
93
      }                  \
94
    }                  \
95
  }                  \
96
  i;        /* return value of Macro */    \
97
})
98

99

100
//_____________________________________________________________________________________________________________________
101

102
byte mypwm=0;
103
byte pmode=1;  //Start Mode
104
byte interrupt_flag=1;
105

106
#ifdef BATTMON
107
byte lowbattcounter=0;
108
#endif
109

110

111

112
ISR(WDT_vect) {  //WatchDogTimer interrupt / Akkuüberwachung
113

114
#ifdef BATTMON //code to check voltage and ramp down
115
  adcread(); 
116
  if (adcresult<BATTMON) { if (++lowbattcounter>8) {mypwm=(mypwm>>1)+3;lowbattcounter=0;} } //Halbiert PWM
117
  else lowbattcounter=0;
118
#endif
119
}
120

121

122

123
ISR(PCINT0_vect) {  //pin change interrupt
124
//PWM=30; //test 
125

126
if( debounce( PINB, tasterpin )){ //Taster entprellt
127
interrupt_flag=0; //aktuellen Modus verlassen
128
pmode++; //nächster Modus
129
}}
130

131
int main(void) {
132

133
  portinit(); //Ports
134
  sleepinit(); //Sleep
135
  ACoff;
136
#ifdef BATTMON
137
  adcinit();
138
#else
139
  ADCoff;
140
#endif
141
  pwminit(); //PWM
142

143
PCMSK = (1 << tasterpin); // Externer Reset auf tasterpin definieren
144
GIMSK = (1 << PCIE); // Pin Change Interrupt freigeben
145

146

147
while(1){
148
interrupt_flag=1; //Dauerschleife aktivieren
149

150
  switch(pmode){
151

152
    case 1:  mypwm=255;  while(interrupt_flag){PWM=mypwm;} break; //100%
153

154
    case 2:  mypwm=120;  while(interrupt_flag){PWM=mypwm;} break; //50%
155
              
156

157
    case 3:  mypwm=0;  //Ausgang auf 0%
158
  sleep_cpu();     //power down
159

160

161
  //--nach power down--
162

163
  pmode=1; //mit 1 Mode starten
164
  break; 
165
              
166

167

168
    default:   mypwm=5; while(interrupt_flag){PWM=mypwm;} pmode=1; break; //all other
169

170
  }//switch
171

172
}
173

174

175

176

177
  return 0;
178
}//main

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren