Cosinus berechnung

Hi,

in meinem Sketch möchte ich den Cosinus benutzen, um einen bestimmten PWM Wert zu erhalten. Dadurch bekomme ich eine nicht lineare Steigung hin.

Unten mal der Sketch. Aber irgendwas klappt nicht.
Da ich bei der Initialisierung l bereits mit 180 und flutstat=1 setze, müsste der Sketch ja eigentlich nach 120 Sekunden mit l=180 anfangen.

Leider erhlate ich über die LCD-Print Ausgabe ganz andere komische Werte:
l wird auf 360 gesetzt und der errechnete value auf 1653.
Da passt also so einiges nicht:
Warum startet er nicht bei 180?
Und wieso kommt bei l=360 für vaule so ein Wert raus? Müsste laut meinem iPhone Taschenrechner folgendes ergeben:

value=(cos(l)+1)*1000;

=> cos(360) = 1
=> 1+1=2
=> 2*1000 = 2000
gemapped dann 255 und 100

Kann jemand weiterhelfen? Rechnet der Arduino anders beim Cosinus oder kann er das überhaupt?

Gruß
Thorsten

const byte stroemung1 = 5;
const byte stroemung2 = 6;
int l=180;
int value; 
int pulseLow; 
int pulseHigh;
boolean stroemungsStat=true;
byte flutStat = 1;
unsigned long wavemillis=millis();
unsigned long stroemungsintervall=0;
const long pulseintervall=1500;
unsigned long intervalldisplay=0;




void getStroemung() {
  if ((hour==10 || hour==22) && flutStat==1){
    flutStat=0;  //EBBE
  }
  if ((hour==4 || hour==16) && flutStat==0){
    flutStat=1;  //FLUT
  }
  intervalldisplay=(120000-(millis()-stroemungsintervall))/1000;
  if (flutStat==0 && ((millis()-stroemungsintervall)>120000)) {
    for (l=0; l<180; l++) {
      value=(cos(l)+1)*1000; 
      pulseLow=map(value,0,2000,75,100); 
      pulseHigh=map(value,0,2000,75,255);
      stroemungsintervall=millis();
    } 
  }
  if (flutStat==1 && ((millis()-stroemungsintervall)>120000)) {
    for (l=180; l<360; l++) {
      value=(cos(l)+1)*1000;
      pulseLow=map(value,0,2000,75,100); 
      pulseHigh=map(value,0,2000,75,255);
      stroemungsintervall=millis();
    }    
  }
}

Du musst zur Berechnung das Bogenmaß nutzen, d. h. der Wert beim Aufruf von cos() muss im Bogenmaß angegeben sein.

Du kannst folgende Umrechnungsformel nutzen:

rad = winkel * PI / 180;

und anschließend deinen gewünschten Wert mit sin(rad) errechnen.

Ciao,

Rudi

hi rudi,

super - danke für den tipp. werd ich mal testen.
winkel wäre demnach mein Wert l, richtig?
Muss rad eine float variable sein?

trotzdem fra ich mich wieso ich die 360 als l bekomme - könnt ihr einen fehler erkennen?

gruß

currymuetze: hi rudi,

super - danke für den tipp. werd ich mal testen. winkel wäre demnach mein Wert l, richtig? Muss rad eine float variable sein?

trotzdem fra ich mich wieso ich die 360 als l bekomme - könnt ihr einen fehler erkennen?

gruß

Ja, rad muss als float oder double deklariert werden

Aber ansonsten verstehe ich dein Problem gerade nicht - wo bekommst du denn die l als 360? Auf dem Display? Kann es sein, dass nur der letzte Wert angezeigt wird?

hi, jip, der LCD gibt das aus. Kann es sein, dass ich die for schleife falsch eingebunden habe? Grad nur ne Überlegung: die if-Bedinung tritt nach 120 Sekunden ein. Dann soll l um ++1 steigen. Kann es sein, dass die for schleife direkt durchläuft bis 360, ohne noch mal das neue intervall zu berücksichtigenß

Muss selbst mla grad überlegen....

Hi,

so, die cosi berechnung funktioniert.

was den 360er Wert angeht: also es liegt an der kombi aus if und for.
Was ich möchte: alle 120 Sekunden soll die for schleife ++1 ausführen bis 180/360

