convert integer to 4 digits

hey,

I am mesuring voltage, maks 15 volt, use a resistor divider an zener to protect arduino input pin against over voltage.

to convert the integer to a string i use this function:

void getvoltage(char *voltage)
{
int whole;
digitalWrite(digital_io_pin7,LOW); // alive led turns off

whole = analogRead(5);

voltage[1]= (whole-(whole/100)*100)/10 +'0' ;
voltage[2]= whole-(whole/10)*10 +'0';
voltage[3]=',';
voltage[4]=whole/10 +'0';
voltage[5]=whole-(whole/10)*10+'0';
voltage[6] = '\0';
delay(1000UL); // delay 30 sec
}

then i send the value to a data.txt file on my server, and view the data in a php/html page, with ethershield from nuelectronics.com

But, i can't figure out how to fit this code to mesure up to 15 volt, and how to use this digit conversion to mesure mvolt for current also.

then i found i might try modulous (%), divide and floor function, but arduino do not support floor?

12345 mod 10 = 5
12345 mod 100 = 45 / 10 = 4.5 (floors to 4)
12345 mod 1000 = 345 / 100 = 3.45 (floors to 3)
12345 mod 10000 = 2345 / 1000 = 2.345 (floors to 2)
12345 mod 100000 = 12345 / 10000 = 1.2345 (floors to 1)

and of course i need to do reverse on my server php file saving the values

Any idees?

thanks

:wink: michael

OK, assuming you're dividing the voltage by 3 to make it a maximum of 5V, you can do something like the following. You don't really need floating point functions like floor and ceil, and should avoid floating point if it's not too hard to think about. You can just do it with integers. Modulus (% operator) returns the remainder after division, so a (x % 10) = the bottom digit of x.

Use the map() function to map your analogRead value into a good range. Since it looks like you want 2 digits of precision, and 15V is your max, then you'll want the normal analogRead value (which goes from 0...1023) mapped to 0...1500. That means 0 = 0V and 1500 = 15.00V.

Try something like this:

char voltageString[6];
// Do these two first since they don't change:
voltageString[5] = 0;  // Null termination
voltageString[2] = ',';  // Decimal separator

int value = analogRead(5);

// Make the value be in between 0 and 1500
int mappedValue = map( value, 0, 1023, 0, 1500 );

// Working backwards, take the bottom digit and shift
voltageString[4] = mappedValue % 10; // Take the bottom digit
mappedValue /= 10;    // Shift by one digit (this is a short way to write mappedValue = mappedValue / 10;)
voltageString[3] = mappedValue % 10; // Take the bottom digit
mappedValue /= 10;    // Shift by one digit

// Decimal was already written above, skip voltageString[2]
voltageString[1] = mappedValue % 10; // Take the bottom digit
mappedValue /= 10;    // Shift by one digit
voltageString[0] = mappedValue % 10; // Take the bottom digit

I hope that helps.

-Paul

thanks, oh yes, i never used map commad before. Think this will be the solution for the current function, low voltage at 0 amp is 2,5 volt and 1 amp 2,67volt.

I found that using the integer 'whole' and modulus %, this code seams to do the job:

whole = analogRead(5);
whole = whole/2;

voltage[1]= (whole % 10000)/1000 +'0' ;
voltage[2]= (whole % 1000)/100 +'0';
voltage[3]=',';
voltage[4]= (whole % 100)/10 +'0';
//whole=whole;+24; //calibrering af måling
voltage[5]= (whole % 10)+'0';
voltage[6] = '\0';

but i will try implement your example, could be more accurate, as you mentioned i am interested in 2 digits of precision / 15 volt.

thanks, hope will be able to contribute here in the future :wink:

/michael

Here comes a piece of code for FLOOR function. CEILING function can also be derived by a little tweak in the code. The variable you want to find its floor value is defined is "variable".

///////////////////FLOOR function//////////////////////
int temp_counter = 0;
while (temp_counter+1<=variable)
{
temp_counter++;
if (temp_counter+1>=variable)
{
variable=temp_counter;
}

}
///////////////////////////////////////////////////////

Cheerio...

Here comes a piece of code for FLOOR function.

Just for future reference, this function is a bit overkill. A simple cast or int-initialisation will give you the same result. So:

