Forum: Mikrocontroller und Digitale Elektronik Attiny13 Blinklicht über Poti!Hilfe!


von Andy (Gast)


Lesenswert?

Hallo,

habe jetzt seit ein paar Tagen versucht und versucht. Aber es will nicht 
funktionieren.
Ich möchte eine Blinklichtschaltung über Poti geregelt machen.

#define F_CPU 3686400  // Taktfrequenz des myAVR-Boards
#include <avr\io.h>  // AVR Register und Konstantendefinitionen
#include <inttypes.h>
#include <avr\interrupt.h>

volatile unsigned char timer_value;

ISR (TIM0_OVF_vect)
{
  PORTB =  PORTB^ ( 1<<PB1 );     // Flankenwechsel für Tonfrequenz
  TCCR0B = timer_value;
}

ISR(ADC_vect)
{
  int adc_value;

  adc_value = ADC;
  timer_value = char(adc_value/5);
  ADCSRA |= (1<<ADSC);      // restart ADC

}
void adcInit()
{
  ADMUX  = 0b00000011;   // Port, Referenzspannung und Auflösung
  ADCSRB = 0b10011110;   // Modus, Interrupt und Start
}

void initTimer0()
{
  timer_value = 0xFF;
  TCCR0B=0x05;                     // 0b00000011,Vorteiler 64
  TIMSK0=0b00001010;      // 0b00000010, maskiere Timer-INT
}

void initPorts()
{
  sbi(DDRB,0);        //OUT Summer
  sbi(DDRB,1);        //OUT LED
}

//======================================================================
main()
{
  adcInit();
  initPorts();  // PortB als Ausgang initialisieren
  initTimer0();  // Timer Interrupt initialisieren
  sei();                    // enable interrupts
  do {} while (true);        // Mainloop
}


Momentan ist es so dass die Led beim einschalten kurz aufleuchtet.
Vielleicht habe ich auch einen Fehler in der Schaltung.
Auf PB3 habe ich den Poti. Gegen VCC und GND.PB1 die LED. Fehlt da noch 
was oder habe ich etwas falsch angeschlossen. Bin echt am verzweifeln.
Habe schon viel Tipps und Hilfe bekommen, bekomme es aber nicht hin.
Ich hoffe auf euer Verständniss einem Neueinsteiger zu helfen.
Gruß
Andy

von Bernd (Gast)


Lesenswert?

bitte keine Zahlen sondern Namen verwenden,
keiner wird Lust haben die Bits aufzudröseln

Kommentare sollten auch zum Programm passen

ansonsten habe ich nicht entdeckt wo die Interrupts freigegeben werden

von ich (Gast)


Lesenswert?

>ADCSRB = 0b10011110;
Soll das nicht ADCSRA sein?

von Hc Z. (mizch)


Lesenswert?

