fork download
  1. import numpy as np
  2. import pandas as pd
  3.  
  4. TARGET_F = 1 # In Hz so 50.0 is 0.020 seconds period and 0.25 is 4 seconds period
  5. CLOCK_MCU = 240000000
  6. TOLERANCE = 0.00000001
  7.  
  8. # -----------------------------------------------------
  9.  
  10.  
  11. def abs_error(num1, num2):
  12. return abs((num1 - num2) / num1)
  13.  
  14.  
  15. def hertz(clock, prescaler, period):
  16. f = clock / (prescaler * period)
  17. return f
  18.  
  19.  
  20. def perfect_divisors():
  21. exacts = []
  22. for psc in range(1, 65536):
  23. arr = CLOCK_MCU / (TARGET_F * psc)
  24. if CLOCK_MCU % psc == 0:
  25. if arr <= 65536:
  26. exacts.append(psc)
  27. return exacts
  28.  
  29.  
  30. def add_exact_period(prescaler):
  31. entries = []
  32. arr = CLOCK_MCU / (TARGET_F * prescaler)
  33. if arr == int(arr):
  34. entry = [prescaler, arr, TARGET_F, 0.0]
  35. entries.append(entry)
  36. return entries
  37.  
  38.  
  39. def possible_prescaler_value():
  40. possibles = []
  41. for psc in range(1, 65536):
  42. if psc in exact_prescalers:
  43. continue
  44. h1 = hertz(CLOCK_MCU, psc, 1)
  45. h2 = hertz(CLOCK_MCU, psc, 65536)
  46. if h1 >= TARGET_F >= h2:
  47. possibles.append(psc)
  48. return possibles
  49.  
  50.  
  51. def close_divisor(psc, tolerance):
  52. arr = CLOCK_MCU / (TARGET_F * psc)
  53. error = abs_error(int(arr), arr)
  54. if error < tolerance and arr < 65536.0:
  55. h = hertz(CLOCK_MCU, psc, int(arr))
  56. return psc, int(arr), h, error
  57. else:
  58. return None
  59.  
  60.  
  61. # ------------------------------------------------------------------------
  62.  
  63. # Make a dataframe to hold results as we compute them
  64. df = pd.DataFrame(columns=['PSC', 'ARR', 'F', 'ERROR'], dtype=np.double)
  65.  
  66. # Get exact prescalars first.
  67. exact_prescalers = perfect_divisors()
  68. exact_values = []
  69. for index in range(len(exact_prescalers)):
  70. rows = add_exact_period(exact_prescalers[index])
  71. for rowindex in range(len(rows)):
  72. df = df.append(pd.DataFrame(np.array(rows[rowindex]).reshape(1, 4), columns=df.columns))
  73.  
  74. # Get possible prescalers.
  75. poss_prescalers = possible_prescaler_value()
  76. close_prescalers = []
  77. for index in range(len(poss_prescalers)):
  78. value = close_divisor(poss_prescalers[index], TOLERANCE)
  79. if value is not None:
  80. close_prescalers.append((value[0], value[1], value[2], value[3]))
  81. df = df.append(pd.DataFrame(np.array(close_prescalers).reshape(len(close_prescalers), 4), columns=df.columns))
  82.  
  83. # Adjust PSC and ARR values by -1 to reflect the way you'd code them.
  84. df['PSC'] = df['PSC'] - 1
  85. df['ARR'] = df['ARR'] - 1
  86.  
  87. # Sort first by errors (zeroes and lowest errors at top of list, and
  88. # then by prescaler value (ascending).
  89. df = df.sort_values(['ERROR', 'PSC'])
  90.  
  91. # Make and populate column indicating if combination is exact.
  92. df['EXACT'] = pd.Series("?", index=df.index)
  93. df['EXACT'] = np.where(df['ERROR'] == 0.0, "YES", "NO")
  94.  
  95. # Format for output.
  96. df['PSC'] = df['PSC'].map('{:.0f}'.format)
  97. df['ARR'] = df['ARR'].map('{:.0f}'.format)
  98. df['F'] = df['F'].map('{:.6f}'.format)
  99. df['ERROR'] = df['ERROR'].map('{:.10f}'.format)
  100.  
  101. output = df.to_string()
  102. print(output)
  103. print()
  104. print('these are the ', df.shape[0], ' total combination meeting your tolerance requirement')
  105. exit(0)
Success #stdin #stdout 0.66s 66260KB
stdin
Standard input is empty
stdout
     PSC    ARR         F         ERROR EXACT
0   3749  63999  1.000000  0.0000000000   YES
0   3839  62499  1.000000  0.0000000000   YES
0   3999  59999  1.000000  0.0000000000   YES
0   4799  49999  1.000000  0.0000000000   YES
0   4999  47999  1.000000  0.0000000000   YES
0   5119  46874  1.000000  0.0000000000   YES
0   5999  39999  1.000000  0.0000000000   YES
0   6249  38399  1.000000  0.0000000000   YES
0   6399  37499  1.000000  0.0000000000   YES
0   7499  31999  1.000000  0.0000000000   YES
0   7679  31249  1.000000  0.0000000000   YES
0   7999  29999  1.000000  0.0000000000   YES
0   9374  25599  1.000000  0.0000000000   YES
0   9599  24999  1.000000  0.0000000000   YES
0   9999  23999  1.000000  0.0000000000   YES
0  11999  19999  1.000000  0.0000000000   YES
0  12499  19199  1.000000  0.0000000000   YES
0  12799  18749  1.000000  0.0000000000   YES
0  14999  15999  1.000000  0.0000000000   YES
0  15359  15624  1.000000  0.0000000000   YES
0  15624  15359  1.000000  0.0000000000   YES
0  15999  14999  1.000000  0.0000000000   YES
0  18749  12799  1.000000  0.0000000000   YES
0  19199  12499  1.000000  0.0000000000   YES
0  19999  11999  1.000000  0.0000000000   YES
0  23999   9999  1.000000  0.0000000000   YES
0  24999   9599  1.000000  0.0000000000   YES
0  25599   9374  1.000000  0.0000000000   YES
0  29999   7999  1.000000  0.0000000000   YES
0  31249   7679  1.000000  0.0000000000   YES
0  31999   7499  1.000000  0.0000000000   YES
0  37499   6399  1.000000  0.0000000000   YES
0  38399   6249  1.000000  0.0000000000   YES
0  39999   5999  1.000000  0.0000000000   YES
0  46874   5119  1.000000  0.0000000000   YES
0  47999   4999  1.000000  0.0000000000   YES
0  49999   4799  1.000000  0.0000000000   YES
0  59999   3999  1.000000  0.0000000000   YES
0  62499   3839  1.000000  0.0000000000   YES
0  63999   3749  1.000000  0.0000000000   YES
0   5557  43180  1.000000  0.0000000083    NO
1  10422  23025  1.000000  0.0000000083    NO
3  20845  11512  1.000000  0.0000000083    NO
2  11512  20845  1.000000  0.0000000083    NO
4  23025  10422  1.000000  0.0000000083    NO
5  43180   5557  1.000000  0.0000000083    NO

these are the  46  total combination meeting your tolerance requirement