Hi, I have the Adafruit Stepper + DC Motor FeatherWing. It has been fun to use so far.
I am a beginner at this, so please pardon a basic question. Instead of using I2C, can I specify digital pins for sending instructions to the motor shield? So far, I have been using I2C and the MotorKit and "onestep". I am interested in trying to replicate some other examples I have seen online which seem to assign signal output from the microcontroller to 2 or 4 digital pins.
I have the FeatherWing stacked onto a Feather ESP32-S3 so there is full connection on all pins. I am most interested in how to do the initial setup (e.g. direction = digitalio.DigitalInOut(board.D6)...etc).
Do you have any examples of circuitpython code that would do this?
Many thanks.
I2C Stepper Question
Moderators: adafruit_support_bill, adafruit
Please be positive and constructive with your questions and comments.
- adafruit_support_bill
- Posts: 88093
- Joined: Sat Feb 07, 2009 10:11 am
Re: I2C Stepper Question
It is not possible to directly access the pins on the Motor Wing. The TB6612 H-Bridge driver chips are connected to the PCS9685 PWM controller chip on the motor wing. The pins on the PCA9685 can only be addressed via i2c.
If you want to experiment with direct control of the TB6612 H-Bridges, we do have a breakout board for that: https://www.adafruit.com/product/2448
If you want to experiment with direct control of the TB6612 H-Bridges, we do have a breakout board for that: https://www.adafruit.com/product/2448
- forum_questions_1
- Posts: 111
- Joined: Tue Oct 25, 2022 4:05 pm
Re: I2C Stepper Question
Thanks Bill. Knowing it is not possible saves me from spending a lot of time trying to do it. Thank you also for that idea on the other product. Is there anything I can do in code with the feather wing outside of onestep? It works pretty well with double and interleave. With microstepping, I have noticed that there is a pulsating. What happens is I can hear the motor run through the microsteps with (what sounds like) a pulse, then it does a brief pause, then it goes to another round of microsteps. It is almost like it still does 200 main steps with the 8/16/etc microsteps in between. I'd like to try to smooth it out so that it doesn't have the pausing (so that it just goes around in microsteps). I took out any sleep time delays so that is not the issue.
- adafruit_support_bill
- Posts: 88093
- Joined: Sat Feb 07, 2009 10:11 am
Re: I2C Stepper Question
Please post the code that you are using.
- forum_questions_1
- Posts: 111
- Joined: Tue Oct 25, 2022 4:05 pm
Re: I2C Stepper Question
Thanks Bill. Here it is.
I have a few notes about how I was trying to change steps and frequency in some of the if statements. I was not able to do it if I had more than one i2C device.
I have a few notes about how I was trying to change steps and frequency in some of the if statements. I was not able to do it if I had more than one i2C device.
Code: Select all
#board_id -- adafruit_feather_esp32s3_4mbflash_2mbpsram
import time
import board
import adafruit_nunchuk
import digitalio
import adafruit_motor
import adafruit_motorkit
import adafruit_pca9685
#duplicative
from adafruit_motorkit import MotorKit
from adafruit_motor import stepper
#busio includes classes I2C, SPI and UART
import busio
from board import SCL, SDA
i2c_bus = busio.I2C(SCL,SDA, frequency = 4000)
#frequency range looks like minimum is 4,000, max around 1,000,000
nc=adafruit_nunchuk.Nunchuk(i2c_bus)
#kit = MotorKit(i2c=board.I2C())
kit = MotorKit(i2c=i2c_bus, steppers_microsteps=8)
#Joystick ranges:
#x neutral 127
#x max 255
#x min 0
#y neutral 128
#y max 255
#y min 0
while True:
x, y = nc.joystick
ax, ay, az = nc.acceleration
#print("joystick = {}, {}".format(x, y))
#print("acceleration = {}, {}, {}".format(ax, ay, az))
#move joystick right. movement will only happen if held in the x == 255 position.
if x == 255:
kit.stepper2.onestep(direction=stepper.FORWARD, style=stepper.DOUBLE)
time.sleep(0)
#move joystick left. movement will only happen if held in the x == 0 position.
elif x == 0:
kit.stepper2.onestep(direction=stepper.BACKWARD, style=stepper.DOUBLE)
time.sleep(0)
#move joystick up. movement will only happen if held in the y == 255 position.
elif y == 255:
kit.stepper2.onestep(direction=stepper.FORWARD, style=stepper.MICROSTEP)
time.sleep(0)
#move joystick down. . movement will only happen if held in the y == 0 position.
elif y == 0:
kit.stepper2.onestep(direction=stepper.BACKWARD, style=stepper.MICROSTEP)
time.sleep(0)
#press button Z, keep repeating loop until cancelled with button c.
elif nc.buttons.Z:
while True:
#When loop begins, if c button press detected, release motor and exit loop
if nc.buttons.C:
kit.stepper2.release()
break
#If Z is pressed and no button C press detected above, Z moves stepper forward continuously
else:
kit.stepper2.onestep(direction=stepper.FORWARD, style=stepper.MICROSTEP)
time.sleep(0.05)
#I would like to be able to change frequencies and steps mid-code as changing these seems to be a way to slow down/speed up the motor
#this works to change the frequency and stepping mid-code but only if no other i2c device:
#kit = MotorKit(i2c=busio.I2C(board.SCL, board.SDA, frequency=100000), steppers_microsteps=16)
#trying to change stepping mid-code in this way makes motor vibrate but doesn't move forward
#kit = MotorKit(i2c=i2c_bus, steppers_microsteps=4)
#probably duplicative
else:
kit.stepper2.release()
#might not need this
time.sleep(0.5)
- forum_questions_1
- Posts: 111
- Joined: Tue Oct 25, 2022 4:05 pm
Re: I2C Stepper Question
I should say as well, that my goal for this is to have a couple of different speed options available via the joystick. One at a faster speed (maybe 5-10 rpm) and then one at a very slow speed (around 0.5 rpm).
- adafruit_support_bill
- Posts: 88093
- Joined: Sat Feb 07, 2009 10:11 am
Re: I2C Stepper Question
Your inner while-loop looks pretty minimal. I don't see anything at the source code level that should cause gaps in the timing. But between the managed environment of CircuitPython and the underlying RTOS on the ESP32, you are a couple layers removed from running on the 'bare metal'.
The CircuitPython Garbace collector can pop up on occasion to clean things up. But your code does not appear to be doing anything that would trigger that. The RTOS might also suspend things at times to attend to background tasks. I'm not familiar enough with the CircuitPython internals to know what interactions with the RTOS there might be.
Do you have any other CircuitPython capable processors? It would be interesting to see if it behaves differently without the RTOS.
The CircuitPython Garbace collector can pop up on occasion to clean things up. But your code does not appear to be doing anything that would trigger that. The RTOS might also suspend things at times to attend to background tasks. I'm not familiar enough with the CircuitPython internals to know what interactions with the RTOS there might be.
Do you have any other CircuitPython capable processors? It would be interesting to see if it behaves differently without the RTOS.
- forum_questions_1
- Posts: 111
- Joined: Tue Oct 25, 2022 4:05 pm
Re: I2C Stepper Question
Thanks Bill. The only other board I have is an ESP32 V2 Feather. I was not able to get it to work with Mu, so I gave up on using it with Circuitpython.
However, just to experiment, I switched out the S3 for the V2 and used an Arduino sketch. The stepper motor performance was noticeably improved (for my particular use). I'll copy the code at the end. It is basically one of the Example sketches with slight modification. The overall noise level was a lot lower and the microstepping was much smoother. I guess I could switch over to Arduino, though I had hoped to make it work in CircuitPython since I got the wii controller set-up well in the CircuitPython code. The Accel_ConstantSpeed example sketch allows me to reduce the speed to less than 1rpm, but it seems limited at a minimum 1rpm in the sketch below (I am not sure how to change that).
I realize this is not the exact experiment you wanted me to try, but I thought it was an interesting result using Arduino.
However, just to experiment, I switched out the S3 for the V2 and used an Arduino sketch. The stepper motor performance was noticeably improved (for my particular use). I'll copy the code at the end. It is basically one of the Example sketches with slight modification. The overall noise level was a lot lower and the microstepping was much smoother. I guess I could switch over to Arduino, though I had hoped to make it work in CircuitPython since I got the wii controller set-up well in the CircuitPython code. The Accel_ConstantSpeed example sketch allows me to reduce the speed to less than 1rpm, but it seems limited at a minimum 1rpm in the sketch below (I am not sure how to change that).
I realize this is not the exact experiment you wanted me to try, but I thought it was an interesting result using Arduino.
Code: Select all
#include <Adafruit_MotorShield.h>
#include <AccelStepper.h>
// Create the motor shield object with the default I2C address
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
// Or, create it with a different I2C address (say for stacking)
// Adafruit_MotorShield AFMS = Adafruit_MotorShield(0x61);
// Connect a stepper motor with 200 steps per revolution (1.8 degree)
// to motor port #2 (M3 and M4)
Adafruit_StepperMotor *myMotor = AFMS.getStepper(200, 2);
void setup() {
Serial.begin(9600); // set up Serial library at 9600 bps
while (!Serial);
Serial.println("Stepper test!");
if (!AFMS.begin()) { // create with the default frequency 1.6KHz
// if (!AFMS.begin(1000)) { // OR with a different frequency, say 1KHz
Serial.println("Could not find Motor Shield. Check wiring.");
while (1);
}
Serial.println("Motor Shield found.");
myMotor->setSpeed(10); // 10 rpm
Serial.println("ARDUINO_TEST 10rpm");
myMotor->step(600, FORWARD, MICROSTEP);
myMotor->release();
//1 rpm seems like it is the minimum (in Accel_ConstantSpeed it can go lower)
myMotor->setSpeed(1); // 1 rpm
Serial.println("ARDUINO_TEST 1rpm");
myMotor->step(100, FORWARD, MICROSTEP);
myMotor->release();
}
//No loop
void loop() {
}
- adafruit_support_bill
- Posts: 88093
- Joined: Sat Feb 07, 2009 10:11 am
Re: I2C Stepper Question
Arduino/C++ is much closer to the 'bare metal' than Python, so the timing will be more deterministic.
Your code above is not actually using the AccelStepper library. It is using the Adafruit library. Speed control in the Adafruit library is not so good. You should be able to get below 1RPM with AccelStepper.
Your code above is not actually using the AccelStepper library. It is using the Adafruit library. Speed control in the Adafruit library is not so good. You should be able to get below 1RPM with AccelStepper.
- forum_questions_1
- Posts: 111
- Joined: Tue Oct 25, 2022 4:05 pm
Re: I2C Stepper Question
Ok, thanks Bill. I'll check out using Accelstepper. Thanks for your help. It was interesting to test python and arduino with the motor.
- forum_questions_1
- Posts: 111
- Joined: Tue Oct 25, 2022 4:05 pm
Re: I2C Stepper Question
Hi Bill,
I tried to mash together code from the WiiChuck examples with an Accel/Adafruit stepper motor example.
I am now getting an unhappy error when I try to run the motor by pressing a wii button and I can't figure it out.
It says, "Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled."
The it does a "Core 1 register dump:". Then it seems to auto reset.
The good news is I am getting all the data feedback from the Wii controller, which I have connected to an Adafruit adapter. I can get an almost instant serial readout of what movements I make with the controller, which I think is incredible.
I tried to add if conditions to the loop to respond to the Wii controller joystick and buttons. For starters, button Z press to move the motor, button c press to release it. When I press the buttons, the error appears and the code restarts without motor movement. The stepper is wired ok, I tried to use one of the stepper examples and it operates well.
Could you take a look at this code and see if there is anything I could fix? I'd appreciate any help. I tried to look online but didn't find examples I could refer to. If you want me to start a new topic, I can do that.
I tried to mash together code from the WiiChuck examples with an Accel/Adafruit stepper motor example.
I am now getting an unhappy error when I try to run the motor by pressing a wii button and I can't figure it out.
It says, "Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled."
The it does a "Core 1 register dump:". Then it seems to auto reset.
The good news is I am getting all the data feedback from the Wii controller, which I have connected to an Adafruit adapter. I can get an almost instant serial readout of what movements I make with the controller, which I think is incredible.
I tried to add if conditions to the loop to respond to the Wii controller joystick and buttons. For starters, button Z press to move the motor, button c press to release it. When I press the buttons, the error appears and the code restarts without motor movement. The stepper is wired ok, I tried to use one of the stepper examples and it operates well.
Could you take a look at this code and see if there is anything I could fix? I'd appreciate any help. I tried to look online but didn't find examples I could refer to. If you want me to start a new topic, I can do that.
Code: Select all
//From WiiChuck "WiiAccessory" example
#include <WiiChuck.h>
//From Adafruit "Accel_ConstantSpeed" example
#include <AccelStepper.h>
#include <Adafruit_MotorShield.h>
//From WiiChuck "WiiAccessory" example (Not sure why readings only work if nunchuck 1 and nunchuck 2 Accesories created)
Accessory nunchuck1;
Accessory nunchuck2;
//From Adafruit "Accel_ConstantSpeed" example
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_StepperMotor *myStepper1 = AFMS.getStepper(200, 2);
//From Adafruit "Accel_ConstantSpeed" example
void forwardstep1() {
myStepper1->onestep(FORWARD, SINGLE);
}
void backwardstep1() {
myStepper1->onestep(BACKWARD, SINGLE);
}
//From Adafruit "Accel_ConstantSpeed" example
AccelStepper Astepper1(forwardstep1, backwardstep1);
void setup() {
Serial.begin(9600);
//From WiiChuck "WiiAccessory" example (there is only 1 controller, but for some reason no readings unless nunchuck 1 and 2 are coded in)
nunchuck1.begin();
nunchuck2.begin();
//my addition to increase speed limit
Astepper1.setMaxSpeed(10);
////From Adafruit "Accel_ConstantSpeed" example
Serial.println("Motor Shield found.");
Astepper1.setSpeed(5);
}
void loop() {
//From WiiChuck "WiiAccessory" example
nunchuck1.readData(); // Read inputs and update maps
//My addition, uses WiiChuck's array of values
//This maps to Joy Y
Serial.println(nunchuck1.values[0]);
//My addition, uses WiiChuck's array of values
//This maps to JoyY
Serial.println(nunchuck1.values[1]);
//My addition
// PROBLEM AREA - IF BUTTONS ARE PRESSED, ERROR MESSAGE AND CODE RESTARTS - IF THESE ARE EXCLUDED OR NO BUTTONS PRESSED THEN CODE WORKS
//Z is value[10} 255, c is value9[11] 255
if (nunchuck1.values[10]==255) {
Serial.println("Button Z");
Astepper1.runSpeed();
}
if (nunchuck1.values[11]==255) {
Serial.println("Button C");
myStepper1->release();
}
else delay(100);
//end of loop
}
- adafruit_support_bill
- Posts: 88093
- Joined: Sat Feb 07, 2009 10:11 am
Re: I2C Stepper Question
First try to isolate the problem. If you comment out the calls to the stepper functions, do you still see the error when you press the button?
Also, the core dump probably has some useful information relevant to diagnosing the problem.
Also, the core dump probably has some useful information relevant to diagnosing the problem.
- forum_questions_1
- Posts: 111
- Joined: Tue Oct 25, 2022 4:05 pm
Re: I2C Stepper Question
Thanks Bill. I got it to work!
I took out stepper calls first, and just left the Serial println for buttons Z and C. They worked with no errors.
Next I commented out the Wii items one by one, from the bottom, to see if they were the problem. First I commented out all the Wii items in the loop, keeping Astepper1.runSpeed() in it. I wound up commenting out all of the Wii items, including the library, and I still got the same error.
I decided to go over to the Accel_ConstantSpeed example code that I knew worked to compare it (it should have been almost the same as I had commented out all the Wii references). Just to see if the motor was connected, I ran Accel_ConstantSpeed and the stepper worked.
Then I switched back to the problem sketch, ran it, and the stepper worked. I added in the Wii items one by one from the top and tested if the stepper still ran after each addition. I finally got down to the loop, added the buttons, and it worked.
The only things I have not added back in were Serial.println(nunchuck.values[0]) and Serial.println(nunchuck.values[1]), which returned a stream of x and y coordinates for the joystick in the serial monitor. I do not need these for it, they were mostly just to see if the Wii data was getting read when I first hooked it up.
I took out stepper calls first, and just left the Serial println for buttons Z and C. They worked with no errors.
Next I commented out the Wii items one by one, from the bottom, to see if they were the problem. First I commented out all the Wii items in the loop, keeping Astepper1.runSpeed() in it. I wound up commenting out all of the Wii items, including the library, and I still got the same error.
I decided to go over to the Accel_ConstantSpeed example code that I knew worked to compare it (it should have been almost the same as I had commented out all the Wii references). Just to see if the motor was connected, I ran Accel_ConstantSpeed and the stepper worked.
Then I switched back to the problem sketch, ran it, and the stepper worked. I added in the Wii items one by one from the top and tested if the stepper still ran after each addition. I finally got down to the loop, added the buttons, and it worked.
The only things I have not added back in were Serial.println(nunchuck.values[0]) and Serial.println(nunchuck.values[1]), which returned a stream of x and y coordinates for the joystick in the serial monitor. I do not need these for it, they were mostly just to see if the Wii data was getting read when I first hooked it up.
- adafruit_support_bill
- Posts: 88093
- Joined: Sat Feb 07, 2009 10:11 am
Re: I2C Stepper Question
Good diagnostic work! The error message you were getting is typically associated with an attempt to access an invalid memory address. Maybe the nunchuck library was doing something like returning a null pointer when there was no data.
- forum_questions_1
- Posts: 111
- Joined: Tue Oct 25, 2022 4:05 pm
Re: I2C Stepper Question
Thanks Bill. I appreciate your help with it.
Please be positive and constructive with your questions and comments.