Forum: Mikrocontroller und Digitale Elektronik Taschenlampe mit Attiny13a


von SBGJunge (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Leute brauche eure Hilfe.

Habe in meiner Taschenlampe einen "Nanjg 105c" (Schaltbild im 
Anhang)Treiber.
Bin am Programm schreiben und stehe jetzt an.

Was ich bis jetzt geschafft habe : 4 Helligkeitsstufen die bei kurzer 
Spannungsunterbrechung durch schalten (nach der 4. Stufe fängt wieder 
bei 1 an ohne Memory).
Bei 3 schnellen Unterbrechungen wird auf Sroboskop umgeschaltet.

Was ich noch haben möchte:
Ab einer gewissen Spannung z.b.3,5V wird die LED jede Minute einmal für 
0,5s unterbrochen.
Ab einer Spannung von z.b. 3,3V wird die Helligkeit um eine Stufe 
runtergeschalten.
Ab einer gewissen Spannung z.b.3,1 wird die LED alle 20s einmal für 0,5s 
unterbrochen.
Einen Spannungstest Modus 5 mal schnell Spannung unterbrechen, blinkt 
dann für je 10% Ladung 1 mal


Danke euch schonmal!

Hier mein Programm:

------------------------------------------------------------------------ 
----
#define F_CPU 4800000
#include <avr/io.h>
#include <stdlib.h>
#include <util/delay.h>
#include <avr/eeprom.h>
#include <avr/pgmspace.h>
//#define MODE_MEMORY
#ifdef MODE_MEMORY // only using eeprom if mode memory is enabled
uint8_t EEMEM MODE_P;
uint8_t EEMEM LVL_P;
#endif


volatile uint8_t noinit_decay _attribute_ ((section (".noinit")));
volatile uint8_t noinit_mode _attribute_ ((section (".noinit")));
// pwm level selected by ramping function
volatile uint8_t noinit_lvl _attribute_ ((section (".noinit")));
// number of times light was on for a short period, used to enter
// extended modes
volatile uint8_t noinit_short _attribute_ ((section (".noinit")));
// extended mode enable, 0 if in regular mode group
volatile uint8_t noinit_strobe _attribute_ ((section (".noinit")));
// extended mode
volatile uint8_t noinit_strobe_mode _attribute_ ((section 
(".noinit")));


// PWM configuration
#define PWM_PIN PB1
#define PWM_LVL OCR0B
#define PWM_TCR 0x21
#define PWM_SCL 0x01
// This will be the same as the PWM_PIN on a stock driver
#define STROBE_PIN PB1
static void inline strobe()
{
  while (1){
    PORTB |= _BV(STROBE_PIN); // on      +++++++++++++++
    _delay_ms(30);
    PORTB &= ~_BV(STROBE_PIN); // off      +++++++++++
    _delay_ms(30);
  }
}
static void inline sleep_ms(uint16_t ms)
{
  while(ms >= 1){
    _delay_ms(1);
    --ms;
  }
}
// Variable strobe
// strobe using the STROBE_PIN. Note that PWM on that pin should not be
// set up, or it should be disabled before calling this function.

int main(void)
{
  if (noinit_decay) // not short press, all noinit data invalid
  {
    noinit_mode = 0;
    noinit_short = 0; // reset short counter
    noinit_strobe = 0;
    noinit_strobe_mode = 0;
    noinit_lvl = 0;
    noinit_volt = 0;
    #ifdef MODE_MEMORY // get mode from eeprom
    noinit_mode = eeprom_read_byte(&MODE_P);
    noinit_lvl = eeprom_read_byte(&LVL_P);
    #endif
  }
  else
  {
    ++noinit_mode;
    ++noinit_short;
  }
  noinit_decay = 0;
  // mode needs to loop back around
  // (or the mode is invalid)
  if (noinit_mode > 3) // anzahl der Modes
  {
    noinit_mode = 0;
  }
  if (noinit_short > 1 && !noinit_strobe)
  {
    noinit_strobe = 1;
    noinit_strobe_mode = 0;
  }
  if (noinit_strobe_mode > 0) // only 1 strobe mode, could add more...
  {
    noinit_strobe_mode = 0; // loop back to first mode
  }



  //setup pins for output. Note that these pins could be the same pin
  DDRB |= _BV(PWM_PIN) | _BV(STROBE_PIN);
  // extended modes, 1 for now, leaving extra code in case I want to
  // add more strobes later
  if (noinit_strobe)
  {
    switch(noinit_strobe_mode){
      case 0:
      strobe();
      break;
    }
  }
  // Initialise PWM on output pin and set level to zero
  TCCR0A = PWM_TCR;
  TCCR0B = PWM_SCL;
  PWM_LVL = 0;
  switch(noinit_mode){
    case 0:
    PWM_LVL = 4;   //ML 2%            +++++++++++++++
    break;
    case 1:
    PWM_LVL = 12;  // 5%
    break;
    case 2:
    PWM_LVL = 85;  //33%
    break;
    case 3:
    PWM_LVL = 255;   //100%
    break;

    #ifdef MODE_MEMORY // remember mode in eeprom
    // save mode without delay, since ramp() will not return.
    eeprom_busy_wait(); //make sure eeprom is ready
    eeprom_write_byte(&MODE_P, noinit_mode); // save mode
    #endif

  }
  // keep track of the number of very short on times
  // used to decide when to go into strobe mode
  _delay_ms(100); // on for too long          ++++++++++++++
  noinit_short = 0; // reset short press counter
  #ifdef MODE_MEMORY // remember mode in eeprom
  eeprom_busy_wait(); //make sure eeprom is ready
  eeprom_write_byte(&MODE_P, noinit_mode); // save mode
  // only save level if it was set, to reduce writes. Not based on
  // mode number in case mode orders change in code.
  if (noinit_lvl != 0)
  {
    eeprom_busy_wait(); //make sure eeprom is ready
    eeprom_write_byte(&LVL_P, noinit_lvl); // save level
  }
  #endif
  while(1);
  return 0;
}

von Karl M. (Gast)


Lesenswert?

Hallo,

wo sind die C-Code Formatierungen ?

von Stefan A. (ripper121)


Lesenswert?

Wenn der Tiny13 direkt an der Batterie hängt kannst du die Interne 
Refrezspannung zum Messen der Batterie nutzen.
http://jeelabs.org/2012/05/04/measuring-vcc-via-the-bandgap/

Sry gerade gelesen: Beitrag "ATTiny13A: Betriebsspannung über Bandgap-Referenz messen?"
Geht beim Tiny13 nicht, aber mit dem Tiny85 geht es.

: Bearbeitet durch User
von Uwe (Gast)


Lesenswert?

Mit dem Analog Comparator kannst du eine externe Spannung mit der 
internen Bandgap-Referenz vergleichen.
Von Atmel gibt's ne App-Note darüber, wie man dem Comparator, einem 
externen R-C und einem Timer ADC realisieren kann.

von stromtuner (Gast)


Lesenswert?

muss man so in "c" mit eckigen Klammern setzen für die Codeansicht...
1
#define F_CPU 4800000
2
#include <avr/io.h>
3
#include <stdlib.h>
4
#include <util/delay.h>
5
#include <avr/eeprom.h>
6
#include <avr/pgmspace.h>
7
//#define MODE_MEMORY
8
#ifdef MODE_MEMORY // only using eeprom if mode memory is enabled
9
uint8_t EEMEM MODE_P;
10
uint8_t EEMEM LVL_P;
11
#endif
12
13
14
volatile uint8_t noinit_decay _attribute_ ((section (".noinit")));
15
volatile uint8_t noinit_mode _attribute_ ((section (".noinit")));
16
// pwm level selected by ramping function
17
volatile uint8_t noinit_lvl _attribute_ ((section (".noinit")));
18
// number of times light was on for a short period, used to enter
19
// extended modes
20
volatile uint8_t noinit_short _attribute_ ((section (".noinit")));
21
// extended mode enable, 0 if in regular mode group
22
volatile uint8_t noinit_strobe _attribute_ ((section (".noinit")));
23
// extended mode
24
volatile uint8_t noinit_strobe_mode _attribute_ ((section 
25
(".noinit")));
26
27
28
// PWM configuration
29
#define PWM_PIN PB1
30
#define PWM_LVL OCR0B
31
#define PWM_TCR 0x21
32
#define PWM_SCL 0x01
33
// This will be the same as the PWM_PIN on a stock driver
34
#define STROBE_PIN PB1
35
static void inline strobe()
36
{
37
  while (1){
38
    PORTB |= _BV(STROBE_PIN); // on      +++++++++++++++
39
    _delay_ms(30);
40
    PORTB &= ~_BV(STROBE_PIN); // off      +++++++++++
41
    _delay_ms(30);
42
  }
43
}
44
static void inline sleep_ms(uint16_t ms)
45
{
46
  while(ms >= 1){
47
    _delay_ms(1);
48
    --ms;
49
  }
50
}
51
// Variable strobe
52
// strobe using the STROBE_PIN. Note that PWM on that pin should not be
53
// set up, or it should be disabled before calling this function.
54
55
int main(void)
56
{
57
  if (noinit_decay) // not short press, all noinit data invalid
58
  {
59
    noinit_mode = 0;
60
    noinit_short = 0; // reset short counter
61
    noinit_strobe = 0;
62
    noinit_strobe_mode = 0;
63
    noinit_lvl = 0;
64
    noinit_volt = 0;
65
    #ifdef MODE_MEMORY // get mode from eeprom
66
    noinit_mode = eeprom_read_byte(&MODE_P);
67
    noinit_lvl = eeprom_read_byte(&LVL_P);
68
    #endif
69
  }
70
  else
71
  {
72
    ++noinit_mode;
73
    ++noinit_short;
74
  }
75
  noinit_decay = 0;
76
  // mode needs to loop back around
77
  // (or the mode is invalid)
78
  if (noinit_mode > 3) // anzahl der Modes
79
  {
80
    noinit_mode = 0;
81
  }
82
  if (noinit_short > 1 && !noinit_strobe)
83
  {
84
    noinit_strobe = 1;
85
    noinit_strobe_mode = 0;
86
  }
87
  if (noinit_strobe_mode > 0) // only 1 strobe mode, could add more...
88
  {
89
    noinit_strobe_mode = 0; // loop back to first mode
90
  }
91
92
93
94
  //setup pins for output. Note that these pins could be the same pin
95
  DDRB |= _BV(PWM_PIN) | _BV(STROBE_PIN);
96
  // extended modes, 1 for now, leaving extra code in case I want to
97
  // add more strobes later
98
  if (noinit_strobe)
99
  {
100
    switch(noinit_strobe_mode){
101
      case 0:
102
      strobe();
103
      break;
104
    }
105
  }
106
  // Initialise PWM on output pin and set level to zero
107
  TCCR0A = PWM_TCR;
108
  TCCR0B = PWM_SCL;
109
  PWM_LVL = 0;
110
  switch(noinit_mode){
111
    case 0:
112
    PWM_LVL = 4;   //ML 2%            +++++++++++++++
113
    break;
114
    case 1:
115
    PWM_LVL = 12;  // 5%
116
    break;
117
    case 2:
118
    PWM_LVL = 85;  //33%
119
    break;
120
    case 3:
121
    PWM_LVL = 255;   //100%
122
    break;
123
124
    #ifdef MODE_MEMORY // remember mode in eeprom
125
    // save mode without delay, since ramp() will not return.
126
    eeprom_busy_wait(); //make sure eeprom is ready
127
    eeprom_write_byte(&MODE_P, noinit_mode); // save mode
128
    #endif
129
130
  }
131
  // keep track of the number of very short on times
132
  // used to decide when to go into strobe mode
133
  _delay_ms(100); // on for too long          ++++++++++++++
134
  noinit_short = 0; // reset short press counter
135
  #ifdef MODE_MEMORY // remember mode in eeprom
136
  eeprom_busy_wait(); //make sure eeprom is ready
137
  eeprom_write_byte(&MODE_P, noinit_mode); // save mode
138
  // only save level if it was set, to reduce writes. Not based on
139
  // mode number in case mode orders change in code.
140
  if (noinit_lvl != 0)
141
  {
142
    eeprom_busy_wait(); //make sure eeprom is ready
143
    eeprom_write_byte(&LVL_P, noinit_lvl); // save level
144
  }
145
  #endif
146
  while(1);
147
  return 0;
148
}

von stromtuner (Gast)


Lesenswert?

oder ggfls als Anhang :|

von stromtuner (Gast)


Lesenswert?

Willst Du jedesmal in den EEPROM schreiben?
Der AVR wird doch sicher weiterhin versorgt, wnn man mal kurz den Knopf 
drückt, um den Mode weiter zu schalten, oder?
So habe ich das jedenfalls gemacht. Ich hatte aber einen Mega16 mit 16 
zusätzlichen LEDs für Schrift undso. Wenn man da kurz den Strom 
ausgetastet hatte, wurde der Interruptpin gezogen und de µC lief 
trotzdem über Diode/Elko weiter. hatte man gut fünf Sekunden Zeit, eine 
entsprechende Sequenz reinzutasten"morsen" ( hier: Buchstaben für den 
anzuzeigenden Text )

von SBGJunge (Gast)


Lesenswert?

Danke für eure Bemühungen aber leider bringt es mich nicht weiter. Hab 
es schon mit if-schleifen probiert aber es wird nichts.

Zu meinem Vorhaben:

Ab einer gewissen Spannung z.b.3,5V wird die LED jede Minute einmal für
0,5s unterbrochen.
Ab einer Spannung von z.b. 3,3V wird die Helligkeit um eine Stufe
runtergeschalten.
Ab einer gewissen Spannung z.b.3,1 wird die LED alle 20s einmal für 0,5s
unterbrochen.
Einen Spannungstest Modus 5 mal schnell Spannung unterbrechen, blinkt
dann für je 10% Ladung 1 mal

von Lukas T. (tapy)


Lesenswert?

SBGJunge schrieb:
> Hab
> es schon mit if-schleifen probiert aber es wird nichts.

Was denn? Ist das Messen der Spannung das Problem? Das Blinken?

von Huh (Gast)


Lesenswert?

SBGJunge schrieb:
> Hab es schon mit if-schleifen probiert aber es wird nichts.

Logisch, weil es keine if-Schleifen gibt :-)
Da ist nirgends eine Schleife...
http://if-schleife.de/

