Xiaomi mi scale v1 Weight Data - bluetooth-lowenergy

I am trying to writing an application that can take weight measurement from Xiaomi mi scale version 1. I get a hex value like this 0624b2070101002e3800004c04(5.50kg) from the Body Composition Measurement service.
According to my research the first byte gives
02:measurement unit
The last two bytes are the weight value,
But when I convert this value to decimal and divide by 200, I don't get the correct value.
Can someone help me get the correct data?

The last two bytes are 4c04. Bluetooth sends data in little endian format so as an integer that is 1100.
The "GATT Specification Supplement 4" document at https://www.bluetooth.com/specifications/specs/ says:
3.27.2.7 Weight field
This field is in kilograms with resolution 0.005 if the bit 0 of the Flag field is 0 or in pounds with a resolution of
0.01 if the bit 0 of the Flag field is 1.
1100 * 0.005 = 5.5kg

The value of hex 4c04 is equal to 19460 which does not give you the desired result.
But changing the endianess (byte-order) to 044c results in a value of 1100 which, divided by 200, gives you the desired result of 5.5kg

I had a similar problem, here is how i do it personally read the whole thing i had everything documented and don't be intimidated by the looks of it it's pretty simple in fact:
for the conversion i use this website cause well I don't know how to convert :)
enter link description here
here is an image showing exactly how it works u need to look to the INT 16 BIG endian and post the whole hex code not just the last two bytes like this:

Related

How are the Bits arranged in a QRcode?

I've wondered how QR codes are working, so i did a research and tried to paint my own in an table in word.
On Wikipedia I found this picture
I understand the configuration, but how you actually store a letter doesnt make sense to me.
With the example letter w.
On even rows black is 0 and on odd rows 1.
So the example should give this binary number 01110011 which would be 115 but w is number 32.
So how do I get the right number
I dont know much about this topic but I found you a video where dude explains it. And from what I understood, there are those cells that are read in order of numbers depending on arrow (there are 4 options here and you posted those yourself). So you simply follow those numbers and write 1s and 0s on paper which results in 8bit number. That video has much more detail.
It is also worth pointing out that it is MSB, meaning if we follow your example (you just considering numbers, not colors since you mislabeled it), it has arrow pointing up, meaning you write right/down to up/left which leads to number : 01110011 which has most significant bit at the left which means its 115

Lookup table for load cell calibration doesn't like negative numbers

I have a load cell connected to an HX711 which all works fine. I am attempting to create a calibration table with 10 points holding the raw sensor output and the calibrated value using a set of weights. The load cell is bi-directional so it works in any direction so the output is positive and negative counts but the zero is not necessarily 0 output.
This all works fine when the numbers are all positive or all negative in each lookup table but fails when there is negative & positive numbers in the captured points. Eg, the output from the HX711 is positive 28,000 with no load. Add a load of 1kg and get a reading of -56,000. The next reading for 1Kg is say, -83,000. These are stored as {28,000, -56000, 83,000} in an array with the the calibrated {0, 1, 2} in another array.
Normally I interpolate the result based on finding which 2 numbers the raw count falls between. Everything works when the numbers are less than -56,000 and I get readings of 1 to 2kg. When the reading is greater than -56,000, it fails to calculate the reading and I end up with NAN.
It can also be the other way around with negative and then positive. (-56,000, 28,000, 55,000} for example.
How to handle this situation?
I worked this out not long after I posted the question and thought that the answer would help anyone else with this same issue. By comparing the 2 values for negative or positive as I stepped through the table and then swapping them around in the calculation, it works. The difference between 28,000 and -56,000 comes out as 84,000 and using this to do the maths works. I confirmed operation by applying 1kg and 2kd test loads. It reads in both directions pos or neg.

rewrite line in SdFat for arduino

My problem is that I am trying to make Controller using Arduino, ESP8266 SDcard module and some sensors. When I try to store some data in SDcard, at first time all works fine, but in second or third time I need to rewrite same line with different values. But there is an issue because line length is not equal with previous.
If it is longer then nothing wrong, but if shorter, then it will leave some unnecessary characters.
The most difficult part is where I need to store value of LED light and time:
255 10 0 Where 255 represents LED-value, 10-Hour, 0-min
Value can be 1 or 3 character long, hour 1 or 2, min 1 or 2...
So is there any solutions for this problem??
Now I am trying to change int to uint8_t to equal all possible values.
Is this approach Right? Maybe someone has made something like that?
Any suggestions will be appreciated.
You can normalize the data as you suggest so that the line length is always the same.
One approach is that all values are uint8_t which would require 3 uint8_t values.
Another is leave it as a string but each field is a fixed width with padded values. e.g. 0050901 for a value 5 at the 9th hour, 1st minute. Or pad with spaces so 5 9 1 for the same representation of this data. (Two spaces before the 5 and one space before the 9 and the 1).
Either approach is fine and just depends on what you prefer or what is easier when consuming and/or writing the data.

