Arduino + SimpleFOC smallest footprint

Should be a simple answer, but I can’t find a straight answer.
I have a project I’m pretty happy with, running a BLDC motor at set speeds using 2 buttons and a toggle switch for the speed change. The motor is set to turn at 33.3 and 45rpm, it seems to work really well. However, the footprint is a little too large. Not unworkable, but I’d like to make the whole project smaller.

i currently have an Arduino UNO (Elgoo version) and a SimpleFOC shield stacked on top. The 5208 motor goes to the SimpleFOC, power to the shield, and buttons wired through the Shield to the Arduino.
What I would like is to use something like an Uno compatible board (Elgoo Nano?), running with SimpleFOC mini to keep the height down to a minimum.

Is this possible without two power supplies? I’m not sure the SimpleFOC can deliver enough power for the Arduino, unless I’m just completely missing how some things work (very possible, I’m brand new to all of this).

I’m not really concerned with a lot of wires, as I can just route them around the cavity - it’s the height that poses an issue.

Is there another alternative that would let me achieve this, if this isn’t possible? Like power into something that would split the power into the two components as required?

To be honest I still don’t understand how your current Uno is being powered from the shield.

Being “powered” would imply that it continues to work even when the uploading USB cable is unplugged from the computer. Is that the case? Otherwise, if the Arduino UNO lights come on only when it is plugged into your computer, then it is not being powered from the shield.

The reason I ask is, both the Uno and Nano have a Vin pin, which can be given a supply between 7 to 12v, for powering without USB. This is usually a typical solution for your problem, but not when high inductive loads like motors are involved. The injected voltage spikes and drops will cause the supply to go outside 7-12V momentarily and repeatedly, causing damage or resets in the Arduino.

That is why you need a better managed voltage regulator, or a buck converter as you correctly guessed. The ones used on drones and high power rc cars are precisely suited to this task, just search for “5V UBEC” on amazon. I myself use this and it works: Amazon.com: 2 Pack ShareGoo 3A 5V DC-DC Converter Step Down UBEC Module for RC Quadcopter Plane FPV Holder Camera Servo Power Supply : Toys & Games The output of this should give 5V, the red wire should go straight into the Nano’s Vin pin. Your power supply needs to be at least 9V for it to work reliably.

OR
If you don’t want to mess around with all that, here is something else I use that works really well. A wall adapter that provides two outputs, one an adjustable high voltage for the shield/motor, and a separate, dedicated 5V USB output. Using that you can simply power the Arduino Nano with a usb cable.
https://www.amazon.com/gp/product/B07J6RC43S/

Just in case you are still looking for the smallest footprint, I have made a motor-shield/mini driver sandwich with a waveshare RP2040 zero
It is possible to program it via your arduino IDE and pretty fast.

