Adafruit STM32F405 express feather cant get pins working

All about boards manufactured by ST
Post Reply
A1bucker@yahoo.com
Posts: 7
Joined: Mon Mar 20, 2023 6:00 pm

Adafruit STM32F405 express feather cant get pins working

Post by A1bucker@yahoo.com »

I am new to the STM32duino but familiar with programming Arduino. usually libraries are not to hard to load and get running on Arduino boards or ESP32 boards but I cant seem to figure out STM32. I do have the STM32 core installed and can load blink and it works. I am trying to get a servo library to work on a single servo using sweep at the moment. Starting small. I can't get any output at any pin. i tried the pinout document from Adafruit. https://learn.adafruit.com/adafruit-stm ... ss/pinouts
but nothing works. I have tied a number of different libraries. I have even just tried to set pin output to like 10 at a time and test each pin on the controller. I am getting nothing.

I think I have to be doing something wrong with configuring for STM32 or I am not understanding pin identification and callout?

did manage to get this library to run, https://github.com/simondlevy/DshotSTM3 ... n/examples but I had to hunt for the pins. I finally got it to work on A0, A1, A2, and A3 using pin call out either D4, D5, D6, D7 or just 4, 5, 6, 7. not per Adafruit pin identification chart and why "D" on analog pins?

I am lost on configuring STM32???


My final goal is to modify this library https//github.com/simondlevy/Hackflight#readme for use with Adafruit STM32F405 feather express to control a 4 in 1 Tekko 65amp ESC https://www.getfpv.com/holybro-tekko32- ... 1-esc.html and 2 servos to control a ground vehicle with 4 motors and 2 high torque servos from a 7 channel pistol style transmitter https://www.radiolink.com/rc6gsv3.
User avatar
fpiSTM
Posts: 1738
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 91
Location: Le Mans
Contact:

Re: Adafruit STM32F405 express feather cant get pins working

Post by fpiSTM »

Could you share an example you used which didn't work? Or how you used pins?
A1bucker@yahoo.com
Posts: 7
Joined: Mon Mar 20, 2023 6:00 pm

Re: Adafruit STM32F405 express feather cant get pins working

Post by A1bucker@yahoo.com »

This is an example I was able to get to work with the pin# as I assigned it. it only turns one motor from the push of a key on the keyboard so not too useful.
To get this to work I entered pin #D4 or D5 orD6 or D7 or 4, 5, 6, 7 and it worked on A), A1, A2, A3

Code: Select all

/*
   Spin a brushless motor using an STM32 F405 MCU.
   NOTE: To get this working on the Adafruit Feather F405, use the
   Generic F405RGTx part number in the Tools menu.
   This file is part of DshotSTM32.
   DshotSTM32 is free software: you can redistribute it and/or modify it under the
   terms of the GNU General Public License as published by the Free Software
   Foundation, either version 3 of the License, or (at your option) any later
   version.
   DshotSTM32 is distributed in the hope that it will be useful, but WITHOUT ANY
   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
   PARTICULAR PURPOSE. See the GNU General Public License for more details.
   You should have received a copy of the GNU General Public License along with
   DshotSTM32. If not, see <https://www.gnu.org/licenses/>.
 */

#include <dshot_stm32f4.h>

#include <vector>

// static const uint8_t PIN = PB5;    // F411
static const uint8_t PIN = PC6;  // F405 

static std::vector<uint8_t> pins = {PIN};

static const uint32_t FREQUENCY = 8000;

static Stm32F4Dshot dshot;


extern "C" void DMA2_Stream1_IRQHandler(void) 
{
    dshot.handleDmaIrqStream1();
}

extern "C" void DMA2_Stream2_IRQHandler(void) 
{
    dshot.handleDmaIrqStream2();
}

static float motorval;

void serialEvent(void)
{
    if (Serial.available()) {
        Serial.read();
        motorval = motorval == 0 ? 0.1 : 0;
    }
}

static void run(const uint32_t usec)
{
    static uint32_t prev;

    if (usec-prev > 1000000/FREQUENCY) {
        prev = usec;
        dshot.write(&motorval);
    }
}

