Issues with AccelStepper and Serial.print

orac

Active member
I have a background project going while I am waiting for parts to arrive.
I have been playing with speedystepper up to this point, but looking further down the road I will need to operate the motor at the same time as a display and various inputs and output. Speed stepper doesn't make this the easiest thing in the world.
At that point i tought i would have a look at a other libraries. Now being in the resonably early stages I tought i would setup a program to print various bit of data out over the serial port.

The .run() command is called every 10 microseconds on timer interrupt so I don't have to remeber to run it. The function called by interrupt
Code:
void run_motor(){
  stepper.run();
  run_count++;
  Serial.print("Run Motor; ");
  Serial.println(run_count);
}
This doesn't work. Remove the 2 serial prints and it's fine.

The next step is to intergrate an encoder into the system. The user interface needs to be arranged as well so i suspect there maybe another encoder or button and a display - or maybe a touch screen. Either way it will most likely be over SPI.

I am working on testing with the encoder which is why there is some code relating to that in there.
Idealy, I would check the encoder once the motor had been stepped as it would save doing an extra call, more testing is needed at this point but will value any input and expierence .

Complete code that i was testing with:
Code:
#include <SPI.h>
#include <AccelStepper.h>
IntervalTimer motor_timer;
const byte CS_pin = 10; //Chip select pin for manual switching
uint16_t rawData = 0; //bits from the encoder (16 bits, but top 2 has to be discarded)
float degAngle = 0; //Angle in degrees
float startAngle = 0; //starting angle for reference
float correctedAngle = 0; //tared angle value (degAngle-startAngle)
float totalAngle = 0; //total accumulated angular displacement
float numberofTurns = 0;
float rpmCounter = 0; //counts the number of turns for a certain period
float revsPerMin = 0; //RPM
int quadrantNumber = 0;
int previousquadrantNumber = 0;
uint16_t startRaw = 0;
const int step_pin = 2;
const int direct = 5;
const int enable_pin = 6;
uint16_t command = 0b1111111111111111; //read command (0xFFF)
int run_count = 0;
int old_run_counter = 0;
int target = 24000;
int loop_count = 0;
AccelStepper stepper(1, step_pin, direct, true);
AccelStepper setEnablePin(enable_pin);
void setup(){
  SPI.begin();
  Serial.begin(115200);
  Serial.println("AS5048A - Magnetic position encoder");
  pinMode(CS_pin, OUTPUT); //CS pin - output
  //Checking the initial angle
  readRegister();             //the first read of the encoder
  startAngle = degAngle;      //correct the angle - most likely going to use raw data
  startRaw = rawData;
  pinMode(enable_pin, OUTPUT);    //motor enable pin
  pinMode(direct, OUTPUT);    //direction pin
  pinMode(step_pin, OUTPUT);  //step pin
  
  stepper.setMaxSpeed(12500);
  stepper.setAcceleration(12500);
  stepper.enableOutputs();
  stepper.setCurrentPosition(0);
  motor_timer.begin(run_motor, 10);
}
void loop() {
  Serial.println("Moving to target");
  stepper.moveTo(target);
  while (stepper.isRunning()){
    //do stuff here
    loop_count++;  
  }
  Serial.print("First loop: ");
  Serial.println(loop_count);
  noInterrupts();
  //do no interrupt stuff here
  
  Serial.println("Hold Off Interrupt");
  //delay(2000);
  old_run_counter = run_count;
  run_count = 0;
  loop_count = 0;
  interrupts();
  Serial.print("Run Motor; ");
  Serial.println(old_run_counter);
  Serial.println("Moving to 0");
  stepper.moveTo(0);
  while (stepper.isRunning()){
    //do stuff here
    loop_count++; 
  }
  Serial.print("Second loop: ");
  Serial.println(loop_count);
  loop_count = 0;
}

