Skip to content

Commit fd6ae6a

Browse files
committed
sine wave approximation memory shrinking
1 parent be4180f commit fd6ae6a

File tree

7 files changed

+58
-35
lines changed

7 files changed

+58
-35
lines changed

README.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ For minimal version of the code more suitable for experimenting please visit the
2828
# Structure
2929
- [Installation](#arduino-simple-foc-instalation)
3030
- [Installing the full Arduino Simple FOC library](#installing-simple-foc-full-library)
31-
- [Installing the minimal Arduino example](#download-minimal-simple-foc-arduino-example)
31+
- [Installing the minimal Arduino example](#download-simple-foc-arduino-minimal-example)
3232
- [Electrical connecitons and schematic](#electrical-connections)
3333
- [Minimal setup](#all-you-need-for-this-project-is-an-exaple-in-brackets)
3434
- [Arduino Simple FOC Shield V1.2](#arduino-simple-foc-shield-v12)
@@ -57,15 +57,15 @@ The simplest way to get hold of the library is direclty by using Arduino IDE and
5757
### Download library directly
5858
If you don't want to use the Arduino IDE and Library manager you can direclty download the library from this website.
5959
- Simplest way to do it is to download the `zip` aerchieve directly on the top of this webiste. Click first on `Clone or Download` and then on `Download ZIP`. Once you have the zip ardhieve downloaded, unzip it and place it in your Arduino Libraries forlder. On Windows it is usually in `Documents > Arduino > libraries`.
60-
- Now reopen your Arduino IDE and you should have the library examples in `File > Examples > Simple FOC`.
60+
Now reopen your Arduino IDE and you should have the library examples in `File > Examples > Simple FOC`.
6161

6262
- If you are more experienced with the terminal you can open your terminal in the Arduino libraries folder direclty and clone the Arduino FOC git repsitory:
63-
```bash
64-
git clone https://github.com/askuric/Arduino-FOC.git
65-
```
66-
- Now reopen your Arduino IDE and you should have the library examples in `File > Examples > Simple FOC`.
63+
```bash
64+
git clone https://github.com/askuric/Arduino-FOC.git
65+
```
66+
Now reopen your Arduino IDE and you should have the library examples in `File > Examples > Simple FOC`.
6767

68-
## Download minimal Simple FOC Arduino example
68+
## Download Simple FOC Arduino minimal example
6969
To download the minmial verison of Simple FOC intended for those willing to experiment and extend the code I suggest using this version over the full library.
7070
This code is completely indepenedet and you can run it as any other Arduino Schetch without the need for any libraries.
7171
The code is place in the [minimal branch](https://github.com/askuric/Arduino-FOC/tree/minimal).
@@ -691,6 +691,7 @@ before running `motor.init()`.
691691
- [x] Add support for acceleration ramping
692692
- [x] Timer interrupt execution rather than in the `loop()`
693693
- FAIL: Perfromance not improved
694+
- [x] Sine wave lookup table implementation
694695

695696
# Contact
696697
Please do not hesitate to leave an issue or contact me direclty by email.

examples/find_pole_pairs_number/find_pole_pairs_number.ino

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,37 +43,48 @@ void setup() {
4343
motor.init();
4444

4545

46+
4647
// pole pairs calculation routine
4748
Serial.println("Motor pole pair number estimation example");
4849
Serial.println("---------------------------------------------\n");
4950

50-
float pp_search_voltage = 3; // maximum power_supply_voltage/2
51-
51+
float pp_search_voltage = 4; // maximum power_supply_voltage/2
52+
float pp_search_angle = 6*M_PI; // search electrical angle to turn
53+
5254
// move motor to the electrical angle 0
5355
motor.setPhaseVoltage(pp_search_voltage,0);
5456
_delay(1000);
5557
// read the encoder angle
56-
float angle0 = encoder.getAngle();
58+
float angle_begin = encoder.getAngle();
5759
_delay(50);
58-
59-
// move the motor slowly to the electrical angle 360 -> 2*pi radians
60-
for(int i =0; i<2000; i++){
61-
motor.setPhaseVoltage(pp_search_voltage, 2*M_PI/2000 * i);
60+
61+
// move the motor slowly to the electrical angle pp_search_angle
62+
float motor_angle = 0;
63+
while(motor_angle <= pp_search_angle){
64+
motor_angle += 0.01;
65+
motor.setPhaseVoltage(pp_search_voltage, motor_angle);
6266
}
6367
_delay(1000);
6468
// read the encoder value for 180
65-
float angle360 = encoder.getAngle();
69+
float angle_end = encoder.getAngle();
6670
_delay(50);
6771
// turn off the motor
6872
motor.setPhaseVoltage(0,0);
6973
_delay(1000);
7074

7175
// caluclate the pole pair number
72-
int pp = round((2*M_PI)/(angle360-angle0));
76+
int pp = round((pp_search_angle)/(angle_end-angle_begin));
7377

7478
Serial.print("Estimated pole pairs number is: ");
7579
Serial.println(pp);
76-
Serial.println("");
80+
Serial.println("Electrical angle / Encoder angle = Pole pairs ");
81+
Serial.print(pp_search_angle*180/M_PI);
82+
Serial.print("/");
83+
Serial.print((angle_end-angle_begin)*180/M_PI);
84+
Serial.print(" = ");
85+
Serial.println((pp_search_angle)/(angle_end-angle_begin));
86+
Serial.println();
87+
7788

7889
// a bit of debugging the result
7990
if(pp <= 0 ){

keywords.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ handleB KEYWIORD2
2929
handleIndex KEYWIORD2
3030
ISR KEYWIORD2
3131
getVelocity KEYWIORD2
32+
setPhaseVoltage KEYWIORD2
3233
getAngle KEYWIORD2
3334
setCounterZero KEYWIORD2
3435
useDebugging KEYWIORD2
@@ -43,7 +44,6 @@ driver KEYWIORD2
4344
pullup KEYWIORD2
4445
quadrature KEYWIORD2
4546

46-
index_search_u_limit KEYWIORD2
4747
index_search_velocity KEYWIORD2
4848

4949

src/BLDCMotor.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -266,16 +266,16 @@ void BLDCMotor::move(float target) {
266266
/*
267267
Method using FOC to set Uq to the motor at the optimal angle
268268
*/
269-
void BLDCMotor::setPhaseVoltage(double Uq, double angle_el) {
269+
void BLDCMotor::setPhaseVoltage(float Uq, float angle_el) {
270270

271271
// angle normalisation in between 0 and 2pi
272272
// only necessary if using _sin and _cos - approximation funcitons
273273
float angle = normalizeAngle(angle_el + index_electric_angle);
274274
// Inverse park transform
275-
// regular sin + cos ~300us
276-
// approx _sin + _cos ~90us
277-
Ualpha = -_sin(angle) * Uq;
278-
Ubeta = _cos(angle) * Uq;
275+
// regular sin + cos ~300us (no memeory usaage)
276+
// approx _sin + _cos ~110us (400Byte ~ 20% of memory)
277+
Ualpha = -_sin(angle) * Uq; // -sin(angle) * Uq;
278+
Ubeta = _cos(angle) * Uq; // cos(angle) * Uq;
279279

280280
// Clarke transform
281281
Ua = Ualpha;
@@ -315,8 +315,8 @@ void BLDCMotor::setPwm(int pinPwm, float U) {
315315
/*
316316
normalizing radian angle to [0,2PI]
317317
*/
318-
double BLDCMotor::normalizeAngle(double angle){
319-
double a = fmod(angle, _2PI);
318+
float BLDCMotor::normalizeAngle(float angle){
319+
float a = fmod(angle, _2PI);
320320
return a >= 0 ? a : (a + _2PI);
321321
}
322322

src/BLDCMotor.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ class BLDCMotor
123123

124124
/** FOC methods */
125125
//Method using FOC to set Uq to the motor at the optimal angle
126-
void setPhaseVoltage(double Uq, double angle_el);
126+
void setPhaseVoltage(float Uq, float angle_el);
127127

128128

129129
// debugging
@@ -142,7 +142,7 @@ class BLDCMotor
142142

143143
/** Utility funcitons */
144144
//normalizing radian angle to [0,2PI]
145-
double normalizeAngle(double angle);
145+
float normalizeAngle(float angle);
146146
//Reference low pass filter
147147
float filterLP(float u);
148148

src/Encoder.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ void Encoder::init(void (*doA)(), void(*doB)()){
219219
}
220220

221221
// if index used intialise the index interrupt
222-
if(hasIndex()) {
222+
if(hasIndex() || doA != nullptr) {
223223
*digitalPinToPCMSK(index_pin) |= bit (digitalPinToPCMSKbit(index_pin)); // enable pin
224224
PCIFR |= bit (digitalPinToPCICRbit(index_pin)); // clear any outstanding interrupt
225225
PCICR |= bit (digitalPinToPCICRbit(index_pin)); // enable interrupt for the group

src/FOCutils.cpp

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,30 +40,41 @@ unsigned long _micros(){
4040

4141

4242
// lookup table for sine calculation in between 0 and 90 degrees
43-
float sine_array[200] = {0.0000,0.0079,0.0158,0.0237,0.0316,0.0395,0.0473,0.0552,0.0631,0.0710,0.0789,0.0867,0.0946,0.1024,0.1103,0.1181,0.1260,0.1338,0.1416,0.1494,0.1572,0.1650,0.1728,0.1806,0.1883,0.1961,0.2038,0.2115,0.2192,0.2269,0.2346,0.2423,0.2499,0.2575,0.2652,0.2728,0.2804,0.2879,0.2955,0.3030,0.3105,0.3180,0.3255,0.3329,0.3404,0.3478,0.3552,0.3625,0.3699,0.3772,0.3845,0.3918,0.3990,0.4063,0.4135,0.4206,0.4278,0.4349,0.4420,0.4491,0.4561,0.4631,0.4701,0.4770,0.4840,0.4909,0.4977,0.5046,0.5113,0.5181,0.5249,0.5316,0.5382,0.5449,0.5515,0.5580,0.5646,0.5711,0.5775,0.5839,0.5903,0.5967,0.6030,0.6093,0.6155,0.6217,0.6279,0.6340,0.6401,0.6461,0.6521,0.6581,0.6640,0.6699,0.6758,0.6815,0.6873,0.6930,0.6987,0.7043,0.7099,0.7154,0.7209,0.7264,0.7318,0.7371,0.7424,0.7477,0.7529,0.7581,0.7632,0.7683,0.7733,0.7783,0.7832,0.7881,0.7930,0.7977,0.8025,0.8072,0.8118,0.8164,0.8209,0.8254,0.8298,0.8342,0.8385,0.8428,0.8470,0.8512,0.8553,0.8594,0.8634,0.8673,0.8712,0.8751,0.8789,0.8826,0.8863,0.8899,0.8935,0.8970,0.9005,0.9039,0.9072,0.9105,0.9138,0.9169,0.9201,0.9231,0.9261,0.9291,0.9320,0.9348,0.9376,0.9403,0.9429,0.9455,0.9481,0.9506,0.9530,0.9554,0.9577,0.9599,0.9621,0.9642,0.9663,0.9683,0.9702,0.9721,0.9739,0.9757,0.9774,0.9790,0.9806,0.9821,0.9836,0.9850,0.9863,0.9876,0.9888,0.9899,0.9910,0.9920,0.9930,0.9939,0.9947,0.9955,0.9962,0.9969,0.9975,0.9980,0.9985,0.9989,0.9992,0.9995,0.9997,0.9999,1.0000,1.0000};
43+
//float sine_array[200] = {0.0000,0.0079,0.0158,0.0237,0.0316,0.0395,0.0473,0.0552,0.0631,0.0710,0.0789,0.0867,0.0946,0.1024,0.1103,0.1181,0.1260,0.1338,0.1416,0.1494,0.1572,0.1650,0.1728,0.1806,0.1883,0.1961,0.2038,0.2115,0.2192,0.2269,0.2346,0.2423,0.2499,0.2575,0.2652,0.2728,0.2804,0.2879,0.2955,0.3030,0.3105,0.3180,0.3255,0.3329,0.3404,0.3478,0.3552,0.3625,0.3699,0.3772,0.3845,0.3918,0.3990,0.4063,0.4135,0.4206,0.4278,0.4349,0.4420,0.4491,0.4561,0.4631,0.4701,0.4770,0.4840,0.4909,0.4977,0.5046,0.5113,0.5181,0.5249,0.5316,0.5382,0.5449,0.5515,0.5580,0.5646,0.5711,0.5775,0.5839,0.5903,0.5967,0.6030,0.6093,0.6155,0.6217,0.6279,0.6340,0.6401,0.6461,0.6521,0.6581,0.6640,0.6699,0.6758,0.6815,0.6873,0.6930,0.6987,0.7043,0.7099,0.7154,0.7209,0.7264,0.7318,0.7371,0.7424,0.7477,0.7529,0.7581,0.7632,0.7683,0.7733,0.7783,0.7832,0.7881,0.7930,0.7977,0.8025,0.8072,0.8118,0.8164,0.8209,0.8254,0.8298,0.8342,0.8385,0.8428,0.8470,0.8512,0.8553,0.8594,0.8634,0.8673,0.8712,0.8751,0.8789,0.8826,0.8863,0.8899,0.8935,0.8970,0.9005,0.9039,0.9072,0.9105,0.9138,0.9169,0.9201,0.9231,0.9261,0.9291,0.9320,0.9348,0.9376,0.9403,0.9429,0.9455,0.9481,0.9506,0.9530,0.9554,0.9577,0.9599,0.9621,0.9642,0.9663,0.9683,0.9702,0.9721,0.9739,0.9757,0.9774,0.9790,0.9806,0.9821,0.9836,0.9850,0.9863,0.9876,0.9888,0.9899,0.9910,0.9920,0.9930,0.9939,0.9947,0.9955,0.9962,0.9969,0.9975,0.9980,0.9985,0.9989,0.9992,0.9995,0.9997,0.9999,1.0000,1.0000};
44+
45+
// int array instead of float array
46+
// 2x storage save (int 2Byte float 4 Byte )
47+
// sin*10000
48+
int sine_array[200] = {0,79,158,237,316,395,473,552,631,710,789,867,946,1024,1103,1181,1260,1338,1416,1494,1572,1650,1728,1806,1883,1961,2038,2115,2192,2269,2346,2423,2499,2575,2652,2728,2804,2879,2955,3030,3105,3180,3255,3329,3404,3478,3552,3625,3699,3772,3845,3918,3990,4063,4135,4206,4278,4349,4420,4491,4561,4631,4701,4770,4840,4909,4977,5046,5113,5181,5249,5316,5382,5449,5515,5580,5646,5711,5775,5839,5903,5967,6030,6093,6155,6217,6279,6340,6401,6461,6521,6581,6640,6699,6758,6815,6873,6930,6987,7043,7099,7154,7209,7264,7318,7371,7424,7477,7529,7581,7632,7683,7733,7783,7832,7881,7930,7977,8025,8072,8118,8164,8209,8254,8298,8342,8385,8428,8470,8512,8553,8594,8634,8673,8712,8751,8789,8826,8863,8899,8935,8970,9005,9039,9072,9105,9138,9169,9201,9231,9261,9291,9320,9348,9376,9403,9429,9455,9481,9506,9530,9554,9577,9599,9621,9642,9663,9683,9702,9721,9739,9757,9774,9790,9806,9821,9836,9850,9863,9876,9888,9899,9910,9920,9930,9939,9947,9955,9962,9969,9975,9980,9985,9989,9992,9995,9997,9999,10000,10000};
4449

4550
// function approximating the sine calculation by using fixed size array
46-
// ~40us
51+
// ~40us (float array)
52+
// ~50us (int array)
4753
// precision +-0.005
4854
// it has to receive an angle in between 0 and 2PI
4955
float _sin(float a){
5056
if(a < _PI_2){
5157
//return sine_array[(int)(199.0*( a / (M_PI/2.0)))];
52-
return sine_array[(int)(126.6873* a)];
58+
//return sine_array[(int)(126.6873* a)]; // float array optimised
59+
return 0.0001*sine_array[(int)(126.6873* a)]; // int array optimised
5360
}else if(a < M_PI){
5461
// return sine_array[(int)(199.0*(1.0 - (a-M_PI/2.0) / (M_PI/2.0)))];
55-
return sine_array[398 - (int)(126.6873*a)];
62+
//return sine_array[398 - (int)(126.6873*a)]; // float array optimised
63+
return 0.0001*sine_array[398 - (int)(126.6873*a)]; // int array optimised
5664
}else if(a < _3PI_2){
5765
// return -sine_array[(int)(199.0*((a - M_PI) / (M_PI/2.0)))];
58-
return -sine_array[-398 + (int)(126.6873*a)];
66+
//return -sine_array[-398 + (int)(126.6873*a)]; // float array optimised
67+
return -0.0001*sine_array[-398 + (int)(126.6873*a)]; // int array optimised
5968
} else {
6069
// return -sine_array[(int)(199.0*(1.0 - (a - 3*M_PI/2) / (M_PI/2.0)))];
61-
return -sine_array[796 - (int)(126.6873*a)];
70+
//return -sine_array[796 - (int)(126.6873*a)]; // float array optimised
71+
return -0.0001*sine_array[796 - (int)(126.6873*a)]; // int array optimised
6272
}
6373
}
6474

6575
// function approfimating cosine calculaiton by using fixed size array
66-
// ~50us
76+
// ~55us (float array)
77+
// ~56us (int array)
6778
// precision +-0.005
6879
// it has to receive an angle in between 0 and 2PI
6980
float _cos(float a){

0 commit comments

Comments
 (0)