static void prompt(const uint32_t usec)
{
    static uint32_t prev;

    if (usec-prev > 1000000) {
        prev = usec;
        Serial.println(
                motorval == 0 ?
                "After removing propellers, hit Enter to start motor" :
                "Hit Enter to stop motor"
                );
    }
}

void setup(void)
{
    Serial.begin(115200);

    dshot.begin(pins);
}

void loop(void)
{
    const auto usec = micros();

    prompt(usec);

    run(usec);
}

Here is an example I could not get to work for motor movement through ESC. I tried the pins as called out and any combination of PA1-PA14, PB1-PB14, PC1-PC14, and PA_1-PA_14, PB_1-PB_14, PC_1-PC_14, nothing would move a servo.

Code: Select all

/* Copyright (c) 2022 Simon D. Levy 
   This file is part of Hackflight.
   Hackflight is free software: you can redistribute it and/or modify it under
   the terms of the GNU General Public License as published by the Free
   Software Foundation, either version 3 of the License, or (at your option)
   any later version.
   Hackflight is distributed in the hope that it will be useful, but WITHOUT
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
   more details.
   You should have received a copy of the GNU General Public License along with
   Hackflight. If not, see <https://www.gnu.org/licenses/>.
 */

#include <hackflight.h>
#include <boards/stm32f/stm32f4.h>
#include <core/mixers/fixedpitch/quadxbf.h>
#include <core/pids/angle.h>
#include <debug.h>
#include <escs/dshot.h>
#include <imus/softquat.h>

#include <sbus.h>

#include <vector>

#include <SPI.h>
#include <mpu6x00.h>

#include <dshot_stm32f4.h>

static const uint8_t LED_PIN     = PB5;
static const uint8_t IMU_CS_PIN  = PA4;
static const uint8_t IMU_INT_PIN = PC4;

static const uint8_t MOTOR1_PIN = PB_0;
static const uint8_t MOTOR2_PIN = PB_1;
static const uint8_t MOTOR3_PIN = PA_3;
static const uint8_t MOTOR4_PIN = PA_2;

static std::vector<uint8_t> stream1MotorPins = {MOTOR3_PIN, MOTOR4_PIN};
static std::vector<uint8_t> stream2MotorPins = {MOTOR1_PIN, MOTOR2_PIN};

static SPIClass spi = SPIClass(
        Stm32FBoard::MOSI_PIN, Stm32FBoard::MISO_PIN, Stm32FBoard::SCLK_PIN);

static Mpu6000 mpu = Mpu6000(spi, IMU_CS_PIN);

static bfs::SbusRx rx(&Serial3);

static Stm32F4Dshot dshot;

static DshotEsc esc = DshotEsc(&dshot);

///////////////////////////////////////////////////////
static AnglePidController anglePid;
static Mixer mixer = QuadXbfMixer::make();
static SoftQuatImu imu(Imu::rotate270);
static std::vector<PidController *> pids = {&anglePid};
///////////////////////////////////////////////////////

static Stm32F4Board board(LED_PIN);

extern "C" void DMA2_Stream1_IRQHandler(void) 
{
    dshot.handleDmaIrqStream1();
}

extern "C" void DMA2_Stream2_IRQHandler(void) 
{
    dshot.handleDmaIrqStream2();
}

// IMU interrupt
static void handleImuInterrupt(void)
{
    board.handleImuInterrupt(imu);
}

// Receiver interrupt
void serialEvent3(void)
{
    if (rx.Read()) {

        bfs::SbusData data = rx.data();

        board.setSbusValues((uint16_t *)data.ch, micros(), data.lost_frame);
    }
}

// Interupt from Skyranger
void serialEvent4(void)
{
    board.handleSkyrangerEvent(Serial4);
}

void setup(void)
{
    // Start receiver UART
    Serial3.begin(100000, SERIAL_8E2);

    // Start Skyranger UART
    Serial4.begin(115200);

    spi.begin();

    mpu.begin();

    board.begin(imu, IMU_INT_PIN, handleImuInterrupt);

    dshot.begin(stream1MotorPins, stream2MotorPins);
}

