Attiny13 mit PWM und 2 LEDs

OP #3105416
Lesenswert?

Hallo Leute,

ich bin neu hier und habe mich schon etwas mit C und dem Tiny13 
beschäftigt, trotzdem bekomme ich es nicht hin, 2 Ausgänge mit jedweils 
1 LED per interner PWM zu dimmen.
dies soll über 2 tastern am eingang passieren.
ich verstehe manche C befehle noch nicht, bzw komm durcheinander.
finde ich irgendwo hier im netz ein grund- C programm, umzu sehen, wie 
die PWM eingestellt wird und funktioniert mit dem Tiny13 ?

ausgang am tiny13 : PB0,1,2
eingang : PB3,4,5

ist es schon mal richtig das dies in Hex :

DDRB= 0xA1 wäre?
und ich den TCCR0A = 0xA1 und
TCCR0B=0x01

setze??

Ich hofe ihr könnt mir helfen :(

Grüße
Manu
#3105426
Lesenswert?

Manuel F. schrieb:

> ausgang am tiny13 : PB0,1,2
> eingang : PB3,4,5
>
> ist es schon mal richtig das dies in Hex :
>
> DDRB= 0xA1 wäre?

wie kommst du auf 0xA1
Du willst PB0,  PB1 und PB2 auf Ausgang schalten.
Dann schreibs halt so

   DDRB |= ( 1 << PB0 ) | ( 1 << PB1 ) | ( 1 << PB2 );

und schon brauchst du dich nicht mehr darum kümmern, was das als 
Hex-Zahl ausmacht. Und als Nebeneffekt siehst du in der Anweisung gleich 
direkt, welche 'Bits' (und damit welche Pins) du auf 1 und damit auf 
Ausgang gestellt hast.

> und ich den TCCR0A = 0xA1 und
> TCCR0B=0x01

Detto.
Die Bits in den Registern haben Namen. Benutze sie und vieles wird 
einfacher.
Es ist ein Trugschluss für alles und jedes Hex-Zahlen zu benutzen. Die 
Schreibweise von Zahlen richtet sich danach, in welchem Zusammenhang sie 
vorkommen. Je nachdem ist die eine oder andere Schreibweise viel besser 
geeignet.

FAQ: Timer
#3105431
Lesenswert?

> ich verstehe manche C befehle noch nicht, bzw komm durcheinander.

Dann musst du üben.
Ein nicht unwesentlicher Sinn in den ersten Übungsprogrammen, die sich 
um LED ein/ausschalten drehen, besteht darin, Schreibweisen für 
Bit-Setzen bzw. Bit-Löschen solange zu wiederholen, bis man sie im 
Schlaf beherrscht.

Dazu muss man aber selbst Programme schreiben! Einfach nur anderer Leute 
Programme anzusehen und laufen zu lassen ist zu wenig.

Die Themenkreise

* Bedeutung der jeweiligen DDRx, PORTx, PINx
* wie werden Einzelbits an den Rgeister gesetzt, gelöscht, getoggelt und
  abgefragt

das sind sind die wesentlichen Punkte, um die es bei den ersten x (x 
größer 15) Programmen, die sich mit LED ein/aus in allen Variationen, 
über Blinken bis hin zum Lauflicht in allen möglichen Schattierungen 
tatsächlich dreht.

Und genau das sind auch die absoluten Basisgrundlagen, deren 
Beherrschung für alles weitere vorausgesetzt wird.
#3105436
Lesenswert?

Hallo,

hast du schon mal einfach nur LED ein/aus programmiert? Wenn nein, dann 
versuch doch das erstmal. z:B. So:
1
#include <avr/io.h>
2
#include <avr/delay.h>
3

4
void main (void)
5
{
6
   DDRB |= (1 << PB0);   // PB0 als Ausgang
7
   while(1)
8
   {
9
      PORTB &= ~(1 << PB0); // PB0 Aus
10
      _delay(500);           //warten
11
      PORTB |= (1 << PB0);  //PB0 Ein
12
   }
13
}

Moritz
OP #3105450
Lesenswert?

danke schon mal für eure antworten.

ja das mit einer LED an/aus automatisch habe ich schon hinbekommen :)
nur der rest mit PWM haut nicht so hin.
Hex mit A1 war natürlich mist.
ich meinte eigentlich

DDRB = 0x07

aber die andere schreibweise ist übersichtlicher und einfacher.

ich werde mich hier etwas rumschauen und bei fragen,frag ich einfach:)
OP #3123064
Lesenswert?

Nun habe ich es schon mal hinbekommen,eine LED am Ausgang OCR0A zu 
Dimmen.
Mit Taster 1 >> LED Hoch dimmen,
Mit Taster 2 >> LED runter Dimmen.
WIe bekomme ich es nun hin, das ich dieses verhalten nur mit EINEM 
Taster mache?
Sprich,Taster 1 drücken, dimmt hoch, los lassen, warten und wert halten, 
weiter drücken, dann runter dimmen?
OP #3146371
Lesenswert?

Hallo erneut :)
soweit habe ich es nun alles zum laufen bekommen.
Ich muss nur noch versuchen, die werte ins EEPROM zu schreiben,bevor ich 
die platine spannungslos mache.
So dass meine LEDs leuchten, wie ich sie ausgeschaltet habe.
Und noch eins bekomme ich nicht hin.
Beide Register OCR0a und OCR0b sollen gegeneinander laufen; Sprich wenn 
ein ausgang 10% und der andere 90% helligkeit hat, und ich nun BEIDE 
ZUSAMMEN dimmen möchte, ist logischerweise die 10%tige schneller aus als 
die andere. ich möchte aber das beide zusammen langsam ausdimmen.
wie bekomm ich das denn hin?
#3146421
Lesenswert?

