Probleme mit der Verbindung PWM + ADC

Gast #2570046
Lesenswert?

Hallo zusammen,
ich bräuchte mal kurz eure Hilfe, weil iwie komm ich hier nicht weiter.

Ich habe mir aus den Tutorials ein Programm versucht zusammen zu 
basteln, dass folgendes macht:
Ich habe am PC0 (ADC) einen FSR-Sensor (funktioniert ähnlich wien Poti 
nur ändert er den Widerstand auf Druck).
Bei PB1 (0C1A) habe ich ein paar LED's angeschlossen übern Transistor.

Das Programm soll, wenn Druck auf dem FSR-Sensor ist, die LED's 
aufleuchten lassen und per PWM dimmen. Liegt kein Druck auf dem Sensor 
soll auch nix passieren. Ich habe beides einzeln hinbekommen, also Druck 
auf den Sensor --> LED's fangen an zu leuchten und ich habe das 
Programm, wo ein LED Fading statt findet. Wenn ich die beiden zusammen 
wurschtel macht er nur ein wirres LED Fading, egal ob Druck oder nicht.
Leider check ich nicht so ganz warum und es würde mich sehr freuen, wenn 
mich einer von euch in die richtige Richtung schubsen könnte :)

Danke schonmal

Ach ja, µC ist ein ATMega48
Angehängte Dateien:
#2570073
Lesenswert?

Wie soll das zusammengehen?

1
uint16_t pwmtable_8B[8]  PROGMEM = {0, 4,  8, 16, 32, 64,  128, 255};
Du hast 8 PWM Stufen definiert

1
    for(tmp=0; tmp<=255; tmp++){              //255 Stufen bei 8-bit, rauf zählen
2
      OCR1A = pgm_read_word(pwmtable_8B+tmp);
3
      my_delay(delay);
4
    }
versuchst aber 256 auszugeben.


Schreib das so doch so
1
uint16_t pwmtable_8B[8]  PROGMEM = {0, 4,  8, 16, 32, 64,  128, 255};
2

3
#define ARRAY_SIZE(x)    (sizeof(x)/sizeof(*x))
...
1
    for(tmp=0; tmp < ARRAY_SIZE(pwmtable_8B); tmp++) {
2
      OCR1A = pgm_read_word( &pwmtable_8B[tmp] );
3
      my_delay(delay);
4
    }

Lass den Compiler für dich arbeiten! Der kann solche fixe Zahlen, die 
aber korrekt sein müssen, viel besser verwalten als du.
Gast #2570091
Lesenswert?

Danke für die schnellen Antworten.

Dass mit den 255 Stufen ist natürlich ein Übertragungsfehler gewesen, 
welchen ich übersehen hatte, jetzt läuft die PWM auch sauber rauf und 
runter.

Wenn ich das so mache, wie Karl Heinz gesagt hat, dann macht der µC nach 
dem Start 3 mal die PWM und dann leuchten die LED's auf höchster Stufe 
kontinuierlich.

Also mein Verdacht ist, dass ich erstens nicht aus der Fadingschleife 
raus gehe, bzw. diese nicht nach einem PWM-Durchlauf beende.

Und was ich überhaupt nicht verstehe, warum der µC gar nicht auf den 
Sensor reagiert?
#2570107
Lesenswert?

Maximilian schrieb:


> Also mein Verdacht ist, dass ich erstens nicht aus der Fadingschleife
> raus gehe, bzw. diese nicht nach einem PWM-Durchlauf beende.

Quatsch.

Du musst systematischer testen.
Was mir an deinem Code schon mal nicht gefällt ist, dass du an den Pins 
rumfummelst. Den Pin mit der LED schaltest du am ANFANG einmal auf 
Ausgang. Und dann lässt du ihn auch in Ruhe. Die Helligkeit stellst du 
nicht mittels irgendwelchen Portausgaben ein, sondern immer nur in dem 
du das OCR Register umstellst. Du verlierst sonst unweigerlich den 
Überblick.