von Stefan F. (Gast)


Lesenswert?

Braucht die LED keinen Vorwiderstand?

von Heinrich (Gast)


Lesenswert?

>Braucht die LED keinen Vorwiderstand?
Der 7135 ist eine 350mA Konstantstromquelle, wenn ich mich recht 
erinnere

von Marc H. (marchorby)


Lesenswert?

Heinrich schrieb:
>>Braucht die LED keinen Vorwiderstand?
> Der 7135 ist eine 350mA Konstantstromquelle, wenn ich mich recht
> erinnere

Das ist richtig!
http://led22.ru/ledcat/ledsource/amc7135.pdf

von Stefan F. (Gast)


Lesenswert?

Oh, wie praktisch! Ich wusste gar nicht, dass man das so kompakt haben 
kann.

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Ja, ne schön kompakte Heizung, die ohne entsprechend großen KK nicht
funktioniert - jedenfalls nicht lange...

von SBGJunge (Gast)


Lesenswert?

ich versuchs jetzt ein letztes mal
Kann mir jemand mit der Programmierung wie oben in der Fragestellung 
weiterhelfen ?

Danke!

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Am besten fügst du in die Hauptschleife einen Zähler ein, indem du sie 
per Timer synchronisierst.

Also z.B. in Pseudocode:
1
Start:
2
Initialisiere Ports auf Ein- und Ausgänge
3
Initialisiere PWM für LED
4
Initialisiere ADC auf ADC MUX und Referenz
5
Initialisiere Zeitbasis Timer auf 500ms Rate 
6
Setze Zähler auf 0
7
Hauptschleife:
8
 Frage ADC ab