void readRegister()
{
  SPI.beginTransaction(SPISettings(3000000, MSBFIRST, SPI_MODE1));
  //--sending the command
  digitalWrite(CS_pin, LOW);
  SPI.transfer16(command);
  digitalWrite(CS_pin, HIGH);
  //delay(10);
  //--receiving the reading
  digitalWrite(CS_pin, LOW);
  rawData = SPI.transfer16(command);
  digitalWrite(CS_pin, HIGH);
  SPI.endTransaction();
  rawData = rawData & 0b0011111111111111; //removing the top 2 bits (PAR and EF)
  int q = rawData - startRaw;
  q = abs(q);
  degAngle = (float)rawData / 16384.0 * 360.0; //16384 = 2^14, 360 = 360 degrees
  Serial.print("Raw Data: ");
  Serial.print(rawData);
  Serial.print(" | ");
  Serial.println(q);
  //Serial.print("Deg: ");
  //Serial.println(degAngle, 6);
}
void run_motor(){
  stepper.run();
  run_count++;
  //Serial.print("Run Motor; ");
  //Serial.println(run_count);
}
 
I doubt the code presented would even compile as
Code:
AccelStepper setEnablePin(enable_pin);
makes no sense. If it actually does compile it's surely not doing what you want
 
that should actually be taken with the line above.

Code:
AccelStepper stepper(1, step_pin, direct, true);
AccelStepper setEnablePin(enable_pin);

the first line here sets the mode and then sets the step pin to pin 2, direcction pin to pin 5 and enables control of the enable pin ie true. If this last bool value is left it assumes there is no enable, I supose you could set it to false as well.

the second line, the one you highlighted simply assigns the pin to enable to stepper driver, in this case pin 6 on the teensy 4.0
More info available here:

If an enable line is also needed, call setEnablePin() after construction
 
You shouldn't try to call Serial.print in a ISR, Serial access itself uses interrupts so you get a deadly embrace where Serial waits for its interrupts but already in an ISR so interrupts are blocked.

If you access a variable like run_count inside an ISR, it should be declared volatile so the compiler doesn't optimize it wrongly.
 
I had to move it to the void setup() to allow it to compile, all seems the same.

You shouldn't try to call Serial.print in a ISR, Serial access itself uses interrupts so you get a deadly embrace where Serial waits for its interrupts but already in an ISR so interrupts are blocked.

If you access a variable like run_count inside an ISR, it should be declared volatile so the compiler doesn't optimize it wrongly.
This seemed to have been the issue. Never had an issue before, but I don't use interrupts much
 
May have come across another issue while experimenting futher. Didn't see much point in making a hile new thread.
Timer interrupt commented out and main loop replaced with the code below.

Code:
readRegister();
  if (rawData != 0){
    stepper.stepForawrd();
    delay(100);
    readRegister();
  }

The error teensyduino gives:

Code:
C:\Users\orac0\AppData\Local\Temp\.arduinoIDE-unsaved2024620-16572-1twlvhj.hzdw\sketch_jul20a\sketch_jul20a.ino: In function 'void loop()':
C:\Users\orac0\AppData\Local\Temp\.arduinoIDE-unsaved2024620-16572-1twlvhj.hzdw\sketch_jul20a\sketch_jul20a.ino:62:24: error: 'long int AccelStepper::stepForward()' is protected within this context
In file included from C:\Users\orac0\AppData\Local\Temp\.arduinoIDE-unsaved2024620-16572-1twlvhj.hzdw\sketch_jul20a\sketch_jul20a.ino:2:
c:\Users\orac0\Documents\Arduino\libraries\AccelStepper\src/AccelStepper.h:597:12: note: declared protected here
  597 |     long   stepForward();
      |            ^~~~~~~~~~~
Multiple libraries were found for "AccelStepper.h"
  Used: C:\Users\orac0\Documents\Arduino\libraries\AccelStepper
  Not used: C:\Users\orac0\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.59.0\libraries\AccelStepper
exit status 1

Compilation error: 'long int AccelStepper::stepForward()' is protected within this context

Compilation error: 'class AccelStepper' has no member named 'stepForawrd'
 
AccelStepper requires you to call stepper.run() frequently, and then you can call things like stepper.moveTo() to start things happening. No delay()'s please, that's going to lock up the processor so nothing can happen.
 
Yes I am aware. The delaty currently as a simple function of allow the mechanic to settle before taking a reading.

The issue is,
Code:
Compilation error: 'long int AccelStepper::stepForward()' is protected within this context
and
Code:
Compilation error: 'class AccelStepper' has no member named 'stepForawrd'