> Und was ich überhaupt nicht verstehe, warum der µC gar nicht auf den
> Sensor reagiert?

Dann musst du das eben erst mal testen, welche ADC Werte du bekommst.

Konfigurier dir eine PWM.

Dann stellst du erst mal fest, ob ein OCR Wert von 0 einer 
ausgeschalteten oder einer eingeschalteten LED entspricht.

Danach konfigurierst du dir (im selben Programm) den ADC und gibst den 
ADC Wert direkt auf die PWM, ohne Schnickschnack.

Und erst dann, wenn das funktioniert, machst du von dort aus weiter.


Ein Komplettprogramm aus Einzelteilen zusammenzuwürfeln funktioniert 
meistens nicht. Du musst das wie ein neues Programm betracheten. Du 
kannst dir aus einem anderen, älteren Projekt Codeteile mittels 
Copy&Paste einfügen, das ist schon ok. Aber du musst das wie "Im Prinzip 
schreib ich das neu, nur hab ich den Code schon" betrachten. So nach dem 
Muster "Och da mach ich eine Mischung aus diesen beiden Programmen", das 
wird meistens nix.
Gast #2570641
Lesenswert?

Ok funktioniert soweit, danke nochmal.
Jetzt habe ich noch eine kleine Frage:
Und zwar möchte ich, dass solange der Sensor gedrückt wird die LED voll 
leuchtet und sobald der Benutzer runter geht, die PWM beginnt. Leider 
funktioniert es bei mir nur so, dass ich drücke und dann gleich die PWM 
beginnt. Habe das mit einer if (druck > bestimmter Wert) Abfrage 
gemacht:

if (Druck > bestimmter Wert1)
{
PORTB |= _BV(1);
}

if else (Druck < bestimmter Wert1) && (Druck > bestimmter Wert2))
{
for (i=0; i<1; i++) pwm_8_8(step_time/2);
}

else
{
PORTB &= 255-_BV(1); //  0 auf Bit 1 Ausgeben, Rest so lassen
}

}

Aber es mag nicht so wie ich will leider...
#2570651
Lesenswert?

> if (Druck > bestimmter Wert1)
> {
> PORTB |= _BV(1);
> }

Nochmal: Wenn die PWM den Pin unter ihrer Fuchtel hat, dann hat sie den 
auch unter ihrer Fuchtel. Da kannst du an den Portpin zuweisen, bis du 
schwarz wirst, das bewirkt gar nichts.
Wenn du die LED aufleuchten lassen willst, dann musst du ans OCR 
Register einen Wert zuweisen, der 'voll aufgedreht' bedeutet.

Daher ja auch die Reihenfolge
1
int main()
2
{
3
  Portpin auf Ausgang
4

5
  PWM konfigurieren
6

7
  PWM einschalten
8

9
  --- ab hier hat die PWM die Kontrolle über den Portpin ---
10

11
  while( 1 ) {
12

13
    Messen
14

15
    if( Messwert > Grenzwert )
16
      OCR1A = Wert für "Led volle Helligkeit"
17

18
    else if( Messwert < anderer Grenzwert )
19
      OCR1A = Wert für "LED dunkel"
20

21
    else
22
      PWM einmal durchdimmen
23
  }
24
}

nochmal im Klartext: vergiss den Portpin. Du hast keine Kontrolle mehr 
über den Portpin. Die Kontrolle hast du an den PWM-Mechanismus des 
Timers abgegeben. Also musst du auch mit diesem Mechanismus arbeiten. Du 
musst nur einen entsprechenden Wert ans OCR Register zuweisen und der 
Timer sorgt dann dafür, dass die LED auch mit dieser Helligkeit 
leuchtet.
Gast #2570717
Lesenswert?