is it a bug scaling 0.0-1.0 float to byte by multiplying by 255?

this is something that has always bugged me when I look at code around the web and in so much of the literature: why do we multiply by 255 and not 256?
sometimes you'll see something like this:
float input = some_function(); // returns 0.0 to 1.0
byte output = input * 255.0;
(i'm assuming that there's an implicit floor going on during the type conversion).
am i not correct in thinking that this is clearly wrong?
consider this:
what range of input gives an output of 0 ? (0 -> 1/255], right?
what range of input gives an output of 1 ? (1/255 -> 2/255], great!
what range of input gives an output of 255 ? only 1.0 does. any significantly smaller value of input will return a lower output.
this means that input is not evently mapped onto the output range.
ok. so you might think: ok use a better rounding function:
byte output = round(input * 255.0);
where round() is the usual mathematical rounding to zero decimal places. but this is still wrong. ask the same questions:
what range of input gives an output of 0 ? (0 -> 0.5/255]
what range of input gives an output of 1 ? (0.5/255 -> 1.5/255], twice as much as for 0 !
what range of input gives an output of 255 ? (254.5/255 -> 1.0), again half as much as for 1
so in this case the input range isn't evenly mapped either!
IMHO. the right way to do this mapping is this:
byte output = min(255, input * 256.0);
again:
what range of input gives an output of 0 ? (0 -> 1/256]
what range of input gives an output of 1 ? (1/256 -> 2/256]
what range of input gives an output of 255 ? (255/256 -> 1.0)
all those ranges are the same size and constitute 1/256th of the input.
i guess my question is this: am i right in considering this a bug, and if so, why is this so prevalent in code?
edit: it looks like i need to clarify. i'm not talking about random numbers here or probability. and i'm not talking about colors or hardware at all. i'm talking about converting a float in the range [0,1] evenly to a byte [0,255] so each range in the input that corresponds to each value in the output is the same size.
You are right. Assuming that valueBetween0and1 can take values 0.0 and 1.0, the "correct" way to do it is something like
byteValue = (byte)(min(255, valueBetween0and1 * 256))
Having said that, one could also argue that the desired quality of the software can vary: does it really matter whether you get 16777216 or 16581375 colors in some throw-away plot?
It is one of those "trivial" tasks which is very easy to get wrong by +1/-1. Is it worth it to spend 5 minutes trying to get the 255-th pixel intensity, or can you apply your precious attention elsewhere? It depends on the situation: (byte)(valueBetween0and1 * 255) is a pragmatic solution which is simple, cheap, close enough to the truth, and also immediately, obviously "harmless" in the sense that it definitely won't produce 256 as output. It's not a good solution if you are working on some image manipulation tool like Photoshop or if you are working on some rendering pipeline for a computer game. But it is perfectly acceptable in almost all other contexts. So, whether it is a "bug" or merely a minor improvement proposal depends on the context.
Here is a variant of your problem, which involves random number generators:
Generate random numbers in specified range - various cases (int, float, inclusive, exclusive)
Notice that e.g. Math.random() in Java or Random.NextDouble in C# return values greater or equal to 0, but strictly smaller than 1.0.
You want the case "Integer-B: [min, max)" (inclusive-exclusive) with min = 0 and max = 256.
If you follow the "recipe" Int-B exactly, you obtain the code:
0 + floor(random() * (256 - 0))
If you remove all the zeros, you are left with just
floor(random() * 256)
and you don't need to & with 0xFF, because you never get 256 (as long as your random number generator guarantees to never return 1).
I think your question is misled. It looks like you start assuming that there is some "fairness rule" that enforces the "right way" of translation. Unfortunately in practice this is not the case. If you want just generate a random color, then you may use whatever logic fits you. But if you do actual image processing, there is no rule that says the each integer value has to be mapped on the same interval on the float value. On the contrary what you really want is a mapping between two inclusive intervals [0;1] and [0;255]. And often you don't know how many real discretization steps there will be in the [0;1] range down the line when the color is actually shown. (On modern monitors there are probable all 256 different levels for each color but on other output devices there might be significantly less choices and the total number might be not a power of 2). And the real mapping rule is that if for two colors red component values are R1 and R2 then proportion of the actual colors' red component brightness should be as close to R1:R2 as possible. And this rule automatically implies multiply by 255 when you want to map onto [0;255] and thus this is what everybody does.
Note that what you suggest is most probably introducing a bug rather than fixing a bug. For example the proportion rules actually means that you can calculate a mix of two colors R1 and R2 with mixing coefficients k1 and k2 as
Rmix = (k1*R1 + k2*R2)/(k1+k2)
Now let's try to calculate 3:1 mix of 100% Red with 100% Black (i.e. 0% Red) two ways:
using [0-255] integers Rmix = (255*3+1*0)/(3+1) = 191.25 ≈ 191
using [0;1] floating range and then converting it to [0-255] Rmix_float = (1.0*3 + 1*0.0)/(3+1) = 0.75 so Rmix_converted_256 = 256*0.75 = 192.
It means your "multiply by 256" logic has actually introduced inconsistency of different results depending on which scale you use for image processing. Obviously if you used "multiply by 255" logic as everyone else does, you'd get a consistent answer Rmix_converted_255 = 255*0.75 = 191.25 ≈ 191.