I alread have the system running as I set out to achieve. It doesn't change the fact that a documented command apparently doesn't exist.

Here is what I am currently running:
Code:
  while (rawData > 20){
    stepper.runToNewPosition(stepper.currentPosition()+5);
    delay(100);
    readRegister();
  }
A little more combersome than just calling for a ssteForward()
 
Sorry for the double post but have just found the runToPosition doesn't work either.

Code:
Compilation error: no matching function for call to 'AccelStepper::runToPosition(long int)'

this does not compile:
Code:
  readRegister();
  while (rawData > 20){
    stepper.runToPosition(stepper.currentPosition()+5);
    delay(100);
    readRegister();
  }

previous post comiles fine and they are next to on another in this listing:
 
Let me repeat, don't use delay() at all. Don't use while().

In loop() call stepper.run() or stepper.runSpeed() - AccelStepper does all its work in those methods and they must be called frequently for steps to be generated correctly. runSpeedToPosition doesn't have an argument.

All the motion is triggered by other calls, such as moveTo(), which are called once to start activity, and rely on the loop() method calling run() or runToPosition().

Look in AccelStepper.h and read the comments, all is explained there.

There are also blocking calls like runToPosition() and runSpeedToPosition(), but they are usually bad news as they lock up the processor during motion, and can't work with multiple steppers moving simultaneously.

Look at the examples...
 
May have come across another issue while experimenting futher. Didn't see much point in making a hile new thread.
Timer interrupt commented out and main loop replaced with the code below.

Code:
readRegister();
  if (rawData != 0){
    stepper.stepForawrd();
    delay(100);
    readRegister();
  }

The error teensyduino gives:

Code:
C:\Users\orac0\AppData\Local\Temp\.arduinoIDE-unsaved2024620-16572-1twlvhj.hzdw\sketch_jul20a\sketch_jul20a.ino: In function 'void loop()':
C:\Users\orac0\AppData\Local\Temp\.arduinoIDE-unsaved2024620-16572-1twlvhj.hzdw\sketch_jul20a\sketch_jul20a.ino:62:24: error: 'long int AccelStepper::stepForward()' is protected within this context
In file included from C:\Users\orac0\AppData\Local\Temp\.arduinoIDE-unsaved2024620-16572-1twlvhj.hzdw\sketch_jul20a\sketch_jul20a.ino:2:
c:\Users\orac0\Documents\Arduino\libraries\AccelStepper\src/AccelStepper.h:597:12: note: declared protected here
  597 |     long   stepForward();
      |            ^~~~~~~~~~~
Multiple libraries were found for "AccelStepper.h"
  Used: C:\Users\orac0\Documents\Arduino\libraries\AccelStepper
  Not used: C:\Users\orac0\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.59.0\libraries\AccelStepper
exit status 1

Compilation error: 'long int AccelStepper::stepForward()' is protected within this context

Compilation error: 'class AccelStepper' has no member named 'stepForawrd'

There's a major clue in the compiler report that you posted:

Multiple libraries were found for "AccelStepper.h"
Used: C:\Users\orac0\Documents\Arduino\libraries\AccelStepper
Not used: C:\Users\orac0\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.59.0\libraries\AccelStepper
exit status 1

You need to remove/rename/disable the (wrong) AccelStepper library that is (mistakenly) being used !!

Mark J Culross
KD5RXT
 
Let me repeat, don't use delay() at all. Don't use while().

Let me repeat, it does not compile.

And Yes, blocking is what i was looking for, which is why I chose the commands that I did. The issue isn't with it running on the controller, but just compiling and persists both inside of and outside of a while loop, with ot without a delay. The issue is not with the code running, it is with it compiling.
The code is looking for a particular location within the encoder, this is the first step to finding the relationship between the stepper motor steps and the encoder steps. As a result blocking and while loops are not a concern or an issue.
Code:
void loop() {
  readRegister();       //do an initial read of encoder
  while (rawData > 20){
    //stepper.runToNewPosition(stepper.currentPosition()+5);    //this compiles and runs as expected on hardware, yes even inside a while with a pause
    //stepper.runToPosition(stepper.currentPosition()+5);       //this does not compile no matter where it is put in code, inside the while, out side the while, with or without pause
    stepper.runForward();                                       //as above
    delay(100);       //allow mechanism to settle
    readRegister();   //re-read encoder, loop if value is not less than 20.
  }
 
  delay(5000);
  /*//hold here, examine for drift - sensor drift indicated, maybe issue with encoder driving?
  while(rawData !=0){
    Serial.println("Holding loop");
    readRegister();
    delay(5000);
  }
  */
}

