Nikolay, Please take care with RAM usage. It is very very tight on these little microcontrollers. I think the simplest way for yours is something like this: (((unsigned long)(can_databuffer[4)<<16) + ((unsigned long)(can_databuffer[5)<<8) + ((unsigned long)(can_databuffer[6)) + 5000UL) / 10000UL Not sure why you are getting a rounding error. Are you sure that the SOC hasn’t dropped between logging the data and plugging in OVMS? Here is what I get: $ echo 'ibase=16; scale=2; 07DCC0/02710' | bc 51.52 Regards, Mark.
On 25 Jun, 2015, at 7:35 am, Nikolay Shishkov <nshishkov@yahoo.com> wrote:
Thanks again... I seem to not been able to grasp the idea and would appreciate a code example. For example byte1=0x07, byte2=0xDC, byte3=0xC0 If I put these in excel and calculate 7*256*256 + 220*256 + 192 I get 520264. Then when I divide this by 10000, I get 52.0264. And this matches the 52% shown by the car.
Currently my code for this conversion is: sv1 = (unsigned long)can_databuffer[4]; sv1 = sv1*65536UL; sv2 = (unsigned long)can_databuffer[5]; sv2 = sv2*256UL; sv3 = (unsigned long)can_databuffer[6]; sv3 = sv3;
car_SOC = (char)((unsigned long)(sv1 + sv2 + sv3 + 5000UL)/10000UL);
And the result for car_SOC is 49. How is this possible? And what would be the correct way to put these 3 bytes together and divide them by 10000 to get to the final value in char?
Thanks in advance, Nikolay
On Monday, June 22, 2015 3:58 PM, Mark Webb-Johnson <mark@webb-johnson.net> wrote:
Division is kind of nasty in 8bit. Actually very nasty. Unless you are dividing by 2, 4, 8, 16, etc. Divide by 2^N is the same as >>N, and that is the shortcut you want to do if at all possible.
That said, your solution seems ok, except the value[2] should be <<8, and you probably want to add 5000 just before divide by 10000, to round correctly.
If you don’t need too much precision, you might find an inaccurate kludge may be good enough.
For example:
205/2048 = 0.1000976562
and that is pretty close to 0.1. So multiply by 205, then shirt right 11 spaces is pretty close to divide by 10. Multiplication is much less expensive than division.
If you look at MiFromKm and KmFromMi in utils.c, you can see similar sorts of approximations to avoid big divisions.
Regards, Mark.
On 22 Jun, 2015, at 4:30 pm, Nikolay Shishkov <nshishkov@yahoo.com <mailto:nshishkov@yahoo.com>> wrote:
I have a situation where I need to convert a value that is stored as 3 bytes to a char. The can be for example 7ED95, which is reported in 3 consequtive bytes 07, ED, 95. This value in decimal is 519573, which corresponds to a 51.9% SOC. Is the proper way to do this conversion (from the 3 bytes to the value of 51) like this:
char soc = (char)(((unsigned long)value[1]<<16 + (unsigned long)value[2]<<16 + (unsigned long)value[3])/10000);
I have been doing stuff like that before with unions, but can't remember how either.
Thanks,
Nikolay
_______________________________________________ OvmsDev mailing list OvmsDev@lists.teslaclub.hk <mailto:OvmsDev@lists.teslaclub.hk> http://lists.teslaclub.hk/mailman/listinfo/ovmsdev
_______________________________________________ OvmsDev mailing list OvmsDev@lists.teslaclub.hk <mailto:OvmsDev@lists.teslaclub.hk> http://lists.teslaclub.hk/mailman/listinfo/ovmsdev <http://lists.teslaclub.hk/mailman/listinfo/ovmsdev>
_______________________________________________ OvmsDev mailing list OvmsDev@lists.teslaclub.hk http://lists.teslaclub.hk/mailman/listinfo/ovmsdev