mikrocontroller.net

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


Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Bernd (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: ich (Gast)
Datum:

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

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK habs mal umgeschrieben ich hoffe es passt so.
#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  = (1<<REFS0) | (1<<MUX1) | (1<<MUX0);// Port, Referenzspannung und Auflösung

ADCSRA = (1<<ADEN) | (1<<ADIF) | (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1); // Modus, Interrupt und Start
}

void initTimer0()
{
  timer_value = 0xFF;
  TCCR0B=(1<<FOC0B) | (1<<CS02) | (1<<CS00); // Vorteiler 1024
  TIMSK0=(1<<OCIE0B) | (1<<TOIE0);//  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
}

Autor: ich (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;

Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also jetzt läst sich die LED dimmen, aber sie blinkt noch nicht.
#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  = (1<<REFS0) | (1<<MUX1) | (1<<MUX0);// Port, Referenzspannung und Auflösung
  ADCSRA = (1<<ADEN) | (1<<ADIF) | (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1); // Modus, Interrupt und Start
}

void initTimer0()
{
  timer_value = 0xFF;
  TCCR0B=(0<<FOC0B) | (0<<WGM02) | (1<<CS02) | (1<<CS00); // Vorteiler 1024
  TIMSK0=(1<<OCIE0B) | (1<<TOIE0);//  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
}
jetzt weis ich zumindes das der Poti über ADC gelesen wird und muss 
jetzt halt noch das blinken hinbekommen.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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);

Autor: ich (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also was ist mit den Timer-Interrupts?

Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: ich (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: ich (Gast)
Datum:

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

Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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
}

Autor: ich (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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
ISR (TIMER0_OVF_vect)
{
  PORTB = ~ PORTB;    // Flankenwechsel für Tonfrequenz
  TCNT0 = timer_value;
}

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

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?

Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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
  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)

Autor: Andy (Gast)
Datum:

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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.