can't seem to multiply by a float?

Im using the stepperdriver library and its for a gauge for a flight sim. because of gears and stuff the airspeed it gets in doesnt correspond to the gauge. Im trying to multiply the airspeed by 3.3 however it only seems to multiply by 3. It also doesnt seem to change if i change the decimal point? any ideas?

   {
     airspeed = "";
     airspeed += getChar();
     airspeed += getChar();
     airspeed += getChar();
     a = airspeed.toFloat();
     a2 = a * 3.3;    
     if (a2 != oldas)
     {
       b = oldas - a2;
       stepper.rotate(b);
       oldas = a2;
     }

No one can guess what data type "airspeed", "a" and "a2" are and what "getChar()" is doing. Do not post partial code, if you want help :slight_smile:

here is the entire code :slight_smile: airspeed is a string that's converted to a float.

#include <Arduino.h>

// Motor steps per revolution. Most steppers are 200 steps or 1.8 degrees/step
#define MOTOR_STEPS 12.5
// Target RPM for cruise speed
#define RPM 100
// Acceleration and deceleration values are always in FULL steps / s^2
#define MOTOR_ACCEL 50
#define MOTOR_DECEL 50

// Microstepping mode. If you hardwired it to save pins, set to the same value here.
#define MICROSTEPS 16

#define DIR 2
#define STEP 3
#define ENABLE 13 // optional (just delete ENABLE from everywhere if not used)

 #include "A4988.h"
 #define MS1 10
 #define MS2 11
 #define MS3 12
 A4988 stepper(MOTOR_STEPS, DIR, STEP, ENABLE, MS1, MS2, MS3);
 
int CodeIn;// used on all serial reads
int KpinNo; 
int Koutpin;

String KoldpinStateSTR, KpinStateSTR, Kstringnewstate,Kstringoldstate;
String gearSimple; 

float a = 0;
float a2;
String airspeed;
float oldas = 0;
int b;


void setup() 
{
  Kstringoldstate = "111111111111111111111111111111111111111111111111111111111111111111111";
  
  for (int KoutPin = 8; KoutPin < 70; KoutPin++)// Get all the pins ready for simconnect codes and "Keys"(all inputs)  
  {
    pinMode(KoutPin, INPUT);
    digitalWrite(KoutPin, HIGH);  
  }
  
 Serial.begin(115200);   

 stepper.begin(RPM, MICROSTEPS);
 stepper.enable();
 stepper.setSpeedProfile(stepper.LINEAR_SPEED, MOTOR_ACCEL, MOTOR_DECEL);
}

void loop() {
  {INPUTS();} //Check the Simconnect and "keys" section for any input pins
  {OTHER();}// Check for "Other" things to do. (Non extraction stuff)
  if (Serial.available()) {
    CodeIn = getChar();
    if (CodeIn == '=') {EQUALS();} // The first identifier is "="
    if (CodeIn == '<') {LESSTHAN();}// The first identifier is "<"
    if (CodeIn == '?') {QUESTION();}// The first identifier is "?"
    if (CodeIn == '/') {SLASH();}// The first identifier is "/" (Annunciators)
  }
} // end of void loop (The main one)

char getChar()// Get a character from the serial buffer
{
  while(Serial.available() == 0);// wait for data
  return((char)Serial.read());// Thanks Doug
}// end of getchar void. 

void OTHER(){
/* In here you would put code that uses other data that
cant be put into an "extraction void" that references something else.
Also in here you would put code to do something that was not
relying on a current extraction trigger.
Or ,, you could just put it all in the main "void loop" and not worry about this "other void" at all.
*/
}// end of "other" void

void EQUALS(){      // The first identifier was "="
 CodeIn = getChar(); // Get the second identifier
  switch(CodeIn) {// Now lets find what to do with it
     
    case 'B':
       //Do something
    break;
    
         //etc etc etc
     }
}// end of equals loop

void LESSTHAN(){    // The first identifier was "<"
CodeIn = getChar(); // Get the second identifier
  switch(CodeIn) {// Now lets find what to do with it
   case 'P'://The second identifier was an "A"
   {
     airspeed = "";
     airspeed += getChar();
     airspeed += getChar();
     airspeed += getChar();
     a = airspeed.toFloat();
     a2 = a * 3.9;    
     if (a2 != oldas)
     {
       b = oldas - a2;
       stepper.rotate(b);
       oldas = a2;
     }
   }
   break;
   case 'A'://The second identifier was an "A"
       {
        
       }
    break;
     
    case 'B':
       //Do something
    break;
       //etc etc etc
     }
}// end of lessthan void

void QUESTION(){    // The first identifier was "?"
CodeIn = getChar(); // Get the second identifier
  switch(CodeIn) {// Now lets find what to do with it
    case 'A'://The second identifier was an "A"
       //Do something
    break;
     
    case 'B':
       //Do something
    break;
     
    case 'Y': // found the second identifier (the "Gear simple")
    break;
         //etc etc etc
     }
}// end of question void

void SLASH(){    // The first identifier was "/" (Annunciator)
  //Do something (See the other voids for layout)
} // end of slash void

void INPUTS() // Simconnect codes and "Keys" section
{
  Kstringnewstate = "";
  for (int KpinNo = 8; KpinNo < 70; KpinNo++){ //set to the input pins. (pins 8 to 70 ,, change the 70 to 19 for Uno cards)
    KpinStateSTR = String(digitalRead(KpinNo)); 
    KoldpinStateSTR = String(Kstringoldstate.charAt(KpinNo - 8));// set to the first pin read (The 8)
    if (KpinStateSTR != KoldpinStateSTR)// checks if it's different to the last reading of that pinNo
    {
      if (KpinNo != 13){ // avoid using pin 13 as an input unless you know the tricks.
        if (KpinNo == 8 && KpinStateSTR == "0"){Serial.println ("C01");} //sets gear handle up
        if (KpinNo == 9 && KpinStateSTR == "0"){Serial.println ("C02");} //sets gear handle down
        if (KpinNo == 10 && KpinStateSTR == "0"){Serial.println ("C15");} //Decrements flap handle position
        if (KpinNo == 11 && KpinStateSTR == "0"){Serial.println ("C14");} //Increments flap handle position
        if (KpinNo == 12 && KpinStateSTR == "0"){Serial.println ("A02");} //Increments COM1sb by one MHz
        if (KpinNo == 14 && KpinStateSTR == "0"){Serial.println ("A01");} //Decrements COM1sb by one MHz
        if (KpinNo == 15 && KpinStateSTR == "0"){Serial.println ("A426543");} //Sets transponder code to 6543
        //  Add more here but remember to change the figure in the next line down. (the 15)
        if (KpinNo > 15){ //Change pinNo number to same as the highest one used for simconnect codes.(the 15)
        Serial.print ("D"); 
      if (KpinNo < 10) Serial.print ("0");
      Serial.print (KpinNo);
      Serial.println (KpinStateSTR);
        }//end of 'its pinNo is greater than 12' 
      }//end of 'its not pin 13'
    }//end of 'its different'       
    Kstringnewstate += KpinStateSTR;
  }//end of 'for' loop (read the pins)
  Kstringoldstate = Kstringnewstate;
}//end of INPUTS void

You are using an awful amount of "String" instances in your code. "String" is known to cause problems due to memory fragmentation, so you should start by removing those from your code. Also, you are adding useless {} braces, eg:

{INPUTS();} //{ and } are useless here.
INPUTS(); //This is enough.

The only string that could be causing these problems is the airspeed string because it reads it in from the serial buffer then converts it to a float or int ( it would be like 220) .

georgegohl888:
The only string that could be causing these problems is the airspeed string because it reads it in from the serial buffer then converts it to a float or int ( it would be like 220) .

You are so wrong.. "INPUTS()" is merrily using instances of "String" in an unfortunate manner. Just get rid of the "String" class - even if it is not the cause of your apparent problem, it will become the cause of another.

EDIT: If you know for sure, that "airspeed" will always be 3 chars long, why not use this:

char airspeed[4];
for (byte i = 0; i < 3; i++) airspeed[i] = getChar();
airspeed[3] = 0; //NULL terminate
a = atof(airspeed); //Ascii TO Float

Im using example code and thats part of the example code and i've used it before and never encountered any problems... I dont fancy changing it if it works.

georgegohl888:
I dont fancy changing it if it works.

Well.. It doen't..

georgegohl888:
Im using example code and thats part of the example code and i've used it before and never encountered any problems... I dont fancy changing it if it works.

Your other "self" seems to want help in changing it.

Thanks for the help. Ive added your suggestions and taken out some of the braces but the original problem still stands. multiplying by 4 give a movement on the stepper that is too large but any value between 3.0 and 3.9 yields the same result? any ideas? thanks

#include <Arduino.h>

// Motor steps per revolution. Most steppers are 200 steps or 1.8 degrees/step
#define MOTOR_STEPS 12.5
// Target RPM for cruise speed
#define RPM 100
// Acceleration and deceleration values are always in FULL steps / s^2
#define MOTOR_ACCEL 50
#define MOTOR_DECEL 50

// Microstepping mode. If you hardwired it to save pins, set to the same value here.
#define MICROSTEPS 16

#define DIR 2
#define STEP 3
#define ENABLE 13 // optional (just delete ENABLE from everywhere if not used)

 #include "A4988.h"
 #define MS1 10
 #define MS2 11
 #define MS3 12
 A4988 stepper(MOTOR_STEPS, DIR, STEP, ENABLE, MS1, MS2, MS3);
 
int CodeIn;// used on all serial reads
int KpinNo; 
int Koutpin;

String KoldpinStateSTR, KpinStateSTR, Kstringnewstate,Kstringoldstate;

float a = 0;
float a2;
//String airspeed;
float oldas = 0;
float b;


void setup() 
{
  Kstringoldstate = "111111111111111111111111111111111111111111111111111111111111111111111";
  
  for (int KoutPin = 8; KoutPin < 70; KoutPin++)// Get all the pins ready for simconnect codes and "Keys"(all inputs)  
  {
    pinMode(KoutPin, INPUT);
    digitalWrite(KoutPin, HIGH);  
  }
  
 Serial.begin(115200);   

 stepper.begin(RPM, MICROSTEPS);
 stepper.enable();
 stepper.setSpeedProfile(stepper.LINEAR_SPEED, MOTOR_ACCEL, MOTOR_DECEL);
}

void loop() {
  INPUTS(); //Check the Simconnect and "keys" section for any input pins
  OTHER();// Check for "Other" things to do. (Non extraction stuff)
  if (Serial.available()) {
    CodeIn = getChar();
    if (CodeIn == '=') {EQUALS();} // The first identifier is "="
    if (CodeIn == '<') {LESSTHAN();}// The first identifier is "<"
    if (CodeIn == '?') {QUESTION();}// The first identifier is "?"
    if (CodeIn == '/') {SLASH();}// The first identifier is "/" (Annunciators)
  }
} // end of void loop (The main one)

char getChar()// Get a character from the serial buffer
{
  while(Serial.available() == 0);// wait for data
  return((char)Serial.read());// Thanks Doug
}// end of getchar void. 

void OTHER(){
/* In here you would put code that uses other data that
cant be put into an "extraction void" that references something else.
Also in here you would put code to do something that was not
relying on a current extraction trigger.
Or ,, you could just put it all in the main "void loop" and not worry about this "other void" at all.
*/
}// end of "other" void

void EQUALS(){      // The first identifier was "="
 CodeIn = getChar(); // Get the second identifier
  switch(CodeIn) {// Now lets find what to do with it
     
    case 'B':
       //Do something
    break;
    
         //etc etc etc
     }
}// end of equals loop

void LESSTHAN(){    // The first identifier was "<"
CodeIn = getChar(); // Get the second identifier
  switch(CodeIn) {// Now lets find what to do with it
   case 'P'://The second identifier was an "A"
   {
     char airspeed[4];
     for (byte i = 0; i < 3; i++) airspeed[i] = getChar();
     airspeed[3] = 0; //NULL terminate
     a = atof(airspeed); //Ascii TO Float
     a2 = a * 3.9;    
     if (a2 != oldas)
     {
       b = oldas - a2;
       stepper.rotate(b);
       oldas = a2;
     }
   }
   break;

       //etc etc etc
     }
}// end of lessthan void

void QUESTION(){    // The first identifier was "?"
CodeIn = getChar(); // Get the second identifier
  switch(CodeIn) {// Now lets find what to do with it
    case 'A'://The second identifier was an "A"
    break;
         //etc etc etc
     }
}// end of question void

void SLASH(){    // The first identifier was "/" (Annunciator)
  //Do something (See the other voids for layout)
} // end of slash void

void INPUTS() // Simconnect codes and "Keys" section
{
  Kstringnewstate = "";
  for (int KpinNo = 8; KpinNo < 70; KpinNo++){ //set to the input pins. (pins 8 to 70 ,, change the 70 to 19 for Uno cards)
    KpinStateSTR = String(digitalRead(KpinNo)); 
    KoldpinStateSTR = String(Kstringoldstate.charAt(KpinNo - 8));// set to the first pin read (The 8)
    if (KpinStateSTR != KoldpinStateSTR)// checks if it's different to the last reading of that pinNo
    {
      if (KpinNo != 13){ // avoid using pin 13 as an input unless you know the tricks.
        if (KpinNo == 8 && KpinStateSTR == "0"){Serial.println ("C01");} //sets gear handle up
        if (KpinNo == 9 && KpinStateSTR == "0"){Serial.println ("C02");} //sets gear handle down
        if (KpinNo == 10 && KpinStateSTR == "0"){Serial.println ("C15");} //Decrements flap handle position
        if (KpinNo == 11 && KpinStateSTR == "0"){Serial.println ("C14");} //Increments flap handle position
        if (KpinNo == 12 && KpinStateSTR == "0"){Serial.println ("A02");} //Increments COM1sb by one MHz
        if (KpinNo == 14 && KpinStateSTR == "0"){Serial.println ("A01");} //Decrements COM1sb by one MHz
        if (KpinNo == 15 && KpinStateSTR == "0"){Serial.println ("A426543");} //Sets transponder code to 6543
        //  Add more here but remember to change the figure in the next line down. (the 15)
        if (KpinNo > 15){ //Change pinNo number to same as the highest one used for simconnect codes.(the 15)
        Serial.print ("D"); 
      if (KpinNo < 10) Serial.print ("0");
      Serial.print (KpinNo);
      Serial.println (KpinStateSTR);
        }//end of 'its pinNo is greater than 12' 
      }//end of 'its not pin 13'
    }//end of 'its different'       
    Kstringnewstate += KpinStateSTR;
  }//end of 'for' loop (read the pins)
  Kstringoldstate = Kstringnewstate;
}//end of INPUTS void

If you want help with some coding you do not understand, please tell how we can guide you. If you want someone to fix your cut'n paste examples to do what you want, hire a programmer.

There is the base code that is used to interface with a program called link2fs. It can send airspeeds for example and split up to the different parts. Im trying to learn how to interface with the stepper using the stepperdriver library. The code i wrote sort of works as in the gauge rotates its just the calibration cant seem to work out. Thats where i need the help, Thank you :slight_smile:

Try to print "airspeed" with serial and see what it gets, and get rid of all the "String" instances. When you are done and still have problems, post your updated code.

// end of "other" void

OTHER isn't a "void". It's a function. "void" just means that the function doesn't return a value.

// end of getchar void.

And the getchar function is not a "void". It isn't even declared "void". It is declared like this:

char getChar()

which means that it returns a char value. It is not "void". It is not "a void". It is a function.

}// end of equals loop

EQUALS is not a loop. It's a function.

Get the picture?

Pete

Converts a valid String to a float. The input String should start with a digit. If the String contains non-digit characters, the function will stop performing the conversion. For example, the Strings "123.45", "123", and "123fish" are converted to 123.45, 123.00, and 123.00 respectively. Note that "123.456" is approximated with 123.46. Note too that floats have only 6-7 decimal digits of precision and that longer Strings might be truncated.

This Arduino description of usage of String seems to be wrong , it contradicts itself.
Of course we all been told over and over that the issue is with using String, not the way Arduino code works.

I would make sure the characters you have collected are only numeric.

Or use real String class to convert to float.
.

If you just print out the input airspeed and the intermediate variables a, a2, oldas and b immediately before the stepper.rotate you'll probably spot what's happening. Or post them here and maybe we will.

Steve

Your code is throwing away the fractional part of every step.

     if (a2 != oldas)
     {
       b = oldas - a2;  // If the result is below 1 this will truncate it to 0
       stepper.rotate(b);
       oldas = a2;
     }

You should keep the fractional parts:

      b = oldas - a2;
     if (b != 0)  // Any full steps to be done?
     {
       stepper.rotate(b);
       oldas += b;  // Keep track of the fractional part not included in this movement.
     }