Manuel F. schrieb:
> Hallo erneut :)
> soweit habe ich es nun alles zum laufen bekommen.
> Ich muss nur noch versuchen, die werte ins EEPROM zu schreiben,bevor ich
> die platine spannungslos mache.
> So dass meine LEDs leuchten, wie ich sie ausgeschaltet habe.

AVR-GCC-Turoial
Da gibt es einen Abschnitt über das EEPROM

> Beide Register OCR0a und OCR0b sollen gegeneinander laufen; Sprich wenn
> ein ausgang 10% und der andere 90% helligkeit hat, und ich nun BEIDE
> ZUSAMMEN dimmen möchte, ist logischerweise die 10%tige schneller aus als
> die andere. ich möchte aber das beide zusammen langsam ausdimmen.
> wie bekomm ich das denn hin?

indem du für den Benutzer eine Variablen einführst, die die jeweilige 
Dimmstufe der einen LED angibt. Die andere ist dann logischerweise 100-x 
davon.
Weiters führst du dir einen Masterdimmer ein. Ebenfalls eine 
Prozentzahl, die angibt, wieviele Prozent der Dimmstufe bzw. des 
Gegenteils davon dann tatsächlich realisiert werden sollen.

Angenommen mit deinen Tasten hast du eingestellt, dass die eine LED zu 
35% leuchten soll. Dann leuchtet die andere LED zu 65%.
Soweit so gut.
Dein Masterdimmer steht auf 100%, was soviel heisst wie: die 35% bzw. 
65% sollen auch tatsächlich realisiert werden.

Wie hell leuchtet dann jede LED wirklich?

LED1:   35 * 100 / 100  ->  35%
LED2:   65 * 100 / 100  ->  65%

Jetzt sei der Wert des Masterdimmers auf 90%. Wie hell müssen jetzt die 
LED eingestellt werden?

LED1:   35 * 90 / 100   ->  31%
LED2:   65 * 90 / 100   ->  58%

d.h. deine vom Benutzer eingestellten LED Werte sind beide auf 90% 
zurückgenommen worden.

D.h. der Benutzer verteilt seine 100% auf die beiden LED, während der 
Masterdimmer dafür zuständig ist, beide LED gemeinsam auf bzw. 
abzudimmen.

So wie es zb Windows in den Sound-Einstellungen macht: Jedes Gerät hat 
einen eigenen Regler. Und für alle gemeinsam ist ein Hauptregler 
zuständig, der alle mitsammen lauter bzw. leiser macht. Mathematisch 
sind das einfach nur Werte zwischen 0 und 1, die miteinander 
multiplizert werden. Aus naheliegenden Gründen wollen wir aber keine 
Gleitkommazahlen. Das 100-fache davon, welches man umgangssrachlich 
'Prozent' nennt, tut es dazu auch - und damit ganze Zahlen.
OP #3152975
Lesenswert?

danke schon mal für die antwort.
ich werde es mal ausprobieren.
nun nochmal zum eeprom; der link geht nicht.
ich habe nun probiert das eeprom zu schreiben und zu lesen, es geht 
jedoch nicht.

mein programm sieht nun zb so aus:
ich benutze beide OCROA/B Register um je eine LED am ausgang zu dimmen.

erst definitionen....etc pp
dann das:

eeprom_busy_wait();         // wait while eeprom busy
OCR0A = eeprom_read_word(0x000);

eeprom_busy_wait();         // wait while eeprom busy
OCR0B = eeprom_read_word(0x000);

dann das hauptprogram.......

dann das zum schluss:

eeprom_busy_wait();            // wait while eeprom busy
old_OCR0A = eeprom_read_word(0x000);
if (old_OCR0A != OCR0A)
  {
  eeprom_busy_wait();
  eeprom_write_word(0x000,OCR0A);
  }

eeprom_busy_wait();         // wait while eeprom busy
old_OCR0B = eeprom_read_word(0x000);
if (old_OCR0B != OCR0B)
 {
  eeprom_busy_wait();
  eeprom_write_word(0x000,OCR0B);
 }
 }

was ist daran denn falsch?
(Firma: matzetronics) #3153914
Lesenswert?

Du möchtest vermutlich auch kein 'word' aus dem EEPROM lesen, sondern 
nur ein byte. Statt
1
OCR0A = eeprom_read_word(0x000);
Ausserdem möchtest du sicher nicht OCR0A und OCR0B von der gleichen 
EEPROM Adresse laden.
nimm also besser
1
// definiere EEPROM Adressen und deren Inhalt. 
2
// Der Inhalt kann einmal mit dem Programmer ins EEPROM geladen werden
3
uint8_t ee_OCRA_Addr __attribute__((section(".eeprom"))) = 0;
4
uint8_t ee_OCRB_Addr __attribute__((section(".eeprom"))) = 0;
5

6
// Schreiben geht so
7
uint8_t a,b;
8
        a = OCR0A;
9
        b = OCR0B;
10
        sei();
11
  eeprom_busy_wait();
12
  eeprom_write_byte(&ee_OCRA_Addr,a);
13
  eeprom_busy_wait();
14
  eeprom_write_byte(&ee_OCRB_Addr,b);
15
  eeprom_busy_wait();
16
        cli();
17
// Und dann lesen. Das geht ohne busy wait
18
OCR0A = eeprom_read_byte(&ee_OCRA_Addr);
19
OCR0B = eeprom_read_byte(&ee_OCRB_Addr);
Du solltest auch dran denken, das eine EEPROM Zelle nach etwa 100000 mal 
schreiben kaputt geht, bzw. nicht mehr die Daten halten kann. Also nicht 
blind reinschreiben, sondern nur, wenn es wirklich was zu schreiben 
gibt, z.b. in einer Brownout Routine.

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