gin66 / FastAccelStepper

A high speed stepper library for Atmega 168/328p (nano), Atmega32u4, Atmega 2560, ESP32, ESP32S2, ESP32S3, ESP32C3 and Atmel SAM Due
MIT License
286 stars 67 forks source link

Error Message When Compiling Example Codes #104

Closed Kuantronic closed 2 years ago

Kuantronic commented 2 years ago

I tried to use two example codes, UsageExample & PrintPosition, to get familiar with this library. However,

FastAccelStepper\src/FastAccelStepper.h:468:30: error: 'MAX_STEPPER' was not declared in this scope FastAccelStepper* _stepper[MAX_STEPPER];

error message appears when I hit compile. It's being compiled for the Arduino Leonardo with the step pin connected to pin 9 which is tied to timer1. What's going on here?

Here is my PrintPosition example code:

#include "FastAccelStepper.h"

// As in StepperDemo for Motor 1 on AVR
#define dirPinStepper 8
#define enablePinStepper 6
#define stepPinStepper 9

FastAccelStepperEngine engine = FastAccelStepperEngine();
FastAccelStepper *stepper = NULL;

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

  Serial.println("Starting");
  Serial.flush();
  engine.init();
  stepper = engine.stepperConnectToPin(stepPinStepper);
  Serial.println("Starting");
  Serial.print("Stepper Pin:");
  Serial.println(stepPinStepper);
  Serial.flush();
  Serial.println((unsigned int)stepper);
  Serial.println((unsigned int)&engine);
  if (stepper) {
    stepper->setDirectionPin(dirPinStepper);
    stepper->setEnablePin(enablePinStepper);
    stepper->setAutoEnable(false);

    stepper->setSpeedInUs(1000);  // the parameter is us/step !!!
    stepper->setAcceleration(10000);
    // stepper->move(7000);
    stepper->runForward();
  } else {
    Serial.println("Stepper Not initialized!");
    delay(1000);
  }
  Serial.print("    F_CPU=");
  Serial.println(F_CPU);
  Serial.print("    TICKS_PER_S=");
  Serial.println(TICKS_PER_S);
  Serial.flush();
}

void loop() {
  delay(100);
  if (stepper) {
    if (stepper->isRunning()) {
      Serial.print("@");
      Serial.println(stepper->getCurrentPosition());
    }
  } else {
    Serial.println("Stepper died?");
    Serial.flush();
    delay(10000);
  }
}
gin66 commented 2 years ago

Arduino Leonardo is using the ATmega32u4, which is currently not supported:

#if defined(TEST)
#define MAX_STEPPER 2
#define TICKS_PER_S 16000000L
#elif defined(ARDUINO_ARCH_AVR)
#if defined(__AVR_ATmega328P__)
#define MAX_STEPPER 2
#elif defined(__AVR_ATmega2560__)
#define MAX_STEPPER 3
#endif

I only can try to make it compile for this uC (if the relevant I/O-modules are register compatible), but for sure I do not have HW for testing.

gin66 commented 2 years ago

You can try the leonardo branch

Kuantronic commented 2 years ago

From some initial testing, this branch seems to work with pins 9 & 10! Using the printPosition example sketch (with some modifications), I was able to step pulse my NEMA 17 motor up to 13Khz before it starts stalling with a 9V supply. Might try higher speed with a higher supply quite soon.

If I try to use pin 11, it just buzzes and the serial monitor does not print the motor position or anything else. Looking at the pinout, OC1C & OC0A are both are on pin 11.

gin66 commented 2 years ago

Thanks for testing and sounds promising.

Apparently OC1C is not useable. Not sure for the reason. That OC0A is routed to this pin, is just an option. Perhaps something needs to be initialized differently. So I tend to just disable OC1C and keep this for leonardo.

Unfortunately my main StepperDemo does not fit into the small memory of leonardo, so I need to reduce code size first. In the moment I had to remove a lot of code, so this is not as functional as I like it to be. This will take some time, before I can merge it to master branch

gin66 commented 2 years ago

just see that RTS is connected to pin 11. Perhaps the problem is linked to serial communication reading that pin ??

Kuantronic commented 2 years ago

Perhaps the problem is linked to serial communication reading that pin ??

I modified the code to either activate serial comm or not with a const bool variable. Pin 11 still didn't work with it turned off. Either way, I did notice that the stepper quietly hummed. I don't have an oscilloscope to measure the output of pin 11 unfortunately.

Here is my code:

#include "FastAccelStepper.h"

#define enablePinStepper 6
#define sprPinStepper 7
#define dirPinStepper 8
#define stepPinStepper 11
#define ledPin 13

FastAccelStepperEngine engine = FastAccelStepperEngine();
FastAccelStepper *stepper = NULL;

const bool useSerial = false;
bool forwardDir = true;
unsigned long lastMillisDirChng, lastMillisPrintPos;

