www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Einfache PWM mit Spannung ADC steuern (Attiny13)


Autor: Fr00sch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich bin neu im Bereich Mikrocontroller und habe mir ein Programm für den 
Attiny13 geschrieben das abhängig von der anliegenden Spannung über den 
ADC das verhältnis von LOW und HIGH des PWMs einstellt:

.include "tn13def.inc"


rjmp   Anfang
Anfang:
;Pins belegen
      ldi r16, 0b11111111
      out DDRB,r16
      ldi r16, 0x00
      out PORTB,r16
   
;ADC initialisieren
      ldi    r16, 0b00100010
    out    ADMUX, r16
    ldi    r16, 0b11000111
    out    ADCSRA, r16

 
Schleife:
      sbi    portb,0
adc0_wait:
    sbic   ADCSRA,ADSC
    rjmp   adc0_wait
    in     r18, ADCL
    in     r17, ADCH
    ldi    r16,255
    sub    r16,r17
Warten1:
      dec    r17
    brne   Warten1
    cbi    portb,0
Warten2:
      dec    r16
    brne   Warten2
rjmp Schleife

Nun habe ich das Problem, wenn ich ein 1MOhm-Poti anschließe, ändert 
sich die Helligkeit der Led nur wenn ich es voll in Einrichtung drehe 
und auch nur auf etwa 50%, wenn ich aber ein 500Ohm-Poti anlegen dann 
lässt sich die Led wunderschön von etwa 90% bis 0% dimmen.
Ich verstehe im Moment nicht so richtig das Problem, weil normalerweise 
ja ein größerer Poti die Schaltung weniger beeinflusst. Könnte es vllt 
sein das irgendein Pullup- oder pulldown-widerstand am Eingang 
eingeschaltet ist und somit das Poti die Spannung nicht alleine 
beeinflusst?

Ich hoffe ihr könnt mir weiterhelfen und falls ich noch mit 
irgendwelchen Infos helfen kann, einfach bescheid sagen.

Gruß Fr00sch

Autor: Jo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du musst den Pullup des ADCs ausschalten. Und nimm kein Poti größer
5k. Warum, kannst du aus dem Datenblatt schön ersehen.

SG Jo

Autor: Mahnel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Auch wenn ich mit der ADC nicht sooo auskenne, würde ich mal behaupten 
das Dein Problem darin begründet ist, das Du zuerst ALLE PBx als 
Ausgänge definierst. Der ADC kann trotzdem werte von den Ports einlesen, 
aber Dein Poti muss "gegen" den Port, der als Ausgang geschaltet ist und 
damit Strom (bis 60mA!) liefert, "anarbeiten".
Über den 1MOhm Poti lacht der Augang nur, damit wirst Du kaum 
Spannungsänderung erziehlen.

Mein Vorschlag wäre: (zumal im Programm später eh nur PB0 geschaltet 
wird)

;Pins belegen
      ldi r16, 0b00000001
      out DDRB,r16
      ldi r16, 0x00
      out PORTB,r16

Habs nicht Probiert, klingt aber Plausibel...

Bis dann und viel Glück (!)  =^.^=

Autor: Fr00sch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke erstmal für die schnelle Antwort


Ich weis aber nicht wie ich ihn abschalte... am anfang definiere ich 
portB als Ausgang
ldi r16,0b11111111
out DDRB,r16
und gebe allen Pins keinen pullup
ldi r16, 0x00
out PORTB,r16
und im späteren verlauf definiere ich einen ausgang als adc-eingang ... 
meiner theorie nach müsste jetzt dort ein eingang ohne pullup sein, aber 
ist anscheinend nicht so ...

kann ich die pullups per MCUCR abschalten wieder?

ich hab nichts über einen 5k-Poti gefunden im Datenblatt,unter welcher 
rubrik soll das stehen?

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Außerdem sollte das zum ADC-Input gehörige DIDR0-Bit gesetzt sein, um 
Querstöme zu vermeiden.  Siehe Datenblatt.

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> am anfang definiere ich
> portB als Ausgang
> ....
> und im späteren verlauf definiere ich einen ausgang als adc-eingang ...
> meiner theorie nach müsste jetzt dort ein eingang ohne pullup sein, aber
> ist anscheinend nicht so ...

Das ist nur Deine Theorie.  Der Ausgang bleibt Ausgang.  Abhilfe ist, 
ihn gleich gar nicht als solchen zu definieren.

Autor: Fr00sch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das klingt logisch Mahnel und habe ich auch schon probiert, aus 
irgendeinem Grund gabs da aber Probleme, werds heute abend nochmal 
probieren und mich dann nochmal melden.

Zum Thema Poti habe ich was gefunden im Datenblatt:
Auf Seite 120 Thema 18.7 ADC Chrakteristiken steht unter Analog Input 
Resistance: 1MOhm

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Zum Thema Poti habe ich was gefunden im Datenblatt:
> Auf Seite 120 Thema 18.7 ADC Chrakteristiken steht unter Analog Input
> Resistance: 1MOhm

