Skip to content
This repository has been archived by the owner on Nov 3, 2024. It is now read-only.

A4950 / Stepping Interface Questions #125

Open
jlmxyz opened this issue Jan 13, 2023 · 6 comments
Open

A4950 / Stepping Interface Questions #125

jlmxyz opened this issue Jan 13, 2023 · 6 comments
Assignees
Labels
question Further information is requested

Comments

@jlmxyz
Copy link

jlmxyz commented Jan 13, 2023

Hi!
I will have some spare time to work on this project, so I'm trying to understand low level motor driving, and in particular want to move from "open loop" mode (in actual design, if I correctly understood, when a step command is given, the coils are driven to perform a step (by step I means a microstep if configured to perform microstep, not motor physical step) then if DISABLE_CORRECTION_TIMER is not set, a position correction is performed....
I didn't had a look into PID code yet....

so I need information about A4950 driver, because when I look into the datasheet, I don't understand how the PWM is used... there are diagram about the ripple introduced by the PWM, but it looks like the intensity isn't modulated... they says that the Iout is 3.4A at 100% duty cycle, but I don't get why 2 PWM entries?

at page 4 there is some logic information about how the inputs relates
seems that

  • when the non PWM modulated input is low, the ouput has fast decay mode
  • when the non PWM modulated input is high, the output is slow decay mode
  • if I1 is modulated the motor is driven reverse
  • if i2 is modulated the motor is driven forward
  • only one input should be modulated at a time the other must be fixed

right?

is Iout = Iout(100%) * DuttyCycle ?

not related but to share my thoughts after some code review....
I think that current driving design is bad because the closed loop is in fact not used... when for example we issue a G6 D${Negative} R${rate} S${nbOfSteps} command, the TIM4(stepScheduleTimer) is activated at ${rate} and at each interrupt perform a step command, so it's open loop, the coils will have some intensity going through, and the magnet will try to allign, but it can go too fast and go further than the wanted position, so creating oscillation... I think this is why you created the PID feature, but I don't see how it could work with actual design...
I think that when a G6 D${Negative} R${rate} S${nbOfSteps} is issued, or when a step request is performed by STEP/DIR/EN interface, a final angle position should be computed, this final angle position should be issued to the position sensor driver, as well as duration, the position sensor driver should then drive the motor...
sensor driver can then filter the request (PID? linear?) and issue microstep move request, check the result, and perform feedback correction (not sure if we can keep the fast sine pre-computation, or at least pre-compute it for more than 1/32 microsteps)

@CAP1Sup
Copy link
Owner

CAP1Sup commented Jan 13, 2023

Hello!

So here's the issue... any traditional 3D printer using these motors is going to expect consistent, linear movement. However, when using PID to run the motor entirely, the motor lags behind a variable amount. Therefore, my solution was to duplicate the stepping as close as possible... and only use PID to set step timing for correctional movements. Therefore, the PID was only ever needed when the driver was out of position.

If you want to take a look at the coding for the A4950s, check out setCoilA/B in motor.cpp. That should hopefully explain things for you.

Before you do any work, I would recommend that you first pursue fixing the step counting. Currently, the input pulses are counted, but occasionally, one is missed. I have done extensive testing, but to no avail. Therefore, I have taken a break from the project... the driver is useless if it can't keep position. My only workaround is that we could use the CAN bus for digital step counts, but I have to do some more research into Klipper to see if it's possible.

Best,
Christian

@jlmxyz
Copy link
Author

jlmxyz commented Jan 13, 2023

missing edge detection on STP pin? isn't this pin driven by interrupt handler? can this be caused by the opto-coupler? (normally not if I'm correct... let me check... TPHL and TPLH are 100ns max, so max freq is 10Mhz... can this be the cause? )

my approach is different, I want to get rid of the motherboard, a bit like klipper do, but klipper never documented the protocol so it's impossible to create a "klipper compatible" standalone... either the project is klipper based, and klipper is designed in a way that it's not easy to integrate (no "communication layer library" that could be integrated into the project... )
so I think I will have a board that use serial as input, take G-codes and act as a CAN master and broadcast G-codes to all can bus attached device... each device will then filter the commands and take appropriate actions.... I've also to take into account coupled motors, with one can act as a master to others (kind of sub channel) because my hardware is dual motor driven on Y and Z axis (mono motor on X and extruders)
this will a lot simplify designs... because the boards can be easily modifed to add thermal sensor, overrun switches...and then act as autonomous systems that communicate to each others, can be extended and so on.... klipper is more designed so systems are dumb, and that the master can setup pins, interrupts and so on... and then don't integrate well with smart systems as closed loop drivers...

best regards

@jlmxyz
Copy link
Author

jlmxyz commented Jan 14, 2023

ok correct me if I'm wrong

  • IN1 and IN2 are driven digital without PWM => they give the direction
  • Vref is created by filtering a PWM signal through a RC filter (so performing a Capacitor charge proportional to PWM duty cycle)

so the drive is voltage based... ok, that's something not easy to figure at first....

@jlmxyz
Copy link
Author

jlmxyz commented Jan 14, 2023

ok now i see why it might miss STP counter... it use TIM2 (to perform I think debouncing) but this approach limits the input frequency to what the capture control settings are.... I'm not really used to this approach, but it can introduce miss detections...
another thing that bother me is that in your code there is
GPIO_InitStructure.Pull = GPIO_PULLDOWN; (in StepperMotor::StepperMotor)
but according to my reverse schematic, pull up are mounted on STP and DIR signals... what can cause an external pull up and internal pull down with this design????

I'm moving all this code outside StepperMotor class since it more relevant to an interface (like serial/CAN) so I'm creating a StpDirEnInterface class to store this code....

@jlmxyz
Copy link
Author

jlmxyz commented Jan 14, 2023

in fact I wonder why some kind of debouncing is done on STEP/DIR interface.... optocouplers shall already filter noise on the line due to the capacitor of the input LED and the capacitor of the grid of the attached opto-transistor... so using a simple GPIO rise/fall interrupt should be enough....
did you tried a more basic approach on theses signal? just attaching GPIO interrupts without timer use?

@CAP1Sup CAP1Sup added the question Further information is requested label Jan 15, 2023
@CAP1Sup
Copy link
Owner

CAP1Sup commented Jan 15, 2023

You're right about the IN1 and IN2 controlling the mode of the A4950. The PWM is output to the A4950 to control the power... check the datasheet for the A4950 for documentation about the power control.

The issue with attaching GPIO interrupts and using a counting function is that the STM32 can only process one interrupt at a time. This led to a bunch of missed steps. I don't remember if I was able to figure out interrupt priority (I rememeber having a lot of issues with it), but I do remember the timer being better. The timer iself is independent from the CPU, so the CPU can do other tasks (like stepping the motor) instead of having to worry about counting.

That's unfortunate to hear about Klipper, I was really hoping that I'd be able to integrate them.

As of right now, I don't have my test setup, so unfortunately I can't really do any testing. I'm fairly involved with combat robotics at this point, so I don't think that I'd have the free time anyways. I can take a look into the GPIO counter if you'd like, but I think that I already tried it.

I would suggest naming the class StepInterface for readability.

Let me know if you have any more questions!

Best,
Christian

@CAP1Sup CAP1Sup changed the title need information about A4950 motor driver A4950 / Stepping Interface Questions Jan 15, 2023
@CAP1Sup CAP1Sup self-assigned this Jan 15, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants