Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 5 of 5

Thread: marlin 2.0 teensy hal with i2c gpio expander

  1. #1
    Junior Member
    Join Date
    Oct 2018
    Posts
    5

    marlin 2.0 teensy hal with i2c gpio expander

    Hello all,
    I've been working on a 3D printing shield for Teensy 3.5/3.6.
    Since I wanted to cram more features on the pcb I decided to use 3x pcf8574 (i2c) for STEP/DIR/EN and CS (for spi drivers).
    I've been looking at the teensy 3.5/3.6 pinout file and I don't think it's going to be that easy.
    I attached part of the schematic.
    How should I go about it?
    I really hope I didn't mess this up by making the board before making sure I can define pins over gpio expanders.
    I tested all hardware and it works electrically.
    There's 6 motor driver sockets, 6 endstops, 3 thermistors (agnd/avcc), one z-probe, one MAX31865 chip for pt100/1000 (with jumper pads for 2-4 wires), 6 fan pwm outputs with option to use 12V for 3 of them, one 12V always on fan, one 24V always on fan, 2 servo connectors (driven by buffer), 3 power supplies that can be replaced (those 1$ buck converters, slim, 4 pins in a row type) 5V, 3.3V and whatever voltage for the 3 fans (all 3 have status led and 3.3V and 12V can be enabled/disabled by teensy, 5V is always on). If they pop they can be replaced by plugging them out of their socket. 2 extruder mosfets and 1 heatbed mosfet that are driven by a buffer. There's 5 fuses (not installed yet), one for each power supply, one for the drivers (24V) and one for bed/extruders.
    Drivers can be drv8825/a4988 or spi like tmc2130 or uart like tmc 2208. There's also a sd-card that should theoretically fit the slot on an ender 3. Added also a socket for esp12e format of esp8266 that also can read the sd-card. esp12e has 6 pins broken out, standard lcd/sdcard expansion connectors and I managed to save only two pins, that I chose to be A10/A11 combo for a differential pair setup with a simple input filter.
    It would be a real shame if I'm this stupid.
    *edit
    To be honest now I'd drop a driver space for a relay for bed/extruders so I can have that extra bit of safety. Ender 3 has 9A for the bed and another 2 for the extruder. A 20A could do even with a second extruder. Also got the rotation wrong on power connectors. And there's a precision reference as well for aref.
    Attached Thumbnails Attached Thumbnails Click image for larger version. 

Name:	Capture2.PNG 
Views:	9 
Size:	40.7 KB 
ID:	15457   Click image for larger version. 

Name:	WhatsApp Image 2018-12-31 at 01.49.18.jpg 
Views:	7 
Size:	167.0 KB 
ID:	15458  

    Click image for larger version. 

Name:	WhatsApp Image 2018-12-29 at 04.30.40.jpg 
Views:	11 
Size:	205.2 KB 
ID:	15459  
    Last edited by bob23; 12-31-2018 at 05:16 AM.

  2. #2
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    5,043
    wow, i'm searching for something like this - is it on github or downloadable somewhere else? ( EAGLE? )
    Which displays does it support?

  3. #3
    Junior Member
    Join Date
    Oct 2018
    Posts
    5
    I first need to see if I can make it work and then I'll see what I do with this project.
    Connectors have SPI/I2C/UART comms and should support most displays. Attached the pinouts for connectors.
    Attached Thumbnails Attached Thumbnails Click image for larger version. 

Name:	Capture.PNG 
Views:	2 
Size:	48.5 KB 
ID:	15468   Click image for larger version. 

