### Full monitoring configuration example Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/code/monitoring.md A complete example showing setup and loop integration for motor monitoring. ```cpp ... void setup(){ ... Serial.begin(115200); // the higher the better motor.useMonitoring(Serial); //display variables motor.monitor_variables = _MON_TARGET | _MON_VEL | _MON_ANGLE; // downsampling motor.monitor_downsample = 100; // default 10 ... } void loop(){ .... motor.monitor(); } ``` -------------------------------- ### Full Dual Motor Example Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/examples/haptics.md Complete implementation including initialization, configuration, and monitoring setup. ```cpp #include BLDCMotor motor1 = BLDCMotor(11); BLDCDriver3PWM driver1 = BLDCDriver3PWM(9, 6, 5, 7); Encoder encoder1 = Encoder(A1, A2, 8192); void doA1(){encoder1.handleA();} void doB1(){encoder1.handleB();} BLDCMotor motor2 = BLDCMotor(11); BLDCDriver3PWM driver2 = BLDCDriver3PWM(3, 13, 10, 8); Encoder encoder2 = Encoder(A3, 2, 500); void doA2(){encoder2.handleA();} void doB2(){encoder2.handleB();} void setup() { // initialise encoder hardware encoder1.init(); encoder1.enableInterrupts(doA1,doB1); encoder2.init(); encoder2.enableInterrupts(doA2,doB2); // link the motor to the sensor motor1.linkSensor(&encoder1); motor2.linkSensor(&encoder2); // config drivers driver1.init(); driver2.init(); // link the motor to the driver motor1.linkDriver(&driver1); motor2.linkDriver(&driver2); // set control loop type to be used motor1.controller = MotionControlType::torque; motor2.controller = MotionControlType::velocity; motor2.LPF_velocity.Tf = 0.02; motor2.PID_velocity.I = 40; // use monitoring with serial for motor init // monitoring port Serial.begin(115200); // enable monitoring motor1.useMonitoring(Serial); motor2.useMonitoring(Serial); // initialise motor ``` -------------------------------- ### Locate voltage control examples Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/boards/simplefoc_shield/getting_started/code.md Start FOC algorithm testing using these voltage control examples. ```sh motion_control > torque_voltage_control > - encoder - magnetic_sensor - hall_sensors ``` -------------------------------- ### Example: SimpleFOCShield v2 Setup with Low-side Current Sense Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/code/current_sense/low_side.md This example demonstrates a typical setup for a BLDC motor using the SimpleFOCShield v2 with low-side current sensing. It includes linking the driver and current sense, initializing the motor, and inverting phase gains if necessary. ```cpp // one possible combination of current sensing pins for SimpleFOCShield v2 // shunt - 5milliOhm // gain - 12.22 V/V LowsideCurrentSense current_sense = LowsideCurrentSense(0.005f, 12.22f, IOUTA, IOUTB, IOUTC); void loop(){ .... // driver init driver.init(); // link the driver to the current sense current_sense.linkDriver(&driver); .... // motor init motor.init(); .... // init current sense current_sense.init(); // link the current sense to the motor motor.linkCurrentSense(¤t_sense); ... // invert phase b gain current_sense.gain_a *=-1; current_sense.gain_b *=-1; current_sense.gain_c *=-1; // skip alignment current_sense.skip_align = true; ... // start the FOC motor.initFOC(); } ``` -------------------------------- ### Multiple Encoder Interrupt Setup Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/code/sensors/encoder.md Example demonstrating how to manage multiple encoders by defining unique callback functions for each instance. ```cpp // encoder 1 Encoder enc1 = Encoder(...); void doA1(){enc1.handleA();} void doB1(){enc1.handleB();} // encoder 2 Encoder enc2 = Encoder(...); void doA2(){enc2.handleA();} void doB2(){enc2.handleB();} void setup(){ ... enc1.init(); enc1.enableInterrupts(doA1,doB1); enc2.init(); enc2.enableInterrupts(doA2,doB2); ... } ``` -------------------------------- ### Serial monitor command examples Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/code/communication/commander/motor.md Examples of serial commands to get and set various motor parameters and control modes. ```sh $ MVP # get PID velocity P gain PID vel| P: 0.20 $ MVP1.2 # set PID velocity P gain PID vel| P: 1.20 $ MAI # get PID angle I gain PID angle| I: 0.00 $ MAF # get LPF angle time constant LPF angle| Tf: 0.00 $ MLV50.4 # set velocity limit Limits| vel: 50.4 $ MLC # get current limit Limits| curr: 0.5 $ MT # get torque control mode Torque: volt $ MT1 # set torque control mode Torque: dc curr $ MT2 # set torque control mode Torque: foc curr $ ME # get motor status enabled/disabled Status: 1 $ MSM # get sensor offset Sensor| offset: 0.0 $ MSM1.2 # set sensor offset Sensor| offset: 1.2 $ MC # get motion control mode Motion: torque $ MC3 # set motion control mode Motion: vel open $ MC2 # set motion control mode Motion: angle $ MCD100 # get motion control downsampling Motion: downsample: 100 $ MMG0 # get variable - target Monitor | target: 0.0 $ MMG1 # get variable - voltage q Monitor | Vq: 1.4 $ MMG6 # get variable - angle Monitor | angle: 23.5 $ MMG6 # get variable - angle Monitor | angle: 24.6 ``` -------------------------------- ### Enable Debugging Output Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/code/index.md Call SimpleFOCDebug::enable(&Serial) at the start of setup() to receive detailed initialization logs. Note that this consumes significant memory and should be disabled in production. ```cpp #include // instantiate motor // instantiate driver // instantiate senor void setup() { // init the serial port // enable the debugging output SimpleFOCDebug::enable(&Serial); // init sensor // link motor and sensor // init driver // link motor and driver // link driver and the current sense // init current sense // link motor and current sense // enable monitoring // configure motor // init motor // init current sense // align encoder and start FOC } void loop() { // FOC execution // motion control loop // monitor variables } ``` -------------------------------- ### Configure Arduino for SimpleFOCWebController Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_libraries/tools/webcontroller.md Setup the Commander interface and motor monitoring to enable communication with the web controller. Ensure the monitor start and end characters match the motor ID used in the commander. ```cpp #include .... // include commander interface Commander command = Commander(Serial); void doMotor(char* cmd) { command.motor(&motor, cmd); } void setup(){ .... // add the motor to the commander interface // The letter id (here 'M') of the motor char motor_id = 'M'; command.add(motor_id,doMotor,"motor"); // tell the motor to use the monitoring motor.useMonitoring(Serial); // configuring the monitoring to be well parsed by the webcontroller motor.monitor_start_char = motor_id; // the same latter as the motor id in the commander motor.monitor_end_char = motor_id; // the same latter as the motor id in the commander command.verbose = VerboseMode::machine_readable; // can be set using the webcontroller - optional ... } void loop(){ .... .... // real-time monitoring calls motor.monitor(); // real-time commander calls command.run(); } ``` -------------------------------- ### Standalone Sensor Example Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/code/sensors/generic.md Example demonstrating how to use a custom sensor as a standalone device, updating and reading its values. ```cpp #include float readMySensorCallback(){ // read my sensor // return the angle value in radians in between 0 and 2PI return ...; } void initMySensorCallback(){ // do the init } // create the sensor GenericSensor sensor = GenericSensor(readMySensorCallback, initMySensorCallback); void setup() { // monitoring port Serial.begin(115200); // initialize sensor hardware sensor.init(); Serial.println("My sensor ready"); _delay(1000); } void loop() { // IMPORTANT - call as frequently as possible // update the sensor values sensor.update(); // display the angle and the angular velocity to the terminal Serial.print(sensor.getAngle()); Serial.print("\t"); Serial.println(sensor.getVelocity()); } ``` -------------------------------- ### Install Dependencies Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_libraries/tools/simplefocstudio.md Installs all required Python libraries listed in requirements.txt. ```sh pip install -r "requirements.txt" ``` -------------------------------- ### Full AS5047 FOC Example Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/code/sensors/magnetic/magnetic_sensor_spi.md A complete example showing motor, driver, and sensor initialization for FOC. ```cpp #include // motor and driver BLDCMotor motor = BLDCMotor(7); BLDCDriver3PWM driver = BLDCDriver3PWM(9, 5, 6, 8); // as5600 sensor quick config MagneticSensorSPI sensor = MagneticSensorSPI(AS5047_SPI, 10); void setup() { // driver driver.init() motor.linkDriver(&driver); // init magnetic sensor hardware sensor.init(); motor.linkSensor(&sensor); // init motor hardware motor.init(); motor.initFOC(); Serial.println("Motor ready"); _delay(1000); } void loop(){ motor.loopFOC(); motor.move(); } ``` -------------------------------- ### Locate motion control loop examples Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/boards/simplefoc_shield/getting_started/code.md Access advanced position, velocity, and torque control examples for tuning. ```sh motion_control > position_motion_control > - encoder - magnetic_sensor - hall_sensors torque_voltage_control > - encoder - magnetic_sensor - hall_sensors velocity_motion_control > - encoder - magnetic_sensor - hall_sensors ``` -------------------------------- ### Full Example: AS5600 Sensor with BLDC Motor and Driver Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/code/sensors/magnetic/magnetic_sensor_i2c.md Complete Arduino sketch demonstrating the setup and initialization of a BLDC motor with an AS5600 magnetic sensor and a 3-PWM driver. ```cpp #include // motor and driver BLDCMotor motor = BLDCMotor(7); BLDCDriver3PWM driver = BLDCDriver3PWM(9, 5, 6, 8); // as5600 sensor quick config MagneticSensorI2C sensor = MagneticSensorI2C(AS5600_I2C); void setup() { // driver driver.init() motor.linkDriver(&driver); // init magnetic sensor hardware sensor.init(); motor.linkSensor(&sensor); // init motor hardware motor.init(); motor.initFOC(); Serial.println("Motor ready"); _delay(1000); } void loop(){ motor.loopFOC(); motor.move(); } ``` -------------------------------- ### Configure Multiple Encoders with Software Interrupts Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/code/sensors/encoder.md Example demonstrating the setup for two encoders using software interrupts. Each encoder requires its own instance, callback functions, and PciListenerImp objects, all registered with PCIManager. ```cpp // encoder 1 Encoder enc1 = Encoder(9, 10, 8192); void doA1(){enc1.handleA();} void doB1(){enc1.handleB();} PciListenerImp listA1(enc1.pinA, doA1); PciListenerImp listB1(enc1.pinB, doB1); // encoder 2 Encoder enc2 = Encoder(13, 12, 8192); void doA2(){enc2.handleA();} void doB2(){enc2.handleB();} PciListenerImp listA2(enc2.pinA, doA2); PciListenerImp listB2(enc2.pinB, doB2); void setup(){ ... // other setup code // encoder 1 enc1.init(); PciManager.registerListener(&listA1); PciManager.registerListener(&listB1); // encoder 2 enc2.init(); PciManager.registerListener(&listA2); PciManager.registerListener(&listB2); ... // rest of setup code } ``` -------------------------------- ### Enable SimpleFOC Debug Output Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/code/debug.md Call this function early in your setup() to enable debug output for motor initialization. It can help diagnose setup problems. ```cpp SimpleFOCDebug::enable(); ``` ```cpp SimpleFOCDebug::enable(&Serial); ``` -------------------------------- ### Install Jekyll and Dependencies Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/README.md Installs the Jekyll static site generator and project-specific dependencies. ```bash gem install jekyll bundler ``` ```bash # Optionally specify "--path /some/other/dir" to avoid needing root. bundle install ``` -------------------------------- ### Locate sensor test examples Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/boards/simplefoc_shield/getting_started/code.md Navigate to these paths in the library examples to verify sensor functionality. ```sh utils > sensor_test > encoder > - encoder_example - encoder_software_interrupts_example magnetic_sensors > - magnetic_sensor_i2c_example - magnetic_sensor_spi_example - magnetic_sensor_analog_example hall_sensors > - hall_sensor_example - hall_sensor_software_interrupts_example ``` -------------------------------- ### Full Motor Control Examples Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/code/getting_started/estimated_currrent/index.md Complete implementation examples for different motor types using estimated current control. ```cpp #include #define POLE_PAIRS TODO #define PHASE_RESISTANCE TODO #define KV_RATING TODO #define INDUCTANCE_Q NOT_SET // optional - can be left as NOT_SET for basic use BLDCMotor motor = BLDCMotor(POLE_PAIRS, PHASE_RESISTANCE, KV_RATING, INDUCTANCE_Q); // TODO instance driver BLDCDriverXPWM driver = BLDCDriverXPWM(); // TODO instance sensor Sensor sensor = Sensor(); Commander command = Commander(Serial); void doMotor(char* cmd) { command.motor(&motor, cmd); } void setup() { Serial.begin(115200); SimpleFOCDebug::enable(&Serial); encoder.init(); encoder.enableInterrupts(doA, doB); motor.linkSensor(&encoder); driver.voltage_power_supply = TODO; // set voltage [V] driver.init(); motor.linkDriver(&driver); // Estimated current control motor.controller = MotionControlType::torque; motor.torque_controller = TorqueControlType::estimated_current; motor.updateCurrentLimit(1.0); // A motor.target = 0.0; // A - zero torque command to start if(!motor.init()) { Serial.println("Motor init failed"); return; } if(!motor.initFOC()) { Serial.println("FOC init failed"); return; } command.add('M', doMotor, "Motor"); _delay(1000); } void loop() { motor.loopFOC(); motor.move(); command.run(); } ``` ```cpp #include #define POLE_PAIRS TODO #define PHASE_RESISTANCE TODO #define KV_RATING TODO #define INDUCTANCE_Q NOT_SET // optional - can be left as NOT_SET for basic use StepperMotor motor = StepperMotor(POLE_PAIRS, PHASE_RESISTANCE, KV_RATING, INDUCTANCE_Q); // TODO instance driver StepperDriverXPWM driver = StepperDriverXPWM(); // TODO instance sensor Sensor sensor = Sensor(); Commander command = Commander(Serial); void doMotor(char* cmd) { command.motor(&motor, cmd); } void setup() { Serial.begin(115200); SimpleFOCDebug::enable(&Serial); encoder.init(); encoder.enableInterrupts(doA, doB); motor.linkSensor(&encoder); driver.voltage_power_supply = TODO; // set voltage [V] driver.init(); motor.linkDriver(&driver); // Estimated current control motor.controller = MotionControlType::torque; motor.torque_controller = TorqueControlType::estimated_current; motor.updateCurrentLimit(1.0); // A motor.target = 0.0; // A - zero torque command to start if(!motor.init()) { Serial.println("Motor init failed"); return; } if(!motor.initFOC()) { Serial.println("FOC init failed"); return; } command.add('M', doMotor, "Motor"); _delay(1000); } void loop() { motor.loopFOC(); motor.move(); command.run(); } ``` ```cpp #include #define POLE_PAIRS TODO #define PHASE_RESISTANCE TODO #define KV_RATING TODO #define INDUCTANCE_Q NOT_SET // optional - can be left as NOT_SET for basic use HybridStepperMotor motor = HybridStepperMotor(POLE_PAIRS, PHASE_RESISTANCE, KV_RATING, INDUCTANCE_Q); // TODO instance driver BLDCDriverXPWM driver = BLDCDriverXPWM(); // TODO instance sensor Sensor sensor = Sensor(); Commander command = Commander(Serial); void doMotor(char* cmd) { command.motor(&motor, cmd); } void setup() { Serial.begin(115200); SimpleFOCDebug::enable(&Serial); encoder.init(); encoder.enableInterrupts(doA, doB); motor.linkSensor(&encoder); driver.voltage_power_supply = TODO; // set voltage [V] driver.init(); motor.linkDriver(&driver); // Estimated current control motor.controller = MotionControlType::torque; motor.torque_controller = TorqueControlType::estimated_current; motor.updateCurrentLimit(1.0); // A motor.target = 0.0; // A - zero torque command to start if(!motor.init()) { Serial.println("Motor init failed"); return; } if(!motor.initFOC()) { Serial.println("FOC init failed"); return; } command.add('M', doMotor, "Motor"); _delay(1000); } void loop() { motor.loopFOC(); motor.move(); command.run(); } ``` -------------------------------- ### FOC Algorithm with Custom Sensor Example Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/code/sensors/generic.md Complete example showing how to integrate a custom sensor with a BLDC motor for FOC control. ```cpp #include float readMySensorCallback(){ // read my sensor // return the angle value in radians in between 0 and 2PI return ...; } void initMySensorCallback(){ // do the init } // create the sensor GenericSensor sensor = GenericSensor(readMySensorCallback, initMySensorCallback); .... BLDCMotor motor = .... ... void setup() { .... // initialize sensor hardware sensor.init(); // link to the motor motor.linkSensor(&sensor); ... motor.initFOC(); ... } void loop() { .... } ``` -------------------------------- ### Example: Inline Current Sense with Custom Shunt and INA240A2 Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/code/getting_started/foc_current/05_test_current.md Example configuration for an InlineCurrentSense with a custom 0.01 Ohm shunt resistor and an INA240A2 amplifier. This specifies the shunt resistance, amplifier gain, and ADC pins A0 and A2. ```cpp `InlineCurrentSense(0.01f, 50.0f, A0, A2)` ``` -------------------------------- ### Serve Website Locally Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/README.md Starts the local development server to preview the website. ```bash bundle exec jekyll serve ``` ```bash bundle exec jekyll serve --incremental ``` -------------------------------- ### Register multiple commands in setup Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/code/communication/commander/index.md Demonstrates adding several custom commands to the Commander instance. ```cpp void setup(){ ... commander.add('M',doSomeMotor,"some motor"); commander.add('P',doSomePID,"some pid"); commander.add('R',doSomeOtherMotor,"some other motor"); ... } ``` -------------------------------- ### Serial Command Examples for LPF Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/code/communication/commander/lpf.md Example serial monitor commands to get and set the LowPassFilter time constant. ```sh $ AF # get time constant Tf: 1.0 $ AF0.05 # set time constant Tf: 0.05 $ AW # unknown command err ``` -------------------------------- ### Example platformio.ini configuration Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/installation/library_platformio.md A standard project configuration file showing the necessary library dependency and archive settings. ```ini ; PlatformIO Project Configuration File ; ; Build options: build flags, source filter ; Upload options: custom upload port, speed and extra flags ; Library options: dependencies, extra library storages ; Advanced options: extra scripting ; ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html [env:mkrwifi1010] platform = atmelsam board = mkrwifi1010 framework = arduino lib_deps = askuric/Simple FOC@^2.2 lib_archive = false ``` -------------------------------- ### Implementing custom LED and analog commands Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/code/communication/commander/custom.md Full example demonstrating custom LED control and analog pin reading via the Commander interface. ```cpp #include // instantiate the commander Commander command = Commander(Serial); // led control function void doLed(char* cmd){ if(atoi(cmd)) digitalWrite(LED_BUILTIN, HIGH); else digitalWrite(LED_BUILTIN, LOW); }; // get analog input void doAnalog(char* cmd){ if (cmd[0] == '0') Serial.println(analogRead(A0)); else if (cmd[0] == '1') Serial.println(analogRead(A1)); else if (cmd[0] == '2') Serial.println(analogRead(A2)); else if (cmd[0] == '3') Serial.println(analogRead(A3)); else if (cmd[0] == '4') Serial.println(analogRead(A4)); }; void setup() { // define pins pinMode(LED_BUILTIN, OUTPUT); pinMode(A0, INPUT); pinMode(A1, INPUT); pinMode(A2, INPUT); pinMode(A3, INPUT); pinMode(A4, INPUT); // Serial port to be used Serial.begin(115200); // add new commands command.add('L', doLed, "led on/off"); command.add('A', doAnalog, "analog read A0-A4"); Serial.println(F("Commander listening")); Serial.println(F(" - Send ? to see the node list...")); Serial.println(F(" - Send L0 to turn the led off and L1 to turn it off")); Serial.println(F(" - Send A0-A4 to read the analog pins")); _delay(1000); } void loop() { // user communication command.run(); _delay(10); } ``` -------------------------------- ### Full Analog Sensor BLDC Motor Example Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/code/sensors/magnetic/magnetic_sensor_analog.md A complete example demonstrating the setup and loop for a BLDC motor using an analog magnetic sensor. ```cpp #include // motor and driver BLDCMotor motor = BLDCMotor(7); BLDCDriver3PWM driver = BLDCDriver3PWM(9, 5, 6, 8); // MagneticSensorAnalog(uint8_t _pinAnalog, int _min, int _max) // pinAnalog - the pin that is reading the analog output from magnetic sensor // min_raw_count - the smallest expected reading. // max_raw_count - the largest value read. MagneticSensorAnalog sensor = MagneticSensorAnalog(A1, 14, 1020); void setup() { // driver driver.init() motor.linkDriver(&driver); // init magnetic sensor hardware sensor.init(); motor.linkSensor(&sensor); // init motor hardware motor.init(); motor.initFOC(); Serial.println("Motor ready"); _delay(1000); } void loop(){ motor.loopFOC(); motor.move(); } ``` -------------------------------- ### Initialize and Start FOC for Two Motors Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/examples/haptics.md Initializes two motors and then aligns their encoders before starting the FOC process. This setup is typically done once at the beginning of the program. ```cpp motor1.init(); motor2.init(); // align encoder and start FOC motor1.initFOC(); motor2.initFOC(); ``` -------------------------------- ### Recommended Initialization Sequence Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/code/current_sense/low_side.md The correct order for initializing drivers, linking components, and starting FOC to ensure proper calibration. ```cpp void setup(){ .... // driver init driver.init(); // link the driver to the current sense current_sense.linkDriver(&driver); .... // motor init motor.init(); .... // init current sense current_sense.init(); // link the current sense to the motor motor.linkCurrentSense(¤t_sense); ... // start the FOC motor.initFOC(); } ``` -------------------------------- ### Initialize Encoder and Enable Interrupts Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/examples/position_control_example.md In the setup() function, initialize the encoder hardware and enable interrupts for channels A and B using the defined callback functions. ```cpp // initialize encoder hardware encoder.init(); // hardware interrupt enable encoder.enableInterrupts(doA, doB); ``` -------------------------------- ### Implement Encoder with Hardware Interrupts Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/code/sensors/encoder.md Example setup for an encoder using hardware-based interrupt routines. ```cpp #include Encoder encoder = Encoder(2, 3, 8192); // interrupt routine initialization void doA(){encoder.handleA();} void doB(){encoder.handleB();} void setup() { // monitoring port Serial.begin(115200); // enable/disable quadrature mode encoder.quadrature = Quadrature::ON; // check if you need internal pullups encoder.pullup = Pullup::USE_EXTERN; // initialize encoder hardware encoder.init(); // hardware interrupt enable encoder.enableInterrupts(doA, doB); Serial.println("Encoder ready"); _delay(1000); } void loop() { // IMPORTANT - call as frequently as possible // update the sensor values encoder.update(); // display the angle and the angular velocity to the terminal Serial.print(encoder.getAngle()); Serial.print("\t"); Serial.println(encoder.getVelocity()); } ``` -------------------------------- ### Position Open-Loop Control Examples Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/code/motion_control/open_loop/angle_openloop.md Basic configuration for position open-loop control using estimated current mode. The examples demonstrate setup for BLDC and Stepper motors with serial command interfaces. ```cpp // Open loop motor control example #include // BLDC motor & driver instance // BLDCMotor(pole pairs, phase resistance, KV rating) BLDCMotor motor = BLDCMotor(11, 7, 90.0); BLDCDriver3PWM driver = BLDCDriver3PWM(9, 5, 6, 8); // instantiate the commander Commander command = Commander(Serial); void doTarget(char* cmd) { command.scalar(&motor.target, cmd); } void doCurrLimit(char* cmd) { command.scalar(&motor.current_limit, cmd); } void doLimitVelocity(char* cmd) { command.scalar(&motor.velocity_limit, cmd); } void setup() { // driver config // power supply voltage [V] driver.voltage_power_supply = 12; driver.init(); // link the motor and the driver motor.linkDriver(&driver); // open loop control config motor.controller = MotionControlType::angle_openloop; // torque control mode motor.torque_controller = TorqueControlType::estimated_current; // limiting motor movements motor.updateCurrentLimit(0.5); // [Amps] motor.updateVelocityLimit(10); // [rad/s] cca 100rpm // init motor hardware motor.init(); motor.initFOC(); // add target command T command.add('T', doTarget, "target angle"); command.add('L', doCurrLimit, "current limit"); command.add('V', doLimitVelocity, "velocity limit"); Serial.begin(115200); Serial.println("Motor ready!"); Serial.println("Set target position [rad]"); _delay(1000); } void loop() { // torque control loop motor.loopFOC(); // open loop angle movements motor.move(); // user communication command.run(); } ``` ```cpp // Open loop motor control example #include // Stepper motor & driver instance // StepperMotor(steps per revolution, phase resistance, KV rating) StepperMotor motor = StepperMotor(50, 12.5, 100); StepperDriver2PWM driver = StepperDriver2PWM(9, 5, 6, 8); // instantiate the commander Commander command = Commander(Serial); void doTarget(char* cmd) { command.scalar(&motor.target, cmd); } void doCurrLimit(char* cmd) { command.scalar(&motor.current_limit, cmd); } void doLimitVelocity(char* cmd) { command.scalar(&motor.velocity_limit, cmd); } void setup() { // driver config // power supply voltage [V] driver.voltage_power_supply = 12; driver.init(); // link the motor and the driver motor.linkDriver(&driver); // open loop control config motor.controller = MotionControlType::angle_openloop; // torque control mode motor.torque_controller = TorqueControlType::estimated_current; // limiting motor movements motor.updateCurrentLimit(0.5); // [Amps] motor.updateVelocityLimit(10); // [rad/s] cca 100rpm // init motor hardware motor.init(); motor.initFOC(); // add target command T command.add('T', doTarget, "target angle"); command.add('L', doCurrLimit, "current limit"); command.add('V', doLimitVelocity, "velocity limit"); Serial.begin(115200); Serial.println("Motor ready!"); Serial.println("Set target position [rad]"); _delay(1000); } void loop() { // torque control loop motor.loopFOC(); // open loop angle movements motor.move(); // user communication command.run(); } ``` -------------------------------- ### Initialize Encoder and Enable Interrupts Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/examples/position_control_example_nucleo.md In the setup() function, initialize the encoder hardware and then enable interrupts for channels A, B, and the index channel using the defined callback functions. ```cpp // initialize encoder hardware encoder.init(); // hardware interrupt enable encoder.enableInterrupts(doA, doB, doI); ``` -------------------------------- ### Implement Encoder with Software Interrupts Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/code/sensors/encoder.md Example setup for an encoder using the PciManager library for software-based interrupts. ```cpp #include #include #include Encoder encoder = Encoder(2, 3, 8192); // interrupt routine initialization void doA(){encoder.handleA();} void doB(){encoder.handleB();} // sensor interrupt init PciListenerImp listenA(encoder.pinA, doA); PciListenerImp listenB(encoder.pinB, doB); void setup() { // monitoring port Serial.begin(115200); // enable/disable quadrature mode encoder.quadrature = Quadrature::ON; // check if you need internal pullups encoder.pullup = Pullup::USE_EXTERN; // initialize encoder hardware encoder.init(); // interrupt initialization PciManager.registerListener(&listenA); PciManager.registerListener(&listenB); Serial.println("Encoder ready"); _delay(1000); } void loop() { // IMPORTANT - call as frequently as possible // update the sensor values encoder.update(); // display the angle and the angular velocity to the terminal Serial.print(encoder.getAngle()); Serial.print("\t"); Serial.println(encoder.getVelocity()); } ``` -------------------------------- ### Serial commands for PID configuration Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/code/communication/commander/pid.md Example serial monitor interactions for getting and setting PID parameters. ```sh $ CP # get P gain P: 1.0 $ CD0.05 # set D gain D: 0.05 $ CO # unknown command err $ CL3.25 # set output limit limit: 3.25 ``` -------------------------------- ### Build Documentation Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/README.md Generates the static HTML files for the documentation site. ```bash bundle exec jekyll build ``` -------------------------------- ### Current Sense Initialization Sequence Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/code/current_sense/inline.md Recommended order for initializing drivers, current sense, and FOC algorithms within the setup process. ```cpp void loop(){ .... // driver init driver.init(); // link the driver to the current sense current_sense.linkDriver(&driver); .... // motor init motor.init(); .... // init current sense current_sense.init(); // link the current sense to the motor motor.linkCurrentSense(¤t_sense); ... // start the FOC motor.initFOC(); } ``` -------------------------------- ### Stepper Motor Index Search Implementation Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/code/motion_control/open_loop/index_search.md Full example of a Stepper motor setup using an encoder with an index signal for alignment. ```cpp #include // motor instance StepperMotor motor = StepperMotor(50); // driver instance StepperDriver2PWM driver = StepperDriver2PWM(9, 10, 11, 8); // encoder instance Encoder encoder = Encoder(2, 3, 500, A0); // channel A and B callbacks void doA(){encoder.handleA();} void doB(){encoder.handleB();} void doIndex(){encoder.handleIndex();} void setup() { // initialize encoder sensor hardware encoder.init(); encoder.enableInterrupts(doA, doB,doIndex); // link the motor to the sensor motor.linkSensor(&encoder); // driver config driver.init(); motor.linkDriver(&driver); // index search velocity [rad/s] motor.velocity_index_search = 3; // rad/s motor.voltage_sensor_align = 4; // Volts // set motion control loop to be used motor.controller = MotionControlType::velocity; // controller configuration // default parameters in defaults.h // velocity PI controller parameters motor.PID_velocity.P = 0.2; motor.PID_velocity.I = 20; // default voltage_power_supply motor.voltage_limit = 6; // jerk control using voltage voltage ramp // default value is 300 volts per sec ~ 0.3V per millisecond motor.PID_velocity.output_ramp = 1000; // velocity low pass filtering time constant motor.LPF_velocity.Tf = 0.01; // use monitoring with serial Serial.begin(115200); // comment out if not needed motor.useMonitoring(Serial); // initialize motor motor.init(); // align encoder and start FOC motor.initFOC(); Serial.println("Motor ready."); _delay(1000); } // angle set point variable float target_velocity = 2; void loop() { // main FOC algorithm function motor.loopFOC(); // Motion control function motor.move(target_velocity); } ``` -------------------------------- ### Commander Interface Tuning Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/practical/tunning_current_loop.md Examples for configuring and using the Commander interface to trigger tuning at runtime. ```cpp command.add('T', onMotor, "motor"); ``` ```sh $ TFC100 # Tune current controller with 100 Hz bandwidth ``` -------------------------------- ### BLDC Motor Index Search Implementation Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/code/motion_control/open_loop/index_search.md Full example of a BLDC motor setup using an encoder with an index signal for alignment. ```cpp #include // motor instance BLDCMotor motor = BLDCMotor(11); // driver instance BLDCDriver3PWM driver = BLDCDriver3PWM(9, 10, 11, 8); // encoder instance Encoder encoder = Encoder(2, 3, 500, A0); // channel A and B callbacks void doA(){encoder.handleA();} void doB(){encoder.handleB();} void doIndex(){encoder.handleIndex();} void setup() { // initialize encoder sensor hardware encoder.init(); encoder.enableInterrupts(doA, doB,doIndex); // link the motor to the sensor motor.linkSensor(&encoder); // driver config driver.init(); motor.linkDriver(&driver); // index search velocity [rad/s] motor.velocity_index_search = 3; // rad/s motor.voltage_sensor_align = 4; // Volts // set motion control loop to be used motor.controller = MotionControlType::velocity; // controller configuration // default parameters in defaults.h // velocity PI controller parameters motor.PID_velocity.P = 0.2; motor.PID_velocity.I = 20; // default voltage_power_supply motor.voltage_limit = 6; // jerk control using voltage voltage ramp // default value is 300 volts per sec ~ 0.3V per millisecond motor.PID_velocity.output_ramp = 1000; // velocity low pass filtering time constant motor.LPF_velocity.Tf = 0.01; // use monitoring with serial Serial.begin(115200); // comment out if not needed motor.useMonitoring(Serial); // initialize motor motor.init(); // align encoder and start FOC motor.initFOC(); Serial.println("Motor ready."); _delay(1000); } // angle set point variable float target_velocity = 2; void loop() { // main FOC algorithm function motor.loopFOC(); // Motion control function motor.move(target_velocity); } ``` -------------------------------- ### Stepper Motor Current Sense Configuration Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/code/current_sense/inline.md Example setup for Stepper motors using SimpleFOC StepShield v1 with alignment skipping. ```cpp // one possible combination of current sensing pins for SimpleFOC StepShield v1 // ACS712-05 current sensor 185mV/A InlineCurrentSense current_sense = InlineCurrentSense(185.0f, A0, A2); voi loop(){ .... // driver init driver.init(); // link the driver to the current sense current_sense.linkDriver(&driver); .... // motor init motor.init(); .... // init current sense current_sense.init(); // link the current sense to the motor motor.linkCurrentSense(¤t_sense); // skip alignment current_sense.skip_align = true; ... // start the FOC motor.initFOC(); } ``` -------------------------------- ### BLDC Motor Current Sense Configuration Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/code/current_sense/inline.md Example setup for BLDC motors using SimpleFOCShield v2, including manual gain inversion and alignment skipping. ```cpp // one possible combination of current sensing pins for SimpleFOCShield v2 // shunt - 10milliOhm // gain - 50 V/V InlineCurrentSense current_sense = InlineCurrentSense(0.01, 50.0, A0, A2); voi loop(){ .... // driver init driver.init(); // link the driver to the current sense current_sense.linkDriver(&driver); .... // motor init motor.init(); .... // init current sense current_sense.init(); // link the current sense to the motor motor.linkCurrentSense(¤t_sense); ... // invert phase b gain current_sense.gain_b *=-1; // skip alignment current_sense.skip_align = true; ... // start the FOC motor.initFOC(); } ``` -------------------------------- ### Run SimpleFOCStudio Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_libraries/tools/simplefocstudio.md Executes the main application script. ```sh python simpleFOCStudio.py ``` ```sh conda activate simplefoc python simpleFOCStudio.py ``` -------------------------------- ### Hall Sensor Initialization with Hardware Interrupts Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/code/sensors/hall_sensor.md Example of initializing a Hall sensor using hardware interrupts. This setup requires defining callback functions for each Hall sensor pin. ```cpp #include // Hall sensor instance // HallSensor(int hallA, int hallB , int hallC , int pp) // - hallA, hallB, hallC - HallSensor A, B and C pins // - pp - pole pairs HallSensor sensor = HallSensor(2, 3, 4, 11); // Interrupt routine initialization // channel A, B and C callbacks void doA(){sensor.handleA();} void doB(){sensor.handleB();} void doC(){sensor.handleC();} void setup() { // monitoring port Serial.begin(115200); // check if you need internal pullups sensor.pullup = Pullup::USE_EXTERN; // initialize sensor hardware sensor.init(); // hardware interrupt enable sensor.enableInterrupts(doA, doB, doC); Serial.println("Sensor ready"); _delay(1000); } void loop() { // IMPORTANT - call as frequently as possible // update the sensor values sensor.update(); // display the angle and the angular velocity to the terminal Serial.print(sensor.getAngle()); Serial.print("\t"); Serial.println(sensor.getVelocity()); } ``` -------------------------------- ### Configure Encoder with Index Pin and Register Listeners Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/code/sensors/encoder.md Example showing the initialization of an encoder with an index pin and the registration of listeners for A, B, and Index channels using PCIManager. ```cpp // class init Encoder encoder = Encoder(9, 10, 8192,11); void doA(){encoder.handleA();} void doB(){encoder.handleB();} void doIndex(){encoder.handleIndex();} // listeners init PciListenerImp listenerA(encoder.pinA, doA); PciListenerImp listenerB(encoder.pinB, doB); PciListenerImp listenerIndex(encoder.index_pin, doIndex); void setup(){ ... // other setup code // enable the hardware enc1.init(); // enable interrupt PciManager.registerListener(&listenerA); PciManager.registerListener(&listenerB); PciManager.registerListener(&listenerIndex); ... // rest of setup code } ``` -------------------------------- ### Initialize InlineCurrentSense with shunt resistor or mVpA Source: https://github.com/simplefoc/simplefoc.github.io/blob/master/docs/simplefoc_library/code/current_sense/inline.md Construct the sensor using either shunt resistor/gain parameters or mV per Amp ratio for hall-based sensors. ```cpp // InlineCurrentSensor constructor // - shunt_resistor - shunt resistor value // - gain - current-sense op-amp gain // - phA - A phase adc pin // - phB - B phase adc pin InlineCurrentSense current_sense = InlineCurrentSense(0.01, 20, A0, A1); ``` ```cpp // InlineCurrentSensor constructor // - mVpA - mV per Amp ratio // - phA - A phase adc pin // - phB - B phase adc pin InlineCurrentSense current_sense = InlineCurrentSense(66.0, A0, A1); ```