ChanServ changed the topic of #rust-embedded to: Welcome to the Rust Embedded IRC channel! Bridged to #rust-embedded:matrix.org and logged at https://libera.irclog.whitequark.org/rust-embedded, code of conduct at https://www.rust-lang.org/conduct.html
KurtisDinelle[m] has joined #rust-embedded
<KurtisDinelle[m]> Hi everyone, was curious if there's an "agreed" upon underlying data type by the community for representing samples returned from sensor drivers.
<KurtisDinelle[m]> A lot of existing Rust sensor drivers out there just seem to use f32 so it seems like that's considered okay, though for example Zephyr prefers to avoid using floats in its drivers to more aptly support devices with poor or non-existent floating-point hardware.
<KurtisDinelle[m]> Anyone have any insight on this? Should we consider some other data type that avoids floating-point while still maintaining some level of precision if we are releasing code to the community?
<Darius> surely it depends on the sensor
<KurtisDinelle[m]> Fair point, let me rephrase it. In published sensor drivers, should we avoid returning samples as floats (when it might make sense to do so for that specific sensor) to provide wider hardware support?
<KurtisDinelle[m]> * avoid returning/calculating samples
<ian_rees[m]> just a casual user/observer - I'd expect that a driver for a particular sensor would give me data in the same data type that the sensor provides it
ian_rees[m] has joined #rust-embedded
<ian_rees[m]> eg if you're writing a driver for a strain gauge IC, and that returns f32 arbitrary strain units, my code is responsible for handling calibration/scaling/etc to turn that in to lbf*hogshead/metres or whatever my application needs
<ian_rees[m]> * eg if you're writing a driver for a strain gauge IC that returns f32 arbitrary strain units, I'd expect to write for handling calibration/scaling/etc to turn that in to lbf*hogshead/metres or whatever my application needs
<Darius> KurtisDinelle[m]: I would be pretty astonished if a sensor returned floats TBH
<M9names[m]> it's not that uncommon
<Darius> ADC counts, sure..
<Darius> but anyway, I would return its native type
<M9names[m]> honestly, i would do both, at least when the units involved are known. no point in forcing the user to do the conversions
<M9names[m]> but leave the underlying data accessible if they want to do it themselves for whatever reason
<KurtisDinelle[m]> <Darius> "Kurtis Dinelle: I would be..." <- I was thinking more along the lines of a sensor that reads some raw value, and then provides a formula for converting it (usually given in the datasheet). For example, some temp sensors are like this and will provide a formula for converting the reading into degrees Celsius, which often results in a decimal number. So that's where the question of using floats comes in if we want to
<KurtisDinelle[m]> maintain precision.
<KurtisDinelle[m]> > <@libera_Darius:catircservices.org> Kurtis Dinelle: I would be pretty astonished if a sensor returned floats TBH
<KurtisDinelle[m]> The Zephyr answer to this is to do all math in a higher order of magnitude (typically 10^6) and then return a struct containing two values: the integer component and the fractional component as millionth parts. Though doing things this way just doesn't feel right for Rust drivers...
<KurtisDinelle[m]> * I was thinking more along the lines of a sensor that reads some raw value, and then provides a formula for converting it (usually given in the datasheet). For example, some temp sensors are like this and will provide a formula for converting the reading into degrees Celsius, which often results in a decimal number. So that's where the question of using floats comes in if we want to maintain precision.
<Darius> dunno, that feels like a project policy not a driver one
whitequark[cis] has joined #rust-embedded
<whitequark[cis]> Darius: there are definitely sensors that return floats
<Darius> TIL
<Darius> I guess, say, GPS does
<Darius> but I guess if you are using a sensor that returns floats in a project you will hopefully also use a micro that can handle them without too much pain..
<whitequark[cis]> I can't imagine what GPS would use floats for
<Darius> lat/long
<Darius> also velocity
<whitequark[cis]> those are all decimal ASCII in NMEA
<whitequark[cis]> the dynamic range is fixed so there's no point in using floats
<whitequark[cis]> though the sensor I'm thinking of also didn't really have a good reason to use floats, I think they just did some conversion on the onboard STM32 and returned the bytes as-is
<whitequark[cis]> it was something silly like a temperature value
<Darius> I guess it depends on your definition, I was thinking they are not integers, you could make any sensor return an ASCII string rep of a float
<Darius> ahh
<whitequark[cis]> oh, I make a distinction between floating point and fixed point
<Darius> ublox's binary uses 1e-7 of degrees as a signed 4 byte int
<whitequark[cis]> if you have a fixed point value like lat/lon you can return them as a number of millionths of degree or something
<Darius> right it is fixed
<Darius> yeah
<whitequark[cis]> meanwhile a float would have an exponent
<Darius> curious their receiver docs do mention floating point and say they are IEEE754
<Darius> but it never actually defines a field to use them
<whitequark[cis]> maybe they did in the past or something
<Darius> yeah could be
<ian_rees[m]> Kurtis Dinelle: if you provide methods that do conversion to float and the user doesn't want them, the unused methods will usually (always?) be optimised out so there's no penalty to the user
<whitequark[cis]> I can't think of many reasons for a sensor to return floating point values because the dynamic range is just not there for most things you can measure
<whitequark[cis]> even when the base quantity varies that much you can rarely measure it with the same precision at the high and low end
<whitequark[cis]> so I would expect any IEEE floats returned by a sensor to be there for convenience
<whitequark[cis]> (there are definitely non-IEEE bespoke floating point formats with a small exponent used too, but those are usually used for some other reason and are best handled by converting into an integer)
<Darius> convenience conversion methods sound like a good solution
<Darius> so long as they don't pull in float cruft when you don't use them :)
<whitequark[cis]> I think you might need LTO to avoid them, but I'm not sure
<whitequark[cis]> nevermind, I checked and rustc compiles with the equivalent of -ffunction-sections
<KurtisDinelle[m]> I appreciate the input everyone, you've given me a few things to think about which I hadn't considered. Thank you!
GeorgesP[m] has joined #rust-embedded
<GeorgesP[m]> Hi all, I am writing a protocol driver that use a embedded_io_async::Read+Write traits to do io communication. It is all fine, but I have great difficulty using the ErrorType/Error to translate embedded_io errors into my own Error enum. Can someone point me at an example? Or briefly explain what I should do ?
<GeorgesP[m]> Of course I am in no_std no_alloc (with heapless if needed) ;)
cinemaSundays has joined #rust-embedded
cinemaSundays has quit []
mobergmann[m] has quit [Quit: Idle timeout reached: 172800s]
crabbedhaloablut has quit []
crabbedhaloablut has joined #rust-embedded
Foxyloxy has quit [Quit: Textual IRC Client: www.textualapp.com]
Foxyloxy has joined #rust-embedded
PedroFerreira[m] has quit [Quit: Idle timeout reached: 172800s]
jakzale has quit [Read error: Connection reset by peer]
jakzale has joined #rust-embedded
Darius has quit [Quit: Bye]
ni has quit [Quit: WeeChat 3.8]
Darius has joined #rust-embedded
ni has joined #rust-embedded
ni has quit [Client Quit]
ni has joined #rust-embedded
ni has quit [Quit: WeeChat 3.8]
ni has joined #rust-embedded
Darius has quit [Quit: Bye]
Darius has joined #rust-embedded
<diondokter[m]> For people using my `device-driver` crate: I'm thinking about refactoring and formalizing the crate. If you have feedback that'd be welcome!
<dirbaio[m]> +1 to json/yaml
<dirbaio[m]> and another few with a modified chiptool to generate code accessing i2c/spi regs
<dirbaio[m]> I have a few drivers written with the device-driver using the macro DSL (v0.4, old, yup)
<dirbaio[m]> * i2c/spi regs, from a yaml file
<dirbaio[m]> and my takeaway was json/yaml makes it much easier to write crappy python with regex crimes to extract regs from C headers and then spit out yaml
TomB[m] has joined #rust-embedded
<TomB[m]> <diondokter[m]> "For people using my `device-..." <- > <@diondokter:matrix.org> For people using my `device-driver` crate: I'm thinking about refactoring and formalizing the crate. If you have feedback that'd be welcome!
<TomB[m]> is this based on the chiptool stuff, I noticed there was a PR adding support for something similar to chiptool
<TomB[m]> * is this based on the chiptool stuff, I noticed there was a PR adding support for something similar to chiptool which was intriguing
<dirbaio[m]> vs if it has to spit out a custom DSL, it's much more work, you have to do all the string formatting yourself
<dirbaio[m]> TomB[m]: device-driver is not based on chiptool, but it's a different attempt at solving kinda the same problem
<TomB[m]> I guess my question here would be whats the difference in regmaps in chiptool vs device-driver, device-driver is just another mapping no?
<TomB[m]> like why not extend chiptool for this sort of thing where there's already lots of nice transforms people have written on the representation, imxrt-ral added quite a few customized transforms and sadly hasn't upstreamed them
<TomB[m]> descriptors in, various transforms, output generation
<TomB[m]> seems like a common issue?
<dirbaio[m]> differences are:
<dirbaio[m]> chiptool: yaml, you use it via a cli tool, accesses regs via memory mapping only (except that PR which adds a trait)
<dirbaio[m]> device-driver: custom syntax, you use it via a macro, accesses regs via a trait you have to impl
<dirbaio[m]> but yeah there's a lot of overlap
<dirbaio[m]> also with svd2rust
<diondokter[m]> <dirbaio[m]> "+1 to json/yaml" <- Already exists in newer versions :)
<dirbaio[m]> ooh 👀
<dirbaio[m]> (I haven't been following latest developments, sorry 🙈)
<dirbaio[m]> haha that looks quite similar to chiptool's :D
<diondokter[m]> There's also support for buffers and commands
<dirbaio[m]> neat
<diondokter[m]> Though someone today found a chip that needs way more command features
<dirbaio[m]> ah, the curse of trying to support everything
<diondokter[m]> Haha yup
<diondokter[m]> It needs commands with parameters that also returns a value
<diondokter[m]> It's a lot like a register, except it isn't :P
ello_ has joined #rust-embedded
ello has quit [Ping timeout: 248 seconds]
<TomB[m]> some devices don't let you read back the register despite it having state which is fun
<TomB[m]> wm8960 (as done with the chiptool PR) was one, there's some other fun ones out there as well...
JamesSizeland[m] has quit [Quit: Idle timeout reached: 172800s]
LucasChiesa[m] has quit [Quit: Idle timeout reached: 172800s]
<thejpster[m]> tlv320aic23 codec is also write only. PITA.
rmsyn[m] has quit [Quit: Idle timeout reached: 172800s]
BogdanOlar[m] has quit [Quit: Idle timeout reached: 172800s]
Diaeresis[m] has quit [Quit: Idle timeout reached: 172800s]
jannic[m] has quit [Quit: Idle timeout reached: 172800s]
adamhott[m] has quit [Quit: Idle timeout reached: 172800s]
adamgreig[m] has quit [Quit: Idle timeout reached: 172800s]
therealprof[m] has quit [Quit: Idle timeout reached: 172800s]
xnor has quit [Ping timeout: 252 seconds]
xnor has joined #rust-embedded
firefrommoonligh has joined #rust-embedded
<firefrommoonligh> <KurtisDinelle[m]> "Fair point, let me rephrase it..." <- No; simply put, it depends entirely on the sensor data and intended targets. I have and will use i8, u8, i16, u32, f32 depending on the sensor and project requirements.
<firefrommoonligh> * project requirements, as Darius said.
<firefrommoonligh> * project requirements, as Darius said., * . You will also note that IC register APIs will use all of these values and more as well, including sometimes types that Rust doesn't have (ix etc); I avoid those for convenience.
<firefrommoonligh> <Darius> "lat/long" <- Nah. I mean, f64 is fine for lat-lon (but overkill, and support on embedded for hardware f64 varies), but f32 is generally not. This is actually a great example of when *not* to use floating point, as its precision characteristics don't work well. Generally, GPS ICs (think Ublox) will use i32 of the coord in degrees x 10^7. I've also seen x 10^8 used.
<firefrommoonligh> s/Nah/Great example/, s/I mean,//, s/*not*/_not_/
<firefrommoonligh> GPS velocity is fine as f32. I can't remember if the chips generally use that or integer.
<firefrommoonligh> Also relevant to a point you brought up: I will usually convert that to a float of m/s in firmware since it's more convenient. But will not convert the lat/lon to float because the precision there is relevant.
<firefrommoonligh> *Velocity is an i32 in mm/s:
danielb[m] has quit [Quit: Idle timeout reached: 172800s]
ejpcmac[m] has quit [Quit: Idle timeout reached: 172800s]
Foxyloxy_ has joined #rust-embedded
Foxyloxy has quit [Ping timeout: 264 seconds]
<thejpster[m]> I one had a sensor give me f16. Yup.
vancz has quit []
<firefrommoonligh> Yea... f16 is not cool. It's awkward to convert to a native rust type, and the precision is too low for many use cases.
<diondokter[m]> firefrommoonligh: Isn't f16 available on nightly? So maybe in the future it'll work nicely
<firefrommoonligh> That would be nice; I've run into it once or twice
<firefrommoonligh> Also: https://docs.rs/half/latest/half/
GrantM11235[m] has joined #rust-embedded
<GrantM11235[m]> yeah, this is the tracking issue https://github.com/rust-lang/rust/issues/116909
<Vicente[m]> Anyone knows why using smol::unblock does not liberate captured values after executing the passed closure? I understand it is executed on another thread, but unblock is async, so after awaiting it should be fine to reuse my value (not clonable)
<JamesMunns[m]> the closure it takes requires the values to be 'static, which can't be borrowed values
<JamesMunns[m]> I don't know if smol has something like scoped threads.
<Vicente[m]> Ok, I was using it to block on tcp read inside a loop, and as I could clone the tcp stream it worked fine. Now, with TLS (ServerConnection) I can't cause it's not clonable
<Vicente[m]> Any one can think of a patch here?
<Vicente[m]> Well, maybe return back the tls value...
<dirbaio[m]> Maybe it'll be easier to use a tls lib that can actually do async