Du gibst 2 Timer-Interrupts frei (welche, habe ich keine Lust, 
aufzudröseln - schreibe bitte die Bitnamen hin und kein 0b<irgendwas>, 
hast jedoch nur eine Timer-Interrupt-Routine.  Das gibt einen 
garantierten Soft-Reset.

von Andy (Gast)


Lesenswert?

OK habs mal umgeschrieben ich hoffe es passt so.
1
#define F_CPU 3686400  // Taktfrequenz des myAVR-Boards
2
#include <avr\io.h>  // AVR Register und Konstantendefinitionen
3
#include <inttypes.h>
4
#include <avr\interrupt.h>
5
6
volatile unsigned char timer_value;
7
8
ISR (TIM0_OVF_vect)
9
{
10
  PORTB =  PORTB^ ( 1<<PB1 );     // Flankenwechsel für Tonfrequenz
11
  TCCR0B = timer_value;
12
}
13
14
ISR(ADC_vect)
15
{
16
  int adc_value;
17
18
  adc_value = ADC;
19
  timer_value = char(adc_value/5);
20
  ADCSRA |= (1<<ADSC);      // restart ADC
21
22
}
23
void adcInit()
24
{
25
ADMUX  = (1<<REFS0) | (1<<MUX1) | (1<<MUX0);// Port, Referenzspannung und Auflösung
26
27
ADCSRA = (1<<ADEN) | (1<<ADIF) | (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1); // Modus, Interrupt und Start
28
}
29
30
void initTimer0()
31
{
32
  timer_value = 0xFF;
33
  TCCR0B=(1<<FOC0B) | (1<<CS02) | (1<<CS00); // Vorteiler 1024
34
  TIMSK0=(1<<OCIE0B) | (1<<TOIE0);//  maskiere Timer-INT
35
}
36
37
void initPorts()
38
{
39
 // sbi(DDRB,0);        //OUT Summer
40
  sbi(DDRB,1);        //OUT LED
41
}
42
43
//======================================================================
44
main()
45
{
46
  adcInit();
47
  initPorts();  // PortB als Ausgang initialisieren
48
  initTimer0();  // Timer Interrupt initialisieren
49
  sei();                    // enable interrupts
50
  do {} while (true);        // Mainloop
51
}

von ich (Gast)


Lesenswert?

Und funktioniert es oder nicht?

Vielleicht solltest du die Wandlung erstmal irgendwo starten. Wie soll 
er in die ISR, wenn noch keine Wandlung gelaufen ist.

Welchen Timerinterrupt willst du eigentlich verwenden oder willst du 
beide verwenden? Wenn du Compare Interrupt verwenden willst, dann muss 
du in den Compare-Register auch ein Wert reinschreiben, damit der 
Interrupt bei Übereinstimmung ausgelöst wird.

Und was wird das hier?
> TCCR0B = timer_value;

von Andy (Gast)


Lesenswert?

Also jetzt läst sich die LED dimmen, aber sie blinkt noch nicht.
1
#define F_CPU 3686400  // Taktfrequenz des myAVR-Boards
2
#include <avr\io.h>  // AVR Register und Konstantendefinitionen
3
#include <inttypes.h>
4
#include <avr\interrupt.h>
5
6
volatile unsigned char timer_value;
7
8
ISR (TIM0_OVF_vect)
9
{
10
  PORTB =  PORTB^ ( 1<<PB1 );     // Flankenwechsel für Tonfrequenz
11
  TCCR0B = timer_value;
12
}
13
14
ISR(ADC_vect)
15
{
16
  int adc_value;
17
18
  adc_value = ADC;
19
  timer_value = char(adc_value/5);
20
  ADCSRA |= (1<<ADSC);      // restart ADC
21
22
}
23
void adcInit()
24
{
25
  ADMUX  = (1<<REFS0) | (1<<MUX1) | (1<<MUX0);// Port, Referenzspannung und Auflösung
26
  ADCSRA = (1<<ADEN) | (1<<ADIF) | (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1); // Modus, Interrupt und Start
27
}
28
29
void initTimer0()
30
{
31
  timer_value = 0xFF;
32
  TCCR0B=(0<<FOC0B) | (0<<WGM02) | (1<<CS02) | (1<<CS00); // Vorteiler 1024
33
  TIMSK0=(1<<OCIE0B) | (1<<TOIE0);//  maskiere Timer-INT
34
}
35
36
void initPorts()
37
{
38
 // sbi(DDRB,0);        //OUT Summer
39
  sbi(DDRB,1);        //OUT LED
40
}
41
42
//======================================================================
43
main()
44
{
45
  adcInit();
46
  initPorts();  // PortB als Ausgang initialisieren
47
  initTimer0();  // Timer Interrupt initialisieren
48
  sei();                    // enable interrupts
49
  do {} while (true);        // Mainloop
50
}
jetzt weis ich zumindes das der Poti über ADC gelesen wird und muss 
jetzt halt noch das blinken hinbekommen.

von Karl H. (kbuchegg)


Lesenswert?

Andy schrieb:
> Also jetzt läst sich die LED dimmen, aber sie blinkt noch nicht.

Ehrlich?

Bei dem Programm hätte ich alles mögliche erwartet, inklusive 
Kernschmelze. Nur nicht, dass sich da irgendein Effekt an der LED zeigt. 
Anscheinend hast du das Glück (Pech?), dass dein µC genau im Verhältnis 
der Poti Stellung abstürzt und das Programm damit im richtigen Takt 
restartet.


Geh doch erst mal schrittweise vor.

* Leeres Programm
* Timer initialisieren
* Interrupt routine anhängen

* erstes Teilziel: LED blinkt korrekt, indem du im Programm einen
  Zahlenwert veränderst.

  Willst du eine andere Blinkrate, dann veränderst du diesen Zahlenwert
  und compilierst neu

* ADC Routine aus dem Tutorial übernehmen.
  Ohne Interrupt!

* Einen Aufruf der ADC Routine direkt in die Hauptschleife einbauen.
  Dort wo vorher dein 'fixer' variabler Zahlenwert war, baust du das
  ADC Ergebnis ein

-> jetzt muss die LED aufs Poti reagieren

* und erst dann baust du den ADC auf Interrupt Betrieb um
  (falls du das dann überhaupt noch willst)

von Stefan B. (stefan) Benutzerseite


Lesenswert?

>   TCCR0B = timer_value;

Dazu hatte ich dir in deinem anderen Thread schon was geschrieben. Diese 
Stelle ist grottenfalsch!

>  ADCSRA |= (1<<ADSC);      // restart ADC

Restart in der ISR sehe ich, aber wo ist der 1. Start ausserhalb der 
ISR? In die ISR mit Restart geht es erst, wenn der 1. Start ein Ergebnis 
liefert...

>  TIMSK0=(1<<OCIE0B) | (1<<TOIE0);//  maskiere Timer-INT
              ^^^^^^a                  ^^^^^^^^b

a/ Die ISR für OCIE0B sehe ich im Restprogramm nicht.

b/ Es ist kein "maskieren", sondern die beiden angegebenen 
Timerinterrupts werden erlaubt.

>  timer_value = char(adc_value/5);

Ein C typischer Cast an dieser Stelle sähe so aus:
 timer_value = (unsigned char) (adc_value/5);

von ich (Gast)


Lesenswert?

Also was ist mit den Timer-Interrupts?

von Andy (Gast)


Lesenswert?

>   TCCR0B = timer_value;

Dazu hatte ich dir in deinem anderen Thread schon was geschrieben. Diese
Stelle ist grottenfalsch!


Wie wäre es denn richtig.
Wo sind jetzt die Fehler oder wie müste das Programm umgeschrieben 
werden dass es geht.

von Karl H. (kbuchegg)


Lesenswert?

Andy schrieb:

> Wie wäre es denn richtig.
> Wo sind jetzt die Fehler oder wie müste das Programm umgeschrieben
> werden dass es geht.

Das Problem:
Das scheint für dich alles noch viel zu viel zu sein. Zu viele Details, 
die alle gleichzeitig beachtet werden wollen.

Ich empfehle dir dringend dich an den Stufenplan, den ich dir weiter 
oben gepostet habe, zu halten.

Es bringt jetzt nicht viel, dir die 20 Zeilen Code zu geben. Du siehst 
sie dir an und sagst: "Schön, da wär ich irgendwann alleine auch drauf 
gekommen" und gehst zur Tagesodnung über. Und beim nächsten Programm 
stehst du wieder daneben.

Du musst schrittweise lernen.
Daher auch der Stufenplan.

von Andy (Gast)


Lesenswert?

Naja das bringt mich nicht weiter wollte nur das Programm hinbekommen.
Beim ATMega8 hat es ja geklappt nur das portieren auf den ATtiny13 
bekomm ich nicht hin und darum dachte ich ihr könnt mir helfen es zum 
laufen zu bekommen. So lernt man auch wenn man dann seine Fehler sieht.

von Karl H. (kbuchegg)


Lesenswert?

Andy schrieb:
> Naja das bringt mich nicht weiter wollte nur das Programm hinbekommen.
> Beim ATMega8 hat es ja geklappt

Mit Verlaub. Entweder
* hast du das nicht selbst geschrieben
* oder es sieht nur so aus als ob es funktioniern würde


Denn im Grunde sind deine Fehler lächerlich einfach:
* Der ADC Interrupt wird ausgelöst, wenn der ADC fertig ist.
  Der fängt aber nicht alleine an!
  Den muss man einmal starten, damit ein erstes Ergebnis vorliegt
  Als Folge dieses Ergebnisses wird die ISR aufgerufen, die
  dann die nächste Wandlung startet.
  Aber irgendwann muss der Prozess einmal starten, so wie eine
  Dominokette auch nicht von alleine umfällt: Den ersten Stein muss
  irgendwer einmal umwerfen. Und erst ab dann läuft die Kette von
  alleine

* Du gibst Interrupts frei, für die du keinen Handler hast.

* Du weist an Konfigurationsregister, die eigentlich iregndwelche
  Funktionalitäten ein/aus schalten, Zeitwerte zu. Kein Mensch weiß
  was dieser Zeitwert überhaupt macht, wenn ihn die Hardware als
  "diesen und jenen Funktionsblock ein/ausschalten" interpretiert.

Das alles sind grundlegende Fehler, die auf einem Mega auch nicht anders 
sind als auf dem Tiny. All diese Fehler wurden dir schon genannt. Aus 
der Tatsache, dass dich diese Fehlerbeschreibungen nicht weiter bringen 
schliesse ich, dass du das Pgm auf dem Mega nicht selbst geschrieben 
hast.

von Karl H. (kbuchegg)


Lesenswert?

* Leeres Programm
* Timer initialisieren
* Interrupt routine anhängen

* erstes Teilziel: LED blinkt korrekt, indem du im Programm einen
  Zahlenwert veränderst.

  Willst du eine andere Blinkrate, dann veränderst du diesen Zahlenwert
  und compilierst neu

* ADC Routine aus dem Tutorial übernehmen.
  Ohne Interrupt!

* Einen Aufruf der ADC Routine direkt in die Hauptschleife einbauen.
  Dort wo vorher dein 'fixer' variabler Zahlenwert war, baust du das
  ADC Ergebnis ein

-> jetzt muss die LED aufs Poti reagieren

* und erst dann baust du den ADC auf Interrupt Betrieb um
  (falls du das dann überhaupt noch willst)

von ich (Gast)


Lesenswert?

Wie Karl heinz Buchegger geschrieben hat, glaube ich auch nicht, dass 
das Programm funktioniert hat. Denn wenn man es selbst geschrieben hätte 
und es hätte auch so funktioniert, wie man es wollte, dann wüsste man, 
was er gemacht hat und dann hätte man das Programm auf den anderen uC 
ohne Probleme übertragen können.

von Karl H. (kbuchegg)


Lesenswert?

Einen Punkt habe ich noch vergessen:
Dir scheint auch das Verständnis dafür zu fehlen, wie da eigentlich eine 
variable Blinkrate erzeugt werden soll.

Entweder man macht das in Software oder man macht das in Hardware. 
Beides sind unterschiedliche Techniken.
Dein jetztiges Programm macht weder noch und es ist noch nicht einmal im 
Ansatz erkennbar, wie du dir das vorstellst.

von ich (Gast)


Lesenswert?

Zeig mal dein Quellcode für den ATmega8, welches (angeblich) 
funktioniert.

von Andy (Gast)


Lesenswert?

#define F_CPU 3686400
#include <avr\io.h>
#include <inttypes.h>
#include <avr\interrupt.h>
//---------------------------------------------------------------------- 
----
unsigned char timer_value;
ISR (TIMER0_OVF_vect)
{
  PORTB = ~ PORTB;    // Flankenwechsel für Tonfrequenz
  TCNT0 = timer_value;
}

ISR(ADC_vect)
{
  int adc_value;
  adc_value=ADC;
  timer_value=char(adc_value/4);
  sbi  (ADCSRA,6);      // restart ADC
}

void adcInit()
{
  ADMUX=0;
  ADCSRA=0xDD;  //0b11011101, ADC-Clock, ADC ON, INT ON
}

void timer0Init()
{
  timer_value=0xFF;
  TCCR0=0x03;        // 0b00000011, Vorteiler 64
  TIMSK=0x01;        // 0b00000001, maskiere Timer-INT
}

void portsInit()
{
  sbi(DDRB,0);      //OUT Summer
  sbi(DDRB,1);      //OUT LED
}

main()
{
  //Initialisierung
  portsInit();      // PortB als Ausgang initialisieren
  timer0Init();      // Timer Interrupt initialisieren
  adcInit();
  sei();                  // enable interrupts
  do { } while(true);    // mainloop
}

von ich (Gast)


Lesenswert?

Das Programm läuft bestimmt auf dem ATmega8. Jetzt muss du nur das 
Datenblatt von ATmega8 nehmen, dir aufschreiben was alles gesetzt ist 
und was nicht. Dann nimmst du das Datenblatt von Attiny13 und setzst die 
gleichen Bits, wie bei ATmega8. Und dann hoffe ich, dass das Programm 
auf dem Attiny läuft.

Das alles ist bestimmt nicht böse gemeint, aber wenn wir dir das 
Programm schreiben, wirst du dabei nichts lernen und ich glaube es ist 
nicht das letzte Mal, dass du den uC programmierst. Deswegen erweitere 
dein Programm Schritt für Schriff, so wie  Karl heinz Buchegger es dir 
vorgeschlagen hat und du wirst bestimmt merken, dass es doch nicht so 
schwer ist.

von Karl H. (kbuchegg)


Lesenswert?

WEnn du jetzt bei deinem Mega8 Program die ganzen 'magischen Konstante', 
wie zb hier

  ADCSRA=0xDD;  //0b11011101, ADC-Clock, ADC ON, INT ON

in eine vernünftige Schreibweise bringst, hast du doch schon fast das 
Tiny Programm.

LOL
Im Mega8 Programm
1
ISR (TIMER0_OVF_vect)
2
{
3
  PORTB = ~ PORTB;    // Flankenwechsel für Tonfrequenz
4
  TCNT0 = timer_value;
5
}

im Tiny Programm
1
ISR (TIM0_OVF_vect)
2
{
3
  PORTB =  PORTB^ ( 1<<PB1 );     // Flankenwechsel für Tonfrequenz
4
  TCCR0B = timer_value;
5
}

vergleich doch mal die beiden! Und ich meine jetzt nicht die Sache mit 
dem PORTB. Die ist schon in Ordnung

Welche Bedeutung hat das TCNT0 Register beim Timer 0?
Welche Bedeutung hat das TCCR0B Register beim Timer 0?

Was hast du daher angerichtet, als du das TCNT0 Register vom Mega8 mit 
dem TCCR0B Register vom Tiny 'übersetzt' hast?

von Andy (Gast)


Lesenswert?

Ok ich entschuldige mich erstmal.
Ich werd jetzt mal versuchen die beiden Datenblätter zu vergleichen und 
alles herausfinden wo die unterschiede sind.
Danke nochmal an alle für die Tipps und Antworten.

von Karl H. (kbuchegg)


Lesenswert?

Andy schrieb:
> Ok ich entschuldige mich erstmal.
> Ich werd jetzt mal versuchen die beiden Datenblätter zu vergleichen und
> alles herausfinden wo die unterschiede sind.

+-------------------------------------------------------------------+
|                                                                   |
|   Fang damit an, den Mega8 Code erst mal vernünftig zu machen!    |
|                                                                   |
+-------------------------------------------------------------------+


So was
1
  ADCSRA=0xDD;  //0b11011101, ADC-Clock, ADC ON, INT ON

ist einfach nur Mist! Ein grosser Haufen Mist!

Und jetzt weist du auch warum!
Weil man beim Übertragen von einem Prozessor auf einen anderen aufpassen 
muss wie ein Haftlmacher. Man muss auch so aufpassen, aber mit einer 
vernünftigen Schreibweise reduziert sich der Aufwand gewaltig. Du wirfst 
dir mit solchen Schreibweisen nur unnötig Prügel zwischen die Beine. 
Prügel? Ganze Baumstämme!

Bereinige das erst mal!
Dann portiert sich dein Programm schon fast von alleine!

(Ich bin allerdings immer noch nicht überzeugt davon, dass du das selbst 
geschrieben hast. Nur zur Klarstellung)

von Andy (Gast)


Lesenswert?

Also habs hinbekommen es geht jetzt soweit. Die Blinkfrequenz ist noch 
nicht so ideal aber ich denke das bekomm ich hin. Danke

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.