Habe das mal so umgeändert, leider passiert das ++ nicht in der for schleife, also es wird nicht hochgezählt.
Hat noch einer einen Tipp?

void getStroemung() {
  if ((hour==10 || hour==22) && flutStat==1){
    flutStat=0;  //EBBE
  }
  if ((hour==4 || hour==16) && flutStat==0){
    flutStat=1;  //FLUT
  }
  intervalldisplay=(120000-(millis()-stroemungsintervall))/1000;
  if (flutStat==0) {
    for (l=0; (l<180) && ((millis()-stroemungsintervall)>120000); l++) {
      rad=l*PI/180;
      value=(cos(rad)+1)*1000; 
      pulseLow=map(value,0,2000,75,100); 
      pulseHigh=map(value,0,2000,75,255);
      stroemungsintervall=millis();
    } 
  }
  if (flutStat==1) {
    for (l=180; (l<360) && ((millis()-stroemungsintervall)>120000); l++) {
      rad=l*PI/180;
      value=(cos(rad)+1)*1000;
      pulseLow=map(value,0,2000,75,100); 
      pulseHigh=map(value,0,2000,75,255);
      stroemungsintervall=millis();
    }    
  }
}

currymuetze:
Grad nur ne Überlegung:
die if-Bedinung tritt nach 120 Sekunden ein. Dann soll l um ++1 steigen.
Kann es sein, dass die for schleife direkt durchläuft bis 360, ohne noch mal das neue intervall zu berücksichtigenß

Muss selbst mla grad überlegen…

Ja, so sieht das jedenfalls aus - die Schleife läuft bis 360 durch - deswegen steht auch l dann auf 360.

Rudi

currymuetze: Hi,

so, die cosi berechnung funktioniert.

was den 360er Wert angeht: also es liegt an der kombi aus if und for. Was ich möchte: alle 120 Sekunden soll die for schleife ++1 ausführen bis 180/360

Habe das mal so umgeändert, leider passiert das ++ nicht in der for schleife, also es wird nicht hochgezählt. Hat noch einer einen Tipp?

Du musst die Steuerung der Schleife in die übergeordnete Funktion auslagern und dort die zeitliche Steuerung unterbringen. In deiner Funktion getStroemung() darf dann immer nur ein Durchlauf stattfinden, d. h. du musst die Variable l als globale Variable definieren oder als Parameter mitgeben.

Wo wird den getStroemung() aufgerufen? Aus loop() heraus? Dann könntest du dort eine lokale Variable als static definieren und diese Variable der Funktion getStroemung() übergeben.

Rudi

Hi Rudi,

hier wird initialisiert:

//****************************************Stroemungspumpen*************************************
const byte stroemung1 = 5;
const byte stroemung2 = 6;
int l=180;
int value; 
int pulseLow; 
int pulseHigh;
boolean stroemungsStat=true;
byte flutStat = 1;
unsigned long wavemillis=millis();
unsigned long stroemungsintervall=0;
const long pulseintervall=1500;
unsigned long intervalldisplay=0;
float rad;

In der void Loop wird die funktion aufgerufen: (getStroemung)

void loop()
{
  getTime();
  getTemp();
  getLuftfeuchte();
  if (millis() - waterlevelmillis > 300000) {
     waterlevel=getWaterlevel();
     level = (41-waterlevel);
     waterlevelmillis = millis();
  }
  //getModus();
  checkButtons();
  getStroemung();
  setHeater();
  setLuefter();
  fadeLight();
  if (modus==0) setLight();
  if (modus==1) startUV(); 
  if (modus==2) stopUV(); 
  setStroemung();
  setSkimmer();
  showLCD();
}

und so sieht die funktion bislag aus:

void getStroemung() {
  if ((hour==10 || hour==22) && flutStat==1){
    flutStat=0;  //EBBE
  }
  if ((hour==4 || hour==16) && flutStat==0){
    flutStat=1;  //FLUT
  }
  intervalldisplay=(120000-(millis()-stroemungsintervall))/1000;
  if (flutStat==0) {
    for (l=0; (l<180) && ((millis()-stroemungsintervall)>120000); l++) {
      rad=l*PI/180;
      value=(cos(rad)+1)*1000; 
      pulseLow=map(value,0,2000,75,100); 
      pulseHigh=map(value,0,2000,75,255);
      stroemungsintervall=millis();
    } 
  }
  if (flutStat==1) {
    for (l=180; (l<360) && ((millis()-stroemungsintervall)>120000); l++) {
      rad=l*PI/180;
      value=(cos(rad)+1)*1000;
      pulseLow=map(value,0,2000,75,100); 
      pulseHigh=map(value,0,2000,75,255);
      stroemungsintervall=millis();
    }    
  }
}

