Forum: Mikrocontroller und Digitale Elektronik Attiny-Anfänger: Hilfe bei Tastensteuerung


von Hans (Gast)


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

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.