Fan etc on external i2c-controller November 01, 2018 03:53PM |
Registered: 7 years ago Posts: 20 |
Re: Fan etc on external i2c-controller November 01, 2018 10:34PM |
Admin Registered: 14 years ago Posts: 7,178 |
Re: Fan etc on external i2c-controller November 02, 2018 02:54AM |
Registered: 7 years ago Posts: 20 |
// @section extruder /** * Extruder cooling fans * * Extruder auto fans automatically turn on when their extruders' * temperatures go above EXTRUDER_AUTO_FAN_TEMPERATURE
Re: Fan etc on external i2c-controller November 02, 2018 03:46AM |
Admin Registered: 14 years ago Posts: 7,178 |
Re: Fan etc on external i2c-controller December 01, 2018 04:09PM |
Registered: 7 years ago Posts: 20 |
M260 A64 M260 B* M260 S1
Re: Fan etc on external i2c-controller December 01, 2018 08:29PM |
Admin Registered: 14 years ago Posts: 7,178 |
Re: Fan etc on external i2c-controller December 02, 2018 05:56AM |
Registered: 7 years ago Posts: 20 |
#define EXPERIMENTAL_I2CBUS
Re: Fan etc on external i2c-controller December 02, 2018 07:03AM |
Admin Registered: 14 years ago Posts: 7,178 |
Re: Fan etc on external i2c-controller December 02, 2018 07:43AM |
Registered: 7 years ago Posts: 20 |
Re: Fan etc on external i2c-controller December 02, 2018 08:49AM |
Admin Registered: 14 years ago Posts: 7,178 |
Re: Fan etc on external i2c-controller December 02, 2018 11:06AM |
Admin Registered: 14 years ago Posts: 7,178 |
#include // PCA9685 I2C address is 0x40(64) #define Addr 0x40 int mode = 0; void setup() { // Initialise I2C communication as MASTER Wire.begin(); // Start I2C Transmission Wire.beginTransmission(Addr); // Select MODE1 register Wire.write(0x00); // Response to LED all-call I2C address Wire.write(0x01); // Stop I2C Transmission Wire.endTransmission(); delay(5); // Start I2C Transmission Wire.beginTransmission(Addr); // Select ALL_LED_ON_L register Wire.write(0x06); // ALL_LED_ON lower byte Wire.write(0x00); // Stop I2C Transmission Wire.endTransmission(); // Start I2C Transmission Wire.beginTransmission(Addr); // Select ALL_LED_ON_H register Wire.write(0x07); // ALL_LED_ON higher byte Wire.write(0x00); // Stop I2C Transmission Wire.endTransmission(); // Start I2C Transmission Wire.beginTransmission(Addr); // Select ALL_LED_OFF_L register Wire.write(0x08); // ALL_LED_OFF lower byte Wire.write(0xFF); // Stop I2C Transmission Wire.endTransmission(); // Start I2C Transmission Wire.beginTransmission(Addr); // Select ALL_LED_OFF_H register Wire.write(0x09); // ALL_LED_OFF higher byte Wire.write(0x0F); // Stop I2C Transmission Wire.endTransmission(); } void loop() { }
M260 A64 M260 B0 M260 B1 M260 S1 M260 A64 M260 B6 M260 B0 M260 S1 M260 A64 M260 B7 M260 B0 M260 S1 M260 A64 M260 B8 M260 B255 M260 S1 M260 A64 M260 B9 M260 B15 M260 S1
Re: Fan etc on external i2c-controller December 02, 2018 12:42PM |
Registered: 7 years ago Posts: 20 |
M260 A64 ;i2c-address in decimal M260 B9 ;choose "LED0_OFF_H" in the Register definitions (chapter 7.3 / page 10) M260 B15 ; what does this mean? Something in Table 7 / page 21?? M260 S1; send to bus
Re: Fan etc on external i2c-controller December 02, 2018 07:30PM |
Admin Registered: 14 years ago Posts: 7,178 |
M260 A64 M260 B0 M260 B1 M260 S1
M260 A64 M260 B6 ;LED_0_ON_L register address see registers 6 - 69 . Each Led has 4 registers a ON_L, ON_H, OFF_L and OFF_H M260 B0 M260 S1 M260 A64 M260 B7 ;LED_0_ON_H M260 B0 M260 S1 M260 A64 M260 B8 ;LED_0_OFF_L M260 B255 M260 S1 M260 A64 M260 B9 ;LED_0_OFF_H M260 B15 M260 S1
M260 A64 M260 B6 ;LED_0_ON_L register address see registers 6 - 69 . Each Led has 4 registers a ON_L, ON_H, OFF_L and OFF_H M260 B255 M260 S1 M260 A64 M260 B7 ;LED_0_ON_H M260 B15 M260 S1 M260 A64 M260 B8 ;LED_0_OFF_L M260 B0 M260 S1 M260 A64 M260 B9 ;LED_0_OFF_H M260 B0 M260 S1
M260 A64 M260 B58 ;LED_13_ON_L (led * 4 +6, led is in range at 0..15) So we want led 13, 13*4+6 = 58 M260 B0 M260 S1 M260 A64 M260 B59 ;LED_13_ON_H (+1 from LED_13_ON_L) M260 B0 M260 S1 M260 A64 M260 B60 ;LED_13_OFF_L (+2 from LED_13_ON_L) M260 B255 M260 S1 M260 A64 M260 B61 ;LED_13_OFF_H (+3 from LED_13_ON_L) M260 B15 M260 S1
Re: Fan etc on external i2c-controller December 09, 2018 04:33AM |
Registered: 7 years ago Posts: 20 |
#define E0_AUTO_FAN_PIN 100
Re: Fan etc on external i2c-controller December 13, 2018 11:58PM |
Admin Registered: 14 years ago Posts: 7,178 |
/** * Driver for the Philips PCA9685 LED driver. * Written by Peter Ellens Dec 2018 Based on PCA9632 Driver by Robert Mendon Feb 2017. */ #ifndef __PCA9685_H__ #define __PCA9685_H__ /* Register addresses */ #define PCA9685_MODE1_REG (byte)0x00 #define PCA9685_MODE2_REG (byte)0x01 #define PCA9685_SUBADR1_REG (byte)0x02 #define PCA9685_SUBADR2_REG (byte)0x03 #define PCA9685_SUBADR3_REG (byte)0x04 #define PCA9685_ALLCALL_REG (byte)0x05 #define PCA9685_LED0_REG (byte)0x06 // Start of LEDx regs, 4B per reg, 2B on phase, 2B off phase, little-endian #define PCA9685_PRESCALE_REG (byte)0xFE #define PCA9685_ALLLED_REG (byte)0xFA // Mode1 register pin layout #define PCA9685_MODE_RESTART (byte)0x80 #define PCA9685_MODE_EXTCLK (byte)0x40 #define PCA9685_MODE_AUTOINC (byte)0x20 #define PCA9685_MODE_SLEEP (byte)0x10 #define PCA9685_MODE_SUBADR1 (byte)0x08 #define PCA9685_MODE_SUBADR2 (byte)0x04 #define PCA9685_MODE_SUBADR3 (byte)0x02 #define PCA9685_MODE_ALLCALL (byte)0x01 // Mode2 register pin layout #define PCA9685_MODE_INVRT (byte)0x10 #define PCA9685_MODE_OCH (byte)0x08 #define PCA9685_MODE_TOTEM_POLE (byte)0x04 #define PCA9685_MODE_OUTNE1 (byte)0x02 #define PCA9685_MODE_OUTNE0 (byte)0x01 #define PCA9685_PWM_FULL (uint16_t)0x01000 // Special value for full on/full off LEDx modes void pca9685_set_port_PWM8(const uint8_t port, uint16_t pwm); void pca9685_set_port_PWM16(const uint8_t port, uint16_t pwm); #endif // __PCA9685_H__
/** * Driver for the Philips PCA9685 LED driver. * Written by Peter Ellens Dec 2018 Based on PCA9632 Driver by Robert Mendon Feb 2017. */ #include "MarlinConfig.h" #ifdef PCA9685 #include "pca9685.h" #include #define PCA9685_MODE1_VALUE PCA9685_MODE_ALLCALL|PCA9685_MODE_AUTOINC #define PCA9685_MODE2_VALUE PCA9685_MODE_TOTEM_POLE #define PCA9685_ADDRESS (byte)0x40 byte PCA9685_init = 0; static void PCA9685_WriteRegister(const byte addr, const byte regadd, const byte value) { Wire.beginTransmission(addr); Wire.write(regadd); Wire.write(value); Wire.endTransmission(); } static void PCA9685_WriteAllRegisters(const byte addr, const byte regadd, const byte value1, const byte value2, const byte value3, const byte value4) { Wire.beginTransmission(addr); Wire.write(regadd); Wire.write(value1); Wire.write(value2); Wire.write(value3); Wire.write(value3); Wire.endTransmission(); } void pca9685_set_port_PWM16(const uint8_t port, uint16_t pwm) { byte on_l=0; byte on_h=0; byte off_l=0; byte off_h=0; Wire.begin(); if (!PCA9685_init) { PCA9685_init = 1; PCA9685_WriteRegister(PCA9685_ADDRESS,PCA9685_MODE1_REG, PCA9685_MODE1_VALUE); PCA9685_WriteRegister(PCA9685_ADDRESS,PCA9685_MODE2_REG, PCA9685_MODE2_VALUE); } if (pwm > PCA9685_PWM_FULL ) pwm = PCA9685_PWM_FULL; if (pwm == PCA9685_PWM_FULL ) on_h = (PCA9685_PWM_FULL&0x1F00)>>8; else if (pwm == 0) off_h = (PCA9685_PWM_FULL&0x1F00)>>8; else { off_h = (pwm&0xF00)>>8; off_l = pwm&0xFF; } PCA9685_WriteAllRegisters(PCA9685_ADDRESS,PCA9685_LED0_REG+(4*port), on_h, on_l, off_h, off_l); } void pca9685_set_port_PWM8(const uint8_t port, uint16_t pwm) { if (pwm >= 255 ) pwm = 256; pca9685_set_port_PWM16(port, pwm<<4); } #endif // PCA9685
// Support for PCA9685 PWM driver #define PCA9685
#ifdef PCA9685 #include "pca9685.h" #endif
inline void gcode_M42() { if (!parser.seenval('S')) return; const byte pin_status = parser.value_byte(); const pin_t pin_number = parser.byteval('P', LED_PIN); if (pin_number < 0) return; if (!parser.boolval('I') && pin_is_protected(pin_number)) return protected_pin_err(); pinMode(pin_number, OUTPUT); digitalWrite(pin_number, pin_status); analogWrite(pin_number, pin_status);
inline void gcode_M42() { if (!parser.seenval('S')) return; const byte pin_status = parser.value_byte(); const pin_t pin_number = parser.byteval('P', LED_PIN); if (pin_number < 0) return; if (!parser.boolval('I') && pin_is_protected(pin_number)) return protected_pin_err(); #ifdef PCA9685 if (pin_number < 100) { #endif pinMode(pin_number, OUTPUT); digitalWrite(pin_number, pin_status); analogWrite(pin_number, pin_status); #ifdef PCA9685 } else { pca9685_set_port_PWM8(pin_number-100, pin_status); } #endif
Re: Fan etc on external i2c-controller April 30, 2020 12:30PM |
Registered: 4 years ago Posts: 5 |
Re: Fan etc on external i2c-controller April 30, 2020 01:25PM |
Admin Registered: 14 years ago Posts: 7,178 |
Re: Fan etc on external i2c-controller April 30, 2020 02:47PM |
Registered: 4 years ago Posts: 5 |
Re: Fan etc on external i2c-controller December 28, 2021 11:02PM |
Admin Registered: 14 years ago Posts: 7,178 |
diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index c50af25e63..3316181893 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -2861,6 +2861,14 @@ // Support for PCA9533 PWM LED driver //#define PCA9533 +// Support for PCA9685 PWM driver +#define PCA9685 +#if ENABLED(PCA9685) + #define PCA9685_ADDRESS (byte)0x40 // I2C address + #define PCA9685_FREQUENCY 200 // PWM frequency 1-3500Hz , 200 is default + #define PCA9685_M43_START_PIN 100 // pins over this number are mapped onto PCA9685 +#endif + /** * RGB LED / LED Strip Control *
diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index 6e44f009ed..05e092cc14 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -4181,7 +4181,7 @@ // // M42 - Set pin states // -//#define DIRECT_PIN_CONTROL +#define DIRECT_PIN_CONTROL // // M43 - display pin status, toggle pins, watch pins, watch endstops & toggle LED, test servo probe
diff --git a/Marlin/src/feature/pca9685.cpp b/Marlin/src/feature/pca9685.cpp new file mode 100644 index 0000000000..e6e8b68d2f --- /dev/null +++ b/Marlin/src/feature/pca9685.cpp @@ -0,0 +1,161 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <[www.gnu.org];. + * + */ + +/** + * Driver for the Philips PCA9685 PWM driver. + */ + +#include "../inc/MarlinConfig.h" + +#if ENABLED(PCA9685) + +#include "pca9685.h" +#include <Wire.h> + +#define PCA9685_MODE1_VALUE PCA9685_MODE_ALLCALL|PCA9685_MODE_AUTOINC +#define PCA9685_MODE2_VALUE PCA9685_MODE_TOTEM_POLE +#ifndef PCA9685_ADDRESS + #define PCA9685_ADDRESS (byte)0x40 +#endif + +/* Register addresses */ +#define PCA9685_MODE1_REG (byte)0x00 +#define PCA9685_MODE2_REG (byte)0x01 +#define PCA9685_SUBADR1_REG (byte)0x02 +#define PCA9685_SUBADR2_REG (byte)0x03 +#define PCA9685_SUBADR3_REG (byte)0x04 +#define PCA9685_ALLCALL_REG (byte)0x05 +#define PCA9685_LED0_REG (byte)0x06 // Start of PWMx regs, 4B per reg, 2B on phase, 2B off phase, little-endian +#define PCA9685_PRESCALE_REG (byte)0xFE +#define PCA9685_ALLLED_REG (byte)0xFA + +// Mode1 register pin layout +#define PCA9685_MODE_RESTART (byte)0x80 +#define PCA9685_MODE_EXTCLK (byte)0x40 +#define PCA9685_MODE_AUTOINC (byte)0x20 +#define PCA9685_MODE_SLEEP (byte)0x10 +#define PCA9685_MODE_SUBADR1 (byte)0x08 +#define PCA9685_MODE_SUBADR2 (byte)0x04 +#define PCA9685_MODE_SUBADR3 (byte)0x02 +#define PCA9685_MODE_ALLCALL (byte)0x01 + +// Mode2 register pin layout +#define PCA9685_MODE_INVRT (byte)0x10 +#define PCA9685_MODE_OCH (byte)0x08 +#define PCA9685_MODE_TOTEM_POLE (byte)0x04 +#define PCA9685_MODE_OUTNE1 (byte)0x02 +#define PCA9685_MODE_OUTNE0 (byte)0x01 + +#define PCA9685_PWM_FULL (uint16_t)0x01000 // Special value for full on/full off LEDx modes + +#define FREQUENCY_OSCILLATOR 25000000 // Int. osc. frequency in datasheet +#define PCA9685_PRESCALE_MIN 3 // minimum prescale value +#define PCA9685_PRESCALE_MAX 255 // maximum prescale value + +byte PCA9685_init = 0; + +static void PCA9685_WriteRegister(const byte addr, const byte regadd, const byte value) { + Wire.beginTransmission(addr); + Wire.write(regadd); + Wire.write(value); + Wire.endTransmission(); +} + +static uint8_t PCA9685_ReadRegister(const byte addr, const byte regadd) { + Wire.beginTransmission(addr); + Wire.write(regadd); + Wire.requestFrom((uint8_t)addr,(uint8_t)1); + uint8_t value = Wire.read(); + Wire.endTransmission(); + return value; +} + +static void PCA9685_WriteAllRegisters(const byte addr, const byte regadd, const byte value1, const byte value2, const byte value3, const byte value4) { + Wire.beginTransmission(addr); + Wire.write(regadd); + Wire.write(value1); + Wire.write(value2); + Wire.write(value3); + Wire.write(value3); + Wire.endTransmission(); +} + +/*! + * @brief Sets the PWM frequency for the entire chip, up to ~1.6 KHz + * @param freq Floating point frequency that we will attempt to match + */ +void PCA9685_setPWMFreq(float freq) { + // Range output modulation frequency is dependant on oscillator + if (freq < 1) + freq = 1; + if (freq > 3500) + freq = 3500; // Datasheet limit is 3052=50MHz/(4*4096) + + float prescaleval = ((FREQUENCY_OSCILLATOR / (freq * 4096.0)) + 0.5) - 1; + if (prescaleval PCA9685_PRESCALE_MIN) + prescaleval = PCA9685_PRESCALE_MIN; + if (prescaleval > PCA9685_PRESCALE_MAX) + prescaleval = PCA9685_PRESCALE_MAX; + uint8_t prescale = (uint8_t)prescaleval; + + uint8_t oldmode = PCA9685_ReadRegister(PCA9685_ADDRESS, PCA9685_MODE1_REG); + uint8_t newmode = (oldmode & ~PCA9685_MODE_RESTART) | PCA9685_MODE_SLEEP; // sleep + PCA9685_WriteRegister(PCA9685_ADDRESS,PCA9685_MODE1_REG, newmode); + PCA9685_WriteRegister(PCA9685_ADDRESS,PCA9685_PRESCALE_REG, prescale); + PCA9685_WriteRegister(PCA9685_ADDRESS,PCA9685_MODE1_REG, oldmode); + safe_delay(5); + // This sets the MODE1 register to turn on auto increment. + PCA9685_WriteRegister(PCA9685_ADDRESS,PCA9685_MODE1_REG, oldmode | PCA9685_MODE_RESTART | PCA9685_MODE_AUTOINC); +} + +void pca9685_set_port_PWM16(const uint8_t port, uint16_t pwm) { + byte on_l=0; + byte on_h=0; + byte off_l=0; + byte off_h=0; + + Wire.begin(); + if (!PCA9685_init) { + PCA9685_init = 1; + PCA9685_WriteRegister(PCA9685_ADDRESS,PCA9685_MODE1_REG, PCA9685_MODE1_VALUE); + PCA9685_WriteRegister(PCA9685_ADDRESS,PCA9685_MODE2_REG, PCA9685_MODE2_VALUE); + PCA9685_setPWMFreq(PCA9685_FREQUENCY); + } + + if (pwm > PCA9685_PWM_FULL ) pwm = PCA9685_PWM_FULL; + + if (pwm == PCA9685_PWM_FULL ) on_h = (PCA9685_PWM_FULL&0x1F00)>>8; + else if (pwm == 0) off_h = (PCA9685_PWM_FULL&0x1F00)>>8; + else { + off_h = (pwm&0xF00)>>8; + off_l = pwm&0xFF; + } + + PCA9685_WriteAllRegisters(PCA9685_ADDRESS,PCA9685_LED0_REG+(4*port), on_h, on_l, off_h, off_l); +} + +void pca9685_set_port_PWM8(const uint8_t port, uint16_t pwm) { + if (pwm >= 255 ) pwm = 256; + pca9685_set_port_PWM16(port, pwm<<4); +} + +#endif // PCA9685
diff --git a/Marlin/src/feature/pca9685.h b/Marlin/src/feature/pca9685.h new file mode 100644 index 0000000000..8815265ff5 --- /dev/null +++ b/Marlin/src/feature/pca9685.h @@ -0,0 +1,29 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <[www.gnu.org];. + * + */ +#pragma once + +/** + * Driver for the Philips PCA9685 PWM driver. + */ + +void pca9685_set_port_PWM8(const uint8_t port, uint16_t pwm); +void pca9685_set_port_PWM16(const uint8_t port, uint16_t pwm);
diff --git a/Marlin/src/gcode/control/M42.cpp b/Marlin/src/gcode/control/M42.cpp index eead971a01..0c6a7aee12 100644 --- a/Marlin/src/gcode/control/M42.cpp +++ b/Marlin/src/gcode/control/M42.cpp @@ -27,6 +27,10 @@ #include "../gcode.h" #include "../../MarlinCore.h" // for pin_is_protected +#if ENABLED(PCA9685) + #include "../../feature/pca9685.h" +#endif + #if HAS_FAN #include "../../module/temperature.h" #endif @@ -118,18 +122,30 @@ void GcodeSuite::M42() { return; } - // An OUTPUT_OPEN_DRAIN should not be changed to normal OUTPUT (STM32) - // Use M42 Px M1/5 S0/1 to set the output type and then set value - #ifndef OUTPUT_OPEN_DRAIN - pinMode(pin, OUTPUT); + #if ENABLED(PCA9685) + if (pin_index < PCA9685_M43_START_PIN) { #endif - extDigitalWrite(pin, pin_status); - #ifdef ARDUINO_ARCH_STM32 - // A simple I/O will be set to 0 by analogWrite() - if (pin_status <= 1 && !PWM_PIN(pin)) return; + // An OUTPUT_OPEN_DRAIN should not be changed to normal OUTPUT (STM32) + // Use M42 Px M1/5 S0/1 to set the output type and then set value + #ifndef OUTPUT_OPEN_DRAIN + pinMode(pin, OUTPUT); + #endif + extDigitalWrite(pin, pin_status); + + #ifdef ARDUINO_ARCH_STM32 + // A simple I/O will be set to 0 by analogWrite() + if (pin_status <= 1 && !PWM_PIN(pin)) return; + #endif + analogWrite(pin, pin_status); + + #if ENABLED(PCA9685) + } + else if (pin_index < PCA9685_M43_START_PIN+16) { + pca9685_set_port_PWM8(pin_index-PCA9685_M43_START_PIN, pin_status); + } + else { SERIAL_ECHO_START(); SERIAL_ECHOLNPGM(" M42 pin ",pin_index," (PCA9685) out of range."); } #endif - analogWrite(pin, pin_status); } #endif // DIRECT_PIN_CONTROL
diff --git a/ini/features.ini b/ini/features.ini index f54b645f85..0ad554c597 100644 --- a/ini/features.ini +++ b/ini/features.ini @@ -124,6 +124,7 @@ BLINKM = src_filter=<src/feature/leds/blinkm.cpp> HAS_COLOR_LEDS = src_filter=+<src/feature/leds/leds.cpp> +<src/gcode/feature/leds/M150.cpp> PCA9533 = src_filter=+<src/feature/leds/pca9533.cpp> PCA9632 = src_filter=+<src/feature/leds/pca9632.cpp> +PCA9685 = src_filter=+<src/feature/pca9685.cpp> PRINTER_EVENT_LEDS = src_filter=+<src/feature/leds/printer_event_leds.cpp> TEMP_STAT_LEDS = src_filter=+<src/feature/leds/tempstat.cpp> MAX7219_DEBUG = src_filter=+<src/feature/max7219.cpp> +<src/gcode/feature/leds/M7219.cpp>