Forum: Mikrocontroller und Digitale Elektronik Typecast bei avr-gcc


von Timo N. (tnn85)


Lesenswert?

Hallo,

ich habe folgende Funktion:
1
//Park position: kleinere Werte bedeuten rückwärts, größere Werte bedeuten vorwärts
2
#define ZERO_SPEED_POS_VALUE 511
3
//Toleranzbereich des Potentiomaterwerts um die Null-, Max- und Min-Position.
4
#define TOLERANCE 10
5
#define MAX_ADC_VALUE 1023
6
#define MAX_SPEED_VALUE 1023
7
8
unsigned int calc_speed_cmd (uint16_t steering_poti_value)
9
{  
10
11
  //if ( (steering_poti_value >= (MAX_ADC_VALUE-TOLERANCE)) | (steering_poti_value <= TOLERANCE) )
12
    //return ((uint16_t) MAX_SPEED_VALUE);
13
    
14
  if (steering_poti_value > (ZERO_SPEED_POS_VALUE + TOLERANCE)){
15
    return ( (uint16_t) (float)(steering_poti_value - ZERO_SPEED_POS_VALUE) *  (float)MAX_SPEED_VALUE / (float)(MAX_ADC_VALUE - ZERO_SPEED_POS_VALUE));
16
  }
17
  if (steering_poti_value < (ZERO_SPEED_POS_VALUE - TOLERANCE)){
18
    return ( (uint16_t) ((float)MAX_SPEED_VALUE - ((float)steering_poti_value *  (float)MAX_SPEED_VALUE / (float)ZERO_SPEED_POS_VALUE)));
19
  }
20
  return 0;
21
}

Die Funktion erledigt folgende Aufgabe:

Ich habe einen ADC-Wert (0-1024) und möchte daraus ein DutyCycle für 
meine PWM generieren. Die Werte von 511 bis 1023 sollen dabei auf den 
Wertebereich 0 bis 1023 abgegbildert werden. Die Werte von 0 bis 511 auf 
den Bereich 1023 bis 0. Also habe ich bei 511 sozusagen den kleinsten 
DutyCycle, bei 1023 oder 0 den Größten.
Das Ganze hat um den Wert 511 noch eine Toleranz, so dass ich auch bei 
etwas kleineren und etwas größeren Werten trotzdem den DutyCycle 0 habe.


Nun meine Frage: Ich möchte das eigentlich ohne den Typecast auf float 
erledigen. Leider verstehe ich noch nicht ganz, wie der implizite 
Typecast bei C oder beim gcc-avr abläuft. Wo finde ich Informationen 
dazu? Gibt es da ein Manual oder so, wo das steht?

von nicht"Gast" (Gast)


Lesenswert?

Ist relativ einfach.

Operierst du mit zwei Int, bekommst du ein int als Ergebnis.

Hast du einen float dabei, ist das Ergebnis auch ein float.


Mach hinter deine #defines ein kleines f oder einen Punkt.

Beispiel:
1
#define MAX_ADC_VALUE 1023.
2
#define MAX_SPEED_VALUE 1023f

von Timo N. (tnn85)


Lesenswert?

Danke für die Antwort.
Eigentlich wollte ich die Berechnung nicht mit Float machen, sondern mit 
uint16. Leider funktioniert die Funktion dann nicht wie gewünscht.
Irgendeine Idee warum?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Timo N. schrieb:
> Leider funktioniert die Funktion dann nicht wie gewünscht.

Zeig doch mal ein paar Beispiele.

Verschiedene Werte für "steering_poti_value", und das gewünschte 
Resultat sowie das nicht gewünschte Resultat.

von Stefan A. (king-crash)


Lesenswert?

Meinst du etwas wie:
1
#include <stdio.h>
2
3
int calc(int n)
4
  {
5
  n = n - 512;
6
  if(n < 0)
7
    {
8
    n *= -1;
9
    }
10
  n = n << 1;
11
  return n;
12
  }
13
14
int main(void)
15
  {
16
  int i;
17
  for(i=0;i<1024;i++)
18
    {
19
    printf("%4d -> %3d\n", i, calc(i));
20
    }
21
  return 0;
22
  }

Ausgabe:
1
...
2
 504 ->  16
3
 505 ->  14
4
 506 ->  12
5
 507 ->  10
6
 508 ->   8
7
 509 ->   6
8
 510 ->   4
9
 511 ->   2
10
 512 ->   0
11
 513 ->   2
12
 514 ->   4
13
 515 ->   6
14
 516 ->   8
15
 517 ->  10
16
 518 ->  12
17
 519 ->  14
18
 520 ->  16
19
 521 ->  18
20
 522 ->  20
21
 523 ->  22
22
...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.