marlin 2.0 teensy hal with i2c gpio expander

Status
Not open for further replies.

bob23

Member
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.
 

Attachments

  • Capture2.PNG
    Capture2.PNG
    40.7 KB · Views: 162
  • WhatsApp Image 2018-12-31 at 01.49.18.jpg
    WhatsApp Image 2018-12-31 at 01.49.18.jpg
    167 KB · Views: 205
  • WhatsApp Image 2018-12-29 at 04.30.40.jpg
    WhatsApp Image 2018-12-29 at 04.30.40.jpg
    205.2 KB · Views: 172
Last edited:
wow, i'm searching for something like this - is it on github or downloadable somewhere else? ( EAGLE? )
Which displays does it support?
 
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.
 

Attachments

  • Capture.PNG
    Capture.PNG
    48.5 KB · Views: 96
  • Capture3.PNG
    Capture3.PNG
    46.9 KB · Views: 92
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.
Capture2.jpgCapture.PNGCapture3.jpg
 

Attachments

  • tt.pdf
    340.5 KB · Views: 143
Last edited:
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?
 
Status
Not open for further replies.
Back
Top