Name:	Capture3.PNG 
Views:	2 
Size:	46.9 KB 
ID:	15469  


  4. #4
    Junior Member
    Join Date
    Oct 2018
    Posts
    5
    I looked at the code and can't figure out how to define the extra pins provided by the i2c expander chips.
    I made a sketch that blinks one pin on each chip, and I managed to control all of them.
    Code:
    #include <Wire.h>
    #include <pcf8574.h>   // import library
    
    
    pcf8574 mcp1(0x20);//instance
    pcf8574 mcp2(0x21);//instance
    pcf8574 mcp3(0x22);//instance
    void setup(){
      
      Wire.setSDA(48);
      Wire.setSCL(47);  
      mcp1.begin();
      mcp1.gpioPinMode(OUTPUT);
      mcp1.gpioPort(LOW);
      mcp2.gpioPort(LOW);
      mcp3.gpioPort(LOW);
      mcp2.begin();
      mcp2.gpioPinMode(OUTPUT);
      mcp3.begin();
      mcp3.gpioPinMode(OUTPUT);
      
    }
    
    void loop(){
    
      mcp1.gpioDigitalWrite(3, 1);
      mcp2.gpioDigitalWrite(3, 1);
      mcp3.gpioDigitalWrite(3, 1);
      delay(3000);
    
      mcp1.gpioDigitalWrite(3, 0);
      mcp2.gpioDigitalWrite(3, 0);
      mcp3.gpioDigitalWrite(3, 0);
      delay(3000);
    }
    I had a look at the HAL files and I can't tell how the pins are defined.
    This is pins_TEENSY35_36.h file:

    Code:
    /**
     * Marlin 3D Printer Firmware
     * Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
     *
     */
    
    /****************************************************************************************
    * Teensy 3.5 (MK64FX512) and Teensy 3.6 (MK66FX1M0) Breadboard pin assignments
    * Requires the Teensyduino software with Teensy 3.5 or Teensy 3.6 selected in Arduino IDE!
    * http://www.pjrc.com/teensy/teensyduino.html
    ****************************************************************************************/
    
    #if !IS_32BIT_TEENSY
      #error "Oops! Select 'Teensy 3.5' or 'Teensy 3.6' in 'Tools > Board.'"
    #endif
    
    #if IS_TEENSY35
      #define BOARD_NAME "Teensy3.5"
    #elif IS_TEENSY36
      #define BOARD_NAME "Teensy3.6"
    #endif
    
    #define AT90USB 1286   // Disable MarlinSerial etc.
    #define USBCON //1286  // Disable MarlinSerial etc.
    /*
    
      teemuatlut plan for Teensy3.5 and Teensy3.6:
                                                         USB
                                              GND |-----#####-----| VIN 5V
          X_STEP_PIN          MOSI1   RX1       0 |     #####     | Analog GND
          X_DIR_PIN           MISO1   TX1       1 |               | 3.3V
          Y_STEP_PIN                       PWM  2 | *NC     AREF* | 23  A9 PWM
          Y_DIR_PIN           SCL2 CAN0TX  PWM  3 | *A26     A10* | 22  A8 PWM
          Z_STEP_PIN          SDA2 CAN0RX  PWM  4 | *A25     A11* | 21  A7 PWM  CS0   MOSI1  RX1
          Z_DIR_PIN           MISO1   TX1  PWM  5 | *GND * * 57   | 20  A6 PWM  CS0   SCK1        FILWIDTH_PIN
          X_ENABLE_PIN                     PWM  6 | *GND * * 56   | 19  A5            SCL0        E0_STEP_PIN
          Y_ENABLE_PIN  SCL0  MOSI0   RX3  PWM  7 |      * * 55   | 18  A4            SDA0        E0_DIR_PIN
          Z_ENABLE_PIN  SDA0  MISO0   TX3  PWM  8 |      * * 54   | 17  A3            SDA0        E0_ENABLE_PIN
                              CS0     RX2  PWM  9 |               | 16  A2            SCL0        TEMP_0_PIN
                              CS0     TX2  PWM 10 |               | 15  A1      CS0               TEMP_BED_PIN
          X_STOP_PIN          MOSI0            11 |               | 14  A0 PWM  CS0               TEMP_1_PIN
          Y_STOP_PIN          MISO0            12 |               | 13 LED            SCK0        LED_PIN
                                             3.3V |               | GND
          Z_STOP_PIN                           24 |   40 * * 53   |    A22 DAC1
    AUX2                                       25 |   41 * * 52   |    A21 DAC0
    AUX2  FAN_PIN             SCL2    TX1      26 |   42 * * 51   | 39 A20      MISO0             SDSS
    AUX2  Z-PROBE PWR         SCK0    RX1      27 | *  *  *  *  * | 38 A19 PWM        SDA1
    AUX2  SOL1_PIN            MOSI0            28 |   43 * * 50   | 37 A18 PWM        SCL1
    D10   CONTROLLER_FAN_PIN  CAN0TX       PWM 29 |   44 * * 49   | 36 A17 PWM
    D9    HEATER_0_PIN        CAN0RX       PWM 30 |   45 * * 48   | 35 A16 PWM                    E1_ENABLE_PIN
    D8    HEATER_BED_PIN      CS1     RX4  A12 31 |   46 * * 47   | 34 A15 PWM        SDA0  RX5   E1_DIR_PIN
                              SCK1    TX4  A13 32 |__GND_*_*_3.3V_| 33 A14 PWM        SCL0  TX5   E1_STEP_PIN
    
              Interior pins:
                              LCD_PINS_RS             40 * * 53   SCK2
                              LCD_PINS_ENABLE         41 * * 52   MOSI2
                              LCD_PINS_D4             42 * * 51   MISO2
                              LCD_PINS_D5     CS2     43 * * 50   A24
                              LCD_PINS_D6     MOSI2   44 * * 49   A23
                              LCD_PINS_D7     MISO2   45 * * 48   TX6   SDA0  BTN_ENC
                              BTN_EN1         SCK2    46 * * 47   RX6   SCL0  BTN_EN2
                                                     GND * * 3.3V
    
    */
    
    //
    // Limit Switches
    //
    #define X_STOP_PIN         24
    #define Y_STOP_PIN         26
    #define Z_STOP_PIN         28
    
    //
    // Steppers
    //
    #define X_STEP_PIN         22
    #define X_DIR_PIN          21
    #define X_ENABLE_PIN       39
    
    #define Y_STEP_PIN         19
    #define Y_DIR_PIN          18
    #define Y_ENABLE_PIN       20
    
    #define Z_STEP_PIN         38
    #define Z_DIR_PIN          37
    #define Z_ENABLE_PIN       17
    
    #define E0_STEP_PIN        31
    #define E0_DIR_PIN         30
    #define E0_ENABLE_PIN      32
    
    #define E1_STEP_PIN        33
    #define E1_DIR_PIN         34
    #define E1_ENABLE_PIN      35
    
    #define HEATER_0_PIN       30
    #define HEATER_1_PIN       36
    #define HEATER_BED_PIN     31
    #ifndef FAN_PIN
      #define FAN_PIN           2
    #endif
    
    #define TEMP_0_PIN          2   // Extruder / Analog pin numbering: 2 => A2
    #define TEMP_1_PIN          0
    #define TEMP_BED_PIN        1   // Bed / Analog pin numbering
    
    #define SDSS               39   // 8
    #define LED_PIN            13
    #define PS_ON_PIN           1
    #define ALARM_PIN          -1
    
    #define FILWIDTH_PIN        6
    #define SOL1_PIN           28
    
    #if 0
    // Pretty sure this is obsolete!
    // Please use Marlin 1.1.x pins files as reference for new pins files.
    #ifndef SDSUPPORT
      // these are defined in the SD library if building with SD support
      #define SCK_PIN          13
      #define MISO_PIN         12
      #define MOSI_PIN         11
    #endif
    #endif
    
    #if ENABLED(ULTRA_LCD)
      #define LCD_PINS_RS      40
      #define LCD_PINS_ENABLE  41
      #define LCD_PINS_D4      42
      #define LCD_PINS_D5      43
      #define LCD_PINS_D6      44
      #define LCD_PINS_D7      45
    #endif
    
    #if ENABLED(NEWPANEL)
      #define BTN_EN1          46
      #define BTN_EN2          47
      #define BTN_ENC          48
    #endif
    
    #if ENABLED(REPRAPWORLD_KEYPAD)
      #define SHIFT_OUT        40
      #define SHIFT_CLK        44
      #define SHIFT_LD         42
    #endif

    As I see it, pin 71 is the last defined pin, and is VREF.
    I was thinking of adding the extra 24 pins something like 72-95 for pin numbers, that I can add in pins_TEENSY35_36.h file for STEP/DIR/ENN.
    This is the teensy 3.5/3.6 HAL.cpp file:

    Code:
    /* **************************************************************************
    
     Marlin 3D Printer Firmware
     Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
     Copyright (c) 2016 Bob Cousins bobcousins42@googlemail.com
    
     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 <http://www.gnu.org/licenses/>.
    ****************************************************************************/
    
    /**
     * Description: HAL for Teensy35 (MK64FX512)
     */
    
    #if defined(__MK64FX512__) || defined(__MK66FX1M0__)
    
    #include "HAL.h"
    #include "../shared/Delay.h"
    
    #include <Wire.h>
    
    uint16_t HAL_adc_result, HAL_adc_select;
    
    static const uint8_t pin2sc1a[] = {
      5, 14, 8, 9, 13, 12, 6, 7, 15, 4, 3, 19+128, 14+128, 15+128, // 0-13 -> A0-A13
      5, 14, 8, 9, 13, 12, 6, 7, 15, 4, // 14-23 are A0-A9
      255, 255, 255, 255, 255, 255, 255, // 24-30 are digital only
      14+128, 15+128, 17, 18, 4+128, 5+128, 6+128, 7+128, 17+128,  // 31-39 are A12-A20
      255, 255, 255, 255, 255, 255, 255, 255, 255,  // 40-48 are digital only
      10+128, 11+128, // 49-50 are A23-A24
      255, 255, 255, 255, 255, 255, 255, // 51-57 are digital only
      255, 255, 255, 255, 255, 255, // 58-63 (sd card pins) are digital only
      3, 19+128, // 64-65 are A10-A11
      23, 23+128,// 66-67 are A21-A22 (DAC pins)
      1, 1+128,  // 68-69 are A25-A26 (unused USB host port on Teensy 3.5)
      26,        // 70 is Temperature Sensor
      18+128     // 71 is Vref
    };
    
    /*
      // disable interrupts
      void cli(void) { noInterrupts(); }
    
      // enable interrupts
      void sei(void) { interrupts(); }
    */
    
    void HAL_adc_init() {
      analog_init();
      while (ADC0_SC3 & ADC_SC3_CAL) {}; // Wait for calibration to finish
      while (ADC1_SC3 & ADC_SC3_CAL) {}; // Wait for calibration to finish
      NVIC_ENABLE_IRQ(IRQ_FTM1);
    }
    
    void HAL_clear_reset_source(void) { }
    
    uint8_t HAL_get_reset_source(void) {
      switch (RCM_SRS0) {
        case 128: return RST_POWER_ON; break;
        case 64: return RST_EXTERNAL; break;
        case 32: return RST_WATCHDOG; break;
        // case 8: return RST_LOSS_OF_LOCK; break;
        // case 4: return RST_LOSS_OF_CLOCK; break;
        // case 2: return RST_LOW_VOLTAGE; break;
      }
      return 0;
    }
    
    extern "C" {
      extern char __bss_end;
      extern char __heap_start;
      extern void* __brkval;
    
      int freeMemory() {
        int free_memory;
        if ((int)__brkval == 0)
          free_memory = ((int)&free_memory) - ((int)&__bss_end);
        else
          free_memory = ((int)&free_memory) - ((int)__brkval);
        return free_memory;
      }
    }
    
    void HAL_adc_start_conversion(const uint8_t adc_pin) {
      uint16_t pin = pin2sc1a[adc_pin];
      if (pin == 0xFF) {
        // Digital only
        HAL_adc_select = -1;
      }
      else if (pin & 0x80) {
        HAL_adc_select = 1;
        ADC1_SC1A = pin & 0x7F;
      }
      else {
        HAL_adc_select = 0;
        ADC0_SC1A = pin;
      }
    }
    
    uint16_t HAL_adc_get_result(void) {
      switch (HAL_adc_select) {
        case 0: return ADC0_RA;
        case 1: return ADC1_RA;
      }
      return 0;
    }
    
    #endif // __MK64FX512__ || __MK66FX1M0__
    and HAL.h file:

    Code:
    /**
     * Marlin 3D Printer Firmware
     *
     * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
     * Copyright (c) 2016 Bob Cousins bobcousins42@googlemail.com
     * Copyright (c) 2015-2016 Nico Tonnhofer wurstnase.reprap@gmail.com
     *
     * 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 <http://www.gnu.org/licenses/>.
     *
     */
    #pragma once
    
    /**
     * Description: HAL for Teensy 3.5 and Teensy 3.6
     */
    
    #define CPU_32_BIT
    
    // --------------------------------------------------------------------------
    // Includes
    // --------------------------------------------------------------------------
    
    // _BV is re-defined in Arduino.h
    #undef _BV
    
    #include <Arduino.h>
    
    // Redefine sq macro defined by teensy3/wiring.h
    #undef sq
    #define sq(x) ((x)*(x))
    
    #include "../shared/math_32bit.h"
    #include "../shared/HAL_SPI.h"
    
    #include "fastio_Teensy.h"
    #include "watchdog_Teensy.h"
    
    #include "HAL_timers_Teensy.h"
    
    #include <stdint.h>
    
    #define ST7920_DELAY_1 DELAY_NS(600)
    #define ST7920_DELAY_2 DELAY_NS(750)
    #define ST7920_DELAY_3 DELAY_NS(750)
    
    // --------------------------------------------------------------------------
    // Defines
    // --------------------------------------------------------------------------
    
    #undef MOTHERBOARD
    #define MOTHERBOARD BOARD_TEENSY35_36
    
    #define IS_32BIT_TEENSY (defined(__MK64FX512__) || defined(__MK66FX1M0__))
    #define IS_TEENSY35 defined(__MK64FX512__)
    #define IS_TEENSY36 defined(__MK66FX1M0__)
    
    #define NUM_SERIAL 1
    
    #if SERIAL_PORT == -1
      #define MYSERIAL0 SerialUSB
    #elif SERIAL_PORT == 0
      #define MYSERIAL0 Serial
    #elif SERIAL_PORT == 1
      #define MYSERIAL0 Serial1
    #elif SERIAL_PORT == 2
      #define MYSERIAL0 Serial2
    #elif SERIAL_PORT == 3
      #define MYSERIAL0 Serial3
    #endif
    
    #define HAL_SERVO_LIB libServo
    
    typedef int8_t pin_t;
    
    #ifndef analogInputToDigitalPin
      #define analogInputToDigitalPin(p) ((p < 12u) ? (p) + 54u : -1)
    #endif
    
    #define CRITICAL_SECTION_START  uint32_t primask = __get_PRIMASK(); __disable_irq()
    #define CRITICAL_SECTION_END    if (!primask) __enable_irq()
    #define ISRS_ENABLED() (!__get_PRIMASK())
    #define ENABLE_ISRS()  __enable_irq()
    #define DISABLE_ISRS() __disable_irq()
    
    #undef sq
    #define sq(x) ((x)*(x))
    
    #ifndef strncpy_P
      #define strncpy_P(dest, src, num) strncpy((dest), (src), (num))
    #endif
    
    // Fix bug in pgm_read_ptr
    #undef pgm_read_ptr
    #define pgm_read_ptr(addr) (*((void**)(addr)))
    // Add type-checking to pgm_read_word
    #undef pgm_read_word
    #define pgm_read_word(addr) (*((uint16_t*)(addr)))
    
    #define RST_POWER_ON   1
    #define RST_EXTERNAL   2
    #define RST_BROWN_OUT  4
    #define RST_WATCHDOG   8
    #define RST_JTAG       16
    #define RST_SOFTWARE   32
    #define RST_BACKUP     64
    
    /** clear reset reason */
    void HAL_clear_reset_source(void);
    
    /** reset reason */
    uint8_t HAL_get_reset_source(void);
    
    FORCE_INLINE void _delay_ms(const int delay_ms) { delay(delay_ms); }
    
    extern "C" {
      int freeMemory(void);
    }
    
    // SPI: Extended functions which take a channel number (hardware SPI only)
    /** Write single byte to specified SPI channel */
    void spiSend(uint32_t chan, byte b);
    /** Write buffer to specified SPI channel */
    void spiSend(uint32_t chan, const uint8_t* buf, size_t n);
    /** Read single byte from specified SPI channel */
    uint8_t spiRec(uint32_t chan);
    
    // ADC
    
    void HAL_adc_init();
    
    #define HAL_START_ADC(pin)  HAL_adc_start_conversion(pin)
    #define HAL_READ_ADC()      HAL_adc_get_result()
    #define HAL_ADC_READY()     true
    
    #define HAL_ANALOG_SELECT(pin) NOOP;
    
    void HAL_adc_start_conversion(const uint8_t adc_pin);
    
    uint16_t HAL_adc_get_result(void);
    
    /*
      uint16_t HAL_getAdcReading(uint8_t chan);
    
      void HAL_startAdcConversion(uint8_t chan);
      uint8_t HAL_pinToAdcChannel(int pin);
    
      uint16_t HAL_getAdcFreerun(uint8_t chan, bool wait_for_conversion = false);
      //uint16_t HAL_getAdcSuperSample(uint8_t chan);
    
      void HAL_enable_AdcFreerun(void);
      //void HAL_disable_AdcFreerun(uint8_t chan);
    */
    
    #define GET_PIN_MAP_PIN(index) index
    #define GET_PIN_MAP_INDEX(pin) pin
    #define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval)
    Got the power supplies, and it seems to be working fine. They are good for 1A without a heatsink. I will test more, but 1A should be fine for this. I still need the fuse connectors. I also attached the schematic.
    Click image for larger version. 

Name:	Capture2.jpg 
Views:	2 
Size:	44.3 KB 
ID:	15529Click image for larger version. 

Name:	Capture.PNG 
Views:	2 
Size:	442.5 KB 
ID:	15530Click image for larger version. 

Name:	Capture3.jpg 
Views:	2 
Size:	77.0 KB 
ID:	15528
    Attached Files Attached Files
    Last edited by bob23; 01-08-2019 at 07:07 AM.

  5. #5
    Junior Member
    Join Date
    Oct 2018
    Posts
    5
    Is this something that is related to the Teensy HAL or maybe a Marlin config issue? As in maybe I have more luck with info on their forums?

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •