Hallo,
für mein aktuelles Programm möchte ich über ein Potentiometer die
Helligkeit von LEDs einstellen.
Die LEDs lassen sich mit Werten von 0 bis 100 per Software PWM ansteuern
(0=ganz aus, 50=ca. mittelhell, 100=maximal hell).
Die eine Seite des Potis hängt an 5V die andere an GND. Der veränderbare
Kontakt des Potis geht dann an PC0 am Atmega8-16.
Hier mein Programm:
1
#include<avr/io.h>
2
#include<util/delay.h>
3
#define an(port,b) (port) |= (1<<(b))
4
#define aus(port,b) (port) &= ~(1<<(b))
5
//Beispielaufruf: an(PORTC,PB1);
6
7
intmain(){
8
// Helligkeit in %
9
intpb1_soll=50;
10
intpb2_soll=100;
11
intcounter=0;
12
13
// Ausgänge schalten
14
DDRB|=(1<<PB1);
15
DDRB|=(1<<PB2);
16
DDRB|=(1<<PB3);
17
18
an(PORTB,PB1);
19
an(PORTB,PB2);
20
21
//ADC einlesen
22
intvalue;
23
ADMUX=0x00;
24
ADCSRA=0x80;
25
26
while(1){
27
28
//ADC Potis auslesen
29
value=0;
30
ADCSRA|=(1<<ADSC);
31
while(ADCSRA&(1<<ADSC)){}
32
value=ADCW;
33
//Hier tritt das Problem auf. value ist immer 1023!
34
if(value<1024){
35
pb2_soll=1;
36
//Schalte LED auf 1% Helligkeit
37
}
38
else{
39
pb2_soll=50;
40
//Schalte LED auf 50% Helligkeit
41
}
42
43
counter++;
44
if(counter>=pb1_soll){
45
aus(PORTB,PB1);
46
}
47
if(counter>=pb2_soll){
48
aus(PORTB,PB2);
49
}
50
if(counter>=100){
51
counter=0;
52
an(PORTB,PB1);
53
an(PORTB,PB2);
54
}
55
}
56
}
Ich möchte eigentlich nur die Variablen in Abhängigkeit des Potis
ändern.
In Value steht aber immer 1023 (schätze mal das hängt mit
Dualzahl->Dezimalzahl zusammen).
Wie komm ich an den tatsächlichen Wert?
Habe auch eben nochmal mit dem Multimeter nachgemessen, Spannung ändert
sich wie gewünscht
Hätte ich das noch nicht angeschaut, hätte ich mich garnicht hier
gemeldet.
Trotzdem vielen Dank für den Hinweis, ich hab mir das jetzt nochmal
durchgeschaut (hatte vorhin schon viele verschiedene Programmversionen
probiert von denen einige auf dem Code des verlinkten Artikel
basierten).
Habe es jetzt tatsächlich hinbekommen. War garnicht so schwer (brauchte
anscheinend nur mal eine Pause, programmiere hier schon seit Mittag...)
Danke erstmal soweit, ich denke jetzt bekomme ichs hin^^
edit:ganz am Ende (wenn es fast ganz hell ist) macht die Helligkeit
plötzlich einen Sprung auf ganz hell. Woran liegt das?
Wenn das Poti fast auf maximal ist, ist die LED eigentlich noch zu
dunkel. Und dann springt sie plötzlich auf ganz hell
1
#include<avr/io.h>
2
#include<util/delay.h>
3
#define an(port,b) (port) |= (1<<(b))
4
#define aus(port,b) (port) &= ~(1<<(b))
5
//Beispielaufruf: an(PORTC,PB1);
6
7
intmain(){
8
// Helligkeit in %
9
intpb1_soll=100;
10
intpb2_soll=100;
11
intcounter=0;
12
13
// Ausgänge schalten
14
DDRB|=(1<<PB1);
15
DDRB|=(1<<PB2);
16
DDRB|=(1<<PB3);
17
18
//ADC-Variable initialisieren
19
uint16_tvalue;
20
uint16_tresult;
21
22
//1=Poti für PB1, ...
23
intakt_poti=1;
24
intanzahl_potis=2;
25
//Poti an PC0 initialisieren
26
ADMUX=(0<<REFS1)|(1<<REFS0);// ADC Ref auf Avcc, PC0 gewählt, normale Formatierung
Ich grabe jetzt mal dieses alte Thema wieder aus, denn mir stellt sich
das gleiche Problem/ Frage. Wenn ich die Spannung messen will von einem
Poti, dann steigt diese nicht linear an sondern progressiv. Wieso und
was kann man da machen?
Meine Idee ist es,dass wenn das Poti in der mitte steht auch die hälfte
der Spannung gemessen wird. Hänge ich das Poti vom MC ab, so ist das der
Fall.
Schaltplan und Code kann ich gerne auch beilegen wenn nötig.
Neuling schrieb:> Ich grabe jetzt mal dieses alte Thema wieder aus, denn mir stellt sich> das gleiche Problem/ Frage. Wenn ich die Spannung messen will von einem> Poti, dann steigt diese nicht linear an sondern progressiv. Wieso und> was kann man da machen?>> Meine Idee ist es,dass wenn das Poti in der mitte steht auch die hälfte> der Spannung gemessen wird. Hänge ich das Poti vom MC ab, so ist das der> Fall.
Da Du nichts zu Deinem Poti schreibst kann man nur raten daß es das
falsche ist.
1) Potis arbeiten nicht notwendigerweise linear.
2) Der Eingang eines ADC hat einen endlichen Widerstand. Und was
passiert wenn man Widerstände parrallel schaltet solltest Du wissen.
Hi
Wenn es hier auch um den Sprung 'am Ende' geht - dort könnte, banal
gesprochen, einfach die Widerstandsbahn 'am Ende' sein, also dort, wo
Diese mit dem Anschlußpin irgendwie verbunden ist - Da muß die Bahn ja
irgendwie anders aussehen als Da, wo kein Pin angeschlossen ist - reiner
Schuß ins Blaue, hatte noch kein Poti offen.
MfG
PS: nur die letzten 4 Beiträge sind aktuell, davor ist seit 6 Jahren
eher ruhig ;)
Wow, dachte nicht das so schnell so viele Antworten kommen :D
Danke euch allen.
So, ich habe in der Zwischenzeit auch etwas weitergeforscht und habe die
schaltung mal etwas abgeändert. Bisher habe ich einen selber
programmierten Binär/Dezimalwandler benutzt und nachdem ich diesen mal
ausgelassen habe und direkt aus dem ADCH Register gelesen habe war der
Verlauf korrekt.
Poti ist ein Lineares 10kOhm. Spannungsabgriff in der mitte.
Nun geht's an die Fehlersuche im Code :D
So, der Fehler ist gefunden... aber noch nicht geklärt. Weshalb ergibt
diese if Abfrage nicht 1? Sollte doch so sein, nicht? Bei 3-5 ergibt es
nicht 1 sonst schon.
Ich ging jetzt davon aus das man den Integer "11111111" wie ein Register
verwenden kann.
1
intmain()
2
{
3
if(11111111&(1<<3))
4
{
5
printf("lol");//printf ist hier nur zum testen eingebaut
So, ist nun auch geklärt, hätte nicht unbedingt fragen müssen :O
Danke trotzdem an alle.
Meine Erkenntniss: Bitoperator "&" arbeitet mit der Binärzahl, d.H. der
Operator "&" hat meine Zahl "11111111" in die Binärzahl umgewandelt und
mit dieser gearbeitet. Korrekt wäre gewesen wenn ich 255 eingeschrieben
hätte (ergibt Binärzahl 11111111) oder einfach als Binärzahl definiert
hätte (0b vorne rangeschrieben)
So da das nun auch geklärt ist wird es nun Zeit zu schlafen (endlich :D)
Abschlussbericht:
Der Fehler lag doch woanders... ich habe zu Beginn in Register DDRB Pin
1-3 folgendermassen als Ausgang gesetzt:
1
DDRB|=(111<<1);
Richtig wäre gewesen:
1
DDRB|=(1<<1)|(1<<2)|(1<<3);
Wusste gar nicht das das so nicht funktioniert und sogar Einfluss auf
den ADC hat.... naja, wieder mal was dazugelernt. Mein Programm
funktioniert jetzt (jeay, nach 4h Fehlersuche hat es doch noch geklappt
:D)
Hi
Neuling schrieb:> int main()> {> if (11111111 & (1<<3))> {> printf("lol"); //printf ist hier nur zum testen eingebaut> }> }
Denke, Das wird vom Compiler direkt wegoptimiert, da sowohl die Zahl
(11111111, 0xA98AC7, 0b101010011000101011000111) wie auch 1<<3 (=0b1000
oder 0x08 oder eben 8) beim Compilieren bekannt sind und die Ver-UND-ung
NULL ergibt - bar gesparter Speicherplatz.
1<<(0,1,2,6,7,9,11,15,16,19,21,23) würde dagegen das 'lol' zur Ausgabe
bringen - aber ebenfalls ohne die IF-Abfrage, da Diese, wie zuvor, ja
bereits beim Compilieren bekannt ist.
Etwas weniger abweisend würde sich in dem Code-Beispiel ein 'foo'
machen, das 'LOL' lässt erkennen, daß Du noch keine Ahnung hast, was Du
da machst und Das wohl auch noch lustig findest.
'foo' oder 'bar' sind hier die üblichen Begriffe, wenn man 'irgendwas'
meint.
MfG