Ive started an Openpnp/Duet config/gcode page for the Openpnp group. Please help keep the page accurate and up to date. The current example is based off my current machine a CHMT36V using a 6HC and x2 1XD's.
Thanks Wayne
Best posts made by wayneosdias
-
Duet Openpnp
-
RE: Duet Mini 5 BTT MAX31865 Issue
@dc42
Ok got comms sorted. I got this initially
Looks like the MISO line isnt pulled up locally on the the BTT board. I guess this makes sense as the board is meant to plug into 'step stick port' on a BTT driver board. In all the literature I read from BTT/Biqu makes no mention of pullups or active line jumpering. Any way pulled the MISO line up to 3V via 10k and now I get the following;
DWC is also reporting semi resonable values so now just some tuning and firmer wiring to get the ball rolling. I have a Duet PT100 dtr board coming from filastruda and I dont think ill have it for a week. I also ordered an Adafruit MAX31865 bob that should be here tomorrow so Ill follow up this thread on how that gos.Huge thanks for this Forum and support, the best
-
RE: SBC loses network connection, alot!
@Phaedrux "You MIGHT be able to get away with longer length if you used a shielded twisted pair cable instead of a flat ribbon, but even so, SPI isn't meant for long runs."
I dont think shielding will help. The issue is increased capacitance and resistance with long wire runs and screws up the spi signal timing. The quickest check would be what others have suggested. Simply move the SBC closer to the 6HC using the original cable. If that fixes your issue no amount of shielding is going solve your problem. You will need to relocate the SBC next to the 6HC.
-
RE: Read Output pin state
@owend
Will do, I need to get the mechanicals back together first.
If you dont know what this is, it's the aftermath drag pin machine crash. The pin with the bent tip slides up and down within the blue coil of the selenoid with the bent frame.I hope to get fixed tonight and put some of my new and improved RRF commands to work
Thanks again.
-
RE: 6HC power selection
@fcwilt THANK YOU! The schem answers all questions.
For my app I will drive an off board FET driver board via V_OUT's set to 12V. -
RE: Custom 1HCL HW/FW bootloader issues
@dc42
Just to put a bow on this (Merry Xmas ). I got it all working. It took another board rev as I had a couple hw hiccups. This included to swapping the MAX3051 to the TJA1441A CAN xcvr per David's #2 note. Any rate, brand new mcu flashed the bootloader first go. I had to first set the fuses as I listed above. The default fuses had several differences, but I didn't note them.Also, all gpio, motor drivers and accelerometer are working as intended. interested. The '1HCL' is config'd as;
x3 step/dir drives
x2 med current outputs
x4 inputs, 24v tol
x1 lis3dH. I have the W on hand but just wanted to get the original circuit working firstI attached the final config with all the extraneous comments deleted in case anyone is interested.
/* * EXP1HCLv1_0.h * * Created on: 3 Dec 2021 * Author: David */ #ifndef SRC_CONFIG_EXP1HCLV1_0_H_ #define SRC_CONFIG_EXP1HCLV1_0_H_ #include <Hardware/PinDescription.h> #define BOARD_TYPE_NAME "EXP1HCL" #define BOOTLOADER_NAME "SAME5x" // General features #define HAS_VREF_MONITOR 0 #define HAS_VOLTAGE_MONITOR 0 #define HAS_12V_MONITOR 0 #define HAS_CPU_TEMP_SENSOR 1 #define HAS_ADDRESS_SWITCHES 0 #define HAS_BUTTONS 1 // Drivers configuration #define SUPPORT_DRIVERS 1 #define HAS_SMART_DRIVERS 0 #define HAS_STALL_DETECT 0 #define SINGLE_DRIVER 0 #define SUPPORT_SLOW_DRIVERS 0 #define SUPPORT_DELTA_MOVEMENT 0 #define DEDICATED_STEP_TIMER 1 #define ACTIVE_HIGH_STEP 1 // 1 = active high, 0 = active low #define ACTIVE_HIGH_DIR 1 // 1 = active high, 0 = active low #define ACTIVE_HIGH_ENABLE 1 #define SUPPORT_TMC51xx 0 #define SUPPORT_TMC2160 0 #define SUPPORT_TMC2660 0 #define SUPPORT_TMC22xx 0 #define SUPPORT_CLOSED_LOOP 0 #define SUPPORT_BRAKE_PWM 0 constexpr size_t NumDrivers = 3; constexpr size_t MaxSmartDrivers = 0; PortGroup * const StepPio = &(PORT->Group[1]); // the PIO that all the step pins are on (port B) constexpr Pin StepPins[NumDrivers] = { PortBPin(8), PortBPin(22), PortBPin(23) }; constexpr Pin DirectionPins[NumDrivers] = { PortBPin(9), PortAPin(24), PortAPin(27) }; constexpr Pin EnablePins[NumDrivers] = { PortBPin(2), PortAPin(20), PortAPin(25) }; #define SUPPORT_THERMISTORS 0 #define SUPPORT_SPI_SENSORS 1 #define SUPPORT_DMA_NEOPIXEL 0 #ifdef DEBUG # define SUPPORT_I2C_SENSORS 0 // in debug mode the SERCOM is used for debugging # define SUPPORT_LIS3DH 0 #else # define SUPPORT_I2C_SENSORS 0 # define SUPPORT_LIS3DH 1 #endif #define SUPPORT_DHT_SENSOR 0 #define NUM_SERIAL_PORTS 0 #define USE_MPU 0 #define USE_CACHE 1 constexpr bool UseAlternateCanPins = true; constexpr size_t MaxPortsPerHeater = 0; constexpr size_t NumThermistorInputs = 0; constexpr Pin BoardTypePin = PortAPin(3); // Diagnostic LEDs constexpr Pin LedPins[] = { PortAPin(31), PortAPin(30) }; constexpr bool LedActiveHigh = false; constexpr Pin VinMonitorPin = PortAPin(2); //constexpr Pin V12MonitorPin = PortAPin(6); //constexpr float VinDividerRatio = (100.0 + 5.1)/5.1; //constexpr float V12DividerRatio = (60.4 + 4.7)/4.7; //constexpr float VinMonitorVoltageRange = VinDividerRatio * 3.3; //constexpr float V12MonitorVoltageRange = V12DividerRatio * 3.3; constexpr Pin ButtonPins[] = { PortAPin(0) }; //Used for CAN ID reset #if SUPPORT_I2C_SENSORS // I2C using pins PA12,13 constexpr uint8_t I2CSercomNumber = 2; constexpr Pin I2CSDAPin = PortAPin(12); constexpr GpioPinFunction I2CSDAPinPeriphMode = GpioPinFunction::C; constexpr Pin I2CSCLPin = PortAPin(13); constexpr GpioPinFunction I2CSCLPinPeriphMode = GpioPinFunction::C; # define I2C_HANDLER0 SERCOM2_0_Handler # define I2C_HANDLER1 SERCOM2_1_Handler # define I2C_HANDLER2 SERCOM2_2_Handler # define I2C_HANDLER3 SERCOM2_3_Handler #endif #if SUPPORT_LIS3DH # if SUPPORT_I2C_SENSORS # define ACCELEROMETER_USES_SPI (0) // accelerometer is connected via I2C constexpr Pin Lis3dhInt1Pin = PortAPin(20); // same as io1.in # else # define ACCELEROMETER_USES_SPI (1) // accelerometer is connected via SPI constexpr Pin Lis3dhCsPin = PortAPin(18); // same as encoder CS pin constexpr Pin Lis3dhInt1Pin = PortAPin(12); // same as io1.in # endif #endif // Shared SPI (used for interface to encoders, not for temperature sensors) constexpr uint8_t SspiSercomNumber = 1; constexpr uint32_t SspiDataInPad = 3; constexpr Pin SSPIMosiPin = PortAPin(16); constexpr GpioPinFunction SSPIMosiPinPeriphMode = GpioPinFunction::C; constexpr Pin SSPISclkPin = PortAPin(17); constexpr GpioPinFunction SSPISclkPinPeriphMode = GpioPinFunction::C; constexpr Pin SSPIMisoPin = PortAPin(19); constexpr GpioPinFunction SSPIMisoPinPeriphMode = GpioPinFunction::C; // Clock generator pin for TMC2160 constexpr uint8_t ClockGenGclkNumber = 5; constexpr Pin ClockGenPin = PortBPin(11); constexpr GpioPinFunction ClockGenPinPeriphMode = GpioPinFunction::M; // Table of pin functions that we are allowed to use constexpr PinDescription PinTable[] = { // TC TCC ADC SERCOM in SERCOM out Exint PinName // Port A { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, 0, nullptr }, // PA00 ButtonPins[0] PortAPin(0) CANRST { TcOutput::tc2_1, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA01 { TcOutput::none, TccOutput::none, AdcInput::adc0_0, SercomIo::none, SercomIo::none, Nx, "ate.vin" }, // PA02 VinMonitorPin PortAPin(2) { TcOutput::none, TccOutput::none, AdcInput::adc0_1, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA03 BoardTypePin PortAPin(3) { TcOutput::none, TccOutput::none, AdcInput::adc0_4, SercomIo::none, SercomIo::none, Nx, "out1" }, // PA04 { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, "out0" }, // PA05 { TcOutput::none, TccOutput::none, AdcInput::adc0_6, SercomIo::none, SercomIo::none, 6, "io0.in" }, // PA06 { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA07 { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA08//nullptr { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, 9, "io1.in" }, // PA09 { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, 10, "io2.in" }, // PA10 { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, 11, "io3.in" }, // PA11 { TcOutput::none, TccOutput::tcc1_2F, AdcInput::none, SercomIo::none, SercomIo::none, 12, nullptr }, // PA12 Lis3dhInt1Pin = PortAPin(12); { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA13 No IO!! { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA14 crystal { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA15 crystal { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA16 SSPIMosiPin = PortAPin(16); { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA17 SSPISclkPin = PortAPin(17); { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, 2, "spi.cs0" }, // PA18 Lis3dhCsPin = PortAPin(18); { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA19 SSPIMisoPin = PortAPin(19); { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA20 { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA21 { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA22 CAN0 Tx { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA23 CAN0 Rx { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA24 { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA25 { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA26 not on chip { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA27 { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA28 not on chip { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA29 not on chip { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA30 LedPins[1] PortAPin(30) { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA31 LedPins[0] PortAPin(31) // Port B { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB00 not on chip { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB01 not on chip { TcOutput::none, TccOutput::tcc2_2F, AdcInput::none, SercomIo::none, SercomIo::sercom5d, Nx, nullptr }, // PB02 EnablePins[2] PortBPin(2) { TcOutput::none, TccOutput::none, AdcInput::adc0_15, SercomIo::sercom5d, SercomIo::none, Nx, nullptr }, // PB03 { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB04 not on chip { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB05 not on chip { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB06 not on chip { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB07 not on chip { TcOutput::none, TccOutput::none, AdcInput::adc0_2, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB08 StepPins[2] PortBPin(8) { TcOutput::none, TccOutput::none, AdcInput::adc0_3, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB09 DirectionPins[2] PortBPin(9) { TcOutput::none, TccOutput::tcc0_4F, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB10 { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB11 ClockGenPin PortBPin(11); { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB12 not on chip { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB13 not on chip { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB14 not on chip { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB15 not on chip { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB16 not on chip { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB17 not on chip { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB18 not on chip { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB19 not on chip { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB20 not on chip { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB21 not on chip { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB22 StepPins[1] PortBPin(22) { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB23 StepPins[0] PortBPin(23) }; static constexpr size_t NumPins = ARRAY_SIZE(PinTable); static constexpr size_t NumRealPins = 32 + 24; // 32 pins on port A (some missing), 24 on port B static_assert(NumPins == NumRealPins); // no virtual pins in this table // Timer/counter used to generate step pulses and other sub-millisecond timings TcCount32 * const StepTc = &(TC0->COUNT32); constexpr IRQn StepTcIRQn = TC0_IRQn; constexpr unsigned int StepTcNumber = 0; #define STEP_TC_HANDLER TC0_Handler // Available UART ports #define NUM_SERIAL_PORTS 0 // DMA channel assignments constexpr DmaChannel DmacChanTmcTx = 0; constexpr DmaChannel DmacChanTmcRx = 1; constexpr DmaChannel DmacChanAdc0Rx = 2; constexpr DmaChannel DmacChanLedTx = 3; constexpr unsigned int NumDmaChannelsUsed = 4; // must be at least the number of channels used, may be larger. Max 12 on the SAME5x. constexpr DmaPriority DmacPrioTmcTx = 0; constexpr DmaPriority DmacPrioTmcRx = 3; constexpr DmaPriority DmacPrioAdcRx = 2; constexpr DmaPriority DmacPrioLed = 1; // Interrupt priorities, lower means higher priority. 0-2 can't make RTOS calls. const NvicPriority NvicPriorityStep = 3; // step interrupt is next highest, it can preempt most other interrupts const NvicPriority NvicPriorityUart = 3; // serial driver makes RTOS calls const NvicPriority NvicPriorityI2C = 3; const NvicPriority NvicPriorityPins = 3; // priority for GPIO pin interrupts const NvicPriority NvicPriorityCan = 4; const NvicPriority NvicPriorityDmac = 5; // priority for DMA complete interrupts const NvicPriority NvicPriorityAdc = 5; #endif /* SRC_CONFIG_EXP1HCLV1_0_H_ */
-
RE: Rating Duet distributers/resalers?
@infiniteloop
Thanks. The issue I've had has been in regard to reseller sales/shipping itself and not Duet itself or 2ndary integration. Duet is without peer, and I have 7 different production machines using Duet controllers. I'm located in USA CA and have attempted to use a CA based vendor twice for Duet and each time the order has been filled incorrectly. This is extremely frustrating. Conversely, I started using Filastruda located on the opposite side of the country in GA. Ive had 6 different Duet orders with Filastruda with no issues and have received the orders much quicker than the CA base vendor.This is just my experience and I don't know if posting this is of any help to anyone else.
...end of rant.
-
M261.2: UART read output findings
Just an Fyi re the new M260.2/M261.2 commands in RRF 3.6. I was stuck for a couple days trying to leverage the 6HC Aux comm port to get/set parameters of a foc motor and report them back to Openpnp via the Main comm port.
Im sending/receiving data on the Aux port as;
M260.2 P1 B{0x52, 0x5A, 0x0D} G4 10 M261.2 P1 B6
The expected Rx data on the Main port is simply a byte array;
{0x5a, 0x65, 0x72, 0x6f,0x3a, 0x5a}
M261.2 indeed reports the data to the Main comm port, but is prepended with" Received (hex) " and the rx bytes are space seperated; ' ' ;
2024-11-25 22:38:29.200 GcodeDriver$ReaderThread TRACE: [GcodeAsyncDriver:COM13] << Received (hex) 5a 65 72 6f 3a 5a
This needs to be understood, but not explicitly stared in M261.2 if anyone is planning to parse the rx data as one would using regex. For my application the regex
^.*( [0-9a-f]{2}){5} (?<Value>[0-9a-f]{2})
Groups the correct Value for me.
Any rate the new commands work great now that I understand the output.
Latest posts made by wayneosdias
-
RE: 1HCL compatibility question
@dc42 yes thanks re 2240.
Re motor/magnets. I have purchased every flavor of the MKS 42Servo B C D and some diff/similar control boards from btt. They all kinda initially work but would become unstable at some point, overshoot/correct and or lose their 'mind' requiring an in situ recalibration. These were just the control boards mounted to the back of old nema17 motors with magnets glued to the shaft.I then tried a motor/control board combo of MKS servo D and it has worked very well in terms of long term stability. When I installed the motor, I noticed the drive side of the shaft. It appears to be an 8mm shaft turned down to 5mm. Taking the control board off looking at the non drive of the shaft and it appears to be milled with the magnet recessed into it. Or maybe the magnet is banded to the shaft? What ever may be the case, the fb/encoding of this controller/motor combo has been rocks solid.
Just food for thought
-
RE: 1HCL compatibility question
Well it's really a testament to David, Duet and the Moderators. I wouldn't even know where to start without them. Mechatronics isn't my thing even though I rely on 4 one-off purpose-built machines for my business. I can just scheme general design concepts and leverage the Duet system to meet the control needs.
-
RE: 1HCL compatibility question
@ironhydroxide
Hi Iron,Interesting offer, but I simply don't have the bandwidth to take on such a project or attempt to support it. With the qty you're looking at, Duet and or possibly a sub-contractor would be your best bet. That said, sounds like your design criteria would be fairly easy to meet, but one off propriety in nature. You need to get a design engineering quote, maybe the folks at Duet could point you in the right direction.
That said I'm just throwing my design out there to share w the community. I didn't put out the full schematic, heres the supply side of things, 24V 5V 3v3. Fyi the pic of the pcb i posted above was a first pass I did in a couple of hrs. Im sure its going to change after some more DRC checks. Ill prolly order the board Monday. Its simply to illustrate the Duet control accessory scheme is flexible enough to meet what it is you're proposing, even with some of your physical design constraints.
I am editing this post by removing the V supply schematic. The schematic was pulled from a different design and not fully reviewed for use in this case. Upon review the circuit needs to be reworked and not acceptable as initially posted.
-
RE: 1HCL compatibility question
@ironhydroxide Hey Iron, This will be a Nema17 mounted Duet 1HCL + Duet Magnet board without any gpio. Im keeping all the original 1HCL Duet peripheral pin assignments, just not using all of them to speed up the process.
This will be my 2nd Custom Duet Expansion. The First go around I added accelerometer, 2 addl drivers and messed around w the pin assignments. It all works great but took a couple weeks to get right. I think the above should work as intended much quicker by not going off script with pin/peripheral assignments. I just don't have time to keep the machine down, I use it for production.
I always order a couple boards. Once I get one built and confirm fxn I can send you a spare pcb if your in the states. In keeping w Duet opensource Ill make all dev files available if you feel like using the design on some level. Keep in mind some of my apparently odd part choices are based on what I have on hand, like the full reel of dual channel Vregs my company is not going to use...
-
RE: 1HCL compatibility question
@ironhydroxide @dc42
I just did this. Just for my pnp set up to get ride of the MKS Servo42D. Basically 1HCL + mag board wo any io
-
RE: Custom 1HCL HW/FW bootloader issues
@dc42
Just to put a bow on this (Merry Xmas ). I got it all working. It took another board rev as I had a couple hw hiccups. This included to swapping the MAX3051 to the TJA1441A CAN xcvr per David's #2 note. Any rate, brand new mcu flashed the bootloader first go. I had to first set the fuses as I listed above. The default fuses had several differences, but I didn't note them.Also, all gpio, motor drivers and accelerometer are working as intended. interested. The '1HCL' is config'd as;
x3 step/dir drives
x2 med current outputs
x4 inputs, 24v tol
x1 lis3dH. I have the W on hand but just wanted to get the original circuit working firstI attached the final config with all the extraneous comments deleted in case anyone is interested.
/* * EXP1HCLv1_0.h * * Created on: 3 Dec 2021 * Author: David */ #ifndef SRC_CONFIG_EXP1HCLV1_0_H_ #define SRC_CONFIG_EXP1HCLV1_0_H_ #include <Hardware/PinDescription.h> #define BOARD_TYPE_NAME "EXP1HCL" #define BOOTLOADER_NAME "SAME5x" // General features #define HAS_VREF_MONITOR 0 #define HAS_VOLTAGE_MONITOR 0 #define HAS_12V_MONITOR 0 #define HAS_CPU_TEMP_SENSOR 1 #define HAS_ADDRESS_SWITCHES 0 #define HAS_BUTTONS 1 // Drivers configuration #define SUPPORT_DRIVERS 1 #define HAS_SMART_DRIVERS 0 #define HAS_STALL_DETECT 0 #define SINGLE_DRIVER 0 #define SUPPORT_SLOW_DRIVERS 0 #define SUPPORT_DELTA_MOVEMENT 0 #define DEDICATED_STEP_TIMER 1 #define ACTIVE_HIGH_STEP 1 // 1 = active high, 0 = active low #define ACTIVE_HIGH_DIR 1 // 1 = active high, 0 = active low #define ACTIVE_HIGH_ENABLE 1 #define SUPPORT_TMC51xx 0 #define SUPPORT_TMC2160 0 #define SUPPORT_TMC2660 0 #define SUPPORT_TMC22xx 0 #define SUPPORT_CLOSED_LOOP 0 #define SUPPORT_BRAKE_PWM 0 constexpr size_t NumDrivers = 3; constexpr size_t MaxSmartDrivers = 0; PortGroup * const StepPio = &(PORT->Group[1]); // the PIO that all the step pins are on (port B) constexpr Pin StepPins[NumDrivers] = { PortBPin(8), PortBPin(22), PortBPin(23) }; constexpr Pin DirectionPins[NumDrivers] = { PortBPin(9), PortAPin(24), PortAPin(27) }; constexpr Pin EnablePins[NumDrivers] = { PortBPin(2), PortAPin(20), PortAPin(25) }; #define SUPPORT_THERMISTORS 0 #define SUPPORT_SPI_SENSORS 1 #define SUPPORT_DMA_NEOPIXEL 0 #ifdef DEBUG # define SUPPORT_I2C_SENSORS 0 // in debug mode the SERCOM is used for debugging # define SUPPORT_LIS3DH 0 #else # define SUPPORT_I2C_SENSORS 0 # define SUPPORT_LIS3DH 1 #endif #define SUPPORT_DHT_SENSOR 0 #define NUM_SERIAL_PORTS 0 #define USE_MPU 0 #define USE_CACHE 1 constexpr bool UseAlternateCanPins = true; constexpr size_t MaxPortsPerHeater = 0; constexpr size_t NumThermistorInputs = 0; constexpr Pin BoardTypePin = PortAPin(3); // Diagnostic LEDs constexpr Pin LedPins[] = { PortAPin(31), PortAPin(30) }; constexpr bool LedActiveHigh = false; constexpr Pin VinMonitorPin = PortAPin(2); //constexpr Pin V12MonitorPin = PortAPin(6); //constexpr float VinDividerRatio = (100.0 + 5.1)/5.1; //constexpr float V12DividerRatio = (60.4 + 4.7)/4.7; //constexpr float VinMonitorVoltageRange = VinDividerRatio * 3.3; //constexpr float V12MonitorVoltageRange = V12DividerRatio * 3.3; constexpr Pin ButtonPins[] = { PortAPin(0) }; //Used for CAN ID reset #if SUPPORT_I2C_SENSORS // I2C using pins PA12,13 constexpr uint8_t I2CSercomNumber = 2; constexpr Pin I2CSDAPin = PortAPin(12); constexpr GpioPinFunction I2CSDAPinPeriphMode = GpioPinFunction::C; constexpr Pin I2CSCLPin = PortAPin(13); constexpr GpioPinFunction I2CSCLPinPeriphMode = GpioPinFunction::C; # define I2C_HANDLER0 SERCOM2_0_Handler # define I2C_HANDLER1 SERCOM2_1_Handler # define I2C_HANDLER2 SERCOM2_2_Handler # define I2C_HANDLER3 SERCOM2_3_Handler #endif #if SUPPORT_LIS3DH # if SUPPORT_I2C_SENSORS # define ACCELEROMETER_USES_SPI (0) // accelerometer is connected via I2C constexpr Pin Lis3dhInt1Pin = PortAPin(20); // same as io1.in # else # define ACCELEROMETER_USES_SPI (1) // accelerometer is connected via SPI constexpr Pin Lis3dhCsPin = PortAPin(18); // same as encoder CS pin constexpr Pin Lis3dhInt1Pin = PortAPin(12); // same as io1.in # endif #endif // Shared SPI (used for interface to encoders, not for temperature sensors) constexpr uint8_t SspiSercomNumber = 1; constexpr uint32_t SspiDataInPad = 3; constexpr Pin SSPIMosiPin = PortAPin(16); constexpr GpioPinFunction SSPIMosiPinPeriphMode = GpioPinFunction::C; constexpr Pin SSPISclkPin = PortAPin(17); constexpr GpioPinFunction SSPISclkPinPeriphMode = GpioPinFunction::C; constexpr Pin SSPIMisoPin = PortAPin(19); constexpr GpioPinFunction SSPIMisoPinPeriphMode = GpioPinFunction::C; // Clock generator pin for TMC2160 constexpr uint8_t ClockGenGclkNumber = 5; constexpr Pin ClockGenPin = PortBPin(11); constexpr GpioPinFunction ClockGenPinPeriphMode = GpioPinFunction::M; // Table of pin functions that we are allowed to use constexpr PinDescription PinTable[] = { // TC TCC ADC SERCOM in SERCOM out Exint PinName // Port A { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, 0, nullptr }, // PA00 ButtonPins[0] PortAPin(0) CANRST { TcOutput::tc2_1, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA01 { TcOutput::none, TccOutput::none, AdcInput::adc0_0, SercomIo::none, SercomIo::none, Nx, "ate.vin" }, // PA02 VinMonitorPin PortAPin(2) { TcOutput::none, TccOutput::none, AdcInput::adc0_1, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA03 BoardTypePin PortAPin(3) { TcOutput::none, TccOutput::none, AdcInput::adc0_4, SercomIo::none, SercomIo::none, Nx, "out1" }, // PA04 { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, "out0" }, // PA05 { TcOutput::none, TccOutput::none, AdcInput::adc0_6, SercomIo::none, SercomIo::none, 6, "io0.in" }, // PA06 { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA07 { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA08//nullptr { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, 9, "io1.in" }, // PA09 { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, 10, "io2.in" }, // PA10 { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, 11, "io3.in" }, // PA11 { TcOutput::none, TccOutput::tcc1_2F, AdcInput::none, SercomIo::none, SercomIo::none, 12, nullptr }, // PA12 Lis3dhInt1Pin = PortAPin(12); { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA13 No IO!! { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA14 crystal { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA15 crystal { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA16 SSPIMosiPin = PortAPin(16); { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA17 SSPISclkPin = PortAPin(17); { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, 2, "spi.cs0" }, // PA18 Lis3dhCsPin = PortAPin(18); { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA19 SSPIMisoPin = PortAPin(19); { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA20 { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA21 { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA22 CAN0 Tx { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA23 CAN0 Rx { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA24 { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA25 { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA26 not on chip { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA27 { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA28 not on chip { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA29 not on chip { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA30 LedPins[1] PortAPin(30) { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PA31 LedPins[0] PortAPin(31) // Port B { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB00 not on chip { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB01 not on chip { TcOutput::none, TccOutput::tcc2_2F, AdcInput::none, SercomIo::none, SercomIo::sercom5d, Nx, nullptr }, // PB02 EnablePins[2] PortBPin(2) { TcOutput::none, TccOutput::none, AdcInput::adc0_15, SercomIo::sercom5d, SercomIo::none, Nx, nullptr }, // PB03 { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB04 not on chip { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB05 not on chip { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB06 not on chip { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB07 not on chip { TcOutput::none, TccOutput::none, AdcInput::adc0_2, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB08 StepPins[2] PortBPin(8) { TcOutput::none, TccOutput::none, AdcInput::adc0_3, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB09 DirectionPins[2] PortBPin(9) { TcOutput::none, TccOutput::tcc0_4F, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB10 { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB11 ClockGenPin PortBPin(11); { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB12 not on chip { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB13 not on chip { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB14 not on chip { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB15 not on chip { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB16 not on chip { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB17 not on chip { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB18 not on chip { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB19 not on chip { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB20 not on chip { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB21 not on chip { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB22 StepPins[1] PortBPin(22) { TcOutput::none, TccOutput::none, AdcInput::none, SercomIo::none, SercomIo::none, Nx, nullptr }, // PB23 StepPins[0] PortBPin(23) }; static constexpr size_t NumPins = ARRAY_SIZE(PinTable); static constexpr size_t NumRealPins = 32 + 24; // 32 pins on port A (some missing), 24 on port B static_assert(NumPins == NumRealPins); // no virtual pins in this table // Timer/counter used to generate step pulses and other sub-millisecond timings TcCount32 * const StepTc = &(TC0->COUNT32); constexpr IRQn StepTcIRQn = TC0_IRQn; constexpr unsigned int StepTcNumber = 0; #define STEP_TC_HANDLER TC0_Handler // Available UART ports #define NUM_SERIAL_PORTS 0 // DMA channel assignments constexpr DmaChannel DmacChanTmcTx = 0; constexpr DmaChannel DmacChanTmcRx = 1; constexpr DmaChannel DmacChanAdc0Rx = 2; constexpr DmaChannel DmacChanLedTx = 3; constexpr unsigned int NumDmaChannelsUsed = 4; // must be at least the number of channels used, may be larger. Max 12 on the SAME5x. constexpr DmaPriority DmacPrioTmcTx = 0; constexpr DmaPriority DmacPrioTmcRx = 3; constexpr DmaPriority DmacPrioAdcRx = 2; constexpr DmaPriority DmacPrioLed = 1; // Interrupt priorities, lower means higher priority. 0-2 can't make RTOS calls. const NvicPriority NvicPriorityStep = 3; // step interrupt is next highest, it can preempt most other interrupts const NvicPriority NvicPriorityUart = 3; // serial driver makes RTOS calls const NvicPriority NvicPriorityI2C = 3; const NvicPriority NvicPriorityPins = 3; // priority for GPIO pin interrupts const NvicPriority NvicPriorityCan = 4; const NvicPriority NvicPriorityDmac = 5; // priority for DMA complete interrupts const NvicPriority NvicPriorityAdc = 5; #endif /* SRC_CONFIG_EXP1HCLV1_0_H_ */
-
RE: Duet Openpnp Head
@dc42
Your Duet solution sounds interesting, but bus loading sounds like a potential issue and I don't have the know how to analyze any performance hits to the CAN bus. I do appreciate your answer though as it reinforces my confidence in my work around.The rationale for vacuum sensing to determine whether a part was successfully 'picked' or not. Vacuum sensing is not mandatory, and I have been running without it for sometime, but it can substantially increase machine efficiency. Efficiency is increased by not allowing the machine to run every potential pick to the vision system 100's mm away.
As you note, Openpnp doesn't necc need to know the actual vacuum value, but whether a part is 'on' or 'off' the nozzle. The challenge in qualifying if a part is 'on' vs 'off' include;
- Different nozzle tips have different vacuum 'on', but part 'off' values
- Different part packages have different 'on' values for the same tip
- The vacuum signal in general is very noisy and slow to build to maximum.
Openpnp has some pretty comprehensive functions to analyze and differentiate vacuum states for all vacuum part/tip parameters. But my machine initially had weak diaphragm pump that was slow and noisy. I couldn't get the Openpnp functions to work consistently in a practical way. I've since upgraded to vacuum ejectors, and I no longer have any of the original control electronics.
Im all Duet3 now with robust pneumatics, I'm pretty confident I could use Duet3 Temp/analog sensing to leverage the Openpnp functions. But this seems like it will be slow especially given the Duet 4Hz sampling rate. This is a full custom system now and I think a purpose-built vacuum sensor feedback system would be much quicker. I don't want to slow the system by packing dwells into the pick/feed process waiting for a stable Temp reading.
This is all just speculation. I don't have the sensor circuit designed or in place yet. I have no idea what the sensor hw actual transfer fxn will look like and or if it'll need filering.
Regardless of the vacuum sensing hw, I like the idea of abstracting the Openpnp fxns and performing them locally on a dedicated vac board mcu. The mcu is updated on the current part/nozzle via Duet3 aux comm and allowed to free run sampling the sensors, only flagging the Duet/Openpnp system via IO_x.in on any state changes.
-
Duet Openpnp Head
I've built a custom Duet Exp3 board using the Duet SAME5x that handles x3 motors, the limits and the outputs. The only thing missing is x2 vacuum analog sensing and I don't think I'll be able to use the Duet control algorithm as the analog/heat task is only 4Hz. There is also some vac based logic processing that needs to take place and I'd like to keep the Duet focused on digital signals and kinematics.
My solution is to use a secondary vacuum sensor board with a dedicated non-Duet mcu to monitor sensor levels and that will set digital io on the Duet inputs. Sensor thresholds will be dynamically set via Openpnp/Duet Aux comm via RS485. Openpnp will simply ask the state of the associated Duet input...
Am I over complicating this? Am I missing a fully native Duet solution?
Current Duet based machine
New Duet based machine, Vacumm sensor board in question
Any input appreciated
-
RE: LIS3D using SPI issues
@dc42 Ah ok, I thought any digital input simply had to be assigned a unique 0-15 Exint. Makes sense now. Ill review the DS and see if I can sort it out.
Thanks for the help
-
RE: LIS3D using SPI issues
I got it sorted :). I was suspecting the INT pin irq was not getting called because both of my newly declared io0 and io1 pins aren't getting flagged in OM. I tried setting other gpio as inputs and the first pin I found that the OM would flag I set to the LIS3 INT1 and now everything works;
/** Doesnt work **// //constexpr Pin Lis3dhInt1Pin = PortAPin(12); //{ TcOutput::none, TccOutput::tcc1_2F, AdcInput::none, SercomIo::none, sercom2cPad0, 4, nullptr }, // PA12 /** Works! **// constexpr Pin Lis3dhInt1Pin = PortBPin(3); { TcOutput::none, TccOutput::none, AdcInput::adc0_15, SercomIo::sercom5d, SercomIo::none, 3, nullptr },// PB03
The proof
Now I just have to sort out what is going in the config.h, with none of my inputs working as I initally set. All the outputs work fine.
Any rate pleased to announce Duet3Exp SPI works Thanks for the help guys!