Twi / i2c driver for 32bit boards with digipot (2 x MCP4451 in this case) / internal stepper drivers.
This would be the final bit to get a majority of the current 32bit boards (Smoothie, Mks Sbase, etc..) working on Marlin 2.0.
Currently enabling "#define DIGIPOT_I2C" ends up with this compile error:
Marlin\srcfeature\digipot\digipot_mcp4451.cpp:28:25: fatal error: utility/twi.h: No such file or directory
If the dev''s dosen have a 32bit board with onboard digipot's i am more than willing to test and help out on my side.
-Currently working on my Mks Sbase (LPC1768) setup :
Fan.
Hotendt temp and control.
Heatbed temp and control.
MKs TFT 3.2.
Endstops.
ZProbe (Inductive Proximity LJ12A3-4-Z/BX).
ATX psu on/off.
Sd Card (Marlin makes EEPROM file).
like everyone else i have a I2C / Smbus sniffer laying around somewhere in my mess if needed :)
The Mks Sbase has this addresses, so that means we need to tell digipot_mcp4451.cpp what board we are compiling for:
// This is for the MCP4451 I2C based digipot
void digipot_i2c_set_current(const uint8_t channel, const float current) {
// these addresses are specific to Azteeg X3 Pro, can be set to others,
// Azteeg X3 Pro case first digipot is at address A0=0, A1= 0, second one is at A0=0, A1= 1 // 0x2C & 0x2E
// Mks Sbase case first digipot is at address A0=0, A1= 0, second one is at A0=1, A1= 0 // 0x2C & 0x2D
const byte addr = channel < 4 ? 0x2C : 0x2E; // channel 0-3 vs 4-7
Try this file. It replaces the digipot_mcp4451.cpp.
digipot_mcp4451.zip
I can see it sending I2C data.
This uses the I2C connector and is set for 400K bits per second.
+ - 3.3V
- - ground
20 - SDA
21 - SCL
Thanks for the help @Bob-the-Kuhn but stepper still not moving...
Just some questions so i understand this better if that ok :)
const byte addr = channel < 4 ? 0x2C : 0x2E; // channel 0-3 vs 4-7 ? (0x2e is 0x2d om Sbase)
What does PinCfg.Funcnum = 1, 2, 3 do ?
is this correct ? :
PinCfg.OpenDrain = 0;
PinCfg.Pinmode = 0;
The port/pin config seems correct, this is from my Sbase setup and must be the same as smoothie since i run that normally:
{0,0}, // DIO20 SCA
{0,1}, // DIO21 SCL
and last, the original routine did this:
Wire.beginTransmission(addr);
Wire.write(a);
Wire.write(b);
Wire.endTransmission();
but now it seems we are sending / doing a stop after we send every byte ?
MCP4451_i2c_start(addr);
MCP4451_i2c_send_byte(a); -->void MCP4451_i2c_stop(void)
MCP4451_i2c_send_byte(b);-->void MCP4451_i2c_stop(void)
this is what i have enabled in Configuration_adv:
#define DIGIPOT_I2C
//#define DIGIPOT_MCP4018 // Requires library from https://github.com/stawel/SlowSoftI2CMaster
// Actual motor currents in Amps, need as many here as DIGIPOT_I2C_NUM_CHANNELS
@Bob-the-Kuhn
Your hack "did" work, i did just not notice it since there are more problems, stepper's still not moving..
But, i measured the vref output from the digpot's, set at 1.0amp they measure 0.5v and at 0.5amp it is 0.250v , so that is fully working now, thank's :)
Can't really grasp why the steppers stil dont move, have doubel checked the smoothie schematic and the Mks Sbase are using the same pin's, and smoothieware (compile by my self) runs on the mks sbase without any problems, so they must be identical, only difference is that Mks Sbase uses DRV8825 and smoothie uses A4982 drivers.
Any known problems with Marlin 2.0 and DRV8825 ? or if someone has some ider's please let me know..
I see that TMC drivers has it's own setup in config, but couldn't find anything special about DRV8825.
I missed the part about the MKS having a different I2C address for the second DIGIPOT.
Change one line:
FROM
const byte addr = channel < 4 ? 0x2C : 0x2E; // channel 0-3 vs 4-7
TO:
const byte addr = channel < 4 ? 0x2C : 0x2D; // channel 0-3 vs 4-7
That would explain why some of the steppers didn't move. Some of them should have moved.
Have you tried increasing the current?
You could also try measuring the Vref on a stepper or two and see if it changes when you change the current setting.
define I2CDEV_S_ADDR 0x78 dosen't seem to be used anywhere, is that what this routine does now:
const byte addr = channel < 4 ? 0x2C : 0x2E; // channel 0-3 vs 4-7 ? (0x2e is 0x2d om Sbase)
Correct - I2CDEV_S_ADDR isn't used and addr is used.
What does PinCfg.Funcnum = 1, 2, 3 do ?
This routine uses the hardware I2C controllers. The Funcnum sets the functionality of the pin. "0" means general purpose digital I/O. 1, 2 & 3 select an alternative functionality for the pin. For pin D57 "1" means it's controlled directly by the I2C0 controller, D20 "3" means it's directly controlled by the I2C1 controller, D38 "2" controlled by the I2C2 controller.
is this correct ? :
PinCfg.OpenDrain = 0;
PinCfg.Pinmode = 0;
Those only mean something when function "0" is selected. When you select an alternative function then the LPC1768 automatically configures the pin.
but now it seems we are sending / doing a stop after we send every byte ?
We only issue a stop just before sending the slave address.
The MCP4451_i2c_start(addr); routine first issues an I2C bus stop condition, then an I2C bus start condition and then the slave address with the read/write bit appended. The start condition tells the I2C slave that the next byte is the slave address and read/write bit.
The MCP4451_i2c_send_byte(a); routine just sends a byte. It does not link to the MCP4451_i2c_stop(void) routine.
The MCP4451_i2c_stop(void) routine does nothing. It is not used in this application.
@Bob-the-Kuhn
Thanks for the explanation, already changed to the correct addresses, but stepper's are stil dead, just making that low volume high pitch sound like normal when i enable them (DRV8825 does that) but as soon as i try jog they do 1/2 step or less and freezes up. tripled check all pin's alle seem ok..
Tested with 0.5amp current (0.250v vref) and 1.0amp current (0.500v) same thing, dead :)
asked for some help over at:
https://github.com/MarlinFirmware/Marlin/issues/7076#issuecomment-335198445
Are those the same voltage levels you used in Smoothie?
I keep forgetting that your board doesn't have the stepper drivers in sockets.
The only thing that comes to mind is to put LEDs (with current limiting resistors) across the A and B pins and see what they do when you manually issue movement commands.
You mentioned that you had the board's schematics. I'd like a copy if you don't mind.
@Bob-the-Kuhn
Yes, checked it against Smoothie and the vref levels are correct :)
I am getting pretty desperate so i fired off a email to Makerbase last night, and got some good tips on what to check direct from the board designer (sorry Arthur if you are reading this, but they did change the drivers), they seem pretty eager to get Marlin 2.0 running on the Sbase :) have a feeling that the step pin isn't pulsing correctly, might have to pull out my oscilloscope :/
Could i bother you to have a look at my files, maybe i have overseen something stupid ? will include the zip file here..
stepper_problem.zip
Well, have checked enable and dir on all axes, they work and toggle as they should, the problem is the step signal to the drivers, measured with my frequency counter running smoothiware they produce a 5.9 Khz signal while jogging, in Marlin i get 0 on all axes.
Is there some protective function / setup in marlin while jogging for the step signal or any other reason for it not to be pulsing ? (signal wiring is 100% correct, and i have also cross check the other step pins while jogging 1 axis) feeling lost here :) also tested inverting the step signal...
Those of you that has it working on re-arm, are you using a release from 4 days back and until today, or a older one ?
For M42
/**
* M42: Change pin status via GCode
*
* P<pin> Pin number (LED if omitted)
* S<byte> Pin status from 0 - 255
*/
inline void gcode_M42() {
if (!parser.seenval('S')) return;
const byte pin_status = parser.value_byte();
const int pin_number = parser.intval('P', LED_PIN);
if (pin_number < 0) return;
if (pin_is_protected(pin_number)) {
SERIAL_ERROR_START();
SERIAL_ERRORLNPGM(MSG_ERR_PROTECTED_PIN);
return;
}
...
static bool pin_is_protected(const int8_t pin) {
static const int8_t sensitive_pins[] PROGMEM = SENSITIVE_PINS;
for (uint8_t i = 0; i < COUNT(sensitive_pins); i++)
if (pin == (int8_t)pgm_read_byte(&sensitive_pins[i])) return true;
return false;
}
...
#define SENSITIVE_PINS { 0, 1, \
X_STEP_PIN, X_DIR_PIN, X_ENABLE_PIN, X_MIN_PIN, X_MAX_PIN, \
Y_STEP_PIN, Y_DIR_PIN, Y_ENABLE_PIN, Y_MIN_PIN, Y_MAX_PIN, \
Z_STEP_PIN, Z_DIR_PIN, Z_ENABLE_PIN, Z_MIN_PIN, Z_MAX_PIN, Z_MIN_PROBE_PIN, \
PS_ON_PIN, HEATER_BED_PIN, FAN_PIN, FAN1_PIN, FAN2_PIN, CONTROLLER_FAN_PIN, \
_E0_PINS _E1_PINS _E2_PINS _E3_PINS _E4_PINS BED_PINS \
_H0_PINS _H1_PINS _H2_PINS _H3_PINS _H4_PINS \
_X2_PINS _Y2_PINS _Z2_PINS \
X_MS1_PIN, X_MS2_PIN, Y_MS1_PIN, Y_MS2_PIN, Z_MS1_PIN, Z_MS2_PIN \
}
X_STEP_PIN, Y_STEP_PIN and Z_STEP_PIN are in the sensitive pins list. But M43 can touch those pins if the I flag is given to the command:
```cpp
/**
But... that pin_is_protected() function only stops M42 and M43 from messing with those pins. It doesn't impact the normal Marlin usage of those pins in the list if Marlin needs to move an axis.
Removed X_STEP_PIN from the protected list and did a M42 P26 S255, it went from 0v to 3.2V so pin is wired correctly and controllable, this is just getting stranger by the minute, something is stopping it from pulsing..
Checked the nFault pin on the DRV8825, it goes low when trying to jog, so it is protecting itself from something, probably against the missing step puls..
Could someone that has a re-arm load the current bugfix-2.0.x release and check if steppers is moving with jog ? please :)
Houston we have steppers :)
I would never have figured this out if i wasn't so nosy and was reading through https://github.com/MarlinFirmware/Marlin/pull/7926.
I was on the correct path, in Configuration_adv.h:
change #define MINIMUM_STEPPER_PULSE 0 to #define MINIMUM_STEPPER_PULSE 80
No wonder i couldn't find a step puls :)
Great!!!! Soon we will have a SmoothieBoard setup! And of course, a Azteeg X5 GT setup too!!!!
80us will be to long,
4 us works nicely, spec say's 1.9us minimum pulse high and 1.9us minimum pulse low, so 3.8 us would be dead on, but we cant do "." as expected, but 4us is close enough i think :)
I will clean up my files and figure out how i do a "pull request" (never done that before) but it might not be useful before @Bob-the-Kuhn fixes the digipot i2c, or should i include the "hacked" i2c in a "pull request" ? :)
@Roxy-3D Smoothie will actually run without any changes with the MKS Sbase files :)
Ok. Will wait for you're pull req =)
it might not be useful before @Bob-the-Kuhn fixes the digipot i2c, or should i include the "hacked" i2c in a "pull request" ? :)
If you include the hacked version... Bob can just edit it (or delete it) to get it to what he is comfortable merging...
I can't compile for the Re-ARM. Somewhere along the sequence of allowing some platformio updates and compiling for AVR and then going back to Re-ARM, the CMSIS library got lost. Just copying an old copy into the correct directory doesn't help. Re-installing Atom & platformio didn't help.
Here's what I have. There's absolutely no testing done on it. I don't know if it even compiles. Please test this and let me know what I need to fix.
Put this in your HAL_LPC1768 directory.
ok,
so i put back the original digipot_mcp4451, did //#include "utility/twi.h" and copy'ed your wire.h to HAL_LPC1768/include/wire.h
Errors while compiling:
In file included from Marlin\srcfeature\digipot\digipot_mcp4451.cpp:31:0:
Marlin\src\HAL\HAL_LPC1768include/Wire.h:31:20: error: conflicting return type specified for 'virtual uint8_t TwoWire::write(uint8_t)'
inline uint8_t write(uint8_t);
^~~~~
In file included from frameworks\CMSIS\LPC1768\lib/Stream.h:27:0,
from Marlin\srcfeature\digipot\digipot_mcp4451.cpp:28:
frameworks\CMSIS\LPC1768\lib/Print.h:51:20: error: overriding 'virtual size_t Print::write(uint8_t)'
virtual size_t write(uint8_t) = 0;
^
In file included from Marlin\srcfeature\digipot\digipot_mcp4451.cpp:31:0:
Marlin\src\HAL\HAL_LPC1768include/Wire.h:35:16: error: cannot declare variable 'Wire' to be of abstract type 'TwoWire'
extern TwoWire Wire;
^~
Marlin\src\HAL\HAL_LPC1768include/Wire.h:25:7: note: because the following virtual functions are pure within 'TwoWire':
class TwoWire : public Stream
^~~
In file included from Marlin\srcfeature\digipot\digipot_mcp4451.cpp:28:0:
frameworks\CMSIS\LPC1768\lib/Stream.h:50:17: note: virtual int Stream::available()
virtual int available() = 0;
^~~
frameworks\CMSIS\LPC1768\lib/Stream.h:51:17: note: virtual int Stream::read()
virtual int read() = 0;
^~~
frameworks\CMSIS\LPC1768\lib/Stream.h:52:17: note: virtual int Stream::peek()
virtual int peek() = 0;
^
frameworks\CMSIS\LPC1768\lib/Stream.h:53:18: note: virtual void Stream::flush()
virtual void flush() = 0;
^~~
In file included from Marlin\srcfeature\digipot\digipot_mcp4451.cpp:31:0:
Marlin\src\HAL\HAL_LPC1768include/Wire.h: In member function 'void TwoWire::beginTransmission(uint8_t)':
Marlin\src\HAL\HAL_LPC1768include/Wire.h:90:15: error: 'I2CDEV_M' was not declared in this scope
_I2C_Stop(I2CDEV_M); // output stop state on I2C bus
^~
* [.pioenvs\Re-ARM\src\srcfeature\digipot\digipot_mcp4451.o] Error 1
I can compile for Re-ARM again!!
I need to make supper and then pay bills so it'll be a while before I have something to try.
had to do //#include "utility/twi.h" since it was pretending to be my mother in law and started bitching about not finding it :) but that will break arduino want it ?
Another thing that needs to be done is moving the i2c addresses from digipot_mcp4451.cpp and out to the board config or something, since this addresses are different on different boards...
//AzteegX3Pro case first digipot is at address A0=0, A1= 0, second one is at A0=0, A1= 1 // 0x2C & 0x2E
//Mks Sbase case first digipot is at address A0=0, A1= 0, second one is at A0=1, A1= 0 // 0x2C & 0x2D
const byte addr = channel < 4 ? 0x2C : 0x2D; // channel 0-3 vs 4-7
I've merged the I2C support via PR #7935.
twi.h was also a pain for me. I couldn't find a logical place for it that would compile. I ended up putting it under the HAL directory.
I agree on the I2C addresses. I ran into the same problem with the LCDs. I'm thinking that they should go into the configuration files. That'll have to wait until I have more time.
@Spawn32 thanks for your investigation on this, this had led me to an almost working setup with my MKS Sbase v1.3.
I'm saying almost, because when using digipots only my X and Y axis steppers are moving.
According to this thread this config should be correct for my board (and it comes from the Sbase config example):
// Uncomment to enable an I2C based DIGIPOT like on the Azteeg X3 Pro
#define DIGIPOT_I2C
#if ENABLED(DIGIPOT_I2C) && !defined(DIGIPOT_I2C_ADDRESS_A) // Default to settings in pins_XXXX.h files
/**
* Common slave addresses:
*
* A (A shifted) B (B shifted) IC
* Smoothie 0x2C (0x58) 0x2D (0x5A) MCP4451
* AZTEEG_X3_PRO 0x2C (0x58) 0x2E (0x5C) MCP4451
* MIGHTYBOARD_REVE 0x2F (0x5E) MCP4018
*/
#define DIGIPOT_I2C_ADDRESS_A 0x2C // unshifted slave address for first DIGIPOT
#define DIGIPOT_I2C_ADDRESS_B 0x2D // unshifted slave address for second DIGIPOT
#endif
//#define DIGIPOT_MCP4018 // Requires library from https://github.com/stawel/SlowSoftI2CMaster
#define DIGIPOT_I2C_NUM_CHANNELS 5 // 5DPRINT: 4 AZTEEG_X3_PRO: 8 MKS SBASE: 5
// Actual motor currents in Amps, need as many here as DIGIPOT_I2C_NUM_CHANNELS
#define DIGIPOT_I2C_MOTOR_CURRENTS { 1.2, 1.2, 1.2, 1.2, 1.2 } // MKS SBASE: 5
How can I troubleshoot the issue? Thanks!
For anyone trying to get the digipots working on the Azteeg X5 GT, it uses the shifted addresses for Smoothie (i.e. 0x58 and 0x5A). One strange thing is that the current settings come out about twice as much as I call for in the firmware. To get 1A at the drivers, I have to specify 0.5A in the firmware. A real headache and Panucatt customer support isn't much help.
@Spawn32 did you get the digipots to work?
For what it's worth, it's working correctly on my MKS Sbase after setting the driver to DRV8825 and setting #define DIGIPOT_I2C_MOTOR_CURRENTS { 1, 1, 0.7, 1, 0.7 }
let's see if @Spawn32 ever comes back, if not we must assume that he no longer have interest
@thinkyhead i think we can close this one
@thinkyhead Another one that needs to be closed. Sorry, I got bored.
@thinkyhead Another one that needs to be closed. Sorry, I got bored.
This issue is being closed due to lack of activity. If you have solved the
issue, please let us know how you solved it. If you haven't, please tell us
what else you've tried in the meantime, and possibly this issue will be
reopened.
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.