also l ist bereits eine globale variable.

meinst du damit, dass ich diese if bedingungn

((millis()-stroemungsintervall)>120000)

in die hauptschleife integrieren muss? wird dadurch dann nur alle 120 sek die forschleife durchlaufen und +1 gesetzt?

Komme leider nicht ganz weiter, habs so geändert:

void getStroemung() {
  if (flutStat==0) {
    for (l=0; l<180; l++) {
      rad=l*PI/180;
      value=(cos(rad)+1)*1000; 
      pulseLow=map(value,0,2000,75,100); 
      pulseHigh=map(value,0,2000,75,255);
    } 
  }
  if (flutStat==1) {
    for (l=180; l<360; l++) {
      rad=l*PI/180;
      value=(cos(rad)+1)*1000;
      pulseLow=map(value,0,2000,75,100); 
      pulseHigh=map(value,0,2000,75,255);
    }    
  }
}
void loop()
{
  getTime();
  getTemp();
  getLuftfeuchte();
  if (millis() - waterlevelmillis > 300000) {
     waterlevel=getWaterlevel();
     level = (41-waterlevel);
     waterlevelmillis = millis();
  }
  //getModus();
  checkButtons();
  if ((hour==10 || hour==22) && flutStat==1) flutStat=0;
  if ((hour==4 || hour==16) && flutStat==0)  flutStat=1;
  if ((millis()-stroemungsintervall)>120000) {
    getStroemung();
    stroemungsintervall=millis();
  }
  setHeater();
  setLuefter();
  fadeLight();
  if (modus==0) setLight();
  if (modus==1) startUV(); 
  if (modus==2) stopUV(); 
  setStroemung();
  setSkimmer();
  showLCD();
}

Klappt leider auch nicht, springt auch direkt auf 360 nach dem ablauf der ersten 120 sekunden
Diese ganzen If FOr While etc Konstrukte werde ich wohl irgendwie nie 100%ig durchschauen…

Hi Thorsten,

die loop()-Funktion sieht schon ganz gut aus.

Allerdings muss der Block

  if ((millis()-stroemungsintervall)>120000) {
    getStroemung();
    stroemungsintervall=millis();
  }

so geändert werden, dass l inkrementiert wird, also in etwas so:

  if ((millis()-stroemungsintervall)>120000) {
    getStroemung();
    stroemungsintervall=millis();
    l++;
  }

Dafür muss die Schleife aus getStroemung() raus, da du damit ja die globale Variable “l” veränderst und außerdem auch 180 mal hintereinander durchläufst. Der Code könnte in etwa so aussehen:

void getStroemung() {
  if (flutStat==0) {
      rad=l*PI/180;
      value=(cos(rad)+1)*1000; 
      pulseLow=map(value,0,2000,75,100); 
      pulseHigh=map(value,0,2000,75,255);
  }
  if (flutStat==1) {
      rad=l*PI/180;
      value=(cos(rad)+1)*1000;
      pulseLow=map(value,0,2000,75,100); 
      pulseHigh=map(value,0,2000,75,255);
  }

Wie nun unschwer zu erkennen ist, sind die beiden Zweige identisch, also kann auch die if-Abfragehier entfallen. Die Funktion sieht also wie folgt aus:

void getStroemung() {
      rad=l*PI/180;
      value=(cos(rad)+1)*1000; 
      pulseLow=map(value,0,2000,75,100); 
      pulseHigh=map(value,0,2000,75,255);
  }

Wenn du nunmehr auch noch das Hochzählen der Variablen l hier erledigst, kannst du loop() so lassen wie es ist und getStroemung() würde wie folgt aussehen:

void getStroemung() {
      rad=l*PI/180;
      value=(cos(rad)+1)*1000; 
      pulseLow=map(value,0,2000,75,100); 
      pulseHigh=map(value,0,2000,75,255);
      l++;
  }

Allerdings musst du nun noch die Abfrage nach flutStat in loop() integrieren, das sollte aber nicht mehr allzuschwer sein.

Ciao,

Rudi