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);
}
}