# large constant

hi there,

i have a problem which i hope someone can help me with.

i got to use a constant z = 10,69230769230769; with arduino but i get an error telling me " error: integer constant is too large for 'long' type"

is there a way to solve this problem?

i would be very glad if someone of you nice people out there could help!

have a nice evening!

Is that a comma? If that is a fractionay number them you need to use a float, as a long is a integer type.

You could try a “long long” data-type, good for -263 to 263-1 range.
But yes, lose the comma. (Is this a cosmology problem?)

thank you awol.

its kind of a gear-ratio-problem. i drive a stepper motor which is connected through a gear and the constant is the gear ratio. to calculate the steps so that the end of the gear for example moves exactly 30 degrees i have to use the whole number (of course with all after the comma.

i never heared of the long long type. would you explain this a little more for me?

Long long is a 64bits integer variable, so if you want the comma use floats, but you will loose a lot of those extra digits.

Data types byte and char are 8 bits, int is 16 bits, long is 32 bits, long long is 64 bits, float and double are the same, both being 32 bits. If that number is floating point, float and double are only capable of 6-7 significant digit precision.

z = 10,69230769230769;

Flawed number notation? If it's a float why only one comma? Maybe that's some EU method to display a decimal point? If so the arduino floats won't work to that amount of precision.

Lefty

oops ;)

no i am confused - maybe it is just a notation error from me. i tried z = 10.69230769230769; and now i do not get an error. i will try this.

if this does not work will it be possible to use z = 1069230769230769; and then bring the factor 100 in my calculation or is the number too big for arduino anyway? by the way at the moment i defined z as long.

It's a very long number, unless you want to be able to not miss one tooth after some odd gazillion turns, you don't need that many digits. I suggest float and if accuracy becomes an issue, do double. BTW, cosmology numbers can be very large or very small, both with many zeros but significant digits are not many. How do you measure that many digits in the first place? :cold_sweat:

so, i tried with z = 10.69230769230769; but the result is the same. the code tells the motor to rotate the gear 30 degrees and the result is 29.99 degrees. when i tell then to move another 30 degrees the result is 59.98 degrees. i mean, well, its not that bad but i am a man who likes precision.

does anyone have a solution, tip, hint, something for me?

mipumat: does anyone have a solution, tip, hint, something for me?

Use an encoder a a PID loop to controll the motor. If put an floating point in a integer var the compiler will only store the integer part and remove the rest, see this:

``````int foo=10.65;
serial.print(foo);
``````

Test this code, the output will be 10 and not 10.65.

here you are!

``````// DREHTELLER
int counter = 0;
int Ser;
int k;                    // k as integer. Number of steps to reach next postion.
int i;                    // i as integer for the for - next loop.
int m;                    // m as integer for the for - next loop.
int outDirection = 2;     // Digital output for outdirection at pin 2
int outClock = 3;         // Digital output for motor clock (steps) at pin 3

int oldVal = 0;           // Define a start "old value" for pushbutton "Next Position".
int oldVal2 = 0;          // Define a start "old value2" for pushbutton "Step".
long z;                    // z as integer, used gear ratio
int microStepMode;        // Kind of microstepping
int milliSteps;           // Number of steps to rotate for 1° if the "Step" button is pressed.

int turnDirection;        // H or L from „Direction“ toggle switch
int makeStep;             // H or L from pushbutton "Step"
int nextPos;              // H or L from pushbutton "Next Position"
int dirSign;              // Sign, +1 or -1 for turn direction
int currentPos;           // Number of the current postion. The initial one = 0 th pos.
float microAngle;         // Value of the microstep angle
float currentAngle;       // Value of the current angle (in degree).
float motorAngle;         // Value of motor step angle (in degree).
float incrementAngle;     // Value of angle increment (in degree).

// LASERMOVER

// buttons
int laserdirpin = 5;
int lasersteppin = 6;
int buttonup = 7;
int buttondown = 8;
int buttonsetup = 9;
int buttonsetdown = 10;
int buttonmove = 11;

// variablen
int up = 0;
int down = 0;
int upmax = 0;
int downmax = 0;
int move = 0;
int pos = 0;
int oben = 0;
int unten = 0;
int temp = 0;
int weg = 0;