Es lässt sich in 14.8 auch Folgendes finden:

The ADC is optimized for analog signals with an output impedance of 
approximately 10 kΩ or less.

Autor: Mahnel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Fr00sch schrieb:
> am anfang definiere ich
> portB als Ausgang
> ldi r16,0b11111111
> out DDRB,r16

Richtig, damit sind ALLE PBs als Ausgänge geschaltet.

> und gebe allen Pins keinen pullup
> ldi r16, 0x00
> out PORTB,r16

Nicht ganz richtig: damit hast Du ALLE PBs auf "0" geschaltet.
Wenn jetzt eine "Stromquelle" gegen "1" angelegt wird, wird der Strom 
über den MC/Port gegen "0" abfliessen.

...hoffe geholfen zu haben...

Autor: Fr00sch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie müsste der korrekte Code nun aussehen, sodass ich nur den Port 0 als 
ausgang nehme und gegen null schalte... bin etwas verwirrt

@all:danke für die Hilfe bis hierhin

Autor: Peter Roth (gelb)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

statt

  ldi r16, 0b11111111
  out DDRB,r16

verwendest du

  sbi DDRB, 0

um nur einen Portpin als Ausgang zu definieren und

  ldi r16, 0x00
  out PORTB,r16

kannst du weglassen, da das der Ursprungszustand ist.

Grüße, Peter

Autor: Fr00sch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
kA warum, aber deine Idee funktioniert nicht, das Drehen am Poti 
verändert nichts, die helligkeit der LED bleibt konstant bei etwa 50%!

Quellcode jetzt:

.include "tn13def.inc"


rjmp   Anfang
Anfang:
;Pins belegen
      sbi    DDRB,0

;ADC initialisieren
      ldi    r16, 0b00100010
    out    ADMUX, r16
    ldi    r16, 0b11000111
    out    ADCSRA, r16

 
Schleife:
      sbi    portb,0
adc0_wait:
    sbic   ADCSRA,ADSC
    rjmp   adc0_wait
    in     r18, ADCL
    in     r17, ADCH
    ldi    r16,255
    sub    r16,r17
Warten1:
      dec    r17
    brne   Warten1
    cbi    portb,0
Warten2:
      dec    r16
    brne   Warten2
rjmp Schleife

Autor: Fr00sch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hilfe, kann mir denn keiner helfen, habe ich vllt einen grundsätzlichen 
Fehler gemacht?
Verstehe das mit der I/O_ports vllt nicht so richtig.
Wie würdet ihr den ADC ansprechen?
Gruß Fr00sch

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

Bewertung
0 lesenswert
nicht lesenswert
Wo wird da innerhalb der Schleife der ADC neu gestartet?

Ich hab jetzt auch ehrlich gesagt keine Lust, aus dem Datenblatt
zusammenzusuchen, was du hier

    ldi    r16, 0b11000111
    out    ADCSRA, r16

alles aktiviert hast.

Autor: Fr00sch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
7.)1 macht den ADC an,
6.)start die conversion,
5.)ADC Interrupt Flag keine,
4.)ADC Interrupt Enable aus,
2.)Prescaler Factor
1.)Prescaler Factor
0.)Prescaler Factor

Seite 91 und 92 im Datenblatt

Autor: Fr00sch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
sbic   ADCSRA,ADSC
startet in der schleife die conversion!

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

Bewertung
0 lesenswert
nicht lesenswert
Fr00sch schrieb:
> sbic   ADCSRA,ADSC
> startet in der schleife die conversion!

Nein.
Das wartet bis die Konvertierung fertig ist.
Aber wo wird sie erneut gestartet?

Dazu müsstest du das ADSC Bit irgendwo erneut setzen. Das tust du aber 
nicht! Mit sbic wird ein Bit abgefragt, aber nicht gesetzt.

  sbic     ... skip (next instruction, if) bit is clear

zusammen mit dem nachfolgendem rjmp ergibt das eine Schleife, die 
solange wartet, bis das ADSC Bit von 1 auf 0 wechselt, welches wiederrum 
laut Beschreibung anzeigt, dass der ADC fertig ist.

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

Bewertung
0 lesenswert
nicht lesenswert
Fr00sch schrieb:
> 7.)1 macht den ADC an,
> 6.)start die conversion,
> 5.)ADC Interrupt Flag keine,
> 4.)ADC Interrupt Enable aus,
> 2.)Prescaler Factor
> 1.)Prescaler Factor
> 0.)Prescaler Factor
>
> Seite 91 und 92 im Datenblatt

Worauf ich hinaus wollte:
Man kann die Binärzahl auch so schreiben, dass man die Bits beim Namen 
nennt.

http://www.mikrocontroller.net/articles/AVR-Tutorial:_ADC

Vergleich doch mal zb das hier
    ldi     temp1, (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0)
    out     ADCSRA, temp1
mit deiner Version. Wo sieht man eher, was Sache ist?

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.