I have just tried uninstalling the library and reinstalling. The result has changed slightly.
Ouput:
Code:
D:\Updated Macro rail\zero_search\zero_search.ino: In function 'void loop()':
D:\Updated Macro rail\zero_search\zero_search.ino:64:13: error: 'class AccelStepper' has no member named 'runForward'; did you mean 'void (* AccelStepper::_forward)()'? (not accessible from this context)
   64 |     readRegister();
      |             ^~~~~~~  
In file included from D:\Updated Macro rail\zero_search\zero_search.ino:2:
c:\Users\orac0\Documents\Arduino\libraries\AccelStepper\src/AccelStepper.h:710:12: note: declared private here
  710 |     void (*_forward)();
      |            ^~~~~~~~

exit status 1

Compilation error: 'class AccelStepper' has no member named 'runForward'; did you mean 'void (* AccelStepper::_forward)()'? (not accessible from this context)
With my almost complete lack of understanding, it seem like the command does not exist

The entire code for this round of testing:
Code:
#include <SPI.h>
#include <AccelStepper.h>
IntervalTimer motor_timer;
const byte CS_pin = 10;  //Chip select pin for manual switching
uint16_t rawData = 0;      //bits from the encoder (16 bits, but top 2 has to be discarded)
float degAngle = 0;        //Angle in degrees
float startAngle = 0;      //starting angle for reference
float correctedAngle = 0;  //tared angle value (degAngle-startAngle)
float totalAngle = 0;      //total accumulated angular displacement
float numberofTurns = 0;
float rpmCounter = 0;  //counts the number of turns for a certain period
float revsPerMin = 0;  //RPM
int quadrantNumber = 0;
int previousquadrantNumber = 0;
uint16_t startRaw = 0;
const int step_pin = 2;
const int direct = 5;
const int enable_pin = 6;
uint16_t command = 0b1111111111111111;  //read command (0xFFF)
int run_count = 0;
int old_run_counter = 0;
int target = 4800;
int loop_count = 0;
AccelStepper stepper(1, step_pin, direct, true);

void setup() {
  SPI.begin();
  Serial.begin(115200);
  //Serial.println("AS5048A - Magnetic position encoder");
  pinMode(CS_pin, OUTPUT);  //CS pin - output
  //Checking the initial angle
  readRegister();         //the first read of the encoder
  startAngle = degAngle;  //correct the angle - most likely going to use raw data
  startRaw = rawData;
  pinMode(enable_pin, OUTPUT);  //motor enable pin
  pinMode(direct, OUTPUT);      //direction pin
  pinMode(step_pin, OUTPUT);    //step pin
  stepper.setEnablePin(enable_pin);
  stepper.setMaxSpeed(12500);
  stepper.setAcceleration(12500);
  stepper.enableOutputs();
  stepper.setCurrentPosition(0);
  //motor_timer.begin(run_motor, 10);   //supress this for testing location search testing
}
void loop() {
  readRegister();       //do an initial read of encoder
  while (rawData > 20){
    //stepper.runToNewPosition(stepper.currentPosition()+5);    //this compiles and runs as expected on hardware, yes even inside a while with a pause
    //stepper.runToPosition(stepper.currentPosition()+5);       //this does not compile no matter where it is put in code, inside the while, out side the while, with or without pause
    stepper.runForward();                                       //as above
    delay(100);       //allow mechanism to settle
    readRegister();   //re-read encoder, loop if value is not less than 20.
  }
 
  delay(5000);
  /*//hold here, examine for drift - sensor drift indicated, maybe issue with encoder driving?
  while(rawData !=0){
    Serial.println("Holding loop");
    readRegister();
    delay(5000);
  }
  */
}

