diff --git a/Motate b/Motate index 508cd27e..3d0d332d 160000 --- a/Motate +++ b/Motate @@ -1 +1 @@ -Subproject commit 508cd27ec332718d335bc62a26e6ec8935929b5c +Subproject commit 3d0d332dc5be522166b801d7f4aa74c35ed001e2 diff --git a/g2core/board/gquintic.mk b/g2core/board/gquintic.mk index 7f267ed8..8ccba539 100755 --- a/g2core/board/gquintic.mk +++ b/g2core/board/gquintic.mk @@ -29,14 +29,14 @@ ifeq ("$(BASE_BOARD)","gquintic") DEVICE_DEFINES += MOTATE_CONFIG_HAS_USBSERIAL=1 ENABLE_TCM=1 - FIRST_LINK_SOURCES += $(sort $(wildcard ${MOTATE_PATH}/Atmel_sam_common/*.cpp)) $(sort $(wildcard ${MOTATE_PATH}/Atmel_sams70/*.cpp)) + FIRST_LINK_SOURCES += $(sort $(wildcard ${MOTATE_PATH}/Atmel_sam_common/*.cpp)) $(sort $(wildcard ${MOTATE_PATH}/Atmel_sams70/*.cpp) $(wildcard ${BOARD_PATH}/*.cpp)) CHIP = SAMS70N19 export CHIP CHIP_LOWERCASE = sams70n19 BOARD_PATH = ./board/gquintic - SOURCE_DIRS += ${BOARD_PATH} device/trinamic device/step_dir_hobbyservo + SOURCE_DIRS += ${BOARD_PATH} device/trinamic device/step_dir_hobbyservo device/max31865 PLATFORM_BASE = ${MOTATE_PATH}/platform/atmel_sam include $(PLATFORM_BASE).mk diff --git a/g2core/board/gquintic/hardware.cpp b/g2core/board/gquintic/0_hardware.cpp similarity index 98% rename from g2core/board/gquintic/hardware.cpp rename to g2core/board/gquintic/0_hardware.cpp index e11d595c..9a2879bc 100755 --- a/g2core/board/gquintic/hardware.cpp +++ b/g2core/board/gquintic/0_hardware.cpp @@ -39,12 +39,16 @@ //Motate::ClockOutputPin external_clk_pin {16000000}; // 16MHz optimally Motate::OutputPin external_clk_pin {Motate::kStartLow}; +SPI_CS_PinMux_used_t spiCSPinMux; +SPIBus_used_t spiBus; + /* * hardware_init() - lowest level hardware init */ void hardware_init() { + spiBus.init(); board_hardware_init(); external_clk_pin = 0; // Force external clock to 0 for now. } diff --git a/g2core/board/gquintic/board_stepper.cpp b/g2core/board/gquintic/board_stepper.cpp index cc58f61d..b588fb42 100755 --- a/g2core/board/gquintic/board_stepper.cpp +++ b/g2core/board/gquintic/board_stepper.cpp @@ -28,47 +28,38 @@ #include "board_stepper.h" - -Motate::SPIChipSelectPinMux - spiCSPinMux; -SPIBus_used_t spiBus; - // These are identical to board_stepper.h, except for the word "extern" and the initialization -Trinamic2130 - motor_1{spiBus, spiCSPinMux.getCS(4)}; +//Trinamic2130 +// motor_1{spiBus, spiCSPinMux.getCS(4)}; Trinamic2130 - motor_2{spiBus, spiCSPinMux.getCS(3)}; + motor_1{spiBus, spiCSPinMux.getCS(3)}; Trinamic2130 - motor_3{spiBus, spiCSPinMux.getCS(2)}; + motor_2{spiBus, spiCSPinMux.getCS(2)}; Trinamic2130 - motor_4{spiBus, spiCSPinMux.getCS(1)}; + motor_3{spiBus, spiCSPinMux.getCS(1)}; Trinamic2130 - motor_5{spiBus, spiCSPinMux.getCS(0)}; + motor_4{spiBus, spiCSPinMux.getCS(0)}; -StepDirHobbyServo motor_6; +StepDirHobbyServo motor_5; -Stepper* Motors[MOTORS] = {&motor_1, &motor_2, &motor_3, &motor_4, &motor_5, &motor_6}; +Stepper* Motors[MOTORS] = {&motor_1, &motor_2, &motor_3, &motor_4, &motor_5}; +//Stepper* Motors[MOTORS] = {&motor_1, &motor_2, &motor_3, &motor_4, &motor_5, &motor_6}; void board_stepper_init() { - spiBus.init(); - for (uint8_t motor = 0; motor < MOTORS; motor++) { Motors[motor]->init(); } } diff --git a/g2core/board/gquintic/board_stepper.h b/g2core/board/gquintic/board_stepper.h index c2cf6ebe..e8eac9d6 100755 --- a/g2core/board/gquintic/board_stepper.h +++ b/g2core/board/gquintic/board_stepper.h @@ -32,35 +32,33 @@ #include "tmc2130.h" #include "step_dir_hobbyservo.h" -typedef Motate::SPIBus SPIBus_used_t; - // These are identical to board_stepper.h, except for the word "extern" and the initialization -extern Trinamic2130 - motor_1; +//extern Trinamic2130 +// motor_1; extern Trinamic2130 - motor_2; + motor_1; extern Trinamic2130 - motor_3; + motor_2; extern Trinamic2130 - motor_4; + motor_3; extern Trinamic2130 - motor_5; -extern StepDirHobbyServo motor_6; + motor_4; +extern StepDirHobbyServo motor_5; extern Stepper* Motors[MOTORS]; diff --git a/g2core/board/gquintic/board_xio.cpp b/g2core/board/gquintic/board_xio.cpp index c48356be..8c881765 100755 --- a/g2core/board/gquintic/board_xio.cpp +++ b/g2core/board/gquintic/board_xio.cpp @@ -75,7 +75,7 @@ void board_hardware_init(void) // called 1st } -void board_xio_init(void) // called later than board_hardware_init (there are thing in between) +void board_xio_init(void) // called later than board_hardware_init (there are things in between) { // Init SPI #if XIO_HAS_SPI diff --git a/g2core/board/gquintic/gquintic-b-pinout.h b/g2core/board/gquintic/gquintic-b-pinout.h index c0bcf0e3..e3b32979 100755 --- a/g2core/board/gquintic/gquintic-b-pinout.h +++ b/g2core/board/gquintic/gquintic-b-pinout.h @@ -148,7 +148,7 @@ _MAKE_MOTATE_PIN(kSocket2_DirPinNumber, 'A', 25); // _MAKE_MOTATE_PIN(kOutput5_PinNumber, 'A', 26); // TC 2,0 _MAKE_MOTATE_PIN(kSocket3_DirPinNumber, 'A', 27); // On Timer 2! _MAKE_MOTATE_PIN(kUnassigned1, 'A', 28); // DIAG1 -_MAKE_MOTATE_PIN(kUnassigned2, 'A', 29); // +_MAKE_MOTATE_PIN(kUnassigned2, 'A', 29); // NO PHYSICAL PIN _MAKE_MOTATE_PIN(kInput1_PinNumber, 'A', 30); // _MAKE_MOTATE_PIN(kInput4_PinNumber, 'A', 31); // @@ -192,13 +192,13 @@ _MAKE_MOTATE_PIN(kUnassigned6, 'D', 19); // _MAKE_MOTATE_PIN(kSPI0_MISOPinNumber, 'D', 20); // _MAKE_MOTATE_PIN(kSPI0_MOSIPinNumber, 'D', 21); // _MAKE_MOTATE_PIN(kSPI0_SCKPinNumber, 'D', 22); // -_MAKE_MOTATE_PIN(kUnassigned7, 'D', 23); // +_MAKE_MOTATE_PIN(kUnassigned7, 'D', 23); // NO PHYSICAL PIN _MAKE_MOTATE_PIN(kSocket2_StepPinNumber, 'D', 24); // _MAKE_MOTATE_PIN(kSocket2_SPISlaveSelectPinNumber, 'D', 25); // _MAKE_MOTATE_PIN(kOutput9_PinNumber, 'D', 26); // PWM 2 _MAKE_MOTATE_PIN(kSocket1_DirPinNumber, 'D', 27); // _MAKE_MOTATE_PIN(kSocket4_EnablePinNumber, 'D', 28); // -_MAKE_MOTATE_PIN(kUnassigned8, 'D', 29); // +_MAKE_MOTATE_PIN(kUnassigned8, 'D', 29); // NO PHYSICAL PIN _MAKE_MOTATE_PIN(kUnassigned9, 'D', 30); // INTERRUPT_OUT _MAKE_MOTATE_PIN(kUnassigned10, 'D', 31); // diff --git a/g2core/board/gquintic/hardware.h b/g2core/board/gquintic/hardware.h index d82ce503..40f9baf0 100644 --- a/g2core/board/gquintic/hardware.h +++ b/g2core/board/gquintic/hardware.h @@ -58,7 +58,7 @@ enum hwPlatform { #define AXES 6 // number of axes supported in this version #define HOMING_AXES 4 // number of axes that can be homed (assumes Zxyabc sequence) -#define MOTORS 6 // number of motors on the board - 5 Trinamics + 1 servo +#define MOTORS 5 // number of motors on the board - 5 Trinamics + 1 servo #define COORDS 6 // number of supported coordinate systems (index starts at 1) #define PWMS 2 // number of supported PWM channels #define TOOLS 32 // number of entries in tool table (index starts at 1) @@ -69,6 +69,7 @@ enum hwPlatform { //////////////////////////// #include "MotatePins.h" +#include "MotateSPI.h" #include "MotateTimers.h" // for TimerChanel<> and related... #include "MotateServiceCall.h" // for ServiceCall<> @@ -134,19 +135,19 @@ typedef TimerChannel<11, 0> fwd_plan_timer_type; // request exec timer in step Motate::service_call_number kSPI_ServiceCallNumber = 3; -// Pin assignments +/**** SPI Setup ****/ + +typedef Motate::SPIBus SPIBus_used_t; +extern SPIBus_used_t spiBus; + +typedef Motate::SPIChipSelectPinMux SPI_CS_PinMux_used_t; +extern SPI_CS_PinMux_used_t spiCSPinMux; + +/**** Motate Global Pin Allocations ****/ pin_number indicator_led_pin_num = Motate::kLED_USBRXPinNumber; static OutputPin IndicatorLed; -/**** Motate Global Pin Allocations ****/ - -//static OutputPin spi_ss1_pin; -//static OutputPin spi_ss2_pin; -//static OutputPin spi_ss3_pin; -//static OutputPin spi_ss4_pin; -//static OutputPin spi_ss5_pin; -//static OutputPin spi_ss6_pin; static OutputPin kinen_sync_pin; static OutputPin grbl_reset_pin; diff --git a/g2core/device/max31865/max31865.h b/g2core/device/max31865/max31865.h new file mode 100644 index 00000000..c393ab98 --- /dev/null +++ b/g2core/device/max31865/max31865.h @@ -0,0 +1,416 @@ +/* + * max31865/max31865.h - suppport for talking to the MAX31865 RTD (PT100) sensor amp/ADC + * This file is part of the G2 project + * + * Copyright (c) 2017 Alden S. Hart, Jr. + * Copyright (c) 2017 Robert Giseburt + * + * This file ("the software") is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2 as published by the + * Free Software Foundation. You should have received a copy of the GNU General Public + * License, version 2 along with the software. If not, see . + * + * As a special exception, you may use this file as part of a software library without + * restriction. Specifically, if other files instantiate templates or use macros or + * inline functions from this file, or you compile this file and link it with other + * files to produce an executable, this file does not by itself cause the resulting + * executable to be covered by the GNU General Public License. This exception does not + * however invalidate any other reasons why the executable file might be covered by the + * GNU General Public License. + * + * THE SOFTWARE IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY + * WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT + * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +// Many thanks to Adafruit! +// More specifically, for their driver at +// https://github.com/adafruit/Adafruit_MAX31865 +// and their breakout board at https://adafru.it/3328 + +#ifndef max31865_h +#define max31865_h + +#include "MotateSPI.h" +#include "MotateBuffer.h" +#include "MotateUtilities.h" // for to/fromLittle/BigEndian + +using Motate::OutputPin; +using Motate::kStartHigh; +using Motate::SPIMessage; +using Motate::SPIInterrupt; +using Motate::SPIDeviceMode; +using Motate::fromBigEndian; +using Motate::toBigEndian; + +// Complete class for MAX31865 drivers. +template +struct MAX31865 final { + // SPI and message handling properties + device_t _device; + SPIMessage _message; + + // Record if we're transmitting to prevent altering the buffers while they + // are being transmitted still. + volatile bool _transmitting = false; + + // We don't want to transmit until we're inited + bool _inited = false; + + // Record what register we just requested, so we know what register the + // the response is for (and to read the response.) + int16_t _active_register = -1; + + // Timer to keep track of when we need to do another periodic update + Motate::Timeout _check_timer; + + // Constructor - this is the only time we directly use the SBIBus + template + MAX31865(SPIBus_t &spi_bus, const chipSelect_t &_cs, bool is_three_pin = false, bool fifty_hz = true) : + _device{spi_bus.getDevice(_cs, + 5000000, + SPIDeviceMode::kSPIMode2 | SPIDeviceMode::kSPI8Bit, + 400, // min_between_cs_delay_ns + 400, // cs_to_sck_delay_ns + 80 // between_word_delay_ns + )} + { + init(is_three_pin, fifty_hz); + }; + + // Prevent copying, and prevent moving (so we know if it happens) + MAX31865(const MAX31865 &) = delete; + MAX31865(MAX31865 &&other) : _device{std::move(other._device)} {}; + + + // ########### + // From here on we store actual values from the MAX31865, and marshall data + // from the in_buffer buffer to them, or from the values to the out_buffer. + + // Note that this includes _startNextReadWrite() and _doneReadingCallback(), + // which are what calls the functions to put data into the out_buffer and + // read data from the in_buffer, respectively. + + // Also, _init() is last, so it can setup a newly created MAX31865 object. + + enum { + CONFIG_reg = 0x00, + RTD_reg = 0x01, + HFAULT_reg = 0x03, + LFAULT_reg = 0x05, + FAULTSTAT_reg = 0x07, + }; + + // IMPORTANT NOTE: The endianness of the ARM is little endian, but other processors + // may be different. + + uint8_t _scribble_buffer[4]; + + struct { + uint8_t address; + union { + uint8_t value; + struct { + uint8_t fifty_or_sixty : 1; // 0 + uint8_t clear_fault : 1; // 1 + uint8_t fault_detection : 2; // 3-2 + uint8_t three_wire : 1; // 4 + uint8_t one_shot : 1; // 5 + uint8_t auto_mode : 1; // 6 + uint8_t v_bias : 1; // 7 + } __attribute__ ((packed)); + }; + } _config; + bool _config_needs_read = false; + bool _config_needs_written = false; + void _postReadConf() {}; + + struct { + uint8_t address; + uint8_t high; + uint8_t low; + } _rtd_value_raw; + float _rtd_value = -1; + bool _rtd_value_needs_read = false; + void _postReadRTD() { + bool fault_detected = _rtd_value_raw.low & 0x01; + uint16_t rtd_value_int = (_rtd_value_raw.high << 7) | (_rtd_value_raw.low >> 1); + _rtd_value = 32768.0/(float)rtd_value_int; + if (fault_detected) { + _fault_status_needs_read = true; + } + if (_interrupt_handler) { + _interrupt_handler(); + } + }; + + struct { + uint8_t address; + uint8_t high; + uint8_t low; + } _fault_high; + bool _fault_high_needs_read = false; + bool _fault_high_needs_written = false; + void _postReadFaultHigh() {}; + + struct { + uint8_t address; + uint8_t high; + uint8_t low; + } _fault_low; + bool _fault_low_needs_read = false; + bool _fault_low_needs_written = false; + void _postReadFaultLow() {}; + + struct { + uint8_t address; + union { + volatile uint8_t value; + struct { + uint8_t _unused : 2; // 1-0 + uint8_t over_under_voltage : 1; // 2 + uint8_t open_detection : 1; // 3 + uint8_t ref_too_low : 1; // 4 + uint8_t ref_too_high : 1; // 5 + uint8_t under_threhold : 1; // 6 + uint8_t over_threshold : 1; // 7 + } __attribute__ ((packed)); + }; + } _fault_status; + bool _fault_status_needs_read = false; + void _postReadFaultStatus() { + /* here is where we would call alarm or something!! */ + }; + + void _startNextReadWrite() + { + if (_transmitting || !_inited) { return; } + _transmitting = true; // preemptively say we're transmitting .. as a mutex + + // We request the next register, and keep track of how long it is. + uint8_t next_reg = 0; + uint8_t *data_buffer = nullptr; + int8_t register_size; + + // We write before we read -- so we don't lose what we set in the registers when writing + + // check if we need to write registers + if (_config_needs_written) { next_reg = 0x80 | CONFIG_reg; data_buffer = (uint8_t*)&_config; register_size = 1; _config_needs_written = false; } else + if (_fault_high_needs_written) { next_reg = 0x80 | HFAULT_reg; data_buffer = (uint8_t*)&_fault_high; register_size = 2; _fault_high_needs_written = false; } else + if (_fault_low_needs_written) { next_reg = 0x80 | LFAULT_reg; data_buffer = (uint8_t*)&_fault_low; register_size = 2; _fault_low_needs_written = false; } else + + // check if we need to read reagisters + if (_config_needs_read) { next_reg = CONFIG_reg; data_buffer = (uint8_t*)&_config; register_size = 1; _config_needs_read = false; } else + if (_rtd_value_needs_read) { next_reg = RTD_reg; data_buffer = (uint8_t*)&_rtd_value_raw; register_size = 2; _rtd_value_needs_read = false; } else + if (_fault_high_needs_read) { next_reg = HFAULT_reg; data_buffer = (uint8_t*)&_fault_high; register_size = 2; _fault_high_needs_read = false; } else + if (_fault_low_needs_read) { next_reg = LFAULT_reg; data_buffer = (uint8_t*)&_fault_low; register_size = 2; _fault_low_needs_read = false; } else + if (_fault_status_needs_read) { next_reg = FAULTSTAT_reg; data_buffer = (uint8_t*)&_fault_status; register_size = 1; _fault_status_needs_read = false; } else + + // otherwise we're done here + { + _active_register = -1; + _transmitting = false; // we're not really transmitting. + return; + } + + _active_register = next_reg; + *data_buffer = next_reg; + + if (next_reg & 0x80) { + // writing, copy what we're + _scribble_buffer[0] = data_buffer[0]; + _scribble_buffer[1] = 0xFF; + _scribble_buffer[2] = 0xFF; + _scribble_buffer[3] = 0xFF; + + _message.setup(data_buffer, _scribble_buffer, 1+register_size, SPIMessage::DeassertAfter, SPIMessage::EndTransaction); + } else { + _scribble_buffer[0] = data_buffer[0]; + _scribble_buffer[1] = 0xFF; + _scribble_buffer[2] = 0xFF; + _scribble_buffer[3] = 0xFF; + + _message.setup(_scribble_buffer, data_buffer, 1+register_size, SPIMessage::DeassertAfter, SPIMessage::EndTransaction); + } + _device.queueMessage(&_message); + }; + + void _doneReadingCallback() + { + _transmitting = false; + + // Check to make sure it was a read, and handle it accordingly + if (0 == (_active_register & 0x80)) { + switch (_active_register) { + case CONFIG_reg: _postReadConf(); break; + case RTD_reg: _postReadRTD(); break; + case HFAULT_reg: _postReadFaultHigh(); break; + case LFAULT_reg: _postReadFaultLow(); break; + case FAULTSTAT_reg: _postReadFaultStatus(); break; + + default: + break; + } + } + + _active_register = -1; + _startNextReadWrite(); + }; + + void init(bool is_three_pin = false, bool fifty_hz = false) + { + _message.message_done_callback = [&] { this->_doneReadingCallback(); }; + + // Establish default values, and then prepare to read the registers we can to establish starting values + + _config.v_bias = false; // effectively enable the device + _config.auto_mode = false; // automatically run conversions + _config.one_shot = false; // this is a command + _config.fault_detection = 0; // this is a command - run automatic fault detection + _config.clear_fault = false; // this is a command, and we want to execture it + _config.fifty_or_sixty = fifty_hz; // this is a command + _config_needs_written = false; + //_config_needs_read = true; + + _fault_high = {HFAULT_reg, 0xff, 0xff}; //_fault_high_needs_read = true; + _fault_low = {LFAULT_reg, 0x00, 0x00}; //_fault_low_needs_read = true; + + _inited = true; + //_startNextReadWrite(); + _check_timer.set(fifty_hz ? 1000/50 : 1000/60); + }; + + // interface to make this a drop-in replacement (after init) for an ADCPin + + float _vref = 3.3; + std::function _interrupt_handler; + + enum { + INITING, + SETUP_WIRES, + CLEAR_FAULT, + SETUP_BIAS, + NEEDS_SAMPLED, + WAITING_FOR_SAMPLE + } _state; + + void startSampling() + { + if (_check_timer.isPast()) { + if (INITING == _state) { + _config_needs_read = true; + _fault_high_needs_read = true; + _fault_low_needs_read = true; + + _check_timer.set(10); + _startNextReadWrite(); + _state = SETUP_WIRES; + } + else if (SETUP_WIRES == _state) { + _config.three_wire = false; + _config_needs_written = true; + _config_needs_read = true; + + _check_timer.set(10); + _startNextReadWrite(); + _state = CLEAR_FAULT; + } + else if (CLEAR_FAULT == _state) { + _config.clear_fault = true; + _config_needs_written = true; + _config_needs_read = true; + + _check_timer.set(10); + _startNextReadWrite(); + _state = SETUP_BIAS; + } + else if (SETUP_BIAS == _state) { + _config.v_bias = true; + _config_needs_written = true; + _config_needs_read = true; + + _check_timer.set(10); + _startNextReadWrite(); + _state = NEEDS_SAMPLED; + } + else if (NEEDS_SAMPLED == _state) { + _config.one_shot = true; + _config_needs_written = true; + _config_needs_read = true; + + _check_timer.set(70); + _startNextReadWrite(); + _state = WAITING_FOR_SAMPLE; + } + else if (WAITING_FOR_SAMPLE == _state) { + _rtd_value_needs_read = true; + + _check_timer.set(1); + _startNextReadWrite(); + _state = SETUP_BIAS; + } + } + }; + + int32_t getRaw() { + uint16_t rtd_value_int = (_rtd_value_raw.high << 7) | (_rtd_value_raw.low >> 1); + return rtd_value_int; + }; + int32_t getValue() { + return _rtd_value; + }; + int32_t getBottom() { + return 0; + }; + float getBottomVoltage() { + return 0; + }; + int32_t getTop() { + return 32767; + }; + float getTopVoltage() { + return _vref; + }; + + void setVoltageRange(const float vref, const float min_expected = 0, const float max_expected = -1, const bool differential = false, const float ideal_steps = 1) + { + _vref = vref; + + // uint16_t min_expected_int = (uint16_t)((min_expected/vref) * 32767.0) << 1; + // fault_low.high = (min_expected_int >> 8) & 0xff; + // fault_low.low = min_expected_int & 0xff; + // fault_low_needs_written = true; + // + // if (max_expected > 0) { + // uint16_t max_expected_int = (uint16_t)((max_expected/vref) * 32767.0) << 1; + // fault_high.high = (max_expected_int >> 8) & 0xff; + // fault_high.low = max_expected_int & 0xff; + // fault_high_needs_written = true; + // } + + // differential should always be false + // we can't control the resolution, so ignore ideal_steps too + }; + float getVoltage() { + return _rtd_value * _vref; + }; + operator float() { return getVoltage(); }; + + void setInterrupts(const uint32_t interrupts) { + // ignore this -- it's too dangerous to accidentally change the SPI interrupts + }; + + // We can only support interrupt inferface option 2: a function with a closure or function pointer + void setInterruptHandler(std::function &&handler) { + _interrupt_handler = std::move(handler); + }; + void setInterruptHandler(const std::function &handler) { + _interrupt_handler = handler; + }; + +}; + +#endif // max31865_h diff --git a/g2core/device/trinamic/tmc2130.h b/g2core/device/trinamic/tmc2130.h index d522c7dc..1c189470 100644 --- a/g2core/device/trinamic/tmc2130.h +++ b/g2core/device/trinamic/tmc2130.h @@ -91,11 +91,11 @@ struct Trinamic2130 final : Stepper { template Trinamic2130(SPIBus_t &spi_bus, const chipSelect_t &_cs) : _device{spi_bus.getDevice(_cs, - 4000000, //1MHz - SPIDeviceMode::kSPIMode2 | SPIDeviceMode::kSPI8Bit, + 4000000, //4MHz + SPIDeviceMode::kSPIMode1 | SPIDeviceMode::kSPI8Bit, 0, // min_between_cs_delay_ns 10, // cs_to_sck_delay_ns - 0 // between_word_delay_ns + 1 // between_word_delay_ns )} {}; diff --git a/g2core/g2core.xcodeproj/project.pbxproj b/g2core/g2core.xcodeproj/project.pbxproj index 66321df6..56400b46 100644 --- a/g2core/g2core.xcodeproj/project.pbxproj +++ b/g2core/g2core.xcodeproj/project.pbxproj @@ -232,6 +232,20 @@ passBuildSettingsInEnvironment = 1; productName = g3_due; }; + D43DFE011E8C84B400A2030D /* G2 gQuadratic Ultimaker2+ */ = { + isa = PBXLegacyTarget; + buildArgumentsString = "$(ACTION) VERBOSE=1 COLOR=0 CONFIG=Ultimaker2Plus DEBUG=0"; + buildConfigurationList = D43DFE021E8C84B400A2030D /* Build configuration list for PBXLegacyTarget "G2 gQuadratic Ultimaker2+" */; + buildPhases = ( + ); + buildToolPath = /usr/bin/make; + buildWorkingDirectory = .; + dependencies = ( + ); + name = "G2 gQuadratic Ultimaker2+"; + passBuildSettingsInEnvironment = 1; + productName = g3_due; + }; D43FF7141D537A5C00FB5B53 /* G2 gQuadratic Test */ = { isa = PBXLegacyTarget; buildArgumentsString = "$(ACTION) VERBOSE=1 COLOR=0 CONFIG=TestQuadratic DEBUG=2"; @@ -290,7 +304,7 @@ }; D492E5AE1E54C2B4005ED97D /* G2 gQuadratic AxiDraw v3 */ = { isa = PBXLegacyTarget; - buildArgumentsString = "$(ACTION) VERBOSE=1 COLOR=0 CONFIG=AxiDrawv3 DEBUG=2"; + buildArgumentsString = "$(ACTION) VERBOSE=1 COLOR=0 CONFIG=AxiDrawv3 DEBUG=0"; buildConfigurationList = D492E5AF1E54C2B4005ED97D /* Build configuration list for PBXLegacyTarget "G2 gQuadratic AxiDraw v3" */; buildPhases = ( ); @@ -426,6 +440,7 @@ D457112317053BFB00EA19A8 /* index */, D4782AB61D9E39EC00B32136 /* G2 EggBot */, D492E5AE1E54C2B4005ED97D /* G2 gQuadratic AxiDraw v3 */, + D43DFE011E8C84B400A2030D /* G2 gQuadratic Ultimaker2+ */, ); }; /* End PBXProject section */ @@ -505,6 +520,22 @@ }; name = Release; }; + D43DFE031E8C84B400A2030D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PATH = "$PATH:/usr/local/gcc-arm-none-eabi/bin"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + D43DFE041E8C84B400A2030D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PATH = "$PATH:/usr/local/gcc-arm-none-eabi/bin"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; D43FF7161D537A5C00FB5B53 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -817,6 +848,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + D43DFE021E8C84B400A2030D /* Build configuration list for PBXLegacyTarget "G2 gQuadratic Ultimaker2+" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D43DFE031E8C84B400A2030D /* Debug */, + D43DFE041E8C84B400A2030D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; D43FF7151D537A5C00FB5B53 /* Build configuration list for PBXLegacyTarget "G2 gQuadratic Test" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/g2core/settings/settings_Ultimaker_2_Plus.h b/g2core/settings/settings_Ultimaker_2_Plus.h index 3c04e757..7edf42ae 100644 --- a/g2core/settings/settings_Ultimaker_2_Plus.h +++ b/g2core/settings/settings_Ultimaker_2_Plus.h @@ -259,6 +259,8 @@ //** Temperature Sensors ** +#include "device/max31865/max31865.h" + #define HAS_TEMPERATURE_SENSOR_1 true #if HAS_TEMPERATURE_SENSOR_1 // Must choose Thermistor or PT100 @@ -269,8 +271,10 @@ /*R1:*/ 144700.0, /*R2:*/ 5190.0, /*R3:*/ 4809.0, /*pullup_resistance:*/ 4700 \ } #else - #define TEMPERATURE_SENSOR_1_TYPE PT100> - #define TEMPERATURE_SENSOR_1_INIT {/*pullup_resistance:*/ 100, /*inline_resistance*/0, /*wheatstone*/ true} + //#define TEMPERATURE_SENSOR_1_TYPE PT100> + //#define TEMPERATURE_SENSOR_1_INIT {/*pullup_resistance:*/ 2200, /*inline_resistance*/0.003, /*differential*/ true} + #define TEMPERATURE_SENSOR_1_TYPE PT100> + #define TEMPERATURE_SENSOR_1_INIT {/*pullup_resistance:*/ 2200, /*inline_resistance*/0.003, /*differential*/ false, spiBus, spiCSPinMux.getCS(6)} #endif // 0 or 1 #endif // HAS_TEMPERATURE_SENSOR_1 @@ -287,7 +291,7 @@ } #else #define TEMPERATURE_SENSOR_2_TYPE PT100> - #define TEMPERATURE_SENSOR_2_INIT {/*pullup_resistance:*/ 100, /*inline_resistance*/0} + #define TEMPERATURE_SENSOR_2_INIT {/*pullup_resistance:*/ 2200, /*inline_resistance*/0} #endif // 0 or 1 #endif // HAS_TEMPERATURE_SENSOR_2 @@ -303,7 +307,7 @@ } #else #define TEMPERATURE_SENSOR_3_TYPE PT100> - #define TEMPERATURE_SENSOR_3_INIT {/*pullup_resistance:*/ 100, /*inline_resistance*/0, /*wheatstone*/ true} + #define TEMPERATURE_SENSOR_3_INIT {/*pullup_resistance:*/ 2200, /*inline_resistance*/0.003, /*differential*/ true} #endif // 0 or 1 #endif // HAS_TEMPERATURE_SENSOR_3 diff --git a/g2core/settings/settings_axidraw_v3.h b/g2core/settings/settings_axidraw_v3.h index 0e78157c..6d2b3978 100755 --- a/g2core/settings/settings_axidraw_v3.h +++ b/g2core/settings/settings_axidraw_v3.h @@ -27,11 +27,13 @@ */ /***********************************************************************/ -/**** TestV9 profile - naked board *************************************/ +/**** AxiDraw v3 Configuration *****************************************/ /***********************************************************************/ +#include "hardware.h" + // ***> NOTE: The init message must be a single line with no CRs or LFs -#define INIT_MESSAGE "Initializing configs to WaterColorBot v2 settings" +#define INIT_MESSAGE "Initializing configs to AxiDraw v3 settings" #define JUNCTION_INTEGRATION_TIME 2.5 // cornering - usually between 0.5 and 2.0 (higher is faster) #define CHORDAL_TOLERANCE 0.01 // chordal accuracy for arc drawing (in mm) diff --git a/g2core/temperature.cpp b/g2core/temperature.cpp index 264d4582..ea2546f5 100755 --- a/g2core/temperature.cpp +++ b/g2core/temperature.cpp @@ -250,7 +250,7 @@ template struct PT100 { float pullup_resistance; float inline_resistance; - bool wheatstone; + bool differential; ADC_t adc_pin {kNormal, [&]{this->adc_has_new_value();} }; float raw_adc_voltage = 0.0; @@ -258,16 +258,31 @@ struct PT100 { typedef PT100 type; - PT100(const float pullup_resistance_, const float inline_resistance_, const bool wheatstone_ = false) + PT100(const float pullup_resistance_, const float inline_resistance_, const bool differential_ = false) : pullup_resistance{ pullup_resistance_ }, inline_resistance{ inline_resistance_ }, - wheatstone{wheatstone_} + differential{differential_} { adc_pin.setInterrupts(kPinInterruptOnChange|kInterruptPriorityLow); adc_pin.setVoltageRange(kSystemVoltage, get_voltage_of_temp(min_temp), get_voltage_of_temp(max_temp), - wheatstone, // if wheatstone, then differential + differential, + 6400.0); + }; + + template + PT100(const float pullup_resistance_, const float inline_resistance_, const bool differential_ = false, Ts&&... additional_values) + : pullup_resistance{ pullup_resistance_ }, + inline_resistance{ inline_resistance_ }, + differential{differential_}, + adc_pin {additional_values...} + { + adc_pin.setInterrupts(kPinInterruptOnChange|kInterruptPriorityLow); + adc_pin.setVoltageRange(kSystemVoltage, + get_voltage_of_temp(min_temp), + get_voltage_of_temp(max_temp), + differential, 6400.0); }; @@ -275,8 +290,8 @@ struct PT100 { // R = 100(1 + A*T + B*T^2); A = 3.9083*10^-3; B = -5.775*10^-7 float r = 100 * (1 + 0.0039083*t + -0.0000005775*t*t) + inline_resistance; - if (wheatstone) { - return (r - pullup_resistance)/(2.0*(pullup_resistance + r)); + if (differential) { + return (kSystemVoltage * r)/(2.0 * pullup_resistance + r); } return r/(r+pullup_resistance)*kSystemVoltage; }; @@ -293,9 +308,9 @@ struct PT100 { float get_resistance() { float r; - if (wheatstone) { + if (differential) { float v = raw_adc_voltage / kSystemVoltage; - r = pullup_resistance*(1-2.0*v)/(2.0*v+1.0) - inline_resistance; + r = (v * 2.0 * pullup_resistance)/(1.0 - v) - inline_resistance; } else { float v = raw_adc_voltage; r = ((pullup_resistance * v) / (kSystemVoltage - v)) - inline_resistance; @@ -317,7 +332,7 @@ struct PT100 { // Call back function from the ADC to tell it that the ADC has a new sample... void adc_has_new_value() { - raw_adc_voltage = (raw_adc_voltage * 10.0 + adc_pin.getVoltage())/11.0; + raw_adc_voltage = (raw_adc_voltage*10.0 + adc_pin.getVoltage())/11.0; raw_adc_value = adc_pin.getRaw(); }; };