Ok, habs so umgebastelt, doch jetzt ist es so, dass wenn der obere 
Grenzwert überschritten wird, leuchten die leds, lass ich los fährt der 
µC auch die PWM, aber 2 mal hintereinander.
Danach springt er nur zufallsmäßig in die PWM nei, des hängt doch 
bestimmt mit dem Zähler zam oder? Kann ich den iwie modifizieren, dass 
der nach einer PWM stoppt und dann beim nächsten Aufruf wieder neu 
startet oder so?

p.S.: Bitte blöden Fragen verzeihen, bin noch bissi am hinein wurschteln 
:)
#2570723
Lesenswert?

Es ist wieder mal an der Zeit an etwas zu erinnern:

Wenn du qualifizierte Kommentare zu deinem Code willst, dann musst du 
den Code auch zeigen. Hier kann keiner wissen, wie und wodurch sich ein 
bestimmtes Verhalten in deinem Code ergibt, wenn man deinen Code nicht 
kennt.

Häng einfach dein C-File als Attachment an. Das ist für dich am 
einfachsten und für uns auch.
#2570736
Lesenswert?

Maximilian schrieb:

> Danach springt er nur zufallsmäßig in die PWM nei, des hängt doch
> bestimmt mit dem Zähler zam oder? Kann ich den iwie modifizieren, dass
> der nach einer PWM stoppt und dann beim nächsten Aufruf wieder neu
> startet oder so?

Dir scheint da etwas durcheinander zu kommen.

PWM  ist der Mechanismus, der es dir ermöglicht die LED auf jede 
beliebige Helligkeit zu setzen.

Das du den Mechanismus dazu benutzt, eine Aufleuchten und wieder 
Runterdimmen zu implementieren ist aber eine andere Sache. Das ist zwar 
nett, hat aber mit der PWM nur insofern zu tun, dass der Mechanismus die 
PWM benutzt um das zu realisieren.

Und wenn eine for-Schleife zu Ende ist, dann ist sie auch zu Ende.
#2570737
Lesenswert?

Maximilian schrieb:
> Also ADC und PWM laufen alleine, nur das oben genannte Problem mag noch
> net so gern laufen

OK. Ich seh mir das File jetzt nicht an. Ich hab extra noch 
dazugeschrieben: Häng das C-File so wie es ist als Attachment mit an. Du 
brauchst es weder umkopieren, du brauchst ihm auch keine andere 
Dateiendung zu geben. Du brauchst gar nichts tun, als das C-File (mit 
der Endung .c) so wie es ist als Attachment anzugeben. Das ist für dich 
supersimpel und hier im Forum löst das dann das Syntaxhighlighting für 
C-Files aus.
#2570746
Lesenswert?

1
  if (adcval > 30)
2
  {
3
    OCR1A = 0;  
4
  } 
5
  else if (adcval < 29)
6
  {
7
    OCR1A = 250;
8
  }
9
  else
10
  {
11
  for (i=0; i<1; i++) pwm_8_8(step_time/2);  
12
  }

du würdest dir leichter tun, wenn du dir endlich mal eine etwas 
vernünftige Form deines Codes angewöhnen würdest
1
    if (adcval > 30)
2
      OCR1A = 0;  
3

4
    else if (adcval < 29)
5
      OCR1A = 250;
6

7
    else
8
      pwm_8_8(step_time/2);

Eine Frage an dich:
Ohne jetzt kompliziert zu denken ... welchen Wert muss adcval haben, 
damit du jemals in die PWM Funktion reinkommst?


(UNd vergleich noch mal deinen Code mit dem Skelett von weiter oben. Wo 
hab ich die Initialisierung und Konfigurierung der PWM und wo hast du 
sie. Was muss daher gegeben sein, damit die LED überhaupt unter PWM 
Kontrolle steht?)
Gast #2570759
Lesenswert?

Meinst du jetzt den Wert bei dem Programm, wann er rein springt oder 
welchen ich haben möchte, ich beantworte einfach beides, geht 
schneller:)