void readRegister() {
  SPI.beginTransaction(SPISettings(3000000, MSBFIRST, SPI_MODE1));
  //--sending the command
  digitalWrite(CS_pin, LOW);
  SPI.transfer16(command);
  digitalWrite(CS_pin, HIGH);
  //delay(10);
  //--receiving the reading
  digitalWrite(CS_pin, LOW);
  rawData = SPI.transfer16(command);
  digitalWrite(CS_pin, HIGH);
  SPI.endTransaction();
  rawData = rawData & 0b0011111111111111;  //removing the top 2 bits (PAR and EF)
  int q = rawData - startRaw;
  q = abs(q);
  degAngle = (float)rawData / 16384.0 * 360.0;  //16384 = 2^14, 360 = 360 degrees
  Serial.print("Raw Data: ");
  Serial.print(rawData);
  Serial.print(" , ");
  Serial.println(q);
  //Serial.print("Deg: ");
  //Serial.println(degAngle, 6);
}
void run_motor() {
  stepper.run();
  run_count++;
}
 
You are attempting to use the wrong AccelStepper library !! See post #12 above for what you need to do to fix your problem.

Mark J Culross
KD5RXT
 
I don't know what else I am supposed to do here. I have removed all traces of the library, made sure it was unistalled and reinstalled to the latest version.

This is the second time of doing this. After the first time the error message changed, this is what I posted above.
I tried installing all of the thing tagged with AccelStepper to no avail.
Seems that for some reason some comands have put into a protected class as i have issues with other comands in there too.

I am going to continue work with the code that works for the testing that I ma trying to run. I just know that i need to avoid some commands due to this issue
 

Attachments

  • installed 1.64-1.png
    installed 1.64-1.png
    291.6 KB · Views: 33
  • unistalled.png
    unistalled.png
    239.5 KB · Views: 38
  • installed 1.64.png
    installed 1.64.png
    333.8 KB · Views: 37
You may not be aware, but the AccelStepper version of the library that you want is installed with TeensyDuino. I can't tell from your description for sure (and your screen captures are not clear enough for me to read...sorry !!), but if you are manually installing the AccelStepper library (either using the Library Manager, or by manually copying it in), you are undoing what TeensyDuino (TD) automatically does for you. TD installs the required Teensy version, which is noted in the "Not used:" line back in post #12. If you did manually install a version of the AccelStepper library, you'll need to uninstall/remove it, then re-install TD 1.59 to get back to the correct Teensy version.

I'm certainly not an expert like others here on this forum, but I'll still try to help the best I can. Since I'm not sitting in your chair & I can't see your computer, you'll have to help me to help you . . . please feel free to ask any questions along the way, & I'll also try to explain the "why" behind anything that I ask you to do.

Mark J Culross
KD5RXT
 
The only reason I manually installed it was due to the issue you high lighted. The issue was there before I unistalled and re-installed.
The only thing left to do is to unistall teensyduino/arduino IDE and starting from a clean slate.

since this is only testing at the moment, build the final code working around the issues should not be much of an issue.
Either way it will have to wait until tomorrow as I need some sleep.
 
OK, sorry, I may not have been very clear in my earlier post(s). I'll attempt to give the instructions here in a way that is less ambiguous, and much more direct. Hopefully, that will make things clearer to understand.

As indicated in your post #7 above, the following library is present on your computer, and it is being used when attempting to compile your sketch:
C:\Users\orac0\Documents\Arduino\libraries\AccelStepper
- this is the wrong library (it is an Arduino generic version of the AccelStepper library, which is either installed by default when installing the Arduino IDE, or has been installed manually, using the Library Manager from the Arduino IDE)
- delete the entire folder for this library

As indicated in your post #7 above, the following library is *not* being used when attempting to compile your sketch:
C:Users\orac0\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.59.0\libraries\AccelStepper
- this is actually the library that you want (it is a Teensy specific version of the AccelStepper library, which is installed automatically as part of TeensyDuino)
- re-install TD 1.59 to make sure that this library is still present

You can find the documentation for the Teensy version of the AccelStepper library <here>. If your sketch is attempting to make function calls to anything that is not listed on that reference page, then it will not work with the Teensy specific version of the library.

Hope that helps . . .

Mark J Culross
KD5RXT
 
Back
Top