void loop(void)
{
    mpu.readSensor();

    int16_t rawGyro[3] = { mpu.getRawGyroX(), mpu.getRawGyroY(), mpu.getRawGyroZ() };
    int16_t rawAccel[3] = { mpu.getRawAccelX(), mpu.getRawAccelY(), mpu.getRawAccelZ() };

    // Support sending attitude data to Skyranger over Serial4
    board.step(imu, pids, mixer, esc, rawGyro, rawAccel, Serial4);
}
I also tried the standard servo library.

Code: Select all

#if !( defined(STM32F0) || defined(STM32F1) || defined(STM32F2) || defined(STM32F3) ||defined(STM32F4) || defined(STM32F7) || \
defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32H7) ||defined(STM32G0) || defined(STM32G4) || \
defined(STM32WB) || defined(STM32MP1) || defined(STM32L5))
#error This code is designed to run on STM32F/L/H/G/WB/MP1 platform! Please check your Tools->Board setting.
#endif

#define TIMER_INTERRUPT_DEBUG 0
#define ISR_SERVO_DEBUG 1

// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error
#include "STM32_ISR_Servo.h"

// Default is TIMER_SERVO (TIM7 for many boards)
#define USE_STM32_TIMER_NO TIMER_SERVO

// Published values for SG90 servos; adjust if needed
#define MIN_MICROS 800 //544
#define MAX_MICROS 2450

#define SERVO_PIN_1 D6
#define SERVO_PIN_2 D7

int servoIndex1 = -1;
int servoIndex2 = -1;

void setup()
{
Serial.begin(115200);
while (!Serial);

delay(500);

Serial.print(F("\nStarting STM32_ISR_MultiServos on ")); Serial.println(BOARD_NAME);
Serial.println(STM32_ISR_SERVO_VERSION);

//Select STM32 timer USE_STM32_TIMER_NO
STM32_ISR_Servos.useTimer(USE_STM32_TIMER_NO);

servoIndex1 = STM32_ISR_Servos.setupServo(SERVO_PIN_1, MIN_MICROS, MAX_MICROS);
servoIndex2 = STM32_ISR_Servos.setupServo(SERVO_PIN_2, MIN_MICROS, MAX_MICROS);

if (servoIndex1 != -1)
Serial.println(F("Setup Servo1 OK"));
else
Serial.println(F("Setup Servo1 failed"));

if (servoIndex2 != -1)
Serial.println(F("Setup Servo2 OK"));
else
Serial.println(F("Setup Servo2 failed"));
}

void loop()
{
int position;

if ( ( servoIndex1 != -1) && ( servoIndex2 != -1) )
{
for (position = 0; position <= 180; position++)
{
// goes from 0 degrees to 180 degrees
// in steps of 1 degree

if (position % 30 == 0)
{
Serial.print(F("Servo1 pos = ")); Serial.print(position);
Serial.print(F(", Servo2 pos = ")); Serial.println(180 - position);
}

STM32_ISR_Servos.setPosition(servoIndex1, position);
STM32_ISR_Servos.setPosition(servoIndex2, 180 - position);
// waits 30ms for the servo to reach the position
delay(30);
}

delay(5000);

for (position = 180; position >= 0; position--)
{
// goes from 180 degrees to 0 degrees
if (position % 30 == 0)
{
Serial.print(F("Servo1 pos = ")); Serial.print(position);
Serial.print(F(", Servo2 pos = ")); Serial.println(180 - position);
}

STM32_ISR_Servos.setPosition(servoIndex1, position);
STM32_ISR_Servos.setPosition(servoIndex2, 180 - position);
// waits 30ms for the servo to reach the position
delay(30);
}

delay(5000);
}
}
Last edited by A1bucker@yahoo.com on Mon Mar 27, 2023 7:43 pm, edited 1 time in total.
A1bucker@yahoo.com
Posts: 7
Joined: Mon Mar 20, 2023 6:00 pm

Re: Adafruit STM32F405 express feather cant get pins working

Post by A1bucker@yahoo.com »

Perhaps someone could post a servo sweep code that should work with Adafruit stm32f405 and I can upload and see if it works? I am okay starting this learning process on a slow curve.
User avatar
fpiSTM
Posts: 1738
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 91
Location: Le Mans
Contact:

