Using PCA9685 and USB Serial at same time results in crash/freezing of STM32

Post here first, or if you can't find a relevant section!
Post Reply
TheMaskedChameleon
Posts: 3
Joined: Tue Apr 21, 2020 7:21 pm

Using PCA9685 and USB Serial at same time results in crash/freezing of STM32

Post by TheMaskedChameleon »

Hi
I've been trying to write some code for a walking robot.
My idea has been to write a class that controls one of the legs. The class would take the desired XY coordinates of the foot, calculate the required joint angles and send the appropiate PWM to the servos on that leg.
The mainboard I'm using is the Adafruit STM32 Feather, connected to a PCA9685 breakout which controls the servos (Using Adafruits servo driver library).
However, I have encounted a problem when using the servo driver library with usb serial.

Heres my code so far:

main.cpp

Code: Select all

#include <Arduino.h>
#include <Adafruit_NeoPixel.h>      // For the Feather on-board RGB LED (Neopixel)
#include <Adafruit_PWMServoDriver.h>
#include "leg.h"                    // Leg class to control one of the legs

// On-board Neopixel
Adafruit_NeoPixel pixels(1, 8, NEO_GRB + NEO_KHZ800);

// Legs
leg front_right(0, 1, 2);


void setup() {

  pixels.begin();
  pixels.clear();     // Set all pixel colors to 'off'
  
  pixels.setPixelColor(0, pixels.Color(0, 0, 31));      // Blue at ~1/8 brightness
  pixels.show();      // Send the updated pixel colors to the hardware.

  Serial.begin(115200);

  Serial.println(F("QUAD WALKER"));

  delay(1000);
  pixels.setPixelColor(0, pixels.Color(0, 31, 0));      // Green at ~1/8 brightness
  pixels.show();      // Send the updated pixel colors to the hardware.
}

void loop() {

  Serial.println(millis());
  delay(500);


  // Toggle onboard LED #13 #PC1
  digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}
leg.h

Code: Select all

#ifndef leg_h
#define leg_h

#include <Arduino.h>
#include <Adafruit_PWMServoDriver.h>

class leg : Adafruit_PWMServoDriver{

    public:
        leg(int coxa, int femur, int tibia);
        
        void set_angle_limits(int min, int max);
        void set_foot_position(int new_x, int new_y, int new_z);

        int get_x_position();
        int get_y_position();
        int get_z_position();

    private:
        int _coxa;          // Servo pin
        int _femur;         // Servo pin
        int _tibia;         // Servo pin

        int current_x;      // Position
        int current_y;      // Position
        int current_z;      // Position

        int _current_coxa;  // Angle
        int _current_femur; // Angle
        int _current_tibia; // Angle
        int _new_coxa;      // Angle
        int _new_femur;     // Angle
        int _new_tibia;     // Angle

        int _min_angle = 0;     // Minimum servo angle, decided by mechanics
        int _max_angle = 180;   // Maximum servo angle, decided by mechanics

};

#endif // leg_h
leg.cpp

Code: Select all

#include "leg.h"

leg::leg(int coxa, int femur, int tibia){

    _coxa = coxa;
    _femur = femur;
    _tibia = tibia;

    // Default 0x40 address
    Adafruit_PWMServoDriver();
    Adafruit_PWMServoDriver::begin();
}

void leg::set_angle_limits(int min, int max){
    _min_angle = min;
    _max_angle = max;
}

void leg::set_foot_position(int new_x, int new_y, int new_z){

    // TODO: Calculate new servo angles for leg to make new position possible.

    // For a test just move the servo
    Adafruit_PWMServoDriver::writeMicroseconds(0, 700);
}

int leg::get_x_position(){return current_x;}
int leg::get_y_position(){return current_y;}
int leg::get_z_position(){return current_z;}
The code complies fine and uploads to the board.

The program should light up the Neopixel blue at the start of Setup(), then green at the end of Setup(). The loop() at this point justs sends the current millis() every 500 milliseconds.

However, the virtual com port does not start and I get an error from windows stating the USB device was not recognised. The Neopixel also does not light up, indicating the STM32 has crashed/froze.

By trail and error I found that the problem occurs when the line

Code: Select all

Adafruit_PWMServoDriver::begin();
is run within leg.cpp
Commenting this line out results in the Neopixels working and the serial port working too.

At first I though it might be a timing issue but the STM32 is controlling the PCA9685 via I2C so the sero library shouldn't be used.

I'm using Platformio in VSCode to upload the code using this cofiguration:

Code: Select all

[env:adafruit_feather_f405]
platform = ststm32
board = adafruit_feather_f405
framework = arduino
upload_protocol = dfu
monitor_speed = 115200
; Extra Libraries
lib_extra_dirs = 
    C:\Users\tomhu\Documents\Libraries
    C:\Users\tomhu\.platformio\packages\framework-arduinoststm32\libraries
; Build Flags
build_flags = 
	-D PIO_FRAMEWORK_ARDUINO_ENABLE_CDC
	-D USBCON
	-D USBD_VID=0x0483
	-D USB_MANUFACTURER=\"Unknown\"
	-D USB_PRODUCT=\"FEATHER_F405\"
	-D HAL_PCD_MODULE_ENABLED
	-D USBD_USE_CDC
	-D HAL_UART_MODULE_ENABLED
I also tried uploading the code via the Arduino IDE, but that results in the same outcome.

I'm posting here as I'm not really sure where the problem is.

Thanks for any help :)
stevestrong
Posts: 502
Joined: Fri Dec 27, 2019 4:53 pm
Answers: 8
Location: Munich, Germany
Contact:

Re: Using PCA9685 and USB Serial at same time results in crash/freezing of STM32

Post by stevestrong »

I assume you are using the STM official core, right?

Didn't you get any error /warning message during build process?
Where is the Adafruit_PWMServoDriver lib located? You did not post it here.
I cannot see where the begin() function of the Adafruit_PWMServoDriver lib is defined.
User avatar
fpiSTM
Posts: 1745
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 91
Location: Le Mans
Contact:

Re: Using PCA9685 and USB Serial at same time results in crash/freezing of STM32

Post by fpiSTM »

I guess you used this lib:
https://github.com/adafruit/Adafruit-PW ... er-Library

I never tried it.
Anyway, first you should try one of its example:
https://github.com/adafruit/Adafruit-PW ... wmtest.ino

In your code you should instantiate it

Code: Select all

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
TheMaskedChameleon
Posts: 3
Joined: Tue Apr 21, 2020 7:21 pm

Re: Using PCA9685 and USB Serial at same time results in crash/freezing of STM32

Post by TheMaskedChameleon »

Thanks for the help both.
I stripped out all but the essential code and it still didn't work.
After some reading it seems using a library within another library is complicated/resource wasteful.
So for now I'll take the KISS approach and remove the servo part within the class.
Now the class will take the XY coordinates of the foot and return the angles of the joints. The main program can then tell the Adafruit Servo library to move the servo's.
Post Reply

Return to “General discussion”