Problem using two motors using magnetic sensors with SPI and stacked SimpleFOCShields

I’m working on a project (a self-balancing robot) that requires the use of two gimbal motors (iPower GM4108) with AS5048A magnetic sensors using SPI. To control them, I’d like to use two stacked SimpleFOCShields (v2.0.4) on a Wemos D1 R32. I’ve been successful at getting one or the other motor/sensor/shields to work, but have run into difficulties getting both sets working simultaneously, specifically due to the fact that the second one requires the use of either pin 11 or 13 for PWM C (the first set is using pin 6 for PWM C). Unfortunately, pins 11 and 13 are already being used for the magnetic sensors’ SPI (MOSI is pin 11, and SCK is pin 13), and so they are not available for PWM C.

I’ve come up with two possible solutions, but I’m not sure of the feasibility of either, so some advice (or other suggestions) would be greatly suggested.

First, would it be possible to move the SPI to other pins? I’ve seen references to SPI done in software, but that supposedly has speed constraints that would probably preclude its use in a self-balancing bot. But I’ve also seen reference (see page 12 at https://www.halloweenfreak.de/arduino/pdfs/D1_R32_ENG.pdf) to two SPI circuits within the ESP32, a VSPI that maps onto the labelled SPI pins on the Wemos (GPIO23, 19, 18 and 5), and an HSPI that uses different pins (GPIO13, 12, 14 and 15). Is it possibly to use the HSPI for the magnetic encoders (in order to free up pin 11 or 13 for use as PWM C), and if so how would that be accomplished in the program?

As a second possibility, would it be possible to solder a jumper wire between the central solder pad for PWM C and an unused pin on the shield (instead on jumping the central solder pad to the pads for pins 11 or 13)? For example, could a jumper wire be used to connect the central PWM C pad to pin 4 of the shield (GPIO17 on the Wemos, which can be used for PWM)?

Any advice you have on these two possibilities, or others, would be greatly appreciated!

You need two separate shields.

Cheers,
Valentine

To be clear, we do have two shields, but they are stacked on a single microcontroller. Am I correct in thinking that by “separate”, you mean that they can’t be stacked, but must be individually controlled by their own microcontrollers? That would make coordination between the microcontrollers difficult.

I think the SPI on ESP32 can be done on soft peripherals but your issue will be that I think there are already basically few or no free pins, on the Arduino Uno style shield.
Is I2C possible? The latency will be higher but the shields were designed for be used 2x I2C, not 2x SPI (afaik).

yes you do need two controllers. yes its a complicated problem. you need a third controller to command the two motor controllers using serial or i2c or canbus. your project is nontrivial. perhaps others on this board may have different opinions.

Pin mapping is a pain. But you might be ok - here is my attempt. It looks as if there are no collisions on VSPI.

// VSPI pins MOSI, MISO, SCK, CS = 23, 19, 18, 5
// HSPI pins MOSI, MISO, SCK, CS = 13, 12, 14, 15

// for driver 1
#define UNO_10 4
#define UNO_5 16
#define UNO_6 27
#define UNO_8 12

// for driver 2
#define UNO_9 13
#define UNO_3 25
#define UNO_11 23
#define UNO_7 14

BLDCDriver3PWM driver1 = BLDCDriver3PWM(UNO_10, UNO_5, UNO_6, UNO_8);
BLDCDriver3PWM driver2 = BLDCDriver3PWM(UNO_9, UNO_3, UNO_11, UNO_7);

It’s quite possible that I’ve got something wrong in the above. It is difficult to map UNO pins to UNO compatible boards that have different numbers.

I think VSPI is the default so you won’t have to do weird things like:

// Unecessary
SPIClass SPI_2(HSPI);
void setup()
{
...
sensor.init(&SPI_2);

You’ll (of course) need to do the solder bridges on the shields appropriately.

Another thing you might want to explore is buying some simplefoc mini boards (they don’t stack) or just using the shields without stacking them. When ever I’ve used the shields, I’ve never stacked them e.g. if I’m using it with an stm blue pill or a nano style esp32

1 Like

Thanks, Owen. You were right that remapping the SPI pins was a bit of a pain, but it DID work – we now have two fully controllable gimbals. I received your message when we were partway through remapping the HSPI, so we just continued in that direction (your way would have been a little easier).

Here’s the relevant code that we used:

#include <SimpleFOC.h>

// alternative pinout
#define HSPI_MISO 19
#define HSPI_MOSI 26
#define HSPI_SCLK 3
#define HSPI_SS 17
#define HSPI_SS2 18

MagneticSensorSPI sensor1 = MagneticSensorSPI(AS5048_SPI, HSPI_SS);
MagneticSensorSPI sensor2 = MagneticSensorSPI(AS5048_SPI, HSPI_SS2);

SPIClass SPI_2(HSPI);

BLDCMotor motor1 = BLDCMotor(11);
BLDCDriver3PWM driver1 = BLDCDriver3PWM(16, 13, 27, 12);
BLDCMotor motor2 = BLDCMotor(11);
BLDCDriver3PWM driver2 = BLDCDriver3PWM(25, 5, 23, 14);

void setup() {
  // start the newly defined spi communication
  SPI_2.begin(HSPI_SCLK, HSPI_MISO, HSPI_MOSI, HSPI_SS); 

  sensor1.init(&SPI_2);
  sensor2.init(&SPI_2);

  motor1.linkSensor(&sensor1);
  motor2.linkSensor(&sensor2);

  driver1.voltage_power_supply = 11.1;
  driver2.voltage_power_supply = 11.1;
  driver1.init();
  driver2.init();

  motor1.linkDriver(&driver1);
  motor2.linkDriver(&driver2);

  motor1.controller = MotionControlType::velocity;
  motor2.controller = MotionControlType::velocity;

  motor1.init();
  motor2.init();

  motor1.initFOC();
  motor2.initFOC();
}

void loop() {
  motor1.loopFOC();
  motor2.loopFOC();

  motor1.move(120);
  motor2.move(120);

}

Thanks for all of the advice!

3 Likes

Hey, I’m glad to read it worked out!

For future readers: one of the big advantages of ESP32 is its PinMux - you can reassign SPI pins (and also the PWM outputs) to any (IO-capable) pins you like.
That’s a big difference to the other MCUs, where you’re typically limited to one or a few pin-choices for each peripheral.