Understanding the BPP inside DICOM images

I'm working with DICOM files since a few days, using FO-DICOM.
I'm using a set of dicom files for my tests, and I've been printing the "Photometric Interpretation" and the "Sample Per Pixel" values, to have a better understanding of what kind of images I'm working with.
The result was "MONOCHROME2" for the Photometric Interpretation, and "1" for the Sample Per Pixel.
What I understood by reading the part3 of the standard is that MONOCHROME2 represent a gray scale, starting from black for its minimum values.
But what is the Sample Per Pixel exactly? I thought this was representing the number of bytes (and not bits) per pixel (that would be logic to have 8 bits per pixel for a scale of gray right?)
But my problem here is that actually, my images seem to have 32 bpp.
I'm working with 512*512 pixels images, and I converted them into byte arrays. So I was expecting arrays of 512*512=262144 bytes.
But I get arrays of 1048630 bytes (which is a bit more than 4*262144)
Does someone have an explanation?
EDIT:
Here's are some of my datas :
PhotometricInterpretation=MONOCHROME2
SamplePerPixel=1
BitsAllocated=16
BitsStored=12
HighBit=11
PixelRepresentation=0
NumberOfFrames=0
The attribute (0028,0002) SamplesPerPixel refers to color images only and tells you the number of planes which are present in the image (e.g. 3 for RGB), so you have
PhotometricInterpretation=RGB
SamplesPerPixel=3
With 8 bits per pixel (I will revisit BPP below). As long as you have PhotometricInterpretation = MONOCHROME1 or MONOCHROME2, you can expect the SamplesPerPixel to be 1 and nothing else.
What you do have to take into consideration is the number of bits per pixel:
BitsAllocated (0028,0100)
BitsStored (0028,0101)
HighBit (0028,0102)
These tell you how many bits are used to encode a pixel value (BitsAllocated) and which of these bits really contain grayscale information (BitsStored, HighBit). HighBit is zero-based and usually but not necessarily = BitsStored-1
An example to illustrate this: For CT images, it is very common to express gray values in hounsfield units which range from -1000 to +3000. These are represented by 12 bits which are stored with a 2-byte-alignment, so
BitsAllocated (0028,0100) = 16
BitsStored (0028,0101) = 12
HighBit (0028,0102) = 11
Another degree of freedom is PixelRepresentation which tells you if the pixel data is encoded unsigned (0) or in 2s complement (1). I have seen both for CT images, however signed pixel data is rather unusual for image types other than CT.
In your example, I would assume that Bits Allocated == 32 or (not very likely) that you have a dataset containing multiple images ('frames'), so NumberOfFrames (0028,0008) > 1. If Number of Frames is absent, you can safely assume to have only one frame.
I have over-simplified a bit here, especially about color images but I think this is complicated enough ;-). Basically, DICOM offers any thinkable degree of freedom to encode pixel data and describe the encoding in the header.
I think I have recommended you to have a look at the DCMTK in a recent post. The DicomImage class features a nice interface (getInterData()) which cares about all that stuff and provides the pixel data read from a DICOM file in a normalized format.
[EDIT]: Feel free to post a DICOM dump of your dataset here, I would have a look at it and tell you how to interpret the pixel data.

Resources