void setup()   {

// DREHTELLER

Serial.begin(9600);
pinMode(outClock, OUTPUT);         //Define outClock as an output
pinMode(outDirection, OUTPUT);     //Define outDirection as an output

//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DEFINE HERE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
incrementAngle = 30;         // Define angle increment (in degrees)
motorAngle = 1.8;              // Motor-step angle (in degree).
z = 10.69230769230769;                        // Define gear ratio
// z = 10,692307692;
microStepMode = 8;             // 1 = fullstep, 2 = halfstep, 4 = 1/4 step, 8 = 1/8 step
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
microAngle = motorAngle/(microStepMode*z);           // Used micro step angle.
k = incrementAngle/motorAngle*microStepMode*z;       // Number of steps needed to go to next pos.
milliSteps = 360/motorAngle*microStepMode*z/360;     // number of steps to rotate 1° if the "Step" button is pressed
currentAngle = 0;                        // Initial value = 0
currentPos = 0;

// LASERMOVER

pinMode(laserdirpin, OUTPUT);
pinMode(lasersteppin, OUTPUT);
pinMode(buttonup, INPUT);
pinMode(buttondown, INPUT);
pinMode(buttonsetup, INPUT);
pinMode(buttonsetdown, INPUT);
pinMode(buttonmove, INPUT);

}

void loop() {

// DREHTELLER

dirSign = -1;
digitalWrite(outDirection,HIGH);     // Set direction output = High

oldVal2 = makeStep;

// Serielle Komunikation
if (Serial.available() >0)
{
}

oldVal = nextPos;

// LASERMOVER

// laser nach oben

if (up == HIGH)
{
int i;

digitalWrite(laserdirpin, HIGH);
for (i = 0; i<1; i++)
{
digitalWrite(lasersteppin, LOW);
digitalWrite(lasersteppin, HIGH);
pos++;
delayMicroseconds(200);
}
}

// laser nach unten

if (down == HIGH)
{
int i;

digitalWrite(laserdirpin, LOW);
for (i = 0; i<1; i++)
{
digitalWrite(lasersteppin, LOW);
digitalWrite(lasersteppin, HIGH);
pos--;
delayMicroseconds(200);
}
}

// obersten punkt speichern

if (upmax == HIGH)
{
oben = pos;
}

// untersten punkt speichern...

if (downmax == HIGH)
{
unten = pos;
temp = pos - oben;
weg = unten - oben;

// ... und Laser in Ausgangsposition bringen

int i;

digitalWrite(laserdirpin, LOW);
for (i = 0; i<temp; i++)
{
digitalWrite(lasersteppin, LOW);
digitalWrite(lasersteppin, HIGH);
pos--;
delayMicroseconds(200);
}
temp = oben;
}

// SCAN

if (Ser == 'S')

{

if (counter < 12)
{

int i;

digitalWrite(laserdirpin, HIGH);
for (i = 0; i<weg; i++)
{
digitalWrite(lasersteppin, LOW);
digitalWrite(lasersteppin, HIGH);
pos++;
delayMicroseconds(10000);
}

Serial.println("T");

// Drehteller auf nächste Position

for (i = 0;i < k;i++)
{
digitalWrite(outClock,HIGH);          // Set clock output = H
currentAngle=currentAngle + microAngle*dirSign;
delay(1);                            // 1ms delay
digitalWrite(outClock,LOW);           // Clock output  = L
delay(1);
}

currentPos = currentPos +1*dirSign;
counter++;
// Laser in Ausgangsposition

digitalWrite(laserdirpin, LOW);
for (i = 0; i<weg; i++)
{
digitalWrite(lasersteppin, LOW);
digitalWrite(lasersteppin, HIGH);
pos--;
delayMicroseconds(200);
}
temp = oben;

Serial.print("Z "); // save the current scan
Serial.print(currentAngle); // save the current scan
Serial.println(".obj"); // save the current scan
Serial.println("E"); // delete the current scan
Serial.println("S"); // start the next scan
}

}

}
``````

liudr: I suggest float and if accuracy becomes an issue, do double.

AVR-GCC does not have double/long float. Declaring a long float gives you a plain old 32-bit float. Same for long double.

A bit long and I don't have any motors. What I spotted were k and milliSteps are both integers so losing 1/100 is typical unless you add 0.005 in the expression. What's up with the milliSteps multiply and then divide by 360? Integer tricks?

does it make sense to make k and millisteps long?

10.(692307) is 139 over 13. There is likely an exact integer solution to whatever you are trying to work out.

its kind of a gear-ratio-problem

Presumably the actual gears have integer numbers of teeth. To get exact results, calculate things using the exact integers, rather than the final decimal ("approximate") ratio. There will still be certain rotations where you won't be able to move exactly that amount; in order to prevent accumulating ever greater errors, you'll have to keep track of the errors and correct for them periodically.

So, for example, if you have a 10 degree stepper (36 steps per rev) and a 139:13 gear ratio, each step is .935251... degrees, but the way to figure out how many steps you need to make 30 degrees of movement is better calculated as ((30*10*13)/139) rather than (.93525 * 30) The first equation will also give you the exact amount of error, whereas in the second you would have to figure out the error of the floating point constant...