Re: Adafruit STM32F405 express feather cant get pins working

Post by fpiSTM »

Where you got those examples?
A1bucker@yahoo.com
Posts: 7
Joined: Mon Mar 20, 2023 6:00 pm

Re: Adafruit STM32F405 express feather cant get pins working

Post by A1bucker@yahoo.com »

Links are in my first post. Github
A1bucker@yahoo.com
Posts: 7
Joined: Mon Mar 20, 2023 6:00 pm

Re: Adafruit STM32F405 express feather cant get pins working

Post by A1bucker@yahoo.com »

1st STM32 problem solved, 100% user. needed to add a ground wire between STM board and servo.

this simple example works.

Code: Select all

/* Sweep
 by BARRAGAN <http://barraganstudio.com>
 This example code is in the public domain.

 modified 8 Nov 2013
 by Scott Fitzgerald
 https://www.arduino.cc/en/Tutorial/LibraryExamples/Sweep
*/

#include <Servo.h>

Servo myservo;  // create servo object to control a servo
// twelve servo objects can be created on most boards

int pos = 0;    // variable to store the servo position

void setup() {
  myservo.attach(D9);  // attaches the servo on pin 9 to the servo object
}

void loop() {
  for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
    // in steps of 1 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15 ms for the servo to reach the position
  }
  for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15 ms for the servo to reach the position
  }
}
But that is a really simple program and my servo does not move smoothly. So I tried this one which is supposed to be for STM32F series controllers. It does not work. I tried many versions of pin names.

Code: Select all

#if !( defined(STM32F0) || defined(STM32F1) || defined(STM32F2) || defined(STM32F3)  ||defined(STM32F4) || defined(STM32F7) || \
       defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32H7)  ||defined(STM32G0) || defined(STM32G4) || \
       defined(STM32WB) || defined(STM32MP1) || defined(STM32L5))
  #error This code is designed to run on STM32F/L/H/G/WB/MP1 platform! Please check your Tools->Board setting.
#endif

#define TIMER_INTERRUPT_DEBUG       0
#define ISR_SERVO_DEBUG             1

// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error
#include "STM32_ISR_Servo.h"

// Default is TIMER_SERVO (TIM7 for many boards)
#define USE_STM32_TIMER_NO          TIMER_SERVO

// Published values for SG90 servos; adjust if needed
#define MIN_MICROS       700  //544
#define MAX_MICROS        2100

#define SERVO_PIN_1       D9
#define SERVO_PIN_2       12
#define SERVO_PIN_3       A3
#define SERVO_PIN_4       PA4
#define SERVO_PIN_5       PB5
#define SERVO_PIN_6       PC6

typedef struct
{
  int     servoIndex;
  uint8_t servoPin;
} ISR_servo_t;

#if ( defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32L5) )

  #define NUM_SERVOS        3
  
  ISR_servo_t ISR_servo[NUM_SERVOS] =
  {
    { -1, SERVO_PIN_1 }, { -1, SERVO_PIN_2 }, { -1, SERVO_PIN_3 }
  };

#else

  #define NUM_SERVOS        6

  ISR_servo_t ISR_servo[NUM_SERVOS] =
  {
    { -1, SERVO_PIN_1 }, { -1, SERVO_PIN_2 }, { -1, SERVO_PIN_3 }, { -1, SERVO_PIN_4 }, { -1, SERVO_PIN_5 }, { -1, SERVO_PIN_6 }
  };

#endif

void setup()
{
  Serial.begin(115200);
  while (!Serial);

  delay(200);

  Serial.print(F("\nStarting MultipleRandomServos on ")); Serial.println(BOARD_NAME);
  Serial.println(STM32_ISR_SERVO_VERSION);

  //Select STM32 timer USE_STM32_TIMER_NO
  STM32_ISR_Servos.useTimer(USE_STM32_TIMER_NO);

  for (int index = 0; index < NUM_SERVOS; index++)
  {
    ISR_servo[index].servoIndex = STM32_ISR_Servos.setupServo(ISR_servo[index].servoPin, MIN_MICROS, MAX_MICROS);

    if (ISR_servo[index].servoIndex != -1)
    {
      Serial.print(F("Setup OK Servo index = ")); Serial.println(ISR_servo[index].servoIndex);
    }
    else
    {
      Serial.print(F("Setup Failed Servo index = ")); Serial.println(ISR_servo[index].servoIndex);
    }
  }
}

