[Ovmsdev] 3 bytes to char
Mark Webb-Johnson
mark at webb-johnson.net
Thu Jun 25 14:33:44 HKT 2015
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 at 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 at 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 at yahoo.com <mailto:nshishkov at 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 at lists.teslaclub.hk <mailto:OvmsDev at lists.teslaclub.hk>
>> http://lists.teslaclub.hk/mailman/listinfo/ovmsdev
>
>
> _______________________________________________
> OvmsDev mailing list
> OvmsDev at lists.teslaclub.hk <mailto:OvmsDev at lists.teslaclub.hk>
> http://lists.teslaclub.hk/mailman/listinfo/ovmsdev <http://lists.teslaclub.hk/mailman/listinfo/ovmsdev>
>
>
> _______________________________________________
> OvmsDev mailing list
> OvmsDev at lists.teslaclub.hk
> http://lists.teslaclub.hk/mailman/listinfo/ovmsdev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openvehicles.com/pipermail/ovmsdev/attachments/20150625/1efa4567/attachment.htm>
More information about the OvmsDev
mailing list