I would like to convert float values to IEEE754 Single precision 32-bit Hex values in the following site on Arduino.
https://www.binaryconvert.com/result_float.html?decimal=051046049048
float f = 3.10;
byte hex[4] = {0};
byte FloatToHex(float f){
.......
}
How can I create a function like this?
It's okay if the format is different.
f is already stored in binary. reinterpret_cast is generally a code smell issue, but its valid use is to view the byte representation of variables.
void FloatToHex(float f, byte* hex){
byte* f_byte = reinterpret_cast<byte*>(&f);
memcpy(hex, f_byte, 4);
}
void setup() {
float f = 3.10;
byte hex[4] = {0};
FloatToHex(f, hex);
//... do stuff with hex now...
}
void loop() {
}
Related
So in my arduino programm I am working with char arrays in a function. I try to save them globally, but no matter how I do it, the global arrays contain only part of the original array and a ton of gibberish symbols.
char* naam;
char* compliment;
byte color = 0;
void setup() {
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
doStuff();
Serial.println(naam);
Serial.println(compliment);
Serial.println(color);
}
void loop() {
// put your main code here, to run repeatedly:
}
void doStuff(){
String raw = "1234567890123456,abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz,0";
int i = raw.indexOf(",");
int j = raw.indexOf(",", i+1);
char a[i+1];
char b[j-i];
raw.substring(0,i).toCharArray(naam, i+1);
raw.substring(i+1,j).toCharArray(compliment, j);
color = (byte) raw.substring(j+2,j+3).toInt();
Serial.println(a);
Serial.println(b);
naam = a;
compliment = b;
}
Can anyone explain to me why this does not work and point me in the right direction?
Here you create two char arrays a and b
char a[i+1];
char b[j-i];
You never assign any values to its elements befor you print them.
Hence you'll print whatever garbage is in those memory locations
Response to comment:
They are filled by the "toCharArray(compliment, j);". The println(a)
prints correctly
When you first call doStuff
You create two uninitialized char arrays a and b.
Then you store two substrings as char array to naam and compliment. Both uninitialized char pointers. So you're basically storing stuff in a random position in memory.
Then you print a and b which contain random garbage.
Then you store the addresses in a and b to naam and compliment.
Once doStuff returns a and b are out of scope. naam and compliment still point at their position but that memory is free to be used by something else.
Appreciate your time.
I am trying to convert "String" read from serial port in serialEvent() of Arduino IDE to integer values with exact representation.
For eg, if String myString = 200 then int myInt should be 200.
I have been somewhat successful but unable to convert String to exact int representation beyond 255.
Solutions I have tried:
1) used .toInt() function in Arduino.
2) used "atoi" and "atol" functions.
3) Serial.parseInt() in loop().
All of these methods start recounting from 0 after every 255 values.
I can't use parseInt since it only works inside loop(). My application requires to store variable value permanently until another value is given through port. For this Arduino Due's flash memory has been used.
The memory storing code seems to work only inside serialEvent().
Code snippet is as below:
#include <stdlib.h>
#include <DueFlashStorage.h>
DueFlashStorage memory;
String x = " ";
int x_size;
int threshold;
void setup(){
Serial.begin(115200);
}
void loop{
Serial.println(memory.read(0));
}
void serialEvent(){
while(Serial.available()){
x = Serial.readStringUntil('\n');
x_size = x.length();
char a[x_size+1];
x.toCharArray(a, x_size+1);
threshold = atoi(a);
memory.write(0, threshold);
}
}
1) Function .toInt() returns LONG and you want INT (I don't know why honestly but it is in documentation)... you need to cast it like this (tried on Arduino ATMEGA and it worked):
#include <stdlib.h>
String x = "1000";
int x_ = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
x_ = (int) x.toInt();
Serial.println(x_);
delay(1000);
}
2) I’m not professional ... but serilEvent() is really old way of doing things and it isn't recommended to use it. You can do it "manually" in the loop() function.
You're only converting 1 character a time, that's why the limit is 255.
If you're not doing anything else, you could stay in a serial.read-loop until all characters are read. For example:
void loop() {
if(Serial.available()) {
byte count = 0;
char number[10]; // determine max size of array
bool wait = true;
while(wait) { // stay in this loop until newline is read
if(Serial.available()) {
number[count] = Serial.read();
if (number[count] == '\n') {
wait = false; // exit while loop
}
count++;
}
}
int threshold = atoi(number);
memory.write(0, threshold);
}
}
For the lack of a good function in Arduino IDE for char/String type to int type conversion (has a limit of 255), I wrote my own conversion code which seems to work perfectly.
int finalcount=0;
void setup(){
Serial.begin(115200);
}
void loop(){
if(Serial.available()) {
int count = 0;
char number[5]; // determine max size of array as 5
bool wait = true;
while(wait) { // stay in this loop until newline is read
if(Serial.available()) {
number[count] = Serial.read();
if (number[count] == '\n') {
finalcount = count; //max array size for integer; could be less than 5
wait = false; // exit while loop
}
count++;
}
}
int val[finalcount]; //array size determined for integer
int placeValue;
int finalval[finalcount];
int temp=0;
int threshold;
for(int i = 0; i<finalcount; i++){
val[i] = (int)number[i]-48; //convert each char to integer separately
placeValue = pow(10,(finalcount-1)-i); //calculate place value with a base of 10
finalval[i] = val[i]*placeValue; //update integers with their place value
temp += finalval[i] ; //add all integers
threshold = temp; //resulting number stored as threshold
}
Serial.println(threshold); //prints beyond 255 successfully !
}
}
I solved the problem using highByte and lowByte functions of Arduino. Works flawlessly.
#include <DueFlashStorage.h>
DueFlashStorage m;
byte a1,a2;
int val;
void setup() {
Serial.begin(115200); //start the serial communication
}
void loop()
{
if (Serial.available()>0)
{
val = Serial.parseInt(); //read the integer value from series
if(val>0){
a1 = highByte(val); //get the higher order or leftmost byte
a2 = lowByte(val); //get the lower order or rightmost byte
m.write(0,a1); //save in arduino due flash memory address 0
m.write(1,a2); //save in arduino due flash memory address 1
}
int myInteger;
myInteger = (m.read(0)*256)+m.read(1); //convert into the true integer value
Serial.println(myInteger);
}
On my NodeMCU V3 I get a string, convert it to two longs, one int and two bytes, save them in a union and send the whole union to an Arduino Mega, which is supposed to read it in an equal union.
When the NodeMCU prints the bytes to the serial monitor of my laptop it shows their exact value, but after sending them I just get two 0s. Still I think it has something to do with the conversion of the bytes but can't figure out what.
I tried:
Using atol instead of strtol for converting the string, but discarded that
after reading about the
disadvantages. atol() v/s. strtol()
It didn't work anyway.
I tried to convert the bytes with lowByte((int) int1).
Here is the relevant part of my code. I made up a string, instead of receiving one for test purposes.
#include <ESP8266WiFi.h>
union Serial { //Union to place the numbers in.
byte by[12];
struct {
long vsollneu;
long ssollneu;
int phisollneu;
byte priosollneu;
byte typsollneu;
} Befehlssammlung;
} Befehle;
long a1,pr1,ty1;
char str[]="2049714 -1927461000 17 80 4"; //String to be seperated
void convert(char*);
void setup(){
Serial.begin(9600);
}
void loop(){
convert(str);
//Serial.write(Befehle.by,12); //Send the Bytes of the Union to the Arduino MEGA
delay(5555);
}
void convert(char* str){ //Converting the String with strtol
char* ende;
Befehle.Befehlssammlung.vsollneu =strtol(str,&ende,10);
Befehle.Befehlssammlung.ssollneu =strtol(ende,&ende,10);
a1 = strtol(ende,&ende,10);
pr1= strtol(ende,&ende,10);
ty1= strtol(ende,NULL,10);
Befehle.Befehlssammlung.phisollneu=(int) a1; //Converting the long to an int
Befehle.Befehlssammlung.priosollneu=(byte) pr1; //Probably that's somehow wrong???
Befehle.Befehlssammlung.typsollneu=(byte) ty1;
// Serial.println(Befehle.Befehlssammlung.vsollneu);
// Serial.println(Befehle.Befehlssammlung.ssollneu);
// Serial.println(Befehle.Befehlssammlung.phisollneu);
// Serial.println(Befehle.Befehlssammlung.priosollneu);
// Serial.println(Befehle.Befehlssammlung.typsollneu);
}
Here is the receiving part of the Arduino Mega:
union IZweiCkontainer {
byte by[12];
struct {
long vsollneu;
long ssollneu ;
int phisollneu;
byte priosollneu;
byte typsollneu;
} Befehlssammlung;
} Befehle;
void setup(){
Serial.begin(115200); //Serial for debugging
Serial3.begin(9600); //Serial for conncetion the the Mcu
}
void loop(){
if(Serial3.available()>0){
while(Serial3.available()){
Serial3.readBytes(Befehle.by,12); //receiving the Bytes and writing them in the "same" union
}
}
Serial.println(Befehle.Befehlssammlung.vsollneu);
Serial.println(Befehle.Befehlssammlung.ssollneu);
Serial.println(Befehle.Befehlssammlung.phisollneu);
Serial.println(Befehle.Befehlssammlung.priosollneu);
Serial.println(Befehle.Befehlssammlung.typsollneu);
}
What bucks me is that everything is fine on the NodeMCU but after sending I get the following output from the Arduino Mega:
2049714
-1927461000
17
0
0
ints and longs on an Arduino and ESP8266 are not the same size.
Use int16_t and int32_t to make sure they are the same size across different architectures.
union {
byte by[12];
struct {
int32_t vsollneu;
int32_t ssollneu;
int16_t phisollneu;
byte priosollneu;
byte typsollneu;
} Befehlssammlung;
} Befehle;
int i;
float number=123.456;
void setup()
{
Serial.begin(9600);
}
void loop()
{
byte a;
a=lowByte(number);
//is this the way i extract the right most byte from a 4 bytes float? equating a byte named a with the function lowByte? Is this how i use the lowByte function? cos i couldnt compile this in my arduino IDE.
delay(1000);
}
/*
what i am trying to do is to transmit float 123.456 over zigbee. and i believe data transmission is done byte by byte. so what i am trying to do is to break this float up into 4 bytes and send them byte by byte. how i do it is i intend to use lowbyte. then i just bitshfit by 8 bits (equivalent to 1 byte) to the right. then i use lowByte again. then again bitshift by 8 and lowByte and the repeat the process until i capture all 4 bytes.
so what i want to find out is how do i break the float into 4 bytes? and store these values for them to be sent?
can it be done in a byte array?
*/
I wanted to to the exact same thing and i found the below would work.
One approach is to use a union that stores the float value along with a unsigned char array. For example:
union v {
float f;
unsigned char uc[4];
};
union v val;
float f;
extern void store_byte (unsigned char v);
void test (void) {
val.f = 34.567; // set floating point value
store_byte (val.uc[0]); // write access to the bytes of the float value
store_byte (val.uc[1]);
store_byte (val.uc[2]);
store_byte (val.uc[3]);
val.uc[0] = 0x3F; // set float value (1.1)
val.uc[1] = 0x8C;
val.uc[2] = 0xCC;
val.uc[3] = 0xCD;
f = val.f; // read the value as FLOAT type.
}
I want my Arduino to receive an integer through the serial communication. Can you help me with this?
It should be in a form like:
int value = strtoint(Serial.read());
There are several ways to read an integer from Serial, largely depending on how the data is encoded when it is sent. Serial.read() can only be used to read individual bytes so the data that is sent needs to be reconstructed from these bytes.
The following code may work for you. It assumes that serial connection has been configured to 9600 baud, that data is being sent as ASCII text and that each integer is delimited by a newline character (\n):
// 12 is the maximum length of a decimal representation of a 32-bit integer,
// including space for a leading minus sign and terminating null byte
byte intBuffer[12];
String intData = "";
int delimiter = (int) '\n';
void setup() {
Serial.begin(9600);
}
void loop() {
while (Serial.available()) {
int ch = Serial.read();
if (ch == -1) {
// Handle error
}
else if (ch == delimiter) {
break;
}
else {
intData += (char) ch;
}
}
// Copy read data into a char array for use by atoi
// Include room for the null terminator
int intLength = intData.length() + 1;
intData.toCharArray(intBuffer, intLength);
// Reinitialize intData for use next time around the loop
intData = "";
// Convert ASCII-encoded integer to an int
int i = atoi(intBuffer);
}
You may use the Serial.parseInt() function, see here: http://arduino.cc/en/Reference/ParseInt