void printServoInfo(int indexServo)
{
  Serial.print(F("Servos idx = "));
  Serial.print(indexServo);
  Serial.print(F(", act. pos. (deg) = "));
  Serial.print(STM32_ISR_Servos.getPosition(ISR_servo[indexServo].servoIndex) );
  Serial.print(F(", pulseWidth (us) = "));
  Serial.println(STM32_ISR_Servos.getPulseWidth(ISR_servo[indexServo].servoIndex));
}

void loop()
{
  int position;      // position in degrees

  position = 0;
  Serial.println(F("Servos @ 0 degree"));
  
  for (int index = 0; index < NUM_SERVOS; index++)
  {
    STM32_ISR_Servos.setPosition(ISR_servo[index].servoIndex, position );
    printServoInfo(index);
  }
  
  // waits 5s between test
  delay(1000);

  position = 90;
  Serial.println(F("Servos @ 90 degree"));
  
  for (int index = 0; index < NUM_SERVOS; index++)
  {
    STM32_ISR_Servos.setPosition(ISR_servo[index].servoIndex, position );
    printServoInfo(index);
  }
  
  // waits 5s between test
  delay(1000);

  position = 180;
  Serial.println(F("Servos @ 180 degree"));
  
  for (int index = 0; index < NUM_SERVOS; index++)
  {
    STM32_ISR_Servos.setPosition(ISR_servo[index].servoIndex, position );
    printServoInfo(index);
  }
  
  // waits 5s between test
  delay(1000);

  Serial.println(F("Servos sweeps from 0-180 degress"));
  
  for (position = 0; position <= 180; position += 1)
  {
    // goes from 0 degrees to 180 degrees
    // in steps of 1 degree
    for (int index = 0; index < NUM_SERVOS; index++)
    {
      STM32_ISR_Servos.setPosition(ISR_servo[index].servoIndex, position );
    }
    
    // waits 50ms for the servo to reach the position
    delay(50);
  }
  
  // waits 5s between test
  delay(1000);

  Serial.println(F("Servos sweeps from 180-0 degress"));
  
  for (position = 180; position >= 0; position -= 1)
  {
    // goes from 0 degrees to 180 degrees
    // in steps of 1 degree
    for (int index = 0; index < NUM_SERVOS; index++)
    {
      STM32_ISR_Servos.setPosition(ISR_servo[index].servoIndex, position );
    }
    
    // waits 50ms for the servo to reach the position
    delay(50);
  }
  
  // waits 5s between test
  delay(1000);

  Serial.println(F("Servos, index depending, be somewhere from 0-180 degress"));
  
  for (position = 0; position <= 180; position += 1)
  {
    // goes from 0 degrees to 180 degrees
    // in steps of 1 degree
    for (int index = 0; index < NUM_SERVOS; index++)
    {
      STM32_ISR_Servos.setPosition(ISR_servo[index].servoIndex, (position + index * (180 / NUM_SERVOS)) % 180 );
    }
    
    // waits 50ms for the servo to reach the position
    delay(50);
  }
  
  delay(1000);

  Serial.println(F("Servos, index depending, be somewhere from 180-0 degress"));
  
  for (position = 180; position >= 0; position -= 1)
  {
    // goes from 0 degrees to 180 degrees
    // in steps of 1 degree
    for (int index = 0; index < NUM_SERVOS; index++)
    {
      STM32_ISR_Servos.setPosition(ISR_servo[index].servoIndex, (position + index * (180 / NUM_SERVOS)) % 180 );
    }
    
    // waits 50ms for the servo to reach the position
    delay(50);
  }
  
  // waits 5s between test
  delay(1000);
}
Post Reply

Return to “STM boards (Discovery, Eval, Nucleo, ...)”