ACS37800 library for Arduino
Loading...
Searching...
No Matches
params.c
1#include <stdio.h>
2#include <stdint.h>
3#include <math.h>
4#include <limits.h>
5#include <assert.h>
6
7// Figure out a good approximation for (x * numerator / denominator), where
8// x is an int16_t to uint16_t. Approximation will be of the form x * p >> s.
9void figure_out_approximation(uint64_t numerator, uint64_t denominator)
10{
11 printf(" ideal: x * %llu / %llu\n", numerator, denominator);
12 assert(numerator < INT_MAX);
13 assert(denominator < INT_MAX);
14
15 int input_min = -0x8000;
16 int input_max = 0xFFFF;
17 uint32_t p_max = 0x7FFF;
18
19 // Figure out the approximation
20 double k = (double)numerator / denominator;
21 uint16_t p = 0;
22 uint8_t shift = 0;
23 for (uint8_t shift_candidate = 0; shift_candidate < 32; shift_candidate++)
24 {
25 uint32_t p_candidate = round(k * (1 << shift_candidate));
26 if (p_candidate > p_max) { break; }
27 p = p_candidate;
28 shift = shift_candidate;
29 }
30 while ((p & 1) == 0)
31 {
32 p >>= 1;
33 shift--;
34 }
35
36 // Figure out its worst error.
37 int worst_error = 0;
38 int worst_i = -99999;
39 double worst_error_percent = 0;
40 for (int i = input_min; i <= input_max; i++)
41 {
42 int ideal = i * (int64_t)numerator / (int)denominator;
43 int approximate = ((int32_t)i * p) >> shift;
44 int this_error = ideal - approximate;
45 if (abs(this_error) > abs(worst_error))
46 {
47 worst_error = this_error;
48 worst_error_percent = 100 * this_error / ideal;
49 worst_i = i;
50 }
51 }
52 printf(" approx: x * %d >> %u", p, shift);
53 if (worst_error == 0)
54 {
55 printf(" (no error)\n");
56 }
57 else
58 {
59 printf(" (worst error is %d (%.2lf%%) at x=%d)\n", worst_error, worst_error_percent, worst_i);
60 }
61}
62
63void calculate_params(uint8_t isense_range, uint32_t riso, uint32_t rsense)
64{
65 printf("Board: riso = %u ohm, isense_range = %u A, rsense = %u ohm\n",
66 riso, isense_range, rsense);
67
68 printf(" vcodes to mA:\n");
69 figure_out_approximation((riso + rsense) * 250, 27500 * rsense);
70
71 printf(" icodes to mA:\n");
72 figure_out_approximation(1000 * isense_range, 27500);
73
74 printf(" pinstant to mW:\n");
75 figure_out_approximation(isense_range * (riso + rsense) * 5, (rsense * 462));
76
77 printf("\n");
78}
79
80int main()
81{
82 // Settings for Pololu boards:
83 calculate_params(30, 4000000, 1000);
84 calculate_params(30, 4000000, 2000);
85 calculate_params(30, 4000000, 4000);
86}