double dx = 1.9;
int i1 = static_cast<int>(dx); // = 1
int i2 = int(dx); // = 1

One does not even need to use a cast.

float fVal = 17.345;
int iVal = fVal;

The cast IS required to stop the compiler from complaining, but, since warnings are turned off, who cares?

Gido,

Thanks for reply. The second tip is cool, and basically I tried it before but in another way, didn;t work.

But how did you come up with the first one? All my Arduino programming knowledge is coming from the Arduino Programming Book, which I'm sure this one is not in it!! IS there another advanced book or so out there on Arduino Programming> Where did you get the command from??

Plz advise.

Thanks upfront.

PaulS, Gido's second one is the same as your actually dude....

No. Gido's second one has a cast in it. The cast is not REQUIRED.

No. Gido's second one has a cast in it.

That's not true, the second has no cast in it. It uses the normal integer initialisation, but explicitly. While your (PaulS) conversion uses the operator=() function of the int class, mine just uses the constructor and should herefore be slightly faster (because your way first creates and int and then assigns a new value). Very likely this will be optimised away by the compiler and not matter, but if you mean for something to happen, you should program it that way and not count on the compiler to fix things.

Furthermore I believe compiler warnings should be paid very careful attention to, but that's just my conviction.

In reply to Shanejet3, the first one with the usage of static_cast() is the standard C++ cast from one type to another. It replaces the C typecasting. If you want further information, you can find it here, section 3.5. It has nothing to do with Arduino programminging per se, it's standard C++.

Thanks Gido, I reckoned that it's coming from C/C++.

So, my question maybe changes too:

What is Arduino hardware able to compile? I mean how far can I go on with programming standard C/C++ ??

Cheers,
S

That's not true, the second has no cast in it.

int i2 = [glow]int[/glow](dx); // = 1

Do you know how the int "function" is implemented?

What is Arduino hardware able to compile?

The Arduino hardware is not able to compile anything.

Most C and C++ functions can be used in Arduino code. There are, obviously, some restrictions. fopen(), fclose(), seekg(). tellg(), etc. rely on a file system that the Arduino does not support.

The sprintf() implementation does not handle floating point numbers.

Do you know how the int "function" is implemented?

Implementation of the int contructor is not in the C++ specification and does not really matter either. All this code does is request the compiler to create an anonymous variable of type int from the float. It will never represent a typecast because it does not ask the compiller to reinterpret the memory block of the float; it uses its value (type + bit information) to intialise an integer, whereas a cast would ignore type and just take the floats memory as-is. There is a fundamental difference. If you're interested, you could also read the link I gave Shanejet3.

What is Arduino hardware able to compile? I mean how far can I go on with programming standard C/C++ ??

First off a little correction: the Arduino boards do not actually compile the software, they just run the machine code the compiler produces. As for how far you can go, I believe some things are not included in the Arduino compiler (such as the operators new and delete, most of the STL etc), but this does not mean one could not write classes with similar functionalty. The biggest limitation for code as I see it, is the space and memory constrainst inherent to microchip programming.

I'm not that familliar with the Arduino compiler though, maybe someone else can be more exact.

Gido,

Fundamental types, like 'int' do not have constructors in C++.

I'm afraid that you are also mistaken about how casts work in C and C++.

If you cast a float to an int, for example:

int i;
float f;
f = 10.0;
i = (int)f;

then the bit representation of the float does NOT get transferred to the int. The whole (i.e., non-fractional) portion of the floating point number is converted to an integer and the results assigned to 'i'. In fact, as Paul S pointed out, assignment from a float to an integer has an implicit type conversion, so the cast serves only to document that the programmer intends for a conversion to take place, and to quiet compiler warnings about the possible loss of precision.

Whether or not to use casts in a case where there is implicit conversion is strictly a matter of programming style, since the generated code will be exactly the same in either case. Personally, I prefer the use of the casts so there is no question about my intent.

As to the notation:i = (int)f;versusi = int(f);they are semantically identical. The second form is called the "functional" form of a type cast. It is not invoking a constructor for a class, it is just doing a plain old C-style type cast. The functional form is just a little bit of "syntactical sugar" as K & R used to call it, added to the C++ language specification.

I hope this clears up some of the confusion.

Regards,

-Mike