Hi,
ich bin ein absoluter Arduino-Neuling und bin gerade dabei, mich da rein zu werkeln.
Normalerweise programmiere ich in vb.net und bin da nicht gerade Anfänger. Aber C macht mich wahnsinnig
Ich habe da ein eigentlich ganz einfaches Problem: Ich möchte z.B. den gemessenen Wert eines Potis in Stufen von 0...10 umrechnen (wahlweise auch 0...255 etc.).
Der Poti hat max. 1023 Ohm, eingestellt sind z.B. 345 Ohm.
Rechnerisch heißt das
Stufe = MaxStufe / MaxWiderstand * gemessenerWiederstand, in diesem Beispiel wäre das
Stufe = 10 / 1023 * 345 = 3,372, als ganze Zahl also gerundet 3.
in VB ist das mit der Konvertierungsfunktion cint() kein Problem.
Aber wie geht das in C?
Ich bekomme als Ergebnis immer nur 0 oder 0.00...
Wie funktioniert die Konvertierungsfunktion int?
Ich hab hier so seltsamen Code gesehen wie a = (int)b;das kommt mir aber doch sehr spanisch vor, normalerweise schreibt man ja wohl die Parameter in Klamern und nicht die Funktion. Funktioniert bei mir auch nicht, obwohl der Compiler keinen Fehler anzeigt. Aber a = int(b);funktioniert in dem Zusammenhang auch nicht.
Kann mich bitte mal jemand aufklären?
k
Das Grundgerüst ist so:
int sensorPin = A0; // select the input pin for the potentiometer
int sensorValue = 0; // variable to store the value coming from the sensor (Poti)
int val; // variable to read the value from the analog pin
int Pause = 1000;
int PotiMax = 1023;
int maxSteps = 10;
int PotiStep = 0; // Startwert
int Step;
float fl; // zum dividieren
void setup() {
Serial.begin(9600);
Serial.println("* * * * WechselLED5 x* * * ");
}
// the loop routine runs over and over again forever:
void loop() {
sensorValue = analogRead(sensorPin);
Serial.print("sensorValue = ");
Serial.println(sensorValue);
// Versuch, den Poti-Widerstand in einen Wert 0..5 umzurechnen
// Max. Potiwert ist 1023
// so, und hier geht's nicht mehr weiter, ich bekomme nur Nullen....
fl = maxSteps / PotiMax * sensorValue;
Step = maxSteps / PotiMax * sensorValue;
Serial.print("fl = ");
Serial.println(fl);
Serial.print("Step = ");
Serial.println(Step);
}
Re-maps a number from one range to another. That is, a value of fromLow would get mapped to toLow, a value of fromHigh to toHigh, values in-between to values in-between, etc.
Das (int) davor habe ich mal explizit hingeschrieben, um zu zeigen was der Compiler verwendet. Das macht er deshalb, weil Deine Variablen als solche deklariert sind.
Damit passiert in beiden Fällen (Ergbnis float und Ergebnis integer) immer eine Integer-Division "10/1023" und die ist IMMER "0". 0 * Irgendwas, bleibt leider 0, daher das Ergebnis. Beim "f1" wird erst am Ende der Rechnung ein Float draus.
Einen Datentyp (nicht Funktion) in Klammern vor eine Variable oder einen Ausdruck zu schreiben ist in C korrekt. Man nenn das "Casten" und zwingt damit den Compiler einen bestimmten Datentyp zu verwenden, auch wenn die Variable eigentlich einen anderen Typ hat. Im o.g. Beispiel zwingt man schon bei der Rechnung den Compiler einen anderen Datentyp zu verwenden.
@markbee: Danke, map ist genau das, was ich hier erreichen wollte!
@mkl0815: Danke, jetzt verstehe ich , wie die Konvertierung funktioniert. Für diese Aufgabenstellung ist es jetzt zwar überflüssig geworden- dank map - aber hilfreich für die Zukunft.
Aber: bei beiden Lösungen (map-Funktion oder Berechnung per Formel) wird das Ergebnis immer abgerundet!
Wenn sich hier z.B. ein float-Wert von 2.45 ergibt, ist das Ergebnis 2 (ist klar), aber bei einem float-Wert von 2.54 ist das int-Ergebnis immer noch 2.
Da muss ich mir noch was überlegen, damit ab 2.5 nach 3 aufgerundet wird, wie das mathematisch üblich ist.
Nebenbei: Das Beispiel in der map-Hilfe http://arduino.cc/en/Reference/Map verwendet anscheinend meinen Poti mit 1023 Ohm. Woher haben die das gewusst?? XD
Auch die Reihenfolge der Berechnung kann das Problem lösen. Zuerst multiplizieren und dann dividieren. Dabei ist aufzupassen, daß der Zwischenwert der Multiplikation kleiner als der max. darstellbare Wert einer vorzeichenbehafteten Int-Zahl ist (32678). bei 10*1023 ist das kein Problem. Zum richtig Runden (0,499 -> 0; 0,500->1) mußt Du noch den halben Wert zwischen 2 Stufen zum gelesenen Potiwert dazuzählen. In diesem Fall wäre das 1023/10/2 = 51
findusdwarf:
Wenn sich hier z.B. ein float-Wert von 2.45 ergibt, ist das Ergebnis 2 (ist klar), aber bei einem float-Wert von 2.54 ist das int-Ergebnis immer noch 2.
Da muss ich mir noch was überlegen, damit ab 2.5 nach 3 aufgerundet wird, wie das mathematisch üblich ist.
Du mußt 0,5 dazuzählen bevor die Float-Zahl nach int wandelst.
findusdwarf:
Nebenbei: Das Beispiel in der map-Hilfe map() - Arduino Reference verwendet anscheinend meinen Poti mit 1023 Ohm. Woher haben die das gewusst?? XD
Der verwendete Widerstandswert ist egal. Das Potentiometer wird zwischen Masse und Versorgungspannung geschaltet. Man mißt die Spannung am Schleifer des Potentiometers. Dei Spannung geht von 0V bis zur Versorgungspannung (ca 5V). Die Versorgungsspannung wird auch als Referenzwert genommen (entspricht dem Wert 1023). mit analogRead bekommst Du eine Zahl von 0 (0V) bis 1023 ( +Versorgungsspannung).