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; }
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
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.
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 | }
|
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 )
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
SBGJunge schrieb: > Hab > es schon mit if-schleifen probiert aber es wird nichts. Was denn? Ist das Messen der Spannung das Problem? Das Blinken?
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/
>Braucht die LED keinen Vorwiderstand? Der 7135 ist eine 350mA Konstantstromquelle, wenn ich mich recht erinnere
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
Oh, wie praktisch! Ich wusste gar nicht, dass man das so kompakt haben kann.
Ja, ne schön kompakte Heizung, die ohne entsprechend großen KK nicht funktioniert - jedenfalls nicht lange...
ich versuchs jetzt ein letztes mal Kann mir jemand mit der Programmierung wie oben in der Fragestellung weiterhelfen ? Danke!
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
Ü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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.