Also der Sensor sitzt unter einem Silikonkissen und durch rumprobieren 
habe ich festgestellt, dass wenn man 30 als Richtwert nimmt, die Arbeit 
für den späteren Benutzer am besten ist.

Wenn ich es jetzt laufen lassen, dann ist es komischerweise nicht 
Wertabhängig sondern so bissi zufallsmäßig, also man kann 10 mal mit dem 
selben Druck draufdrücken (überprüfe es an der Widerstandsänderung übers 
Multimeter) und es leuchtet kurz auf und beim 11 mal fährt er wie 
gewollt die PWM.
#2570798
Lesenswert?

Maximilian schrieb:

> Also der Sensor sitzt unter einem Silikonkissen und durch rumprobieren
> habe ich festgestellt, dass wenn man 30 als Richtwert nimmt, die Arbeit
> für den späteren Benutzer am besten ist.


Der Wert wird aber höcht wahrscheinlich nicht ständig 30 sein. Je 
nachdem wie gut dein ADC die Referenzspannung gebuffert hat, ist er auch 
mal 29 oder 31. Und wenn der Sensor ein bischen rauscht, dann ist er 
auch mal 28 oder 32

Deine Hysterese, in der du die LED nur 'blinken' lässt, ist verdammt 
klein. Du willst doch haben, dass sie nur dann voll aufleuchtet, wenn 
jemand auf den Sensor draufdrückt. D.h. da kommt dann plötzlich ein 
extrem großer Wert vom ADC! Extrem groß ist zwar größer als 30, aber 31 
ist es auch.
Gast #2571605
Lesenswert?

Ja das ist schon sehr richtig.
Also die 30 ist nur son Richtwert-grenzwert: so fest soll der Benutzer 
quasi mindestens Drücken, damit die LEDs aufleuchten.

Aber die 2 Sachen was mir einfach nicht einleuchten wollen (hab die 
halbe Nacht dran rumgetüftelt, leider kein pos. Ergebniss), die PWM 
startet nicht immer, des macht den Eindruck, als müsste man den 
richtigen Zeitpunkt "treffen" und wenn ich diesen getroffen habe, dann 
fährt sie 2 mal und nicht nur 1 mal.
Woran kann das denn liegen?
#2571684
Lesenswert?

Maximilian schrieb:
> Ja das ist schon sehr richtig.
> Also die 30 ist nur son Richtwert-grenzwert: so fest soll der Benutzer
> quasi mindestens Drücken, damit die LEDs aufleuchten.

> startet nicht immer, des macht den Eindruck, als müsste man den
> richtigen Zeitpunkt "treffen" und wenn ich diesen getroffen habe, dann
> fährt sie 2 mal und nicht nur 1 mal.
> Woran kann das denn liegen?

Weil dein Wert vom ADC eben nicht 29 oder 30 ist.
Mach halt deine Hysterese mal ein bischen größer und erlaub einen 
größeren Toleranzbereich, in dem durchgedimmt werden soll.

Alternativ: Häng eine UART an und lass dir die Werte vom ADC mal 
ausgeben, damit du selber mal siehst, dass die Werte eben nicht so schön 
sind, wie du dir das in Gedanken vorstellst. Die werden ein wenig 
schwanken. Und diese Schwankungen must du zumindest in den Grenzwerten 
berücksichtigen, damit dir die Funktionalität da nicht dauernd aus einem 
Bereich in den anderen wechselt.

Dein ADC liefert Werte von 0 bis 1023 für 0 bis 2.56V
D.h. eine Schwankung des ADC Wertes von 2 entspricht einer Änderung der 
Spannung von 5 MILLI-Volt! 5-tausendstel Volt. Ist dein Sensor wirklich 
so rauschfrei? Die reale Welt ist nicht so ideal, wie du dir das 
vorstellst.
Angehängte Dateien:

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