Page 1 of 2
float acting like double
Posted: Mon Jan 12, 2026 11:31 pm
by jcbless
I've got this line in main.c:
If I set setVal right before using it, then the float seems to get interpreted correctly.
However, if I set setVal in another thread (with or without a mutex protecting it), then the float will get interpreted as a truncated double when processing it to get hexadecimal bytes out.
Do you have any ideas why we might be getting different behaviors when processing setVal from either location?
Thanks,
John
Re: float acting like double
Posted: Tue Jan 13, 2026 8:28 am
by Giovanni
A float is single precision, 4 bytes in size, manipulating it from another thread makes no difference.
Giovanni
Re: float acting like double
Posted: Wed Jan 14, 2026 9:14 am
by alex31
This is a strange, not standard behavior.
Do you manipulate the variable directly, or through cast to integral value ?
You can try to declare the variable volatile to force the compiler to access the value through it's memory location.
A.
Re: float acting like double
Posted: Wed Jan 14, 2026 3:58 pm
by jcbless
I agree that it is strange behavior. I've never seen anything like it before.
The variable is always assigned directly as a float. There is no casting going on.
That's a good point about volatiile. I'll give that a try.
Re: float acting like double
Posted: Wed Jan 14, 2026 4:20 pm
by jcbless
Now I'm even further confused. If I take the case where things seemed to be working (assigning setVal in the same thread as used) and I add the volatile keyword to the declaration of setVal - now the end result is no longer correct. I'm definitely frustrated by the behavior I'm seeing.
Thanks,
John
Re: float acting like double
Posted: Wed Jan 14, 2026 4:50 pm
by Giovanni
Device? is there a cache involved?
Giovanni
Re: float acting like double
Posted: Wed Jan 14, 2026 7:17 pm
by jcbless
It is a STM32H753. It does have cache, but I guess it only works with external RAM which I don't think we have.
Re: float acting like double
Posted: Wed Jan 14, 2026 7:43 pm
by Giovanni
It can cache also internal SRAMs so be careful if you access data with DMAs.
Giovanni
Re: float acting like double
Posted: Thu Jan 15, 2026 7:32 pm
by jcbless
After a recommendation from my manager, I am giving a couple paragraphs of a description to see if that helps describe the situation better:
We have four motors that we’re trying to control via UARTs. The main command we are sending to the motors is a rotational speed command which uses a single precision float. The command is made using functions from the API given by the motor company. Then the command is sent using serial write commands from ChibiOS (sdWrite).
Under certain circumstances when processing the single precision float, the data of the float seems to get converted or processed in some manner as a double precision float. To explain further, if I feed in a variable originally declared as static float setVal, and then send it via a UART, then the data sent on the UART matches the first four bytes of a double precision float for the setVal number. Also, if displaying the same data via a chprintf, the data shown also matches the first four bytes of a double precision float.
Re: float acting like double
Posted: Thu Jan 15, 2026 8:58 pm
by jcbless
Here's a simplified version of the code in main that relates to the problem:
Code: Select all
static float setVal;
// Definition of Thread1 thread
static THD_FUNCTION(Thread1, arg) {
while (true) {
chMtxLock(& mt);
//setVal = 250.0f;
vertiqVelocity(setVal, setVal, setVal, setVal);
chMtxUnlock(& mt);
chThdSleepMilliseconds(10);
}
}
int main(void) {
...
while (1) {
chMtxLock(&mt);
setVal = 250.0f;
chMtxUnlock(&mt);
chThdSleepMilliseconds(1000);
}
}
Then the code in a file called VertiqInterface:
Code: Select all
...
void vertiqVelocity(float v1, float v2, float v3, float v4){
vm1.vertiqSetMotorVelocity(v1);
vm2.vertiqSetMotorVelocity(v2);
vm3.vertiqSetMotorVelocity(v3);
vm4.vertiqSetMotorVelocity(v4);
}
And then code in vertiqMotors.cc:
Code: Select all
...
void vertiqMotor::vertiqSetMotorVelocity(float m) {
if (0 == m) {
// When m is 0, then set the velocity to MINSPEED
vertiqSetVelocity(MINSPEED);
} else {
// Otherwise, set the velocity proportionately between MINSPEED and
// MAXSPEED
//vertiqSetVelocity((float) (std::clamp(m, 0.0f, 1.0f) *
// (float) (MAXSPEED - MINSPEED) +
// (float) MINSPEED));
vertiqSetVelocity((float) m);
}
}
int8_t vertiqMotor::vertiqSetVelocity(float val) {
//uint32_t * val1 = (uint32_t *)((void *) (& setVal));
uint32_t val1;
memcpy(&val1, &val, 4);
chprintf(chpu, "Float into vSV: %x\r\n", val1);
prop.ctrl_velocity_.set(com, val);
//Interface with hardware:
return vertiqWrite();
}
int8_t vertiqMotor::vertiqWrite(void) {
uint8_t packet_buf[64]; // Buffer for packet
uint8_t length = 0; // Length of packet
// Get the packet from the com interface and place it into the packet buffer
if (com.GetTxBytes(packet_buf, length)) {
uint32_t * val1 = (uint32_t *)((void *) (packet_buf + length - 6));
//chprintf(chpu, "Float in write: %x\r\n", * val1);
sdWrite(chp, (const uint8_t *) packet_buf, length);
return 0;
} else {
return -1;
}
}
Both the output from chprintf and sdWrite will look like a partial double in this circumstance as written here. However if setVal gets written to the spot where it is commented out at the top of this code, then the output looks like a normal single precision float.