9
 Wenn ADC > 3,5V: setze LED PWM auf 100%
10
 Sonst wenn ADC < 3,5V und ADC > 3,3V:
11
      Wenn Zähler > 119 setze LED PWM auf 0%; Zähler = 0;
12
      sonst setze LED PWM auf 100%;
13
 Sonst wenn ADC < 3,3V und ADC > 3,1V : setze LED PWM auf 80%;
14
 Sonst wenn ADC < 3,1V:              
15
      Wenn Zähler > 39 setze LED PWM auf 0%; Zähler = 0;
16
      sonst setze LED PWM auf 100%;   // oder auch auf 80% oder 50% zum Stromsparen
17
18
Zähler++;
19
Wenn Zähler > 254: Zähler = 0;
20
Warte auf Ablaufen des 500ms Zeitbasis Timers
21
gehe zu Hauptschleife

Das ganze kann man statt mit if-else auch mit switch-case realisieren.

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Über Reset zu gehen, finde ich unsicher. Man weiß nie, wo das Main 
gerade abgewürgt wird.
Mach einfach C1 so groß, daß der MC bei kurzem Abschalten in Betrieb 
bleibt. BOD kann man auf 1,8V setzen.
Und dann nimm den ADC als normalen Tasten-Eingang.
Wozu soll D1 gut sein?

Die Bedienung klingt höllisch kompliziert. Daher solltest Du zuerst 
einen Programmablaufplan erstellen, um nicht den Durchblick zu 
verlieren.
Mit dem PAP ist das Umsetzen in Code dann einfach.

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.