What is your power supply voltage, and what type is it? Battery, wall adapter etc?

  1. In your current setup, how is the Arduino Uno being powered? The same method should work for the Arduino Nano since they are both quite similar in their power requirements.

  2. I have never used the Mini, but looking at the design it seems the on-board regulator on the Mini can only provide 3.3V, whereas Arduino Nano requires 5V.

  3. If your current Uno based setup is working acceptably, and the only problem is the height, then why don’t you just replace the Mini’s 90-deg stacking header with a regular straight header (will require desoldering and re-soldering, but it looks like only 5 pins from the pictures. Then the Mini will be flat and upside down over the Uno (or you could make it flat and right-side up). You will need to give some structural support to it to make sure there is no unintended flexing.

Update…
So I received the Nano from Amazon (cheap clone) and tried to create a replica setup of my original attempt. However, the same code seems to just make the BLDC motor vibrate a little (feels like a small amount of cogging, but doesn’t turn.
My plan, was to have a single power input from a DC plug, into 2x buck converters - one set to 5v, the other to 12v.
Everything I have read says that the Nano should operate the same as the Uno, so the code should work. I wired it up with a SimpleFOC mini, which is what I used before the full shield, and had it working. But it doesn’t with this setup.
I then tried to go back to basics, and have it wired up the same as I had it with the original - USB powering the Nano (was the uno in the first attempt) and DC power to the SimpleFOC Mini. But it just doesn’t work.
I have a couple of potentials, unless someone can point me in the direction of a better answer:

  1. The Board is a bad one, and just doesn’t work
  2. My power setup did something to the nano and killed it (operationally speaking - it still powers up with lights on)
  3. Other - something I’m not aware of

Ideally, I’d like a small footprint setup, with a single power in, driving a small arduino like a nano, and a SimpleFOC mini type driver baord, for the smallest footprint possible.
Any ideas?

Thanks
5.

I have some of these I can send you if you’re interested:

It kinda sounds like what you’re looking for. It has the same power levels as the SimpleFOC Mini, but is easier to use. I have matching magnetic sensor boards that plug right into it, it’s very easy to set up.

The best Nano to use with it is the Nano ESP32, but it will work with any of the Arduino Nanos except the new Nano Matter.

This is my current setup - minus on pin from the other connection on the switch, which I broke off this morning in a hurry.

Looks like you‘re using pins 5,6,9 for PWM, and 8 for enable? Seems ok.

Would you mind sharing the test code you’ve been running?

/// Open loop motor control example
#include <SimpleFOC.h>
bool doonce = 1;
int debouncetime = 10000;

const int BUTTON_PIN = 10;

int input4Pin = 13;
int input3Pin = 12;
int input2Pin = 11;
int input1Pin = 10; 
// this declares each of our buttons and their pins
// make sure that you use the pins your buttons are wired to

// BLDC motor & driver instance
// BLDCMotor motor = BLDCMotor(pole pair number);
BLDCMotor motor = BLDCMotor (11);
// BLDCDriver3PWM driver = BLDCDriver3PWM(pwmA, pwmB, pwmC, Enable(optional));
BLDCDriver3PWM driver = BLDCDriver3PWM(9, 5, 6, 8);

// Stepper motor & driver instance
//StepperMotor motor = StepperMotor(50);
//StepperDriver4PWM driver = StepperDriver4PWM(9, 5, 10, 6,  8);

void setup() {
  pinMode(input4Pin, INPUT_PULLUP);
  pinMode(input3Pin, INPUT_PULLUP);
  pinMode(input2Pin, INPUT_PULLUP);
  pinMode(input1Pin, INPUT_PULLUP); // these lines declare each of the buttons as an input

   // driver config
  // power supply voltage [V]
  driver.voltage_power_supply = 4.448; //12 then 4.4
  // limit the maximal dc voltage the driver can set
  // as a protection measure for the low-resistance motors
  // this value is fixed on startup
  driver.voltage_limit = 12; //12
  driver.init();
  // link the motor and the driver
  motor.linkDriver(&driver);

  // limiting motor current (provided resistance)
  //motor.current_limit = 0.058824;   // [Amps was 0.35]

  motor.voltage_limit = 1;
 
  // open loop control config
  motor.controller = MotionControlType::velocity_openloop;

  // init motor hardware
  motor.init();

  Serial.begin(115200);
  Serial.println("Motor ready!");
  Serial.println("Set target velocity [rad/s]");
  _delay(1000);

  motor.disable(); // stops motor
}

  void loop() {

     // read the state of the switch/button:
  int buttonState = digitalRead(BUTTON_PIN);

  // print out the button's state 
  Serial.println(buttonState);

 // button on pin 10
  if (digitalRead(10)==LOW) { // high state means on
       motor.disable(); // stops motor
    }
// button on pin 11
  if (digitalRead(11)==LOW) { // high state means on
     motor.move(3.484)
     digitalWrite; // this button sets the speed to 33.3rpm
  }
 
 // button on pin 12
  if (digitalRead(12)==LOW) { // high state means on
     motor.move(4.709); // this button sets the speed to 45rpm 39.071
    }
// button on pin 13
  if (digitalRead(13)==LOW) { // high state means on
     motor.enable(); // starts motor
     doonce = 1;
      delay(debouncetime);
  }

}

Hey, so looking at the code, I am wondering if these are push buttons or toggle buttons?

The move() function has to be called often, once per iteration of the main loop. If these were momentary push buttons that would not be happening.

If they are toggle buttons, then I also wonder why to have four of them? From a UX perspective this makes no sense because the user could set enable and disable at the same time or 45 and 33 rpm at the same time.
In reality you only need one toggle button for each function… one selects between 33 and 45 rpm, and the other is for enabling/disabling.
I also would not check the buttons each time through the loop. I’d check them maybe 10x per second, maximum, to help with debouncing.

All in all for testing the motor I would recommend removing all the code related to the buttons, just leave a call to motor.move() in the main loop, and see if it’s working then.
If so, you can add a new button code back in, step by step and carefully, and make sure it’s all working after each step.

Maybe I’ve commented out too much, or just incorrectly, but I tried a couple of different ways…

this is the code

/// Open loop motor control example
#include <SimpleFOC.h>
bool doonce = 1;
int debouncetime = 10000;

//const int BUTTON_PIN = 10;

//int input4Pin = 13;
//int input3Pin = 12;
//int input2Pin = 11;
//int input1Pin = 10; 
// this declares each of our buttons and their pins
// make sure that you use the pins your buttons are wired to

// BLDC motor & driver instance
// BLDCMotor motor = BLDCMotor(pole pair number);
BLDCMotor motor = BLDCMotor (11);
// BLDCDriver3PWM driver = BLDCDriver3PWM(pwmA, pwmB, pwmC, Enable(optional));
BLDCDriver3PWM driver = BLDCDriver3PWM(9, 5, 6, 8);

// Stepper motor & driver instance
//StepperMotor motor = StepperMotor(50);
//StepperDriver4PWM driver = StepperDriver4PWM(9, 5, 10, 6,  8);

void setup() {
  //pinMode(input4Pin, INPUT_PULLUP);
  //pinMode(input3Pin, INPUT_PULLUP);
  //pinMode(input2Pin, INPUT_PULLUP);
  //pinMode(input1Pin, INPUT_PULLUP); // these lines declare each of the buttons as an input

   // driver config
  // power supply voltage [V]
  driver.voltage_power_supply = 12; //12 then 4.4
  // limit the maximal dc voltage the driver can set
  // as a protection measure for the low-resistance motors
  // this value is fixed on startup
  driver.voltage_limit = 12; //12
  driver.init();
  // link the motor and the driver
  motor.linkDriver(&driver);

  // limiting motor current (provided resistance)
  //motor.current_limit = 0.058824;   // [Amps was 0.35]

  motor.voltage_limit = 1;
 
  // open loop control config
  motor.controller = MotionControlType::velocity_openloop;

  // init motor hardware
  motor.init();

  Serial.begin(115200);
  Serial.println("Motor ready!");
  Serial.println("Set target velocity [rad/s]");
  _delay(1000);

  motor.disable(); // stops motor
}

  void loop() {

     // read the state of the switch/button:
  //int buttonState = digitalRead(BUTTON_PIN);

  // print out the button's state 
  //Serial.println(buttonState);

 // button on pin 10
//  if (digitalRead(10)==LOW) { // high state means on
//       motor.disable(); // stops motor
 //   }
// button on pin 11
//  if (digitalRead(11)==LOW) { // high state means on
     motor.move(3.484);
 //    digitalWrite; // this button sets the speed to 33.3rpm
//  }
 
 // button on pin 12
//  if (digitalRead(12)==LOW) { // high state means on
//     motor.move(4.709); // this button sets the speed to 45rpm 39.071
//    }
// button on pin 13
//  if (digitalRead(13)==LOW) { // high state means on
//     motor.enable(); // starts motor
//     doonce = 1;
//      delay(debouncetime);
//  }

}

But I get a vibrate for a second, then nothing

That looks ok, but you do have to enable the motor, and also 1V voltage limit seems a bit low to me, although that depends on the motor you’re using…

Here are a couple of video’s of the nano and UNO. The noise on the UNO is laregly the base it’s on. If you hold it at the bottom, it’s much quieter.

The nano is running this code:

/// Open loop motor control example
#include <SimpleFOC.h>
bool doonce = 1;
int debouncetime = 10000;

const int BUTTON_PIN = 10;

int input4Pin = 13;
int input3Pin = 12;
int input2Pin = 11;
int input1Pin = 10; 
// this declares each of our buttons and their pins
// make sure that you use the pins your buttons are wired to

// BLDC motor & driver instance
// BLDCMotor motor = BLDCMotor(pole pair number);
BLDCMotor motor = BLDCMotor (11);
// BLDCDriver3PWM driver = BLDCDriver3PWM(pwmA, pwmB, pwmC, Enable(optional));
BLDCDriver3PWM driver = BLDCDriver3PWM(9, 5, 6, 8);


void setup() {
  pinMode(input4Pin, INPUT_PULLUP);
  pinMode(input3Pin, INPUT_PULLUP);
  pinMode(input2Pin, INPUT_PULLUP);
  pinMode(input1Pin, INPUT_PULLUP); // these lines declare each of the buttons as an input

   // driver config
  // power supply voltage [V]
  driver.voltage_power_supply = 12; //12 then 4.4
  // limit the maximal dc voltage the driver can set
  // as a protection measure for the low-resistance motors
  // this value is fixed on startup
  driver.voltage_limit = 12; //12
  driver.init();
  // link the motor and the driver
  motor.linkDriver(&driver);


  motor.voltage_limit = 1;
 
  // open loop control config
  motor.controller = MotionControlType::velocity_openloop;

  // init motor hardware
  motor.init();

  Serial.begin(115200);
  Serial.println("Motor ready!");
  Serial.println("Set target velocity [rad/s]");
  _delay(1000);

  motor.disable(); // stops motor
}

  void loop() {

motor.enable();

motor.move(3.334);

     // read the state of the switch/button:
//  int buttonState = digitalRead(BUTTON_PIN);

  // print out the button's state 
 // Serial.println(buttonState);

 // button on pin 10
 // if (digitalRead(10)==LOW) { // high state means on
 //      motor.disable(); // stops motor
 //   }
// button on pin 11
//  if (digitalRead(11)==LOW) { // high state means on
 //    motor.move(30); // this button sets the speed to 33.3rpm
//  }
 
 // button on pin 12
 // if (digitalRead(12)==LOW) { // high state means on
 //    motor.move(50); // this button sets the speed to 45rpm 39.071
 //   }
// button on pin 13
 // if (digitalRead(13)==LOW) { // high state means on
      // starts motor
  //   doonce = 1;
  //    delay(debouncetime);
 // }

}

Progress - ISH…

I went back to basics, and found the below code, where I modified the motor.target based on 6.28 being 1 Revolution per second, and adjusted to get close to 33.3RPM and 45RPM.
I’ve left out the button stuff, for now - I just wanted to get the motor moving.

The only issue I have here (until I start adding bits) is the consistency of movement.
it fluctuates around 33.3 and 45, but with slight dips and spikes (more than with the FOC Shield and Uno.

So - My question for right now, is - is this due to the code and fluctuations the voltage as indicated by me, or is that more likely to be from poor voltage / current supplied by my FOC Mini, which I suspect to be a clone (Amazon UK Purchase).

Is this something that the proper FOC mini would solve, or is the issue still in the code (or a combination)?

side Question - The official page says out of stock on the thumbnails for the SimpleFOC boards, but the main page shows an order button. Are they available officially, or is the shop no longer an official channel? I can buy from AliExpress, but if the board i have is the issue, I have no guarantee that the one I get from somewhere else would be made using bettr components.

#include <SimpleFOC.h>

// BLDCMotor(pole pair number, phase resistance (optional) );
BLDCMotor motor = BLDCMotor(11);
// BLDCDriver3PWM(pwmA, pwmB, pwmC, Enable(optional));
BLDCDriver3PWM driver = BLDCDriver3PWM(9, 5, 6, 8);

// instantiate the commander
Commander command = Commander(Serial);
void doTarget(char* cmd) { command.scalar(&motor.target, cmd); }
void doLimit(char* cmd) { command.scalar(&motor.voltage_limit, cmd); }

void setup() {

  // use monitoring with serial 
  Serial.begin(115200);
  // enable more verbose output for debugging
  // comment out if not needed
  SimpleFOCDebug::enable(&Serial);

  // driver config
  // power supply voltage [V]
  driver.voltage_power_supply = 12;
  // limit the maximal dc voltage the driver can set
  // as a protection measure for the low-resistance motors
  // this value is fixed on startup
  driver.voltage_limit = 6;
  if(!driver.init()){
    Serial.println("Driver init failed!");
    return;
  }
  // link the motor and the driver
  motor.linkDriver(&driver);

  // limiting motor movements
  // limit the voltage to be set to the motor
  // start very low for high resistance motors
  // current = voltage / resistance, so try to be well under 1Amp
  motor.voltage_limit = 12;   // [V]
 
  // open loop control config
  motor.controller = MotionControlType::velocity_openloop;

  // init motor hardware
  if(!motor.init()){
    Serial.println("Motor init failed!");
    return;
  }

  // set the target velocity [rad/s]
  //motor.target = 3.48; // 33.3RPM
  motor.target = 4.71; // 45RPM

  // add target command T
  command.add('T', doTarget, "target velocity");
  command.add('L', doLimit, "voltage limit");

  Serial.println("Motor ready!");
  Serial.println("Set target velocity [rad/s]");
  _delay(1000);
}

void loop() {

  // open loop velocity movement
  motor.move();

  // user communication
  command.run();
}