void setup() {
    engine.init();
    stepper = engine.stepperConnectToPin(stepPinStepper);
    pinMode(ledPin, OUTPUT);

    delay(2500);

    if (useSerial) {
        Serial.begin(115200);
        Serial.println("Starting");
        Serial.print("Stepper Pin:");
        Serial.println(stepPinStepper);
        Serial.println((unsigned int)stepper);
        Serial.println((unsigned int)&engine);
    }

    if (stepper) {
        pinMode(sprPinStepper, OUTPUT);
        digitalWrite(sprPinStepper, HIGH);

        stepper->setDirectionPin(dirPinStepper);
        stepper->setEnablePin(enablePinStepper);
        stepper->setAutoEnable(false);

        stepper->setSpeedInHz(12800);
        stepper->setAcceleration(6400);
    }
    else {
        if (useSerial) Serial.println("Stepper Not initialized!");
        else digitalWrite(ledPin, HIGH);
        delay(2500);
    }

    if (useSerial) {
        Serial.print("    F_CPU=");
        Serial.println(F_CPU);
        Serial.print("    TICKS_PER_S=");
        Serial.println(TICKS_PER_S);
    }

    lastMillisDirChng = millis();
    stepper->runForward();
}

void loop() {
    if (millis() - lastMillisDirChng > 10000) {
        if (useSerial) Serial.println("Changing Direction!");
        forwardDir = !forwardDir;
        if (forwardDir) stepper->runForward();
        else stepper->runBackward();
        lastMillisDirChng = millis();
    }

    if (millis() - lastMillisPrintPos > 250 && useSerial) {
        Serial.println("pos@" + String(stepper->getCurrentPosition()));
        lastMillisPrintPos = millis();
    }
}
Kuantronic commented 2 years ago

Apparently OC1C is not useable. Not sure for the reason. That OC0A is routed to this pin, is just an option. Perhaps something needs to be initialized differently. So I tend to just disable OC1C and keep this for Leonardo.

Yeah it seems OC0A is the default for pin 11. Not sure how to go about switching to OC1A. I found this forum question with no replies and this stackexchange question that is somewhat related.

gin66 commented 2 years ago

Please try

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

  Serial.println("Starting");
  Serial.flush();
  digitalRead(11); // ADD THIS LINE
  engine.init();
  stepper = engine.stepperConnectToPin(stepPinStepper);
Kuantronic commented 2 years ago

I added the digitalRead(11); before the engine.init();,

If serial is NOT used, the motor turns but it's at a way lower speed than what was set.

If Serial is used, nothing happens and the Leonardo is not longer detected by the PC. I had to double tap the reset button to access the bootloader and upload a blink sketch to get it back to normal.

gin66 commented 2 years ago

Ok. Thanks for checking. So best to not use OC1C

Kuantronic commented 2 years ago

Ok. Thanks for checking. So best to not use OC1C

It seems so. Unless a way to configure OC1C as the default timer for pin 11, best to avoid it.

Kuantronic commented 2 years ago

So the only thing needed to merge this branch is to get the example StepperDemo sketch to fit into the size of the Leonardo? Is there anything else that needs to be done?

gin66 commented 2 years ago

The StepperDemo has been already code optimized. As I still have to work on the parser, it is not merged. Then I still want to see, if I can use the emulator to test the atmega32u4 code.

gin66 commented 2 years ago

seems to be supported (https://github.com/buserror/simavr/blob/a56b550872906a971ac128002772d90c9e30377d/simavr/cores/sim_mega32u4.c)

gin66 commented 2 years ago

While merging, I have found two silly bugs, which have led to access memory outside the boundary. Always good to look at the diffs :-)

Maybe the explanation for the OC1C problem....

Could you please try again ?

gin66 commented 2 years ago

I mean the updated leonardo branch

gin66 commented 2 years ago

Cool... compilation for atmega328 requires 27728 Bytes, while same code for leonardo requires 30592 Bytes. Perhaps the serial USB support ?

So I still need to save ~2kBytes....

gin66 commented 2 years ago

fits to the byte. But the emulator does not run it. not even a much smaller sketch.

gin66 commented 2 years ago

or the emulator does not print from serial usb, which is very likely.

Kuantronic commented 2 years ago

Is the newest branch still from the same link? I can try again with pin 11.

Kuantronic commented 2 years ago

I mean the updated leonardo branch

I downloaded from this branch just now. Still the same thing. I did noticed it said it was updated 3 days ago. Can you send me the link for the newest branch?

gin66 commented 2 years ago

just pushed my local branch. Have missed this. sorry for the inconvenience

gin66 commented 2 years ago

As I got the emulator to work, I have made the 0.24.1 available with OC1A, OC1B and OC1C. The emulator for sure supports only OC1A and OC1B. Hope with the bugfix, OC1C is working now. At least I am optimistic.

Kuantronic commented 2 years ago

OC1C is working now

Pin 11 seems to be working just like pin 8 & 9 now! :) I checked the new changes. Was it just defining the max stepper and number of queues by 2 rather than 3 in the header file that was causing the problem?

gin66 commented 2 years ago

Yes. OC1C is directly mapped:

#define fas_queue_C fas_queue[2]

and the queue is defined as

StepperQueue fas_queue[NUM_QUEUES];

if NUM_QUEUE is only 2, then for channel C the code will read and write out of bounds.

Kuantronic commented 2 years ago

I see. Thanks for taking the time to incorporate the ATmega32U4 MCU to the library :)