From 2394532304beedf70996904722957411651540b7 Mon Sep 17 00:00:00 2001 From: Axel Sepulveda Date: Fri, 3 Oct 2025 00:46:37 -0300 Subject: [PATCH 01/27] add ads1118 libraries --- Marlin/src/libs/adc/adc_ads1118.cpp | 137 ++++++++++++++++++++++++++++ Marlin/src/libs/adc/adc_ads1118.h | 65 +++++++++++++ 2 files changed, 202 insertions(+) create mode 100644 Marlin/src/libs/adc/adc_ads1118.cpp create mode 100644 Marlin/src/libs/adc/adc_ads1118.h diff --git a/Marlin/src/libs/adc/adc_ads1118.cpp b/Marlin/src/libs/adc/adc_ads1118.cpp new file mode 100644 index 0000000000..6a7ebebc85 --- /dev/null +++ b/Marlin/src/libs/adc/adc_ads1118.cpp @@ -0,0 +1,137 @@ +/** + * 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 . + * + */ + +/** + * adc_ads1118.cpp - library for Texas Instruments ADS1118 - 16-Bit Analog-to-Digital Converter + * + * For implementation details, please take a look at the datasheet: + * https://www.ti.com/product/ADS1118 + * + */ + +#include "../../inc/MarlinConfig.h" + +#if ENABLED(HAS_ADS1118) + + #include "adc_ads1118.h" + + #include "../../HAL/shared/Delay.h" + #include "../../core/macros.h" + + // Initialize the ADS1118, global instance + ADC_ADS1118 ads1118(ADS1118_CS_PIN, ADS1118_MOSI_PIN, ADS1118_MISO_PIN, ADS1118_SCK_PIN); + + // Constructor + ADC_ADS1118::ADC_ADS1118(uint8_t cs_pin, uint8_t mosi_pin, uint8_t miso_pin, uint8_t sck_pin) + : cs(cs_pin), mosi(mosi_pin), miso(miso_pin), sck(sck_pin) {} + + + void ADC_ADS1118::init() { + SET_OUTPUT(cs); + SET_OUTPUT(mosi); + SET_OUTPUT(sck); + SET_INPUT(miso); + + deselect(); + sckLow(); + } + + int16_t ADC_ADS1118::readChannel(uint8_t channel) { + uint16_t config = configForChannel(channel, false); + transfer16(config); + + // ADS1118 takes ~8 ms to convert + delay(10); + + int16_t value = (int16_t)transfer16(config); + return value; + } + + float ADC_ADS1118::readVoltage(uint8_t channel, float vref) { + int16_t raw = readChannel(channel); + return (raw / 32768.0f) * vref; // scale 16 bits to voltage + } + + float ADC_ADS1118::readInternalTemp() { + uint16_t config = configForChannel(0, true); + transfer16(config); + + delay(10); + + int16_t raw = (int16_t)transfer16(config); + return raw * 0.03125f; // 0.03125 °C by LSB and datasheet + } + + uint16_t ADC_ADS1118::configChannel(uint8_t channel, bool temp) { + uint16_t config = 0; + + if (temp) { + config = 0x0F80; // Config internal temp + } + else { + // Config single-ended inputs PGA ±2.048V + switch(channel) { + case 0: config = 0x8583; break; + case 1: config = 0x9083; break; + case 2: config = 0xA083; break; + case 3: config = 0xB083; break; + default: config = 0x8583; break; + } + } + + return config; + } + + uint16_t ADC_ADS1118::transfer16(uint16_t data) { + uint8_t high = transfer8((uint8_t)(data >> 8)); + uint8_t low = transfer8((uint8_t)(data & 0xFF)); + return (uint16_t)(high << 8) | low; + } + + uint8_t ADC_ADS1118::transfer8(uint8_t data) { + uint8_t recv = 0; + for (uint8_t i = 0; i < 8; i++) { + // Send MSB first + if (data & 0x80) WRITE(mosi, HIGH); else WRITE(mosi, LOW); + data <<= 1; + + sckHigh(); + DELAY_NS(100); // small delay for stability + + recv <<= 1; + if (READ(miso)) recv |= 0x01; + + sckLow(); + DELAY_NS(100); + } + return recv; + } + + void ADC_ADS1118::select() { WRITE(cs, LOW); } + void ADC_ADS1118::deselect() { WRITE(cs, HIGH); } + + void ADC_ADS1118::sckHigh() { WRITE(sck, HIGH); } + void ADC_ADS1118::sckLow() { WRITE(sck, LOW); } + + ADS1118 ads1118; + +#endif // HAS_ADS1118_ADC diff --git a/Marlin/src/libs/adc/adc_ads1118.h b/Marlin/src/libs/adc/adc_ads1118.h new file mode 100644 index 0000000000..682a985856 --- /dev/null +++ b/Marlin/src/libs/adc/adc_ads1118.h @@ -0,0 +1,65 @@ +/** + * 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 . + * + */ +#pragma once + +/** + * Based on Arduino Library for Texas Instruments ADS1118 - 16-Bit Analog-to-Digital Converter with internal Reference and Temperature Sensor + * https://www.ti.com/product/ADS1118 + * https://github.com/ADS1xxx-Series-ADC-Libraries/ADS1118 + */ + +#include "../../inc/MarlinConfigPre.h" + +#if ENABLED(HAS_ADS1118) + + #include + + class ADS1118 { + public: + ADC_ADS1118(uint8_t cs_pin, uint8_t mosi_pin, uint8_t miso_pin, uint8_t sck_pin); + + void init(); + int16_t readChannel(uint8_t channel); + float readVoltage(uint8_t channel, float vref = 2.048f); + float readInternalTemp(); + + bool Error; + private: + uint8_t cs, mosi, miso, sck; + + uint16_t transfer16(uint16_t data); + uint8_t transfer8(uint8_t data); + + void select(); + void deselect(); + + void sckHigh(); + void sckLow(); + + // Configuración de registros + uint16_t configForChannel(uint8_t channel, bool temp = false); + }; + + extern ADS1118 ads1118; + + +#endif // ENABLED(HAS_ADS1118) \ No newline at end of file From a131aa8c7c3ee17a8e3b862fc6e3b68e0994237c Mon Sep 17 00:00:00 2001 From: Axel Sepulveda Date: Fri, 3 Oct 2025 00:47:17 -0300 Subject: [PATCH 02/27] feat: ads1118 readings --- Marlin/src/inc/Conditionals-4-adv.h | 2 + Marlin/src/module/temperature.cpp | 104 +++++++++++++++++++++++++++- Marlin/src/module/temperature.h | 6 ++ 3 files changed, 111 insertions(+), 1 deletion(-) diff --git a/Marlin/src/inc/Conditionals-4-adv.h b/Marlin/src/inc/Conditionals-4-adv.h index 4eb53728be..dd80827153 100644 --- a/Marlin/src/inc/Conditionals-4-adv.h +++ b/Marlin/src/inc/Conditionals-4-adv.h @@ -425,6 +425,8 @@ #define TEMP_SENSOR_0_IS_AD8495 1 #elif TEMP_SENSOR_0 == -1 #define TEMP_SENSOR_0_IS_AD595 1 +#elif TEMP_SENSOR_0 == -18 + #define TEMP_SENSOR_0_IS_ADS1118 1 #elif TEMP_SENSOR_0 > 0 #define TEMP_SENSOR_0_IS_THERMISTOR 1 #if TEMP_SENSOR_0 == 1000 diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index 172d044e42..d6a133f096 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -207,6 +207,20 @@ #include "stepper.h" #endif + +#define TEMP_SENSOR_IS_ADS(n, M) (ENABLED(TEMP_SENSOR_##n##_IS_ADS##M) || (ENABLED(TEMP_SENSOR_REDUNDANT_IS_ADS##M) && REDUNDANT_TEMP_MATCH(SOURCE, E##n))) + +// ADS1118 +#if HAS_ADS1118 + #include +#endif + +// ADS TC related macros +#if TEMP_SENSOR_IS_ADS(0, TEMP_SENSOR_ADS1118) + ads1118.init(); +#endif + + #if ENABLED(FILAMENT_WIDTH_SENSOR) #include "../feature/filwidth.h" #endif @@ -2615,6 +2629,19 @@ void Temperature::task() { } #endif + +#if ANY_THERMISTOR_IS(-18) + +// Conversion for ADS1118 in differential mode (K-type) +// Each LSB bit ≈ 62.5 µV → ~1.5 °C (no calibration). +// Adjustable with GAIN and OFFSET from Configuration_adv.h + + static constexpr celsius_float_t temp_ads1118(const raw_adc_t raw) { + return raw * TEMP_SENSOR_ADS1118_GAIN + TEMP_SENSOR_ADS1118_OFFSET; + } + +#endif + #if HAS_HOTEND // Derived from RepRap FiveD extruder::getTemperature() // For hot end temperature measurement. @@ -2644,6 +2671,8 @@ void Temperature::task() { return temp_ad595(raw); #elif TEMP_SENSOR_0_IS_AD8495 return temp_ad8495(raw); + #elif TEMP_SENSOR_0_IS_ADS1118 + return temp_ads1118(raw); #else break; #endif @@ -2914,6 +2943,14 @@ void Temperature::updateTemperaturesFromRawValues() { temp_bed.setraw(read_max_tc_bed()); #endif + // Read ADC ADS1118 + #if TEMP_SENSOR_IS_ADS(0,TEMP_SENSOR_ADS1118) + temp_hotend[0].setraw(READ_ADS(0)); + #endif + #if TEMP_SENSOR_IS_ADS(1,TEMP_SENSOR_ADS1118) + temp_hotend[1].setraw(READ_ADS(1)); + #endif + #if HAS_HOTEND HOTEND_LOOP() temp_hotend[e].celsius = analog_to_celsius_hotend(temp_hotend[e].getraw(), e); #endif @@ -3810,7 +3847,7 @@ void Temperature::disable_all_heaters() { return max_tc_temp; } -#endif // HAS_MAX_TC +#endif // TEMP_SENSOR_IS_MAX_TC(0) || TEMP_SENSOR_IS_MAX_TC(1) || TEMP_SENSOR_IS_MAX_TC(2) #if TEMP_SENSOR_IS_MAX_TC(BED) /** @@ -3930,6 +3967,71 @@ void Temperature::disable_all_heaters() { #endif // TEMP_SENSOR_IS_MAX_TC(BED) +#if ENABLED(HAS_ADS1118) + /** + * @brief Read ADS Thermocouple temperature. + * + * Reads the thermocouple board via HW or SW SPI, using a library (LIB_USR_x) or raw SPI reads. + * Doesn't strictly return a temperature; returns an "ADC Value" (i.e. raw register content). + * + * @param hindex the hotend we're referencing (if MULTI_MAX_TC) + * @return integer representing the board's buffer, to be converted later if needed + */ +raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { + #define ADS1118_HEAT_INTERVAL 250UL // tiempo mínimo entre lecturas (ms) + + static raw_adc_t ads1118_temp_previous[2] = { 0, 0 }; + static uint8_t ads1118_errors[2] = { 0, 0 }; + static millis_t next_ads1118_ms[2] = { 0, 0 }; + + const millis_t ms = millis(); + if (PENDING(ms, next_ads1118_ms[hindex])) + return ads1118_temp_previous[hindex]; // devolver última lectura si no toca medir aún + + next_ads1118_ms[hindex] = ms + ADS1118_HEAT_INTERVAL; + + raw_adc_t ads_val = 0; + + // Elegir configuración diferencial según hindex + uint16_t config; + if (hindex == 0) + config = 0x0003 | 0x8000; // AIN0 - AIN1, modo single-shot, PGA ±2.048V, 128 SPS + else + config = 0x3000 | 0x8000; // AIN2 - AIN3, modo single-shot, PGA ±2.048V, 128 SPS + + // Enviar config al ADS1118 + ads1118.transfer16(config); + + // Tiempo de conversión (8 ms típico) + delay(10); + + // Leer valor + int16_t raw = (int16_t)ads1118.transfer16(config); + + // Manejo de errores simples: raw = 0x7FFF o 0x8000 podrían ser saturación + if (raw == 0x7FFF || raw == -32768) { + ads1118_errors[hindex]++; + if (ads1118_errors[hindex] > 3) { + SERIAL_ERROR_START(); + SERIAL_ECHOLNPGM("ADS1118 Fault: Conversion error!"); + ads_val = (raw_adc_t)(TEMP_SENSOR_0_MAX_TC_TMAX << 4); // forzar error + } + } + else { + ads1118_errors[hindex] = 0; // resetear errores si ok + // Convertir raw a formato fijo (ejemplo: 1/16 °C si es termocupla) + ads_val = (raw_adc_t)raw; + } + + ads1118_temp_previous[hindex] = ads_val; + + return ads_val; +} +#endif // ENABLED(HAS_ADS1118) + + + + /** * Update raw temperatures * diff --git a/Marlin/src/module/temperature.h b/Marlin/src/module/temperature.h index 92fae44deb..2bcc42bf63 100644 --- a/Marlin/src/module/temperature.h +++ b/Marlin/src/module/temperature.h @@ -1362,6 +1362,12 @@ class Temperature { static raw_adc_t read_max_tc_bed(); #endif + // ADS Thermocouples + #if HAS_ADS1118 + #define READ_ADS(N) read_ads1118(N) + static raw_adc_t read_ads1118(const uint8_t hindex=0); + #endif + #if HAS_AUTO_FAN #if ENABLED(POWER_OFF_WAIT_FOR_COOLDOWN) static bool autofans_on; From 1fa5b88e15cfb545de3564d550692af5a9341244 Mon Sep 17 00:00:00 2001 From: Axel Sepulveda Date: Thu, 9 Oct 2025 01:12:21 -0300 Subject: [PATCH 03/27] update ADS implementation for async conversion --- Marlin/src/libs/adc/adc_ads1118.cpp | 273 ++++++++++++++++++---------- Marlin/src/libs/adc/adc_ads1118.h | 40 ++-- 2 files changed, 202 insertions(+), 111 deletions(-) diff --git a/Marlin/src/libs/adc/adc_ads1118.cpp b/Marlin/src/libs/adc/adc_ads1118.cpp index 6a7ebebc85..f1475c8415 100644 --- a/Marlin/src/libs/adc/adc_ads1118.cpp +++ b/Marlin/src/libs/adc/adc_ads1118.cpp @@ -31,107 +31,192 @@ #include "../../inc/MarlinConfig.h" #if ENABLED(HAS_ADS1118) + + #include "adc_ads1118.h" + + #include "../../HAL/shared/Delay.h" + #include "../../core/macros.h" + + // Initialize the ADS1118, global instance + ADS1118::init(ADS1118_CS_PIN, ADS1118_MOSI_PIN, ADS1118_MISO_PIN, ADS1118_SCK_PIN); + - #include "adc_ads1118.h" + #define ADS1118_CONV_MS 10 + #define ADS1118_CH_MASK 12 - #include "../../HAL/shared/Delay.h" - #include "../../core/macros.h" + // Constructor + void ADS1118::init(uint8_t cs, uint8_t mosi, uint8_t miso, uint8_t sck) { + _cs = cs; _mosi = mosi; _miso = miso; _sck = sck; - // Initialize the ADS1118, global instance - ADC_ADS1118 ads1118(ADS1118_CS_PIN, ADS1118_MOSI_PIN, ADS1118_MISO_PIN, ADS1118_SCK_PIN); - - // Constructor - ADC_ADS1118::ADC_ADS1118(uint8_t cs_pin, uint8_t mosi_pin, uint8_t miso_pin, uint8_t sck_pin) - : cs(cs_pin), mosi(mosi_pin), miso(miso_pin), sck(sck_pin) {} - - - void ADC_ADS1118::init() { - SET_OUTPUT(cs); - SET_OUTPUT(mosi); - SET_OUTPUT(sck); - SET_INPUT(miso); - - deselect(); - sckLow(); - } - - int16_t ADC_ADS1118::readChannel(uint8_t channel) { - uint16_t config = configForChannel(channel, false); - transfer16(config); - - // ADS1118 takes ~8 ms to convert - delay(10); - - int16_t value = (int16_t)transfer16(config); - return value; - } - - float ADC_ADS1118::readVoltage(uint8_t channel, float vref) { - int16_t raw = readChannel(channel); - return (raw / 32768.0f) * vref; // scale 16 bits to voltage - } - - float ADC_ADS1118::readInternalTemp() { - uint16_t config = configForChannel(0, true); - transfer16(config); - - delay(10); - - int16_t raw = (int16_t)transfer16(config); - return raw * 0.03125f; // 0.03125 °C by LSB and datasheet - } - - uint16_t ADC_ADS1118::configChannel(uint8_t channel, bool temp) { - uint16_t config = 0; - - if (temp) { - config = 0x0F80; // Config internal temp + SET_OUTPUT(_cs); + SET_OUTPUT(m_osi); + SET_OUTPUT(_sck); + SET_INPUT(_miso); + + deselect(); + sckLow(); } - else { - // Config single-ended inputs PGA ±2.048V + + // Sets ADS to start a single shot conversion, it will be read async when ready (after ADS1118_CONV_MS), non blocking + void ADS1118::startConversion(uint8_t pair) { + if (_isBusy) return; + + uint16_t config = 0x858B; // 0b 1000 0101 1000 1011 : SS start, single-ended off, gain ±2.048V, single-shot mode, 128SPS, ADC mode, Pullup enable, Write config + switch (pair) { + case 0: config |= (0x0 << ADS1118_CH_MASK); _currentchannel = 0; break; // AIN0-AIN1 + case 1: config |= (0x3 << ADS1118_CH_MASK); _currentchannel = 1; break; // AIN2-AIN3 + default: config |= (0x0 << ADS1118_CH_MASK); _currentchannel = 0; break; + } + + WRITE(_cs, LOW); + transfer16(config); + WRITE(_cs, HIGH); + + _isBusy = true; + _startTime = millis(); + } + + // Determine that a conversion is ready by its elapsed time + bool ADS1118::ready() { + if (!_isBusy) return true; + if (millis() - _startTime >= ADS1118_CONV_MS) { + uint16_t raw; + WRITE(_cs, LOW); + transfer16(raw); + WRITE(_cs, HIGH); + _lastValue = (int16_t)raw; + _isBusy = false; + } + return !_isBusy; + } + + int16_t ADS1118::read() { + return _lastValue; + } + + bool ADS1118::busy() { + return _isBusy; + } + + void ADS1118::loop() { + ready(); // simplemente actualiza el estado si ya pasó el tiempo + } + + // Sets ADS to start Continuous conversion mode + void ADS1118::startContinuousConversion(uint8_t pair) { + if (_isBusy) return; + + uint16_t config = 0x848B; // b 1000 0100 1000 1011 : SS start, single-ended off, gain ±2.048V, Continuous conversion mode, 128SPS, ADC mode, Pullup enable, Write config + switch (pair) { + case 0: config |= (0x0 << ADS1118_CH_MASK); _currentchannel = 0; break; // AIN0-AIN1 + case 1: config |= (0x3 << ADS1118_CH_MASK); _currentchannel = 1; break; // AIN2-AIN3 + default: config |= (0x0 << ADS1118_CH_MASK); _currentchannel = 0; break; + } + + WRITE(_cs, LOW); + transfer16(config); + WRITE(_cs, HIGH); + + _isBusy = true; + _startTime = millis(); + } + + // Check if ADS has a complete conversion + bool ADS1118::checkDataReady() { + WRITE(_cs, LOW); + uint8_t isReady = !READ(_miso); // Read MISO, is low when ready + WRITE(_cs, HIGH); + + return isReady; + + } + + // Check if ADS has a complete conversion + uint16_t ADS1118::readData() { + + WRITE(_cs, LOW); + uint16_t data = transfer16(0); + WRITE(_cs, HIGH); + return data; + + } + + + // Reads and returns a single channel inmediately with delay (blocking) + int16_t ADS1118::readChannel(uint8_t channel) { + uint16_t config = configChannel(channel); + transfer16(config); + + // ADS1118 takes ~8 ms to convert + delay(10); + + int16_t value = (int16_t)transfer16(config); + return value; + } + + float ADS1118::readVoltage(uint8_t channel, float vref) { + int16_t raw = readChannel(channel); + return (raw / 32768.0f) * vref; // scale 16 bits to voltage + } + + float ADS1118::readInternalTemp() { + uint16_t config = 0x8F80; // Config internal temp read & start SS conversion + transfer16(config); + + delay(10); + + int16_t raw = (int16_t)transfer16(config); + return raw * 0.03125f; // 0.03125 °C by LSB and datasheet + } + + uint16_t ADS1118::configChannel(uint8_t channel) { + uint16_t config = 0; + + + // Config single-ended inputs PGA ±2.048V, SS mode, 128SPS no pull up switch(channel) { - case 0: config = 0x8583; break; - case 1: config = 0x9083; break; - case 2: config = 0xA083; break; - case 3: config = 0xB083; break; + case 0: config = 0xC583; break; // 0b 1100 0101 1000 0011 Ch1 & start SS conversion + case 1: config = 0xD583; break; // 0b 1101 0101 1000 0011 Ch2 & start SS conversion + case 2: config = 0xE583; break; // 0b 1110 0101 1000 0011 Ch3 & start SS conversion + case 3: config = 0xF583; break; // 0b 1111 0101 1000 0011 Ch4 & start SS conversion default: config = 0x8583; break; } + + + return config; } - - return config; - } - - uint16_t ADC_ADS1118::transfer16(uint16_t data) { - uint8_t high = transfer8((uint8_t)(data >> 8)); - uint8_t low = transfer8((uint8_t)(data & 0xFF)); - return (uint16_t)(high << 8) | low; - } - - uint8_t ADC_ADS1118::transfer8(uint8_t data) { - uint8_t recv = 0; - for (uint8_t i = 0; i < 8; i++) { - // Send MSB first - if (data & 0x80) WRITE(mosi, HIGH); else WRITE(mosi, LOW); - data <<= 1; - - sckHigh(); - DELAY_NS(100); // small delay for stability - - recv <<= 1; - if (READ(miso)) recv |= 0x01; - - sckLow(); - DELAY_NS(100); + + uint16_t ADS1118::transfer16(uint16_t data) { + uint8_t high = transfer8((uint8_t)(data >> 8)); + uint8_t low = transfer8((uint8_t)(data & 0xFF)); + return (uint16_t)(high << 8) | low; } - return recv; - } - - void ADC_ADS1118::select() { WRITE(cs, LOW); } - void ADC_ADS1118::deselect() { WRITE(cs, HIGH); } - - void ADC_ADS1118::sckHigh() { WRITE(sck, HIGH); } - void ADC_ADS1118::sckLow() { WRITE(sck, LOW); } - - ADS1118 ads1118; - + + uint8_t ADS1118::transfer8(uint8_t data) { + uint8_t recv = 0; + for (uint8_t i = 0; i < 8; i++) { + // Send MSB first + if (data & 0x80) WRITE(mosi, HIGH); else WRITE(mosi, LOW); + data <<= 1; + + sckHigh(); + DELAY_NS(100); // small delay for stability + + recv <<= 1; + if (READ(miso)) recv |= 0x01; + + sckLow(); + DELAY_NS(100); + } + return recv; + } + + void ADS1118::select() { WRITE(_cs, LOW); } + void ADS1118::deselect() { WRITE(_cs, HIGH); } + + void ADS1118::sckHigh() { WRITE(_sck, HIGH); } + void ADS1118::sckLow() { WRITE(_sck, LOW); } + + ADS1118 ads1118; + #endif // HAS_ADS1118_ADC diff --git a/Marlin/src/libs/adc/adc_ads1118.h b/Marlin/src/libs/adc/adc_ads1118.h index 682a985856..6744948d4c 100644 --- a/Marlin/src/libs/adc/adc_ads1118.h +++ b/Marlin/src/libs/adc/adc_ads1118.h @@ -34,29 +34,35 @@ #include class ADS1118 { - public: - ADC_ADS1118(uint8_t cs_pin, uint8_t mosi_pin, uint8_t miso_pin, uint8_t sck_pin); + public: + static void init(uint8_t cs, uint8_t mosi, uint8_t miso, uint8_t sck); + static void startConversion(uint8_t pair); // inicia conversión + static bool ready(); // indica si ya se puede leer + static int16_t read(); // lee valor convertido + static bool busy(); // estado de conversión + static void loop(); // ciclo no bloqueante - void init(); - int16_t readChannel(uint8_t channel); - float readVoltage(uint8_t channel, float vref = 2.048f); - float readInternalTemp(); - - bool Error; + + private: - uint8_t cs, mosi, miso, sck; - - uint16_t transfer16(uint16_t data); - uint8_t transfer8(uint8_t data); + static void spiTransfer(uint8_t data, uint8_t &resp); + static void writeWord(uint16_t word); + static void readWord(uint16_t &word); void select(); - void deselect(); - + void deselect(); + void sckHigh(); - void sckLow(); + void sckLow(); + + static uint8_t _cs, _mosi, _miso, _sck; + static unsigned long _startTime; + static int16_t _lastValue; + static bool _isBusy; + static uint8_t _currentchannel; + + uint16_t configForChannel(uint8_t channel); - // Configuración de registros - uint16_t configForChannel(uint8_t channel, bool temp = false); }; extern ADS1118 ads1118; From 06904ac500a9473d84c529f94f4dbebb7e8d6a70 Mon Sep 17 00:00:00 2001 From: Axel Sepulveda Date: Thu, 9 Oct 2025 01:26:01 -0300 Subject: [PATCH 04/27] update implementation --- Marlin/src/libs/adc/adc_ads1118.cpp | 6 +++--- Marlin/src/libs/adc/adc_ads1118.h | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Marlin/src/libs/adc/adc_ads1118.cpp b/Marlin/src/libs/adc/adc_ads1118.cpp index f1475c8415..894f503b47 100644 --- a/Marlin/src/libs/adc/adc_ads1118.cpp +++ b/Marlin/src/libs/adc/adc_ads1118.cpp @@ -76,7 +76,7 @@ _startTime = millis(); } - // Determine that a conversion is ready by its elapsed time + // Determine that a conversion is ready by its elapsed time, if true, reads data and stores in _lastValue bool ADS1118::ready() { if (!_isBusy) return true; if (millis() - _startTime >= ADS1118_CONV_MS) { @@ -103,11 +103,11 @@ } // Sets ADS to start Continuous conversion mode - void ADS1118::startContinuousConversion(uint8_t pair) { + void ADS1118::startContinuousConversion(uint8_t channel_pair) { if (_isBusy) return; uint16_t config = 0x848B; // b 1000 0100 1000 1011 : SS start, single-ended off, gain ±2.048V, Continuous conversion mode, 128SPS, ADC mode, Pullup enable, Write config - switch (pair) { + switch (ch_pair) { case 0: config |= (0x0 << ADS1118_CH_MASK); _currentchannel = 0; break; // AIN0-AIN1 case 1: config |= (0x3 << ADS1118_CH_MASK); _currentchannel = 1; break; // AIN2-AIN3 default: config |= (0x0 << ADS1118_CH_MASK); _currentchannel = 0; break; diff --git a/Marlin/src/libs/adc/adc_ads1118.h b/Marlin/src/libs/adc/adc_ads1118.h index 6744948d4c..9451a666a1 100644 --- a/Marlin/src/libs/adc/adc_ads1118.h +++ b/Marlin/src/libs/adc/adc_ads1118.h @@ -42,7 +42,9 @@ static bool busy(); // estado de conversión static void loop(); // ciclo no bloqueante - + static bool checkDataReady(); + static void startContinuousConversion(uint8_t channel_pair) + static uint16_t readData(); private: static void spiTransfer(uint8_t data, uint8_t &resp); From 0bb9e65e8c4706d1f5f51477434d0bf0878f5967 Mon Sep 17 00:00:00 2001 From: Axel Sepulveda Date: Thu, 9 Oct 2025 02:14:06 -0300 Subject: [PATCH 05/27] store the config, use english --- Marlin/src/libs/adc/adc_ads1118.cpp | 2 +- Marlin/src/libs/adc/adc_ads1118.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Marlin/src/libs/adc/adc_ads1118.cpp b/Marlin/src/libs/adc/adc_ads1118.cpp index 894f503b47..d41395c075 100644 --- a/Marlin/src/libs/adc/adc_ads1118.cpp +++ b/Marlin/src/libs/adc/adc_ads1118.cpp @@ -99,7 +99,7 @@ } void ADS1118::loop() { - ready(); // simplemente actualiza el estado si ya pasó el tiempo + ready(); // updates status and value } // Sets ADS to start Continuous conversion mode diff --git a/Marlin/src/libs/adc/adc_ads1118.h b/Marlin/src/libs/adc/adc_ads1118.h index 9451a666a1..fea72c9f6b 100644 --- a/Marlin/src/libs/adc/adc_ads1118.h +++ b/Marlin/src/libs/adc/adc_ads1118.h @@ -60,6 +60,7 @@ static uint8_t _cs, _mosi, _miso, _sck; static unsigned long _startTime; static int16_t _lastValue; + static int16_t _config; static bool _isBusy; static uint8_t _currentchannel; From 6e8a7b122b4bbcc4990b34fe52dd081707d880ce Mon Sep 17 00:00:00 2001 From: Axel Sepulveda Date: Thu, 9 Oct 2025 02:16:27 -0300 Subject: [PATCH 06/27] continuous conversion --- Marlin/src/module/temperature.cpp | 34 ++++++------------------------- 1 file changed, 6 insertions(+), 28 deletions(-) diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index d6a133f096..15b2807e28 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -217,7 +217,7 @@ // ADS TC related macros #if TEMP_SENSOR_IS_ADS(0, TEMP_SENSOR_ADS1118) - ads1118.init(); + ads1118.startContinuousConversion(0); #endif @@ -3978,35 +3978,13 @@ void Temperature::disable_all_heaters() { * @return integer representing the board's buffer, to be converted later if needed */ raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { - #define ADS1118_HEAT_INTERVAL 250UL // tiempo mínimo entre lecturas (ms) - static raw_adc_t ads1118_temp_previous[2] = { 0, 0 }; static uint8_t ads1118_errors[2] = { 0, 0 }; - static millis_t next_ads1118_ms[2] = { 0, 0 }; - - const millis_t ms = millis(); - if (PENDING(ms, next_ads1118_ms[hindex])) - return ads1118_temp_previous[hindex]; // devolver última lectura si no toca medir aún - - next_ads1118_ms[hindex] = ms + ADS1118_HEAT_INTERVAL; - - raw_adc_t ads_val = 0; - - // Elegir configuración diferencial según hindex - uint16_t config; - if (hindex == 0) - config = 0x0003 | 0x8000; // AIN0 - AIN1, modo single-shot, PGA ±2.048V, 128 SPS - else - config = 0x3000 | 0x8000; // AIN2 - AIN3, modo single-shot, PGA ±2.048V, 128 SPS - - // Enviar config al ADS1118 - ads1118.transfer16(config); - - // Tiempo de conversión (8 ms típico) - delay(10); - - // Leer valor - int16_t raw = (int16_t)ads1118.transfer16(config); + static millis_t next_ads1118_ms[2] = { 0, 0 }; + + // Loop ready and read w/cache + ads1118.loop(); + int16_t raw = ads1118.readChannel(hindex); // Manejo de errores simples: raw = 0x7FFF o 0x8000 podrían ser saturación if (raw == 0x7FFF || raw == -32768) { From 330ab89ecb58a3c1cd1ffd630b9f271ced840ed0 Mon Sep 17 00:00:00 2001 From: Axel Sepulveda Date: Thu, 9 Oct 2025 02:29:29 -0300 Subject: [PATCH 07/27] single hotend --- Marlin/src/inc/Conditionals-4-adv.h | 2 ++ Marlin/src/module/temperature.cpp | 23 ++++++++++++++++------- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/Marlin/src/inc/Conditionals-4-adv.h b/Marlin/src/inc/Conditionals-4-adv.h index dd80827153..4fb51e719d 100644 --- a/Marlin/src/inc/Conditionals-4-adv.h +++ b/Marlin/src/inc/Conditionals-4-adv.h @@ -427,6 +427,8 @@ #define TEMP_SENSOR_0_IS_AD595 1 #elif TEMP_SENSOR_0 == -18 #define TEMP_SENSOR_0_IS_ADS1118 1 + #define TEMP_SENSOR_0_ADS_TMIN 0 + #define TEMP_SENSOR_0_ADS_TMAX 1024 #elif TEMP_SENSOR_0 > 0 #define TEMP_SENSOR_0_IS_THERMISTOR 1 #if TEMP_SENSOR_0 == 1000 diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index 15b2807e28..7febd636ee 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -3973,18 +3973,27 @@ void Temperature::disable_all_heaters() { * * Reads the thermocouple board via HW or SW SPI, using a library (LIB_USR_x) or raw SPI reads. * Doesn't strictly return a temperature; returns an "ADC Value" (i.e. raw register content). + * Currently only supports channel 0 (single extruder) * - * @param hindex the hotend we're referencing (if MULTI_MAX_TC) + * @param hindex the hotend we're referencing (different channel in ADS1118) * @return integer representing the board's buffer, to be converted later if needed */ raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { - static raw_adc_t ads1118_temp_previous[2] = { 0, 0 }; + #define ADS1118_HEAT_INTERVAL 250UL // + + static raw_adc_t ads1118_temp_previous[2] = { 0, 0 }; static uint8_t ads1118_errors[2] = { 0, 0 }; static millis_t next_ads1118_ms[2] = { 0, 0 }; - // Loop ready and read w/cache - ads1118.loop(); - int16_t raw = ads1118.readChannel(hindex); + + const millis_t ms = millis(); + if (PENDING(ms, next_ads1118_ms[hindex]) || !ads1118.checkDataReady()) + return ads1118_temp_previous[hindex]; // return cached value + + next_ads1118_ms[hindex] = ms + ADS1118_HEAT_INTERVAL; + + // To do: If eneable more hotends, cycle through different channels + int16_t raw = ads1118.readData(); // Manejo de errores simples: raw = 0x7FFF o 0x8000 podrían ser saturación if (raw == 0x7FFF || raw == -32768) { @@ -3992,11 +4001,11 @@ raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { if (ads1118_errors[hindex] > 3) { SERIAL_ERROR_START(); SERIAL_ECHOLNPGM("ADS1118 Fault: Conversion error!"); - ads_val = (raw_adc_t)(TEMP_SENSOR_0_MAX_TC_TMAX << 4); // forzar error + ads_val = (raw_adc_t)(TEMP_SENSOR_0_ADS_TMAX << 4); // force error } } else { - ads1118_errors[hindex] = 0; // resetear errores si ok + ads1118_errors[hindex] = 0; // reset errors if ok // Convertir raw a formato fijo (ejemplo: 1/16 °C si es termocupla) ads_val = (raw_adc_t)raw; } From 9fbe9fe8f45a6f48aef8d32b202aa20a51622424 Mon Sep 17 00:00:00 2001 From: Axel Sepulveda Date: Fri, 10 Oct 2025 01:46:42 -0300 Subject: [PATCH 08/27] correct init --- Marlin/src/libs/adc/adc_ads1118.cpp | 35 +++++++++++++++++++++-------- Marlin/src/module/temperature.cpp | 10 +++++++-- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/Marlin/src/libs/adc/adc_ads1118.cpp b/Marlin/src/libs/adc/adc_ads1118.cpp index d41395c075..56c56d5ea3 100644 --- a/Marlin/src/libs/adc/adc_ads1118.cpp +++ b/Marlin/src/libs/adc/adc_ads1118.cpp @@ -32,22 +32,18 @@ #if ENABLED(HAS_ADS1118) - #include "adc_ads1118.h" - - #include "../../HAL/shared/Delay.h" - #include "../../core/macros.h" - - // Initialize the ADS1118, global instance - ADS1118::init(ADS1118_CS_PIN, ADS1118_MOSI_PIN, ADS1118_MISO_PIN, ADS1118_SCK_PIN); - + #include "adc_ads1118.h" + #include "../../HAL/shared/Delay.h" + #include "../../core/macros.h" + #define ADS1118_CONV_MS 10 #define ADS1118_CH_MASK 12 // Constructor void ADS1118::init(uint8_t cs, uint8_t mosi, uint8_t miso, uint8_t sck) { _cs = cs; _mosi = mosi; _miso = miso; _sck = sck; - + SET_OUTPUT(_cs); SET_OUTPUT(m_osi); SET_OUTPUT(_sck); @@ -55,6 +51,7 @@ deselect(); sckLow(); + } // Sets ADS to start a single shot conversion, it will be read async when ready (after ADS1118_CONV_MS), non blocking @@ -186,6 +183,25 @@ return config; } + uint32_t ADS1118::transfer32(uint16_t data) { + uint16_t result_prev, config_echo; + + result_prev = transfer16(data); // envía config, recibe resultado anterior + config_echo = transfer16(0x0000); // envía dummy, recibe eco de configuración + + // Combina ambos en un solo valor de 32 bits + return ((uint32_t)result_prev << 16) | config_echo; + } + + uint16_t ADS1118::readConfig() { + uint16_t config_echo; + + transfer16(0x0000); + config_echo = transfer16(0x0000); // envía dummy, recibe eco de configuración + SERIAL_ECHOLNPGM("ADS1118 Configuration: 0x"); SERIAL_ECHOLN(config_echo, HEX); + return config_echo; + } + uint16_t ADS1118::transfer16(uint16_t data) { uint8_t high = transfer8((uint8_t)(data >> 8)); uint8_t low = transfer8((uint8_t)(data & 0xFF)); @@ -217,6 +233,7 @@ void ADS1118::sckHigh() { WRITE(_sck, HIGH); } void ADS1118::sckLow() { WRITE(_sck, LOW); } + // ADS1118, global instance ADS1118 ads1118; #endif // HAS_ADS1118_ADC diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index 7febd636ee..0970056969 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -3051,6 +3051,11 @@ void Temperature::init() { TERN_(PROBING_HEATERS_OFF, paused_for_probing = false); + #if HAS_ADS1118 + ads1118.init(ADS1118_CS_PIN, ADS1118_MOSI_PIN, ADS1118_MISO_PIN, ADS1118_SCK_PIN); // Initialize the ADS1118, global instance + ads1118.readConfig(); + #endif + // Init (and disable) SPI thermocouples #if TEMP_SENSOR_IS_ANY_MAX_TC(0) && PIN_EXISTS(TEMP_0_CS) OUT_WRITE(TEMP_0_CS_PIN, HIGH); @@ -3979,7 +3984,7 @@ void Temperature::disable_all_heaters() { * @return integer representing the board's buffer, to be converted later if needed */ raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { - #define ADS1118_HEAT_INTERVAL 250UL // + #define ADS1118_HEAT_INTERVAL 250UL // 250 ms static raw_adc_t ads1118_temp_previous[2] = { 0, 0 }; static uint8_t ads1118_errors[2] = { 0, 0 }; @@ -3992,8 +3997,9 @@ raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { next_ads1118_ms[hindex] = ms + ADS1118_HEAT_INTERVAL; - // To do: If eneable more hotends, cycle through different channels + // To do: If there are more hotends enabled, cycle through different channels int16_t raw = ads1118.readData(); + SERIAL_ECHOLNPGM("ADS1118 Read: 0x"); SERIAL_ECHOLN(raw, HEX); // Manejo de errores simples: raw = 0x7FFF o 0x8000 podrían ser saturación if (raw == 0x7FFF || raw == -32768) { From a2e664e55a480f246b969da10d41cbbef64f4d3b Mon Sep 17 00:00:00 2001 From: Axel Sepulveda Date: Fri, 10 Oct 2025 01:54:14 -0300 Subject: [PATCH 09/27] move init --- Marlin/src/module/temperature.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index 0970056969..522b847698 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -215,11 +215,6 @@ #include #endif -// ADS TC related macros -#if TEMP_SENSOR_IS_ADS(0, TEMP_SENSOR_ADS1118) - ads1118.startContinuousConversion(0); -#endif - #if ENABLED(FILAMENT_WIDTH_SENSOR) #include "../feature/filwidth.h" @@ -3056,6 +3051,12 @@ void Temperature::init() { ads1118.readConfig(); #endif + // ADS TC related macros + #if TEMP_SENSOR_IS_ADS(0, TEMP_SENSOR_ADS1118) + ads1118.startContinuousConversion(0); + ads1118.readConfig(); + #endif + // Init (and disable) SPI thermocouples #if TEMP_SENSOR_IS_ANY_MAX_TC(0) && PIN_EXISTS(TEMP_0_CS) OUT_WRITE(TEMP_0_CS_PIN, HIGH); From 79bfc57d56e2a258670c60ef2c0d6db53227a611 Mon Sep 17 00:00:00 2001 From: Axel Sepulveda Date: Mon, 13 Oct 2025 23:31:20 -0300 Subject: [PATCH 10/27] use standard funciontions, update library functions --- Marlin/src/libs/adc/adc_ads1118.cpp | 104 ++++++++++++++++------------ Marlin/src/libs/adc/adc_ads1118.h | 34 ++++++--- 2 files changed, 84 insertions(+), 54 deletions(-) diff --git a/Marlin/src/libs/adc/adc_ads1118.cpp b/Marlin/src/libs/adc/adc_ads1118.cpp index 56c56d5ea3..816090b262 100644 --- a/Marlin/src/libs/adc/adc_ads1118.cpp +++ b/Marlin/src/libs/adc/adc_ads1118.cpp @@ -42,12 +42,17 @@ // Constructor void ADS1118::init(uint8_t cs, uint8_t mosi, uint8_t miso, uint8_t sck) { - _cs = cs; _mosi = mosi; _miso = miso; _sck = sck; + cs_pin = cs; mosi_pin = mosi; miso_pin = miso; sck_pin = sck; - SET_OUTPUT(_cs); - SET_OUTPUT(m_osi); - SET_OUTPUT(_sck); - SET_INPUT(_miso); +// #define TEMP_0_CS_PIN 79 // E6 +// #define TEMP_0_SCK_PIN 78 // E2 +// #define TEMP_0_MISO_PIN 80 // E7 +// #define TEMP_0_MOSI_PIN 84 // H2 + + pinMode(cs_pin, OUTPUT); + pinMode(mosi_pin, OUTPUT); + pinMode(sck_pin, OUTPUT); + pinMode(miso_pin, INPUT); deselect(); sckLow(); @@ -56,43 +61,43 @@ // Sets ADS to start a single shot conversion, it will be read async when ready (after ADS1118_CONV_MS), non blocking void ADS1118::startConversion(uint8_t pair) { - if (_isBusy) return; + if (isBusy) return; uint16_t config = 0x858B; // 0b 1000 0101 1000 1011 : SS start, single-ended off, gain ±2.048V, single-shot mode, 128SPS, ADC mode, Pullup enable, Write config switch (pair) { - case 0: config |= (0x0 << ADS1118_CH_MASK); _currentchannel = 0; break; // AIN0-AIN1 - case 1: config |= (0x3 << ADS1118_CH_MASK); _currentchannel = 1; break; // AIN2-AIN3 - default: config |= (0x0 << ADS1118_CH_MASK); _currentchannel = 0; break; + case 0: config |= (0x0 << ADS1118_CH_MASK); currentchannel = 0; break; // AIN0-AIN1 + case 1: config |= (0x3 << ADS1118_CH_MASK); currentchannel = 1; break; // AIN2-AIN3 + default: config |= (0x0 << ADS1118_CH_MASK); currentchannel = 0; break; } - WRITE(_cs, LOW); + digitalWrite(cs_pin, LOW); transfer16(config); - WRITE(_cs, HIGH); + digitalWrite(cs_pin, HIGH); - _isBusy = true; - _startTime = millis(); + isBusy = true; + startTime = millis(); } // Determine that a conversion is ready by its elapsed time, if true, reads data and stores in _lastValue bool ADS1118::ready() { - if (!_isBusy) return true; - if (millis() - _startTime >= ADS1118_CONV_MS) { + if (!isBusy) return true; + if (millis() - startTime >= ADS1118_CONV_MS) { uint16_t raw; - WRITE(_cs, LOW); + digitalWrite(cs_pin, LOW); transfer16(raw); - WRITE(_cs, HIGH); - _lastValue = (int16_t)raw; - _isBusy = false; + digitalWrite(cs_pin, HIGH); + lastValue = (int16_t)raw; + isBusy = false; } - return !_isBusy; + return !isBusy; } int16_t ADS1118::read() { - return _lastValue; + return lastValue; } bool ADS1118::busy() { - return _isBusy; + return isBusy; } void ADS1118::loop() { @@ -101,28 +106,30 @@ // Sets ADS to start Continuous conversion mode void ADS1118::startContinuousConversion(uint8_t channel_pair) { - if (_isBusy) return; + SERIAL_ECHOLNPGM("ADS1118 Set to start conv"); + if (isBusy) return; uint16_t config = 0x848B; // b 1000 0100 1000 1011 : SS start, single-ended off, gain ±2.048V, Continuous conversion mode, 128SPS, ADC mode, Pullup enable, Write config - switch (ch_pair) { - case 0: config |= (0x0 << ADS1118_CH_MASK); _currentchannel = 0; break; // AIN0-AIN1 - case 1: config |= (0x3 << ADS1118_CH_MASK); _currentchannel = 1; break; // AIN2-AIN3 - default: config |= (0x0 << ADS1118_CH_MASK); _currentchannel = 0; break; + switch (channel_pair) { + case 0: config |= (0x0 << ADS1118_CH_MASK); currentchannel = 0; break; // AIN0-AIN1 + case 1: config |= (0x3 << ADS1118_CH_MASK); currentchannel = 1; break; // AIN2-AIN3 + default: config |= (0x0 << ADS1118_CH_MASK); currentchannel = 0; break; } - WRITE(_cs, LOW); + digitalWrite(cs_pin, LOW); transfer16(config); - WRITE(_cs, HIGH); + digitalWrite(cs_pin, HIGH); - _isBusy = true; - _startTime = millis(); + isBusy = true; + startTime = millis(); + SERIAL_ECHOLNPGM("ADS1118 Leaving start conv"); } // Check if ADS has a complete conversion bool ADS1118::checkDataReady() { - WRITE(_cs, LOW); - uint8_t isReady = !READ(_miso); // Read MISO, is low when ready - WRITE(_cs, HIGH); + digitalWrite(cs_pin, LOW); + uint8_t isReady = !digitalRead(miso_pin); // Read MISO, is low when ready + digitalWrite(cs_pin, HIGH); return isReady; @@ -131,9 +138,9 @@ // Check if ADS has a complete conversion uint16_t ADS1118::readData() { - WRITE(_cs, LOW); + digitalWrite(cs_pin, LOW); uint16_t data = transfer16(0); - WRITE(_cs, HIGH); + digitalWrite(cs_pin, HIGH); return data; } @@ -198,7 +205,7 @@ transfer16(0x0000); config_echo = transfer16(0x0000); // envía dummy, recibe eco de configuración - SERIAL_ECHOLNPGM("ADS1118 Configuration: 0x"); SERIAL_ECHOLN(config_echo, HEX); + SERIAL_ECHOPGM("ADS1118 Configuration: 0x"); SERIAL_ECHOLN(config_echo, HEX); return config_echo; } @@ -212,14 +219,14 @@ uint8_t recv = 0; for (uint8_t i = 0; i < 8; i++) { // Send MSB first - if (data & 0x80) WRITE(mosi, HIGH); else WRITE(mosi, LOW); + if (data & 0x80) digitalWrite(mosi_pin, HIGH); else digitalWrite(mosi_pin, LOW); data <<= 1; sckHigh(); DELAY_NS(100); // small delay for stability recv <<= 1; - if (READ(miso)) recv |= 0x01; + if (digitalRead(miso_pin)) recv |= 0x01; sckLow(); DELAY_NS(100); @@ -227,11 +234,22 @@ return recv; } - void ADS1118::select() { WRITE(_cs, LOW); } - void ADS1118::deselect() { WRITE(_cs, HIGH); } + void ADS1118::select() { digitalWrite(cs_pin, LOW); } + void ADS1118::deselect() { digitalWrite(cs_pin, HIGH); } - void ADS1118::sckHigh() { WRITE(_sck, HIGH); } - void ADS1118::sckLow() { WRITE(_sck, LOW); } + void ADS1118::sckHigh() { digitalWrite(sck_pin, HIGH); } + void ADS1118::sckLow() { digitalWrite(sck_pin, LOW); } + + // Definiciones de variables estáticas + uint8_t ADS1118::cs_pin = 0; + uint8_t ADS1118::mosi_pin = 0; + uint8_t ADS1118::miso_pin = 0; + uint8_t ADS1118::sck_pin = 0; + unsigned long ADS1118::startTime = 0; + int16_t ADS1118::lastValue = 0; + int16_t ADS1118::config = 0; + bool ADS1118::isBusy = false; + uint8_t ADS1118::currentchannel = 0; // ADS1118, global instance ADS1118 ads1118; diff --git a/Marlin/src/libs/adc/adc_ads1118.h b/Marlin/src/libs/adc/adc_ads1118.h index fea72c9f6b..26521b4bc7 100644 --- a/Marlin/src/libs/adc/adc_ads1118.h +++ b/Marlin/src/libs/adc/adc_ads1118.h @@ -33,6 +33,8 @@ #include + #define TEMP_SENSOR_ADS1118 -18 + class ADS1118 { public: static void init(uint8_t cs, uint8_t mosi, uint8_t miso, uint8_t sck); @@ -43,28 +45,38 @@ static void loop(); // ciclo no bloqueante static bool checkDataReady(); - static void startContinuousConversion(uint8_t channel_pair) + static void startContinuousConversion(uint8_t channel_pair); static uint16_t readData(); + static int16_t readChannel(uint8_t channel); + static uint16_t readConfig (); private: static void spiTransfer(uint8_t data, uint8_t &resp); static void writeWord(uint16_t word); static void readWord(uint16_t &word); - void select(); - void deselect(); + static uint32_t transfer32 (uint16_t data); + static uint16_t transfer16 (uint16_t data); + static uint8_t transfer8 (uint8_t data); - void sckHigh(); - void sckLow(); - static uint8_t _cs, _mosi, _miso, _sck; - static unsigned long _startTime; - static int16_t _lastValue; - static int16_t _config; - static bool _isBusy; - static uint8_t _currentchannel; + static void select(); + static void deselect(); + + static void sckHigh(); + static void sckLow(); + + static uint8_t cs_pin, mosi_pin, miso_pin, sck_pin; + static unsigned long startTime; + static int16_t lastValue; + static int16_t config; + static bool isBusy; + static uint8_t currentchannel; uint16_t configForChannel(uint8_t channel); + static uint16_t configChannel(uint8_t channel); + float readVoltage(uint8_t channel, float vref); + float readInternalTemp(); }; From c27df8ec0f632fdb4707cdf36786cff76b2f257f Mon Sep 17 00:00:00 2001 From: Axel Sepulveda Date: Mon, 13 Oct 2025 23:32:00 -0300 Subject: [PATCH 11/27] conditionals and warnings --- Marlin/src/inc/Conditionals-4-adv.h | 3 ++- Marlin/src/inc/Warnings.cpp | 8 ++++++++ Marlin/src/module/temperature.cpp | 27 +++++++++++++++++++++------ 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/Marlin/src/inc/Conditionals-4-adv.h b/Marlin/src/inc/Conditionals-4-adv.h index 4fb51e719d..fd7d8fc444 100644 --- a/Marlin/src/inc/Conditionals-4-adv.h +++ b/Marlin/src/inc/Conditionals-4-adv.h @@ -426,7 +426,8 @@ #elif TEMP_SENSOR_0 == -1 #define TEMP_SENSOR_0_IS_AD595 1 #elif TEMP_SENSOR_0 == -18 - #define TEMP_SENSOR_0_IS_ADS1118 1 + #define HAS_ADS1118 1 + #define TEMP_SENSOR_0_IS_ADS1118 1 #define TEMP_SENSOR_0_ADS_TMIN 0 #define TEMP_SENSOR_0_ADS_TMAX 1024 #elif TEMP_SENSOR_0 > 0 diff --git a/Marlin/src/inc/Warnings.cpp b/Marlin/src/inc/Warnings.cpp index f11eedbe52..2a8e1995cf 100644 --- a/Marlin/src/inc/Warnings.cpp +++ b/Marlin/src/inc/Warnings.cpp @@ -114,6 +114,14 @@ #warning "Warning! Don't use dummy thermistors (998/999) for final build!" #endif +#if ENABLED(HAS_ADS1118) + #warning "ADS1118 support is in development" +#endif + +#if ANY_THERMISTOR_IS(-18) + #warning "ADS1118 support (-18) is in development" +#endif + #if NONE(HAS_RESUME_CONTINUE, HOST_PROMPT_SUPPORT, UNIT_TEST, NO_USER_FEEDBACK_WARNING) #warning "Your Configuration provides no method to acquire user feedback! (Define NO_USER_FEEDBACK_WARNING to suppress this warning.)" #endif diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index 522b847698..b58eb3f447 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -212,7 +212,7 @@ // ADS1118 #if HAS_ADS1118 - #include + #include "../libs/adc/adc_ads1118.h" #endif @@ -2939,10 +2939,15 @@ void Temperature::updateTemperaturesFromRawValues() { #endif // Read ADC ADS1118 - #if TEMP_SENSOR_IS_ADS(0,TEMP_SENSOR_ADS1118) + #if TEMP_SENSOR_IS_ADS(0,1118) + #warning "ADS1118 is selected for temp 0" + SERIAL_ECHOLNPGM("ADS1118 Setting Raw hotend 0"); temp_hotend[0].setraw(READ_ADS(0)); + SERIAL_ECHOPGM("ADS1118 Raw hotend 0: "); SERIAL_ECHOLN(temp_hotend[0].getraw()); #endif - #if TEMP_SENSOR_IS_ADS(1,TEMP_SENSOR_ADS1118) + #if TEMP_SENSOR_IS_ADS(1,1118) + #warning "ADS1118 is selected for temp 1" + SERIAL_ECHOLNPGM("ADS1118 Setting Raw hotend 1"); temp_hotend[1].setraw(READ_ADS(1)); #endif @@ -3046,13 +3051,21 @@ void Temperature::init() { TERN_(PROBING_HEATERS_OFF, paused_for_probing = false); +// #define TEMP_0_CS_PIN 79 // E6 +// #define TEMP_0_SCK_PIN 78 // E2 +// #define TEMP_0_MISO_PIN 80 // E7 +// #define TEMP_0_MOSI_PIN 84 // H2 + #if HAS_ADS1118 - ads1118.init(ADS1118_CS_PIN, ADS1118_MOSI_PIN, ADS1118_MISO_PIN, ADS1118_SCK_PIN); // Initialize the ADS1118, global instance + ads1118.init(TEMP_0_CS_PIN, TEMP_0_MOSI_PIN, TEMP_0_MISO_PIN, TEMP_0_SCK_PIN); // Initialize the ADS1118, global instance ads1118.readConfig(); #endif + // ADS TC related macros - #if TEMP_SENSOR_IS_ADS(0, TEMP_SENSOR_ADS1118) + #if TEMP_SENSOR_IS_ADS(0, 1118) + #warning "ADS1118 is selected for temp 0" + SERIAL_ECHOLNPGM("ADS1118 Entering to start continuous conv"); ads1118.startContinuousConversion(0); ads1118.readConfig(); #endif @@ -3990,6 +4003,8 @@ raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { static raw_adc_t ads1118_temp_previous[2] = { 0, 0 }; static uint8_t ads1118_errors[2] = { 0, 0 }; static millis_t next_ads1118_ms[2] = { 0, 0 }; + + static raw_adc_t ads_val = TEMP_SENSOR_0_ADS_TMAX; const millis_t ms = millis(); @@ -4000,7 +4015,7 @@ raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { // To do: If there are more hotends enabled, cycle through different channels int16_t raw = ads1118.readData(); - SERIAL_ECHOLNPGM("ADS1118 Read: 0x"); SERIAL_ECHOLN(raw, HEX); + SERIAL_ECHOPGM("ADS1118 Read: 0x"); SERIAL_ECHOLN(raw, HEX); // Manejo de errores simples: raw = 0x7FFF o 0x8000 podrían ser saturación if (raw == 0x7FFF || raw == -32768) { From 269bf6d44deb537f32057742c507a69ca37679e6 Mon Sep 17 00:00:00 2001 From: Axel Sepulveda Date: Wed, 29 Oct 2025 21:45:49 -0300 Subject: [PATCH 12/27] read and read config --- Marlin/src/libs/adc/adc_ads1118.cpp | 13 +++++-------- Marlin/src/module/temperature.cpp | 4 ++-- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/Marlin/src/libs/adc/adc_ads1118.cpp b/Marlin/src/libs/adc/adc_ads1118.cpp index 816090b262..2d8da6613b 100644 --- a/Marlin/src/libs/adc/adc_ads1118.cpp +++ b/Marlin/src/libs/adc/adc_ads1118.cpp @@ -130,19 +130,15 @@ digitalWrite(cs_pin, LOW); uint8_t isReady = !digitalRead(miso_pin); // Read MISO, is low when ready digitalWrite(cs_pin, HIGH); - return isReady; - } - // Check if ADS has a complete conversion + // Read ADS data uint16_t ADS1118::readData() { - digitalWrite(cs_pin, LOW); uint16_t data = transfer16(0); digitalWrite(cs_pin, HIGH); return data; - } @@ -202,10 +198,11 @@ uint16_t ADS1118::readConfig() { uint16_t config_echo; - - transfer16(0x0000); + select(); + transfer16(0x0000); // envía dummy 16 bits, ignore reply, config is in the next 16 bit transfer config_echo = transfer16(0x0000); // envía dummy, recibe eco de configuración - SERIAL_ECHOPGM("ADS1118 Configuration: 0x"); SERIAL_ECHOLN(config_echo, HEX); + SERIAL_ECHOPGM("ADS1118 Configuration: "); SERIAL_ECHOLN(config_echo); + deselect(); return config_echo; } diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index b58eb3f447..93673df62c 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -2941,9 +2941,9 @@ void Temperature::updateTemperaturesFromRawValues() { // Read ADC ADS1118 #if TEMP_SENSOR_IS_ADS(0,1118) #warning "ADS1118 is selected for temp 0" - SERIAL_ECHOLNPGM("ADS1118 Setting Raw hotend 0"); + // SERIAL_ECHOLNPGM("ADS1118 Setting Raw hotend 0"); temp_hotend[0].setraw(READ_ADS(0)); - SERIAL_ECHOPGM("ADS1118 Raw hotend 0: "); SERIAL_ECHOLN(temp_hotend[0].getraw()); + SERIAL_ECHOPGM("ADS1118 Get Raw hotend 0: "); SERIAL_ECHOLN(temp_hotend[0].getraw()); #endif #if TEMP_SENSOR_IS_ADS(1,1118) #warning "ADS1118 is selected for temp 1" From e006c8a736c5fd38e9766cd6548be0998ccd6b2a Mon Sep 17 00:00:00 2001 From: Axel Sepulveda Date: Thu, 6 Nov 2025 01:09:33 -0300 Subject: [PATCH 13/27] reading ads, add thermocouple --- Marlin/src/inc/Conditionals-4-adv.h | 1 + Marlin/src/libs/adc/adc_ads1118.cpp | 72 +++++++++++++++++++++++++---- Marlin/src/libs/adc/adc_ads1118.h | 57 +++++++++++++++++++++++ Marlin/src/module/temperature.cpp | 6 +-- 4 files changed, 124 insertions(+), 12 deletions(-) diff --git a/Marlin/src/inc/Conditionals-4-adv.h b/Marlin/src/inc/Conditionals-4-adv.h index fd7d8fc444..d670dce3e5 100644 --- a/Marlin/src/inc/Conditionals-4-adv.h +++ b/Marlin/src/inc/Conditionals-4-adv.h @@ -426,6 +426,7 @@ #elif TEMP_SENSOR_0 == -1 #define TEMP_SENSOR_0_IS_AD595 1 #elif TEMP_SENSOR_0 == -18 + #warning "Config is TEMP_SENSOR_0 == -18" #define HAS_ADS1118 1 #define TEMP_SENSOR_0_IS_ADS1118 1 #define TEMP_SENSOR_0_ADS_TMIN 0 diff --git a/Marlin/src/libs/adc/adc_ads1118.cpp b/Marlin/src/libs/adc/adc_ads1118.cpp index 2d8da6613b..9f2000e47b 100644 --- a/Marlin/src/libs/adc/adc_ads1118.cpp +++ b/Marlin/src/libs/adc/adc_ads1118.cpp @@ -22,7 +22,7 @@ /** * adc_ads1118.cpp - library for Texas Instruments ADS1118 - 16-Bit Analog-to-Digital Converter - * + * based in the sailfish code for ADS1118, ThermocoupleReader, TemperatureTable * For implementation details, please take a look at the datasheet: * https://www.ti.com/product/ADS1118 * @@ -92,9 +92,9 @@ return !isBusy; } - int16_t ADS1118::read() { - return lastValue; - } + int16_t ADS1118::read() { + return lastValue; + } bool ADS1118::busy() { return isBusy; @@ -108,8 +108,9 @@ void ADS1118::startContinuousConversion(uint8_t channel_pair) { SERIAL_ECHOLNPGM("ADS1118 Set to start conv"); if (isBusy) return; - - uint16_t config = 0x848B; // b 1000 0100 1000 1011 : SS start, single-ended off, gain ±2.048V, Continuous conversion mode, 128SPS, ADC mode, Pullup enable, Write config + // 0x048B b 0000 0100 1000 1011 : SS start, single-ended off, gain ±2.048V, Continuous conversion mode, 128SPS, ADC mode, Pullup enable, Write config + // 0x049B: read internal temp + uint16_t config = 0x048B; switch (channel_pair) { case 0: config |= (0x0 << ADS1118_CH_MASK); currentchannel = 0; break; // AIN0-AIN1 case 1: config |= (0x3 << ADS1118_CH_MASK); currentchannel = 1; break; // AIN2-AIN3 @@ -141,7 +142,6 @@ return data; } - // Reads and returns a single channel inmediately with delay (blocking) int16_t ADS1118::readChannel(uint8_t channel) { uint16_t config = configChannel(channel); @@ -166,7 +166,7 @@ delay(10); int16_t raw = (int16_t)transfer16(config); - return raw * 0.03125f; // 0.03125 °C by LSB and datasheet + return (raw>>2) * 0.03125f; // 14 bit left aligned, 0.03125 °C per LSB as datasheet } uint16_t ADS1118::configChannel(uint8_t channel) { @@ -182,7 +182,6 @@ default: config = 0x8583; break; } - return config; } @@ -251,4 +250,59 @@ // ADS1118, global instance ADS1118 ads1118; +void ThermocoupleK::init() {} + +// --- Convierte lectura ADC a °C --- +float ThermocoupleK:: tempReadtoCelsius(int16_t rawADC) { + //Serial.println((int16_t)pgm_read_word(&ThermocoupleK_Lookup[TEMP_TABLE_SIZE - 1])); + + if (rawADC > (int16_t) pgm_read_word(&table_thermocouple_k[TEMP_TABLE_SIZE - 1].adc)) + return TEMP_MAX_TEMP; + if (rawADC < (int16_t) pgm_read_word(&table_thermocouple_k[0].adc)) + return TEMP_MIN_TEMP; + + // Búsqueda lineal en la tabla (de menor a mayor valor ADC) + for (uint16_t i = 0; i < TEMP_TABLE_SIZE - 1; i++) { + + int16_t adc1 = pgm_read_word(&table_thermocouple_k[i].adc); + int16_t adc2 = pgm_read_word(&table_thermocouple_k[i + 1].adc); + // Serial.print(i); Serial.print(" "); Serial.print(adc1); Serial.print(" "); Serial.print(adc2); + + if (rawADC >= adc1 && rawADC < adc2) { // in beteen tableValue and nextValue + // Temperatura aproximada por interpolación lineal + //float frac = float(rawADC - adc2) / float(adc1 - adc2); + int16_t t1 = pgm_read_word(&table_thermocouple_k[i].temp); + int16_t t2 = pgm_read_word(&table_thermocouple_k[i+1].temp); + // Serial.print(" "); Serial.print(t1); Serial.print(" "); Serial.print(t2); + float tempC = t1 + (float) (rawADC - adc1) * (float(t2 - t1) / float(adc2 - adc1)) ; // TEMP_TABLE_OFFSET + i + frac; + return tempC; + } + // Serial.println(""); + } + + return TEMP_MIN_TEMP; +} + +void ThermocoupleK::setTcold(float tcold) { + _Tcold = tcold; +} + +float ThermocoupleK::getTcold() { + return _Tcold ; +} + +void ThermocoupleK::setThot(float thot) { + _Thot = thot; +} + +float ThermocoupleK::getThot() { + return _Thot ; +} + +float ThermocoupleK:: getTempCelsius() { + + return _Thot + _Tcold; +} + + #endif // HAS_ADS1118_ADC diff --git a/Marlin/src/libs/adc/adc_ads1118.h b/Marlin/src/libs/adc/adc_ads1118.h index 26521b4bc7..f567ee24cb 100644 --- a/Marlin/src/libs/adc/adc_ads1118.h +++ b/Marlin/src/libs/adc/adc_ads1118.h @@ -35,6 +35,49 @@ #define TEMP_SENSOR_ADS1118 -18 + typedef struct { + int16_t adc; + int16_t temp; + } ADC_Lookup; + + const static ADC_Lookup PROGMEM table_thermocouple_k[] = { + { -304, -64}, + { -232, -48}, + { -157, -32}, + { -79, -16}, + { 0, 0}, + { 82, 16}, + { 164, 32}, + { 248, 48}, + { 333, 64}, + { 418, 80}, + { 503, 96}, + { 588, 112}, + { 672, 128}, + { 755, 144}, + { 837, 160}, + { 919, 176}, + { 1001, 192}, + { 1083, 208}, + { 1165, 224}, + { 1248, 240}, + { 1331, 256}, + { 1415, 272}, + { 1499, 288}, + { 1584, 304}, + { 1754, 336}, + { 1840, 352}, + { 1926, 368}, + { 2012, 384}, + { 2099, 400} + + }; + + #define TEMP_TABLE_SIZE (sizeof(table_thermocouple_k) / sizeof(table_thermocouple_k[0])) + #define TEMP_MIN_TEMP 0 + #define TEMP_MAX_TEMP 300 + #define TEMP_TABLE_OFFSET 0 // grados Celsius por índice + class ADS1118 { public: static void init(uint8_t cs, uint8_t mosi, uint8_t miso, uint8_t sck); @@ -82,5 +125,19 @@ extern ADS1118 ads1118; + class ThermocoupleK { + public: + void init(); + float tempReadtoCelsius(int16_t rawADC); + float getTempCelsius(); + float _Tcold, _Thot; + + void setTcold(float tcold); + float getTcold(); + + void setThot(float thot); + float getThot(); +}; + #endif // ENABLED(HAS_ADS1118) \ No newline at end of file diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index 93673df62c..817dba35ec 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -4014,8 +4014,8 @@ raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { next_ads1118_ms[hindex] = ms + ADS1118_HEAT_INTERVAL; // To do: If there are more hotends enabled, cycle through different channels - int16_t raw = ads1118.readData(); - SERIAL_ECHOPGM("ADS1118 Read: 0x"); SERIAL_ECHOLN(raw, HEX); + uint16_t raw = ads1118.readData(); + SERIAL_ECHOPGM("ADS1118 Read: "); SERIAL_ECHOLN(raw); // Manejo de errores simples: raw = 0x7FFF o 0x8000 podrían ser saturación if (raw == 0x7FFF || raw == -32768) { @@ -4029,7 +4029,7 @@ raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { else { ads1118_errors[hindex] = 0; // reset errors if ok // Convertir raw a formato fijo (ejemplo: 1/16 °C si es termocupla) - ads_val = (raw_adc_t)raw; + ads_val = (raw_adc_t) raw; // raw; // Fijo temporalmente } ads1118_temp_previous[hindex] = ads_val; From dddf4c2049fa4cecf0ac19c0d823185adcc35d52 Mon Sep 17 00:00:00 2001 From: Axel Sepulveda Date: Fri, 7 Nov 2025 23:21:57 -0300 Subject: [PATCH 14/27] ADS1118 improvements reading temps --- Marlin/src/inc/Conditionals-4-adv.h | 6 +++ Marlin/src/libs/adc/adc_ads1118.cpp | 20 ++++++++- Marlin/src/libs/adc/adc_ads1118.h | 69 +++++++++++++++++++++++++++++ Marlin/src/module/temperature.cpp | 36 ++++++++++++--- 4 files changed, 125 insertions(+), 6 deletions(-) diff --git a/Marlin/src/inc/Conditionals-4-adv.h b/Marlin/src/inc/Conditionals-4-adv.h index d670dce3e5..4f5002be53 100644 --- a/Marlin/src/inc/Conditionals-4-adv.h +++ b/Marlin/src/inc/Conditionals-4-adv.h @@ -474,6 +474,12 @@ #define TEMP_SENSOR_1_IS_AD8495 1 #elif TEMP_SENSOR_1 == -1 #define TEMP_SENSOR_1_IS_AD595 1 +#elif TEMP_SENSOR_1 == -18 + #warning "Config is TEMP_SENSOR_1 == -18" + #define HAS_ADS1118 1 + #define TEMP_SENSOR_1_IS_ADS1118 1 + #define TEMP_SENSOR_1_ADS_TMIN 0 + #define TEMP_SENSOR_1_ADS_TMAX 1024 #elif TEMP_SENSOR_1 > 0 #define TEMP_SENSOR_1_IS_THERMISTOR 1 #if TEMP_SENSOR_1 == 1000 diff --git a/Marlin/src/libs/adc/adc_ads1118.cpp b/Marlin/src/libs/adc/adc_ads1118.cpp index 9f2000e47b..6d309f47ec 100644 --- a/Marlin/src/libs/adc/adc_ads1118.cpp +++ b/Marlin/src/libs/adc/adc_ads1118.cpp @@ -140,7 +140,15 @@ uint16_t data = transfer16(0); digitalWrite(cs_pin, HIGH); return data; - } + } + + // Reads and writes ADS data + uint16_t ADS1118::readWriteData(uint16_t config) { + digitalWrite(cs_pin, LOW); + uint16_t data = transfer16(config); + digitalWrite(cs_pin, HIGH); + return data; + } // Reads and returns a single channel inmediately with delay (blocking) int16_t ADS1118::readChannel(uint8_t channel) { @@ -249,6 +257,16 @@ // ADS1118, global instance ADS1118 ads1118; + + #if ENABLED(TEMP_SENSOR_0_IS_ADS1118) + #warning "ThcK 0 is enabled" + ThermocoupleK thck_0; + #endif + + #if ENABLED(TEMP_SENSOR_1_IS_ADS1118) + #warning "ThcK 1 is enabled" + ThermocoupleK thck_1; + #endif void ThermocoupleK::init() {} diff --git a/Marlin/src/libs/adc/adc_ads1118.h b/Marlin/src/libs/adc/adc_ads1118.h index f567ee24cb..ad9c88254e 100644 --- a/Marlin/src/libs/adc/adc_ads1118.h +++ b/Marlin/src/libs/adc/adc_ads1118.h @@ -35,6 +35,70 @@ #define TEMP_SENSOR_ADS1118 -18 +// ADS config register bits and values: +// Bit 15: Single-shot conversion start +#define ADS_SS_NOP 0x0000 +#define ADS_SS_START 0x8000 +// Bits 14-12 Mux +#define INPUT_CHAN_0_1 0x0000 // *Default* +#define INPUT_CHAN_0_3 0x1000 +#define INPUT_CHAN_1_3 0x2000 +#define INPUT_CHAN_2_3 0x3000 +#define INPUT_CHAN_0_G 0x4000 +#define INPUT_CHAN_1_G 0x5000 +#define INPUT_CHAN_2_G 0x6000 +#define INPUT_CHAN_3_G 0x7000 + + +/// Bits 11-9 ADC PGA gain select bits +/// the gain setting sets the voltage range for the ADC. Full Scale Range +/// voltage is the read value at 0x7FFF (the ADC returns a 16bit integer integer value) +/// we use the highest possible gain setting - k-Type thermocouples have a voltage +/// difference of ~12mV at 300C +#define PGA_0_6_14 0x0000 // Gain = 1, Full Scale Voltage is 6.14V +#define PGA_1_4_09 0x0200 // Gain = 1.5, Full Scale Voltage is 4.09V +#define PGA_2_2_04 0x0400 // Gain = 3, Full Scale Voltage is 2.04V *Default* +#define PGA_3_1_02 0x0600 // Gain = 6, Full Scale Voltage is 1.02V +#define PGA_4_0_512 0x0800 // Gain = 12, Full Scale Voltage is 0.512V +#define PGA_5_0_256 0x0A00 // Gain = 24, Full Scale Voltage is 0.256V + +/// Bit 8: operating mode: single sample or continous conversion +#define CONTINUOUS_CONVERSION_MODE 0x0000 // continous conversion +#define SINGLE_SHOT_MODE 0x0100 // single sample + +/// Bit 7-5: Data Rate, Sample Frequency select bits (Hz) +#define SAMPLE_FREQ_860 0x00E0 +#define SAMPLE_FREQ_475 0x00C0 +#define SAMPLE_FREQ_250 0x00A0 +#define SAMPLE_FREQ_128 0x0080 //* default +#define SAMPLE_FREQ_64 0x0060 +#define SAMPLE_FREQ_32 0x0040 +#define SAMPLE_FREQ_16 0x0020 +#define SAMPLE_FREQ_08 0x0000 + +/// Bit 4: ADC mode (thermocouples) vs temperature sensor (on-board cold_junction temp sensor) +#define ADC_MODE 0x0000 +#define TEMP_MODE 0x0010 + +/// Bit 3: Pull up enable +#define PULL_UP_DISABLE 0x0000 +#define PULL_UP_ENABLE 0x0008 + +/// write new data to the config register ( if bits <2:1> are not <01> the config bytes are ignored) +#define ADS_NOP 0x0000 +#define WRITE_CONFIG 0x0002 + +/// number of read cycles between cold junction temperature reads +/// we don't need to read the cold junction temperature every cycle +/// because we don't expect it to change much +#define TEMP_CHECK_COUNT 120 + +#define THERM_CHANNEL_ONE 0 +#define THERM_CHANNEL_TWO 1 +#define THERM_CHANNEL_HBP 2 +#define THERM_COLD_JUNCTION 3 + + typedef struct { int16_t adc; int16_t temp; @@ -78,6 +142,8 @@ #define TEMP_MAX_TEMP 300 #define TEMP_TABLE_OFFSET 0 // grados Celsius por índice + + class ADS1118 { public: static void init(uint8_t cs, uint8_t mosi, uint8_t miso, uint8_t sck); @@ -92,6 +158,9 @@ static uint16_t readData(); static int16_t readChannel(uint8_t channel); static uint16_t readConfig (); + + uint16_t config_ADC_SS_CH0 = ADS_SS_START | PGA_5_0_256 | SINGLE_SHOT_MODE| SAMPLE_FREQ_128 | ADC_MODE | PULL_UP_ENABLE | WRITE_CONFIG; + uint16_t config_SS_TEMP = ADS_SS_START | PGA_5_0_256 | SINGLE_SHOT_MODE | SAMPLE_FREQ_128 | TEMP_MODE | PULL_UP_ENABLE | WRITE_CONFIG; private: static void spiTransfer(uint8_t data, uint8_t &resp); diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index 817dba35ec..f8d9ad0a46 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -3065,9 +3065,13 @@ void Temperature::init() { // ADS TC related macros #if TEMP_SENSOR_IS_ADS(0, 1118) #warning "ADS1118 is selected for temp 0" - SERIAL_ECHOLNPGM("ADS1118 Entering to start continuous conv"); - ads1118.startContinuousConversion(0); - ads1118.readConfig(); + thck_0.init(); + SERIAL_ECHOLNPGM("ADS1118 Entering to start conv"); + thck_0.setTcold (ads1118.readInternalTemp()); + SERIAL_ECHOLNPGM("ADS1118 Tcold:"); + SERIAL_ECHOLNPGM(thck_0.getTcold()); + //ads1118.readConfig(); + #endif // Init (and disable) SPI thermocouples @@ -4000,11 +4004,17 @@ void Temperature::disable_all_heaters() { raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { #define ADS1118_HEAT_INTERVAL 250UL // 250 ms + static raw_adc_t ads1118_coldJ_temp_current[2] = { 0, 0 }; + static raw_adc_t ads1118_hotJ_temp_current[2] = { 0, 0 }; + static raw_adc_t ads1118_temp_previous[2] = { 0, 0 }; static uint8_t ads1118_errors[2] = { 0, 0 }; static millis_t next_ads1118_ms[2] = { 0, 0 }; static raw_adc_t ads_val = TEMP_SENSOR_0_ADS_TMAX; + + static uint8_t curr_state ; + static uint8_t prev_state ; const millis_t ms = millis(); @@ -4014,8 +4024,24 @@ raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { next_ads1118_ms[hindex] = ms + ADS1118_HEAT_INTERVAL; // To do: If there are more hotends enabled, cycle through different channels - uint16_t raw = ads1118.readData(); - SERIAL_ECHOPGM("ADS1118 Read: "); SERIAL_ECHOLN(raw); + uint16_t raw ; + if (curr_state == 0) + { + /* code */ + raw = ads1118.readWriteData(ads1118.config_ADC_SS_CH0); + prev_state = curr_state ; + curr_state = 1 ; + } + else + { + /* code */ + raw = ads1118.readWriteData(ads1118.config_ADC_SS_TEMP); + prev_state = curr_state ; + curr_state = 0 ; + } + + + SERIAL_ECHOPGM("ADS1118 State:Read "); SERIAL_ECHOPGM(curr_state); SERIAL_ECHOPGM(":"); SERIAL_ECHOLN(raw); // Manejo de errores simples: raw = 0x7FFF o 0x8000 podrían ser saturación if (raw == 0x7FFF || raw == -32768) { From 1bc6eacd49701e460ddcafb85391bd50c82cfa69 Mon Sep 17 00:00:00 2001 From: Axel Sepulveda Date: Sun, 16 Nov 2025 11:36:19 -0300 Subject: [PATCH 15/27] ADS1118 cycle readings and async convert --- Marlin/src/libs/adc/adc_ads1118.cpp | 43 +++++++--- Marlin/src/libs/adc/adc_ads1118.h | 22 ++++- Marlin/src/module/temperature.cpp | 120 +++++++++++++++++++++------- 3 files changed, 144 insertions(+), 41 deletions(-) diff --git a/Marlin/src/libs/adc/adc_ads1118.cpp b/Marlin/src/libs/adc/adc_ads1118.cpp index 6d309f47ec..6891ce1e9b 100644 --- a/Marlin/src/libs/adc/adc_ads1118.cpp +++ b/Marlin/src/libs/adc/adc_ads1118.cpp @@ -174,8 +174,15 @@ delay(10); int16_t raw = (int16_t)transfer16(config); - return (raw>>2) * 0.03125f; // 14 bit left aligned, 0.03125 °C per LSB as datasheet + return convertInternalTemp(raw) ; } + + // Converts raw internal temperature data to °C + float ADS1118::convertInternalTemp(int16_t data) { + + return (float) (data>>2) * 0.03125f; // 14 bit left aligned, 0.03125 °C per LSB as datasheet + } + uint16_t ADS1118::configChannel(uint8_t channel) { uint16_t config = 0; @@ -257,16 +264,18 @@ // ADS1118, global instance ADS1118 ads1118; + ThermocoupleK thck_0; + ThermocoupleK thck_1; - #if ENABLED(TEMP_SENSOR_0_IS_ADS1118) - #warning "ThcK 0 is enabled" - ThermocoupleK thck_0; - #endif + // #if ENABLED(TEMP_SENSOR_0_IS_ADS1118) + // #warning "ThcK 0 is enabled" + // ThermocoupleK thck_0; + // #endif - #if ENABLED(TEMP_SENSOR_1_IS_ADS1118) - #warning "ThcK 1 is enabled" - ThermocoupleK thck_1; - #endif + // #if ENABLED(TEMP_SENSOR_1_IS_ADS1118) + // #warning "ThcK 1 is enabled" + // ThermocoupleK thck_1; + // #endif void ThermocoupleK::init() {} @@ -301,6 +310,22 @@ float ThermocoupleK:: tempReadtoCelsius(int16_t rawADC) { return TEMP_MIN_TEMP; } +float ThermocoupleK:: calcTempCelsius() { + _Tcold = ads1118.convertInternalTemp(_raw_cold); + _Thot = tempReadtoCelsius(_raw_hot); + SERIAL_ECHOPGM("ADS1118 TCold "); SERIAL_ECHOLN(_Tcold); + SERIAL_ECHOPGM("ADS1118 THot "); SERIAL_ECHOLN(_Thot); + return _Thot + _Tcold; +} + + +void ThermocoupleK::setRawCold(int16_t raw_cold) { + _raw_cold = raw_cold; +} + +void ThermocoupleK::setRawHot(int16_t raw_hot) { + _raw_hot = raw_hot; +} void ThermocoupleK::setTcold(float tcold) { _Tcold = tcold; } diff --git a/Marlin/src/libs/adc/adc_ads1118.h b/Marlin/src/libs/adc/adc_ads1118.h index ad9c88254e..5d14621237 100644 --- a/Marlin/src/libs/adc/adc_ads1118.h +++ b/Marlin/src/libs/adc/adc_ads1118.h @@ -158,10 +158,18 @@ static uint16_t readData(); static int16_t readChannel(uint8_t channel); static uint16_t readConfig (); + static uint16_t readWriteData(uint16_t config); - uint16_t config_ADC_SS_CH0 = ADS_SS_START | PGA_5_0_256 | SINGLE_SHOT_MODE| SAMPLE_FREQ_128 | ADC_MODE | PULL_UP_ENABLE | WRITE_CONFIG; - uint16_t config_SS_TEMP = ADS_SS_START | PGA_5_0_256 | SINGLE_SHOT_MODE | SAMPLE_FREQ_128 | TEMP_MODE | PULL_UP_ENABLE | WRITE_CONFIG; + float convertInternalTemp(int16_t data); + float readInternalTemp(); + + + uint16_t config_ADC_SS_CH0 = ADS_SS_START | INPUT_CHAN_0_1| PGA_5_0_256 | SINGLE_SHOT_MODE| SAMPLE_FREQ_128 | ADC_MODE | PULL_UP_ENABLE | WRITE_CONFIG; + uint16_t config_ADC_SS_CH1 = ADS_SS_START | INPUT_CHAN_2_3 | PGA_5_0_256 | SINGLE_SHOT_MODE| SAMPLE_FREQ_128 | ADC_MODE | PULL_UP_ENABLE | WRITE_CONFIG; + uint16_t config_ADC_SS_TEMP = ADS_SS_START | PGA_5_0_256 | SINGLE_SHOT_MODE | SAMPLE_FREQ_128 | TEMP_MODE | PULL_UP_ENABLE | WRITE_CONFIG; + + private: static void spiTransfer(uint8_t data, uint8_t &resp); static void writeWord(uint16_t word); @@ -188,7 +196,7 @@ uint16_t configForChannel(uint8_t channel); static uint16_t configChannel(uint8_t channel); float readVoltage(uint8_t channel, float vref); - float readInternalTemp(); + }; @@ -198,8 +206,13 @@ public: void init(); float tempReadtoCelsius(int16_t rawADC); + float calcTempCelsius(); float getTempCelsius(); float _Tcold, _Thot; + int16_t _raw_cold, _raw_hot; + + void setRawCold(int16_t raw_cold); + void setRawHot(int16_t raw_hot); void setTcold(float tcold); float getTcold(); @@ -208,5 +221,8 @@ float getThot(); }; + extern ThermocoupleK thck_0; + extern ThermocoupleK thck_1; + #endif // ENABLED(HAS_ADS1118) \ No newline at end of file diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index f8d9ad0a46..42eeea2a8f 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -2631,8 +2631,23 @@ void Temperature::task() { // Each LSB bit ≈ 62.5 µV → ~1.5 °C (no calibration). // Adjustable with GAIN and OFFSET from Configuration_adv.h - static constexpr celsius_float_t temp_ads1118(const raw_adc_t raw) { - return raw * TEMP_SENSOR_ADS1118_GAIN + TEMP_SENSOR_ADS1118_OFFSET; + static constexpr celsius_float_t temp_ads1118(const uint8_t e) { + + celsius_float_t temp = 0 ; + + switch (e) { + case 0: + temp = thck_0.calcTempCelsius(); + SERIAL_ECHO("temp ads1118: "); SERIAL_ECHOLN(temp); + break; + case 1: + temp = thck_1.calcTempCelsius(); + break; + default: + temp = -14.0f; // Fallback to error temperature + break; + } + return temp ; } #endif @@ -2641,6 +2656,7 @@ void Temperature::task() { // Derived from RepRap FiveD extruder::getTemperature() // For hot end temperature measurement. celsius_float_t Temperature::analog_to_celsius_hotend(const raw_adc_t raw, const uint8_t e) { + //SERIAL_ECHOLN(e); if (e >= HOTENDS) { SERIAL_ERROR_START(); SERIAL_ECHO(e); @@ -2667,7 +2683,7 @@ void Temperature::task() { #elif TEMP_SENSOR_0_IS_AD8495 return temp_ad8495(raw); #elif TEMP_SENSOR_0_IS_ADS1118 - return temp_ads1118(raw); + return temp_ads1118(e); #else break; #endif @@ -2687,6 +2703,8 @@ void Temperature::task() { return temp_ad595(raw); #elif TEMP_SENSOR_1_IS_AD8495 return temp_ad8495(raw); + #elif TEMP_SENSOR_1_IS_ADS1118 + return temp_ads1118(e); #else break; #endif @@ -2939,16 +2957,29 @@ void Temperature::updateTemperaturesFromRawValues() { #endif // Read ADC ADS1118 + // Note: For ADS1118, we don't call setraw() because read_ads1118() returns int16_t + // (differential measurement can be negative) but raw_adc_t is uint16_t. + // Instead, the ThermocoupleK object (thck_0/thck_1) handles the conversion + // internally, and analog_to_celsius_hotend() will retrieve the computed + // temperature via thck_0.getThot(). This avoids type overflow and keeps + // the conversion logic centralized and ISR-light. #if TEMP_SENSOR_IS_ADS(0,1118) #warning "ADS1118 is selected for temp 0" - // SERIAL_ECHOLNPGM("ADS1118 Setting Raw hotend 0"); + temp_hotend[0].setraw(READ_ADS(0)); - SERIAL_ECHOPGM("ADS1118 Get Raw hotend 0: "); SERIAL_ECHOLN(temp_hotend[0].getraw()); + SERIAL_ECHOPGM("ADS1118 Tcold="); + SERIAL_ECHO(thck_0.getTcold()); + SERIAL_ECHOPGM(" Thot="); + SERIAL_ECHOLN(thck_0.getThot()); #endif #if TEMP_SENSOR_IS_ADS(1,1118) #warning "ADS1118 is selected for temp 1" - SERIAL_ECHOLNPGM("ADS1118 Setting Raw hotend 1"); + temp_hotend[1].setraw(READ_ADS(1)); + SERIAL_ECHOPGM("ADS1118 Tcold="); + SERIAL_ECHO(thck_1.getTcold()); + SERIAL_ECHOPGM(" Thot="); + SERIAL_ECHOLN(thck_1.getThot()); #endif #if HAS_HOTEND @@ -3069,7 +3100,7 @@ void Temperature::init() { SERIAL_ECHOLNPGM("ADS1118 Entering to start conv"); thck_0.setTcold (ads1118.readInternalTemp()); SERIAL_ECHOLNPGM("ADS1118 Tcold:"); - SERIAL_ECHOLNPGM(thck_0.getTcold()); + SERIAL_ECHOLN(thck_0.getTcold()); //ads1118.readConfig(); #endif @@ -4013,38 +4044,65 @@ raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { static raw_adc_t ads_val = TEMP_SENSOR_0_ADS_TMAX; - static uint8_t curr_state ; - static uint8_t prev_state ; - + static uint16_t curr_state ; + static uint16_t prev_state ; + + static uint8_t sampleCount ; + + static millis_t lastmillis ; const millis_t ms = millis(); - if (PENDING(ms, next_ads1118_ms[hindex]) || !ads1118.checkDataReady()) + SERIAL_ECHOPGM("ADS1118 elapsed: "); SERIAL_ECHOLN(ms- lastmillis); + lastmillis = ms ; + if (PENDING(ms, next_ads1118_ms[hindex]) ) // || !ads1118.checkDataReady() return ads1118_temp_previous[hindex]; // return cached value next_ads1118_ms[hindex] = ms + ADS1118_HEAT_INTERVAL; // To do: If there are more hotends enabled, cycle through different channels - uint16_t raw ; - if (curr_state == 0) + int16_t raw ; + + if (sampleCount < 1) { - /* code */ - raw = ads1118.readWriteData(ads1118.config_ADC_SS_CH0); prev_state = curr_state ; - curr_state = 1 ; + curr_state = ads1118.config_ADC_SS_TEMP ; + sampleCount++ ; } - else + else if (hindex == 0) { - /* code */ - raw = ads1118.readWriteData(ads1118.config_ADC_SS_TEMP); prev_state = curr_state ; - curr_state = 0 ; + curr_state = ads1118.config_ADC_SS_CH0 ; + sampleCount = 0 ; + } else if (hindex == 1){ + prev_state = curr_state ; + curr_state = ads1118.config_ADC_SS_CH1 ; + sampleCount = 0 ; + } + + raw = (int16_t) ads1118.readWriteData(curr_state); + + if (prev_state == ads1118.config_ADC_SS_TEMP) + { + //thck_0.setTcold(ads1118.convertInternalTemp(raw)); + thck_0.setRawCold(raw); + SERIAL_ECHOPGM("Last read Raw cold: "); SERIAL_ECHOLN(raw); + //SERIAL_ECHOPGM("TCold "); SERIAL_ECHOLN(thck_0.getTcold()); + + } + else if (prev_state == ads1118.config_ADC_SS_CH0) + { + //ads1118_hotJ_temp_current[hindex] = raw ; + //thck_0.setThot(thck_0.tempReadtoCelsius(raw)); + thck_0.setRawHot(raw); + SERIAL_ECHOPGM("Last read Raw hot"); SERIAL_ECHOLN(raw); + //SERIAL_ECHOPGM("ADS1118 THot "); SERIAL_ECHOLN(thck_0.getThot()); } - SERIAL_ECHOPGM("ADS1118 State:Read "); SERIAL_ECHOPGM(curr_state); SERIAL_ECHOPGM(":"); SERIAL_ECHOLN(raw); + // SERIAL_ECHOPGM("ADS1118 State:Read "); SERIAL_ECHOLN(curr_state); SERIAL_ECHOPGM(":"); SERIAL_ECHOLN(raw); - // Manejo de errores simples: raw = 0x7FFF o 0x8000 podrían ser saturación - if (raw == 0x7FFF || raw == -32768) { + // Handle read error or disconnection : raw = 0x7FFF or 0x8000 + if (raw == 0x7FFF || raw == 0x8000) { ads1118_errors[hindex]++; if (ads1118_errors[hindex] > 3) { SERIAL_ERROR_START(); @@ -4052,15 +4110,19 @@ raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { ads_val = (raw_adc_t)(TEMP_SENSOR_0_ADS_TMAX << 4); // force error } } - else { + else if (raw < 32767){ ads1118_errors[hindex] = 0; // reset errors if ok - // Convertir raw a formato fijo (ejemplo: 1/16 °C si es termocupla) - ads_val = (raw_adc_t) raw; // raw; // Fijo temporalmente + ads_val = (raw_adc_t) (((int16_t)raw) + 32768); // raw shift to unsigned int; + } else { // if we add 32767 to raw it will overflow + ads1118_errors[hindex] = 0; // reset errors if ok + SERIAL_ECHOLNPGM("ADS1118 Warn: Cannot shift adc read from signed to unsigned!"); + ads_val = (raw_adc_t) (raw); // as is ; } + //ads_val = (raw_adc_t) 3000; // raw; - ads1118_temp_previous[hindex] = ads_val; - - return ads_val; + ads1118_temp_previous[hindex] = ads_val; // not necessary + SERIAL_ECHOPGM("ADS1118 ads_val: "); SERIAL_ECHOLN(ads_val); + return ads_val; // return the raw value, it will not be used directly for conversion but for errors, (raw values are stored in thermocouple class) } #endif // ENABLED(HAS_ADS1118) From 249020d171589f209270eaae6622eca34b6d3813 Mon Sep 17 00:00:00 2001 From: Axel Sepulveda Date: Sun, 16 Nov 2025 11:45:36 -0300 Subject: [PATCH 16/27] disable comments --- Marlin/src/libs/adc/adc_ads1118.cpp | 4 ++-- Marlin/src/module/temperature.cpp | 26 +++++++++++++------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Marlin/src/libs/adc/adc_ads1118.cpp b/Marlin/src/libs/adc/adc_ads1118.cpp index 6891ce1e9b..06e6343a49 100644 --- a/Marlin/src/libs/adc/adc_ads1118.cpp +++ b/Marlin/src/libs/adc/adc_ads1118.cpp @@ -313,8 +313,8 @@ float ThermocoupleK:: tempReadtoCelsius(int16_t rawADC) { float ThermocoupleK:: calcTempCelsius() { _Tcold = ads1118.convertInternalTemp(_raw_cold); _Thot = tempReadtoCelsius(_raw_hot); - SERIAL_ECHOPGM("ADS1118 TCold "); SERIAL_ECHOLN(_Tcold); - SERIAL_ECHOPGM("ADS1118 THot "); SERIAL_ECHOLN(_Thot); + //SERIAL_ECHOPGM("ADS1118 TCold "); SERIAL_ECHOLN(_Tcold); + //SERIAL_ECHOPGM("ADS1118 THot "); SERIAL_ECHOLN(_Thot); return _Thot + _Tcold; } diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index 42eeea2a8f..2303d7e73c 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -2638,7 +2638,7 @@ void Temperature::task() { switch (e) { case 0: temp = thck_0.calcTempCelsius(); - SERIAL_ECHO("temp ads1118: "); SERIAL_ECHOLN(temp); + //SERIAL_ECHO("temp ads1118: "); SERIAL_ECHOLN(temp); break; case 1: temp = thck_1.calcTempCelsius(); @@ -2967,19 +2967,19 @@ void Temperature::updateTemperaturesFromRawValues() { #warning "ADS1118 is selected for temp 0" temp_hotend[0].setraw(READ_ADS(0)); - SERIAL_ECHOPGM("ADS1118 Tcold="); - SERIAL_ECHO(thck_0.getTcold()); - SERIAL_ECHOPGM(" Thot="); - SERIAL_ECHOLN(thck_0.getThot()); + // SERIAL_ECHOPGM("ADS1118 Tcold="); + // SERIAL_ECHO(thck_0.getTcold()); + // SERIAL_ECHOPGM(" Thot="); + // SERIAL_ECHOLN(thck_0.getThot()); #endif #if TEMP_SENSOR_IS_ADS(1,1118) #warning "ADS1118 is selected for temp 1" temp_hotend[1].setraw(READ_ADS(1)); - SERIAL_ECHOPGM("ADS1118 Tcold="); - SERIAL_ECHO(thck_1.getTcold()); - SERIAL_ECHOPGM(" Thot="); - SERIAL_ECHOLN(thck_1.getThot()); + // SERIAL_ECHOPGM("ADS1118 Tcold="); + // SERIAL_ECHO(thck_1.getTcold()); + // SERIAL_ECHOPGM(" Thot="); + // SERIAL_ECHOLN(thck_1.getThot()); #endif #if HAS_HOTEND @@ -4052,7 +4052,7 @@ raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { static millis_t lastmillis ; const millis_t ms = millis(); - SERIAL_ECHOPGM("ADS1118 elapsed: "); SERIAL_ECHOLN(ms- lastmillis); + //SERIAL_ECHOPGM("ADS1118 elapsed: "); SERIAL_ECHOLN(ms- lastmillis); lastmillis = ms ; if (PENDING(ms, next_ads1118_ms[hindex]) ) // || !ads1118.checkDataReady() return ads1118_temp_previous[hindex]; // return cached value @@ -4085,7 +4085,7 @@ raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { { //thck_0.setTcold(ads1118.convertInternalTemp(raw)); thck_0.setRawCold(raw); - SERIAL_ECHOPGM("Last read Raw cold: "); SERIAL_ECHOLN(raw); + //SERIAL_ECHOPGM("Last read Raw cold: "); SERIAL_ECHOLN(raw); //SERIAL_ECHOPGM("TCold "); SERIAL_ECHOLN(thck_0.getTcold()); } @@ -4094,7 +4094,7 @@ raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { //ads1118_hotJ_temp_current[hindex] = raw ; //thck_0.setThot(thck_0.tempReadtoCelsius(raw)); thck_0.setRawHot(raw); - SERIAL_ECHOPGM("Last read Raw hot"); SERIAL_ECHOLN(raw); + //SERIAL_ECHOPGM("Last read Raw hot"); SERIAL_ECHOLN(raw); //SERIAL_ECHOPGM("ADS1118 THot "); SERIAL_ECHOLN(thck_0.getThot()); } @@ -4121,7 +4121,7 @@ raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { //ads_val = (raw_adc_t) 3000; // raw; ads1118_temp_previous[hindex] = ads_val; // not necessary - SERIAL_ECHOPGM("ADS1118 ads_val: "); SERIAL_ECHOLN(ads_val); + //SERIAL_ECHOPGM("ADS1118 ads_val: "); SERIAL_ECHOLN(ads_val); return ads_val; // return the raw value, it will not be used directly for conversion but for errors, (raw values are stored in thermocouple class) } #endif // ENABLED(HAS_ADS1118) From 4ddc6c93eb549b5bbdda6a326be165754ae5e50b Mon Sep 17 00:00:00 2001 From: Axel Sepulveda Date: Sun, 16 Nov 2025 11:48:20 -0300 Subject: [PATCH 17/27] comment unused --- Marlin/src/module/temperature.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index 2303d7e73c..aa85010b9d 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -4035,8 +4035,8 @@ void Temperature::disable_all_heaters() { raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { #define ADS1118_HEAT_INTERVAL 250UL // 250 ms - static raw_adc_t ads1118_coldJ_temp_current[2] = { 0, 0 }; - static raw_adc_t ads1118_hotJ_temp_current[2] = { 0, 0 }; + //static raw_adc_t ads1118_coldJ_temp_current[2] = { 0, 0 }; + //static raw_adc_t ads1118_hotJ_temp_current[2] = { 0, 0 }; static raw_adc_t ads1118_temp_previous[2] = { 0, 0 }; static uint8_t ads1118_errors[2] = { 0, 0 }; @@ -4049,7 +4049,7 @@ raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { static uint8_t sampleCount ; - static millis_t lastmillis ; + //static millis_t lastmillis ; const millis_t ms = millis(); //SERIAL_ECHOPGM("ADS1118 elapsed: "); SERIAL_ECHOLN(ms- lastmillis); @@ -4101,8 +4101,8 @@ raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { // SERIAL_ECHOPGM("ADS1118 State:Read "); SERIAL_ECHOLN(curr_state); SERIAL_ECHOPGM(":"); SERIAL_ECHOLN(raw); - // Handle read error or disconnection : raw = 0x7FFF or 0x8000 - if (raw == 0x7FFF || raw == 0x8000) { + // Handle read error or disconnection : raw = 0x7FFF or 0x8000 (-32768) + if (raw == 0x7FFF || raw == -32768) { ads1118_errors[hindex]++; if (ads1118_errors[hindex] > 3) { SERIAL_ERROR_START(); @@ -4120,7 +4120,7 @@ raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { } //ads_val = (raw_adc_t) 3000; // raw; - ads1118_temp_previous[hindex] = ads_val; // not necessary + ads1118_temp_previous[hindex] = ads_val; // cache value //SERIAL_ECHOPGM("ADS1118 ads_val: "); SERIAL_ECHOLN(ads_val); return ads_val; // return the raw value, it will not be used directly for conversion but for errors, (raw values are stored in thermocouple class) } From 3defdf1024d6b5c50388d25caafbe73ba69d1dd9 Mon Sep 17 00:00:00 2001 From: Axel Sepulveda Date: Sun, 16 Nov 2025 12:11:32 -0300 Subject: [PATCH 18/27] comment last milllis debug --- Marlin/src/module/temperature.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index aa85010b9d..9dd47de7d3 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -4053,7 +4053,7 @@ raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { const millis_t ms = millis(); //SERIAL_ECHOPGM("ADS1118 elapsed: "); SERIAL_ECHOLN(ms- lastmillis); - lastmillis = ms ; + //lastmillis = ms ; if (PENDING(ms, next_ads1118_ms[hindex]) ) // || !ads1118.checkDataReady() return ads1118_temp_previous[hindex]; // return cached value From 7ecb4a5a99931456c129c54cbaa41c4d543b0213 Mon Sep 17 00:00:00 2001 From: Axel Sepulveda Date: Mon, 17 Nov 2025 00:30:47 -0300 Subject: [PATCH 19/27] fix internal temp reading, temperature direction, max range, disable serial debugs --- Marlin/src/libs/adc/adc_ads1118.cpp | 11 +++++++--- Marlin/src/libs/adc/adc_ads1118.h | 5 ++++- Marlin/src/module/temperature.cpp | 34 ++++++++++++++--------------- 3 files changed, 29 insertions(+), 21 deletions(-) diff --git a/Marlin/src/libs/adc/adc_ads1118.cpp b/Marlin/src/libs/adc/adc_ads1118.cpp index 06e6343a49..74ba908d24 100644 --- a/Marlin/src/libs/adc/adc_ads1118.cpp +++ b/Marlin/src/libs/adc/adc_ads1118.cpp @@ -168,12 +168,14 @@ } float ADS1118::readInternalTemp() { - uint16_t config = 0x8F80; // Config internal temp read & start SS conversion + uint16_t config = config_ADC_SS_TEMP; // Config internal temp read 0x8F80; // Config internal temp read & start SS conversion + select(); transfer16(config); - + deselect(); delay(10); - + select(); int16_t raw = (int16_t)transfer16(config); + deselect(); return convertInternalTemp(raw) ; } @@ -259,6 +261,9 @@ unsigned long ADS1118::startTime = 0; int16_t ADS1118::lastValue = 0; int16_t ADS1118::config = 0; + uint16_t ADS1118::current_config = 0; + uint16_t ADS1118::previous_config = 0; + bool ADS1118::isBusy = false; uint8_t ADS1118::currentchannel = 0; diff --git a/Marlin/src/libs/adc/adc_ads1118.h b/Marlin/src/libs/adc/adc_ads1118.h index 5d14621237..7ac4b934b9 100644 --- a/Marlin/src/libs/adc/adc_ads1118.h +++ b/Marlin/src/libs/adc/adc_ads1118.h @@ -167,7 +167,9 @@ uint16_t config_ADC_SS_CH0 = ADS_SS_START | INPUT_CHAN_0_1| PGA_5_0_256 | SINGLE_SHOT_MODE| SAMPLE_FREQ_128 | ADC_MODE | PULL_UP_ENABLE | WRITE_CONFIG; uint16_t config_ADC_SS_CH1 = ADS_SS_START | INPUT_CHAN_2_3 | PGA_5_0_256 | SINGLE_SHOT_MODE| SAMPLE_FREQ_128 | ADC_MODE | PULL_UP_ENABLE | WRITE_CONFIG; uint16_t config_ADC_SS_TEMP = ADS_SS_START | PGA_5_0_256 | SINGLE_SHOT_MODE | SAMPLE_FREQ_128 | TEMP_MODE | PULL_UP_ENABLE | WRITE_CONFIG; - + + static uint16_t current_config ; + static uint16_t previous_config ; private: @@ -190,6 +192,7 @@ static unsigned long startTime; static int16_t lastValue; static int16_t config; + static bool isBusy; static uint8_t currentchannel; diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index 9dd47de7d3..fbcd51cb5b 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -2998,7 +2998,7 @@ void Temperature::updateTemperaturesFromRawValues() { TERN_(HAS_POWER_MONITOR, power_monitor.capture_values()); #if HAS_HOTEND - #define _TEMPDIR(N) TEMP_SENSOR_IS_ANY_MAX_TC(N) ? 0 : TEMPDIR(N), + #define _TEMPDIR(N) (TEMP_SENSOR_IS_ANY_MAX_TC(N) || TEMP_SENSOR_IS_ADS (N,1118) ) ? 0 : TEMPDIR(N), static constexpr int8_t temp_dir[HOTENDS] = { REPEAT(HOTENDS, _TEMPDIR) }; HOTEND_LOOP() { @@ -3097,10 +3097,13 @@ void Temperature::init() { #if TEMP_SENSOR_IS_ADS(0, 1118) #warning "ADS1118 is selected for temp 0" thck_0.init(); - SERIAL_ECHOLNPGM("ADS1118 Entering to start conv"); + //SERIAL_ECHOLNPGM("ADS1118 start initial conversion for Tcold..."); thck_0.setTcold (ads1118.readInternalTemp()); - SERIAL_ECHOLNPGM("ADS1118 Tcold:"); - SERIAL_ECHOLN(thck_0.getTcold()); + + ads1118.current_config = ads1118.config_ADC_SS_TEMP; + ads1118.previous_config = ads1118.current_config; + //SERIAL_ECHOPGM("ADS1118 Tcold: "); + //SERIAL_ECHOLN(thck_0.getTcold()); //ads1118.readConfig(); #endif @@ -4044,9 +4047,6 @@ raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { static raw_adc_t ads_val = TEMP_SENSOR_0_ADS_TMAX; - static uint16_t curr_state ; - static uint16_t prev_state ; - static uint8_t sampleCount ; //static millis_t lastmillis ; @@ -4064,24 +4064,24 @@ raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { if (sampleCount < 1) { - prev_state = curr_state ; - curr_state = ads1118.config_ADC_SS_TEMP ; + ads1118.previous_config = ads1118.current_config ; + ads1118.current_config = ads1118.config_ADC_SS_TEMP ; sampleCount++ ; } else if (hindex == 0) { - prev_state = curr_state ; - curr_state = ads1118.config_ADC_SS_CH0 ; + ads1118.previous_config = ads1118.current_config ; + ads1118.current_config = ads1118.config_ADC_SS_CH0 ; sampleCount = 0 ; } else if (hindex == 1){ - prev_state = curr_state ; - curr_state = ads1118.config_ADC_SS_CH1 ; + ads1118.previous_config = ads1118.current_config ; + ads1118.current_config = ads1118.config_ADC_SS_CH1 ; sampleCount = 0 ; } - raw = (int16_t) ads1118.readWriteData(curr_state); + raw = (int16_t) ads1118.readWriteData(ads1118.current_config); - if (prev_state == ads1118.config_ADC_SS_TEMP) + if (ads1118.previous_config == ads1118.config_ADC_SS_TEMP) { //thck_0.setTcold(ads1118.convertInternalTemp(raw)); thck_0.setRawCold(raw); @@ -4089,12 +4089,12 @@ raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { //SERIAL_ECHOPGM("TCold "); SERIAL_ECHOLN(thck_0.getTcold()); } - else if (prev_state == ads1118.config_ADC_SS_CH0) + else if (ads1118.previous_config == ads1118.config_ADC_SS_CH0) { //ads1118_hotJ_temp_current[hindex] = raw ; //thck_0.setThot(thck_0.tempReadtoCelsius(raw)); thck_0.setRawHot(raw); - //SERIAL_ECHOPGM("Last read Raw hot"); SERIAL_ECHOLN(raw); + //SERIAL_ECHOPGM("Last read Raw hot: "); SERIAL_ECHOLN(raw); //SERIAL_ECHOPGM("ADS1118 THot "); SERIAL_ECHOLN(thck_0.getThot()); } From 25ba4915b092e538d077e974d8aae6faeff97bea Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Mon, 17 Nov 2025 19:11:42 -0600 Subject: [PATCH 20/27] Clean up, format --- Marlin/src/inc/Conditionals-4-adv.h | 10 +- Marlin/src/inc/Warnings.cpp | 4 - Marlin/src/lcd/HD44780/marlinui_HD44780.cpp | 4 +- Marlin/src/libs/adc/adc_ads1118.cpp | 535 ++++++++++---------- Marlin/src/libs/adc/adc_ads1118.h | 216 ++++---- Marlin/src/module/temperature.cpp | 66 +-- 6 files changed, 399 insertions(+), 436 deletions(-) diff --git a/Marlin/src/inc/Conditionals-4-adv.h b/Marlin/src/inc/Conditionals-4-adv.h index 4f5002be53..0af64e8c2a 100644 --- a/Marlin/src/inc/Conditionals-4-adv.h +++ b/Marlin/src/inc/Conditionals-4-adv.h @@ -426,11 +426,10 @@ #elif TEMP_SENSOR_0 == -1 #define TEMP_SENSOR_0_IS_AD595 1 #elif TEMP_SENSOR_0 == -18 - #warning "Config is TEMP_SENSOR_0 == -18" #define HAS_ADS1118 1 - #define TEMP_SENSOR_0_IS_ADS1118 1 + #define TEMP_SENSOR_0_IS_ADS1118 1 #define TEMP_SENSOR_0_ADS_TMIN 0 - #define TEMP_SENSOR_0_ADS_TMAX 1024 + #define TEMP_SENSOR_0_ADS_TMAX 1024 #elif TEMP_SENSOR_0 > 0 #define TEMP_SENSOR_0_IS_THERMISTOR 1 #if TEMP_SENSOR_0 == 1000 @@ -475,11 +474,10 @@ #elif TEMP_SENSOR_1 == -1 #define TEMP_SENSOR_1_IS_AD595 1 #elif TEMP_SENSOR_1 == -18 - #warning "Config is TEMP_SENSOR_1 == -18" #define HAS_ADS1118 1 - #define TEMP_SENSOR_1_IS_ADS1118 1 + #define TEMP_SENSOR_1_IS_ADS1118 1 #define TEMP_SENSOR_1_ADS_TMIN 0 - #define TEMP_SENSOR_1_ADS_TMAX 1024 + #define TEMP_SENSOR_1_ADS_TMAX 1024 #elif TEMP_SENSOR_1 > 0 #define TEMP_SENSOR_1_IS_THERMISTOR 1 #if TEMP_SENSOR_1 == 1000 diff --git a/Marlin/src/inc/Warnings.cpp b/Marlin/src/inc/Warnings.cpp index 2a8e1995cf..1091e4f5fb 100644 --- a/Marlin/src/inc/Warnings.cpp +++ b/Marlin/src/inc/Warnings.cpp @@ -114,10 +114,6 @@ #warning "Warning! Don't use dummy thermistors (998/999) for final build!" #endif -#if ENABLED(HAS_ADS1118) - #warning "ADS1118 support is in development" -#endif - #if ANY_THERMISTOR_IS(-18) #warning "ADS1118 support (-18) is in development" #endif diff --git a/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp b/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp index a7507bd1e8..bbd0f5e0f8 100644 --- a/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp +++ b/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp @@ -452,11 +452,11 @@ bool MarlinUI::detected() { #if ENABLED(LCD_I2C_TYPE_MCP23017) // Reading these buttons is too slow for interrupt context // so they are read during LCD update in the main loop. - uint8_t slow_bits = lcd.readButtons() + uint8_t slow_bits = (lcd.readButtons() #if !BUTTON_EXISTS(ENC) << B_I2C_BTN_OFFSET #endif - ; + ); #if ENABLED(LCD_I2C_VIKI) if ((slow_bits & (B_MI | B_RI)) && PENDING(millis(), next_button_update_ms)) // LCD clicked slow_bits &= ~(B_MI | B_RI); // Disable LCD clicked buttons if screen is updated diff --git a/Marlin/src/libs/adc/adc_ads1118.cpp b/Marlin/src/libs/adc/adc_ads1118.cpp index 74ba908d24..c7387fc75b 100644 --- a/Marlin/src/libs/adc/adc_ads1118.cpp +++ b/Marlin/src/libs/adc/adc_ads1118.cpp @@ -1,6 +1,6 @@ /** * Marlin 3D Printer Firmware - * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * Copyright (c) 2025 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] * * Based on Sprinter and grbl. * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm @@ -25,330 +25,315 @@ * based in the sailfish code for ADS1118, ThermocoupleReader, TemperatureTable * For implementation details, please take a look at the datasheet: * https://www.ti.com/product/ADS1118 - * */ #include "../../inc/MarlinConfig.h" -#if ENABLED(HAS_ADS1118) - - #include "adc_ads1118.h" - - #include "../../HAL/shared/Delay.h" - #include "../../core/macros.h" - - #define ADS1118_CONV_MS 10 - #define ADS1118_CH_MASK 12 - - // Constructor - void ADS1118::init(uint8_t cs, uint8_t mosi, uint8_t miso, uint8_t sck) { - cs_pin = cs; mosi_pin = mosi; miso_pin = miso; sck_pin = sck; +#if HAS_ADS1118 -// #define TEMP_0_CS_PIN 79 // E6 -// #define TEMP_0_SCK_PIN 78 // E2 -// #define TEMP_0_MISO_PIN 80 // E7 -// #define TEMP_0_MOSI_PIN 84 // H2 +#include "adc_ads1118.h" - pinMode(cs_pin, OUTPUT); - pinMode(mosi_pin, OUTPUT); - pinMode(sck_pin, OUTPUT); - pinMode(miso_pin, INPUT); - - deselect(); - sckLow(); - - } - - // Sets ADS to start a single shot conversion, it will be read async when ready (after ADS1118_CONV_MS), non blocking - void ADS1118::startConversion(uint8_t pair) { - if (isBusy) return; - - uint16_t config = 0x858B; // 0b 1000 0101 1000 1011 : SS start, single-ended off, gain ±2.048V, single-shot mode, 128SPS, ADC mode, Pullup enable, Write config - switch (pair) { - case 0: config |= (0x0 << ADS1118_CH_MASK); currentchannel = 0; break; // AIN0-AIN1 - case 1: config |= (0x3 << ADS1118_CH_MASK); currentchannel = 1; break; // AIN2-AIN3 - default: config |= (0x0 << ADS1118_CH_MASK); currentchannel = 0; break; - } - - digitalWrite(cs_pin, LOW); - transfer16(config); - digitalWrite(cs_pin, HIGH); - - isBusy = true; - startTime = millis(); - } - - // Determine that a conversion is ready by its elapsed time, if true, reads data and stores in _lastValue - bool ADS1118::ready() { - if (!isBusy) return true; - if (millis() - startTime >= ADS1118_CONV_MS) { - uint16_t raw; - digitalWrite(cs_pin, LOW); - transfer16(raw); - digitalWrite(cs_pin, HIGH); - lastValue = (int16_t)raw; - isBusy = false; - } - return !isBusy; +#include "../../HAL/shared/Delay.h" +#include "../../core/macros.h" + +#define ADS1118_CONV_MS 10 +#define ADS1118_CH_MASK 12 + +// Constructor +void ADS1118::init(uint8_t cs, uint8_t mosi, uint8_t miso, uint8_t sck) { + cs_pin = cs; mosi_pin = mosi; miso_pin = miso; sck_pin = sck; + + //#define TEMP_0_CS_PIN 79 // E6 + //#define TEMP_0_SCK_PIN 78 // E2 + //#define TEMP_0_MISO_PIN 80 // E7 + //#define TEMP_0_MOSI_PIN 84 // H2 + + pinMode(cs_pin, OUTPUT); + pinMode(mosi_pin, OUTPUT); + pinMode(sck_pin, OUTPUT); + pinMode(miso_pin, INPUT); + + deselect(); + sckLow(); +} + +// Sets ADS to start a single shot conversion. It will be read async when ready (after ADS1118_CONV_MS), non blocking +void ADS1118::startConversion(const uint8_t pair) { + if (isBusy) return; + + uint16_t config = 0x858B; // 0b 1000 0101 1000 1011 : SS start, single-ended off, gain ±2.048V, single-shot mode, 128SPS, ADC mode, Pullup enable, Write config + switch (pair) { + case 0: config |= (0x0 << ADS1118_CH_MASK); currentchannel = 0; break; // AIN0-AIN1 + case 1: config |= (0x3 << ADS1118_CH_MASK); currentchannel = 1; break; // AIN2-AIN3 + default: config |= (0x0 << ADS1118_CH_MASK); currentchannel = 0; break; } - - int16_t ADS1118::read() { - return lastValue; + + digitalWrite(cs_pin, LOW); + transfer16(config); + digitalWrite(cs_pin, HIGH); + + isBusy = true; + startTime = millis(); +} + +// Determine that a conversion is ready by its elapsed time, if true, reads data and stores in _lastValue +bool ADS1118::ready() { + if (!isBusy) return true; + if (millis() - startTime >= ADS1118_CONV_MS) { + uint16_t raw; + digitalWrite(cs_pin, LOW); + transfer16(raw); + digitalWrite(cs_pin, HIGH); + lastValue = (int16_t)raw; + isBusy = false; } - - bool ADS1118::busy() { - return isBusy; - } - - void ADS1118::loop() { - ready(); // updates status and value - } - - // Sets ADS to start Continuous conversion mode - void ADS1118::startContinuousConversion(uint8_t channel_pair) { - SERIAL_ECHOLNPGM("ADS1118 Set to start conv"); - if (isBusy) return; - // 0x048B b 0000 0100 1000 1011 : SS start, single-ended off, gain ±2.048V, Continuous conversion mode, 128SPS, ADC mode, Pullup enable, Write config - // 0x049B: read internal temp - uint16_t config = 0x048B; - switch (channel_pair) { - case 0: config |= (0x0 << ADS1118_CH_MASK); currentchannel = 0; break; // AIN0-AIN1 - case 1: config |= (0x3 << ADS1118_CH_MASK); currentchannel = 1; break; // AIN2-AIN3 - default: config |= (0x0 << ADS1118_CH_MASK); currentchannel = 0; break; - } - - digitalWrite(cs_pin, LOW); - transfer16(config); - digitalWrite(cs_pin, HIGH); - - isBusy = true; - startTime = millis(); - SERIAL_ECHOLNPGM("ADS1118 Leaving start conv"); - } - - // Check if ADS has a complete conversion - bool ADS1118::checkDataReady() { - digitalWrite(cs_pin, LOW); - uint8_t isReady = !digitalRead(miso_pin); // Read MISO, is low when ready - digitalWrite(cs_pin, HIGH); - return isReady; - } + return !isBusy; +} - // Read ADS data - uint16_t ADS1118::readData() { - digitalWrite(cs_pin, LOW); - uint16_t data = transfer16(0); - digitalWrite(cs_pin, HIGH); - return data; - } - - // Reads and writes ADS data - uint16_t ADS1118::readWriteData(uint16_t config) { - digitalWrite(cs_pin, LOW); - uint16_t data = transfer16(config); - digitalWrite(cs_pin, HIGH); - return data; - } - - // Reads and returns a single channel inmediately with delay (blocking) - int16_t ADS1118::readChannel(uint8_t channel) { - uint16_t config = configChannel(channel); - transfer16(config); - - // ADS1118 takes ~8 ms to convert - delay(10); - - int16_t value = (int16_t)transfer16(config); - return value; - } - - float ADS1118::readVoltage(uint8_t channel, float vref) { - int16_t raw = readChannel(channel); - return (raw / 32768.0f) * vref; // scale 16 bits to voltage - } - - float ADS1118::readInternalTemp() { - uint16_t config = config_ADC_SS_TEMP; // Config internal temp read 0x8F80; // Config internal temp read & start SS conversion - select(); - transfer16(config); - deselect(); - delay(10); - select(); - int16_t raw = (int16_t)transfer16(config); - deselect(); - return convertInternalTemp(raw) ; - } +int16_t ADS1118::read() { return lastValue; } - // Converts raw internal temperature data to °C - float ADS1118::convertInternalTemp(int16_t data) { - - return (float) (data>>2) * 0.03125f; // 14 bit left aligned, 0.03125 °C per LSB as datasheet - } +bool ADS1118::busy() { return isBusy; } - - uint16_t ADS1118::configChannel(uint8_t channel) { - uint16_t config = 0; - - - // Config single-ended inputs PGA ±2.048V, SS mode, 128SPS no pull up - switch(channel) { - case 0: config = 0xC583; break; // 0b 1100 0101 1000 0011 Ch1 & start SS conversion - case 1: config = 0xD583; break; // 0b 1101 0101 1000 0011 Ch2 & start SS conversion - case 2: config = 0xE583; break; // 0b 1110 0101 1000 0011 Ch3 & start SS conversion - case 3: config = 0xF583; break; // 0b 1111 0101 1000 0011 Ch4 & start SS conversion - default: config = 0x8583; break; - } - - return config; - } - - uint32_t ADS1118::transfer32(uint16_t data) { - uint16_t result_prev, config_echo; +void ADS1118::loop() { ready(); } // updates status and value - result_prev = transfer16(data); // envía config, recibe resultado anterior - config_echo = transfer16(0x0000); // envía dummy, recibe eco de configuración +// Sets ADS to start Continuous conversion mode +void ADS1118::startContinuousConversion(const uint8_t channel_pair) { + SERIAL_ECHOLNPGM("ADS1118 Set to start conv"); + if (isBusy) return; + // 0x048B b 0000 0100 1000 1011 : SS start, single-ended off, gain ±2.048V, Continuous conversion mode, 128SPS, ADC mode, Pullup enable, Write config + // 0x049B: read internal temp + uint16_t config = 0x048B; + switch (channel_pair) { + case 0: config |= (0x0 << ADS1118_CH_MASK); currentchannel = 0; break; // AIN0-AIN1 + case 1: config |= (0x3 << ADS1118_CH_MASK); currentchannel = 1; break; // AIN2-AIN3 + default: config |= (0x0 << ADS1118_CH_MASK); currentchannel = 0; break; + } - // Combina ambos en un solo valor de 32 bits - return ((uint32_t)result_prev << 16) | config_echo; - } + digitalWrite(cs_pin, LOW); + transfer16(config); + digitalWrite(cs_pin, HIGH); - uint16_t ADS1118::readConfig() { - uint16_t config_echo; - select(); - transfer16(0x0000); // envía dummy 16 bits, ignore reply, config is in the next 16 bit transfer - config_echo = transfer16(0x0000); // envía dummy, recibe eco de configuración - SERIAL_ECHOPGM("ADS1118 Configuration: "); SERIAL_ECHOLN(config_echo); - deselect(); - return config_echo; - } + isBusy = true; + startTime = millis(); + SERIAL_ECHOLNPGM("ADS1118 Leaving start conv"); +} - uint16_t ADS1118::transfer16(uint16_t data) { - uint8_t high = transfer8((uint8_t)(data >> 8)); - uint8_t low = transfer8((uint8_t)(data & 0xFF)); - return (uint16_t)(high << 8) | low; - } - - uint8_t ADS1118::transfer8(uint8_t data) { - uint8_t recv = 0; - for (uint8_t i = 0; i < 8; i++) { - // Send MSB first - if (data & 0x80) digitalWrite(mosi_pin, HIGH); else digitalWrite(mosi_pin, LOW); - data <<= 1; - - sckHigh(); - DELAY_NS(100); // small delay for stability - - recv <<= 1; - if (digitalRead(miso_pin)) recv |= 0x01; - - sckLow(); - DELAY_NS(100); - } - return recv; - } - - void ADS1118::select() { digitalWrite(cs_pin, LOW); } - void ADS1118::deselect() { digitalWrite(cs_pin, HIGH); } - - void ADS1118::sckHigh() { digitalWrite(sck_pin, HIGH); } - void ADS1118::sckLow() { digitalWrite(sck_pin, LOW); } +// Check if ADS has a complete conversion +bool ADS1118::checkDataReady() { + digitalWrite(cs_pin, LOW); + const uint8_t isReady = !digitalRead(miso_pin); // Read MISO, is low when ready + digitalWrite(cs_pin, HIGH); + return isReady; +} - // Definiciones de variables estáticas - uint8_t ADS1118::cs_pin = 0; - uint8_t ADS1118::mosi_pin = 0; - uint8_t ADS1118::miso_pin = 0; - uint8_t ADS1118::sck_pin = 0; - unsigned long ADS1118::startTime = 0; - int16_t ADS1118::lastValue = 0; - int16_t ADS1118::config = 0; - uint16_t ADS1118::current_config = 0; - uint16_t ADS1118::previous_config = 0; +// Read ADS data +uint16_t ADS1118::readData() { + digitalWrite(cs_pin, LOW); + const uint16_t data = transfer16(0); + digitalWrite(cs_pin, HIGH); + return data; +} - bool ADS1118::isBusy = false; - uint8_t ADS1118::currentchannel = 0; - - // ADS1118, global instance - ADS1118 ads1118; - ThermocoupleK thck_0; - ThermocoupleK thck_1; +// Read and write ADS data +uint16_t ADS1118::readWriteData(const uint16_t config) { + digitalWrite(cs_pin, LOW); + const uint16_t data = transfer16(config); + digitalWrite(cs_pin, HIGH); + return data; +} - // #if ENABLED(TEMP_SENSOR_0_IS_ADS1118) - // #warning "ThcK 0 is enabled" - // ThermocoupleK thck_0; - // #endif +// Reads and returns a single channel inmediately with delay (blocking) +int16_t ADS1118::readChannel(const uint8_t channel) { + const uint16_t config = configChannel(channel); + transfer16(config); + + // ADS1118 takes ~8 ms to convert + delay(10); + + const int16_t value = (int16_t)transfer16(config); + return value; +} + +float ADS1118::readVoltage(const uint8_t channel, const float vref) { + const int16_t raw = readChannel(channel); + return (raw / 32768.0f) * vref; // scale 16 bits to voltage +} + +float ADS1118::readInternalTemp() { + const uint16_t config = config_ADC_SS_TEMP; // Config internal temp read 0x8F80; // Config internal temp read & start SS conversion + select(); + transfer16(config); + deselect(); + delay(10); + select(); + int16_t raw = (int16_t)transfer16(config); + deselect(); + return convertInternalTemp(raw); +} + +// Convert raw internal temperature data to °C +float ADS1118::convertInternalTemp(const int16_t data) { + return float(data >> 2) * 0.03125f; // 14 bit left aligned, 0.03125 °C per LSB as datasheet +} + +uint16_t ADS1118::configChannel(const uint8_t channel) { + uint16_t config = 0; + + // Config single-ended inputs PGA ±2.048V, SS mode, 128SPS no pull up + switch (channel) { + case 0: config = 0xC583; break; // 0b 1100 0101 1000 0011 Ch1 & start SS conversion + case 1: config = 0xD583; break; // 0b 1101 0101 1000 0011 Ch2 & start SS conversion + case 2: config = 0xE583; break; // 0b 1110 0101 1000 0011 Ch3 & start SS conversion + case 3: config = 0xF583; break; // 0b 1111 0101 1000 0011 Ch4 & start SS conversion + default: config = 0x8583; break; + } + + return config; +} + +uint32_t ADS1118::transfer32(uint16_t data) { + uint16_t result_prev = transfer16(data); // send config, receive previous result + uint16_t config_echo = transfer16(0x0000); // send dummy, receive echo of configuration + + // Combine both into a single 32-bit value + return ((uint32_t)result_prev << 16) | config_echo; +} + +uint16_t ADS1118::readConfig() { + uint16_t config_echo; + select(); + transfer16(0x0000); // send 16‑bit dummy, ignore reply; configuration is in the following 16‑bit transfer + config_echo = transfer16(0x0000); // send dummy, receive echo of configuration + SERIAL_ECHOPGM("ADS1118 Configuration: "); SERIAL_ECHOLN(config_echo); + deselect(); + return config_echo; +} + +uint16_t ADS1118::transfer16(uint16_t data) { + uint8_t high = transfer8((uint8_t)(data >> 8)); + uint8_t low = transfer8((uint8_t)(data & 0xFF)); + return (uint16_t)(high << 8) | low; +} + +uint8_t ADS1118::transfer8(uint8_t data) { + uint8_t recv = 0; + for (uint8_t i = 0; i < 8; i++) { + // Send MSB first + if (data & 0x80) digitalWrite(mosi_pin, HIGH); else digitalWrite(mosi_pin, LOW); + data <<= 1; + + sckHigh(); + DELAY_NS(100); // small delay for stability + + recv <<= 1; + if (digitalRead(miso_pin)) recv |= 0x01; + + sckLow(); + DELAY_NS(100); + } + return recv; +} + +void ADS1118::select() { digitalWrite(cs_pin, LOW); } +void ADS1118::deselect() { digitalWrite(cs_pin, HIGH); } + +void ADS1118::sckHigh() { digitalWrite(sck_pin, HIGH); } +void ADS1118::sckLow() { digitalWrite(sck_pin, LOW); } + +// Definiciones de variables estáticas +uint8_t ADS1118::cs_pin = 0; +uint8_t ADS1118::mosi_pin = 0; +uint8_t ADS1118::miso_pin = 0; +uint8_t ADS1118::sck_pin = 0; +unsigned long ADS1118::startTime = 0; +int16_t ADS1118::lastValue = 0; +int16_t ADS1118::config = 0; +uint16_t ADS1118::current_config = 0; +uint16_t ADS1118::previous_config = 0; + +bool ADS1118::isBusy = false; +uint8_t ADS1118::currentchannel = 0; + +// ADS1118, global instance +ADS1118 ads1118; +ThermocoupleK thck_0; +ThermocoupleK thck_1; + +//#if ENABLED(TEMP_SENSOR_0_IS_ADS1118) +// #warning "ThcK 0 is enabled" +// ThermocoupleK thck_0; +//#endif + +//#if ENABLED(TEMP_SENSOR_1_IS_ADS1118) +// #warning "ThcK 1 is enabled" +// ThermocoupleK thck_1; +//#endif - // #if ENABLED(TEMP_SENSOR_1_IS_ADS1118) - // #warning "ThcK 1 is enabled" - // ThermocoupleK thck_1; - // #endif - void ThermocoupleK::init() {} // --- Convierte lectura ADC a °C --- -float ThermocoupleK:: tempReadtoCelsius(int16_t rawADC) { - //Serial.println((int16_t)pgm_read_word(&ThermocoupleK_Lookup[TEMP_TABLE_SIZE - 1])); +float ThermocoupleK:: tempReadtoCelsius(const int16_t rawADC) { + //Serial.println((int16_t)pgm_read_word(&ThermocoupleK_Lookup[TEMP_TABLE_SIZE - 1])); - if (rawADC > (int16_t) pgm_read_word(&table_thermocouple_k[TEMP_TABLE_SIZE - 1].adc)) - return TEMP_MAX_TEMP; - if (rawADC < (int16_t) pgm_read_word(&table_thermocouple_k[0].adc)) - return TEMP_MIN_TEMP; + if (rawADC > (int16_t) pgm_read_word(&table_thermocouple_k[TEMP_TABLE_SIZE - 1].adc)) + return TEMP_MAX_TEMP; + if (rawADC < (int16_t) pgm_read_word(&table_thermocouple_k[0].adc)) + return TEMP_MIN_TEMP; - // Búsqueda lineal en la tabla (de menor a mayor valor ADC) - for (uint16_t i = 0; i < TEMP_TABLE_SIZE - 1; i++) { - - int16_t adc1 = pgm_read_word(&table_thermocouple_k[i].adc); - int16_t adc2 = pgm_read_word(&table_thermocouple_k[i + 1].adc); - // Serial.print(i); Serial.print(" "); Serial.print(adc1); Serial.print(" "); Serial.print(adc2); + // Búsqueda lineal en la tabla (de menor a mayor valor ADC) + for (uint16_t i = 0; i < TEMP_TABLE_SIZE - 1; i++) { - if (rawADC >= adc1 && rawADC < adc2) { // in beteen tableValue and nextValue - // Temperatura aproximada por interpolación lineal - //float frac = float(rawADC - adc2) / float(adc1 - adc2); - int16_t t1 = pgm_read_word(&table_thermocouple_k[i].temp); - int16_t t2 = pgm_read_word(&table_thermocouple_k[i+1].temp); - // Serial.print(" "); Serial.print(t1); Serial.print(" "); Serial.print(t2); - float tempC = t1 + (float) (rawADC - adc1) * (float(t2 - t1) / float(adc2 - adc1)) ; // TEMP_TABLE_OFFSET + i + frac; - return tempC; - } - // Serial.println(""); - } + int16_t adc1 = pgm_read_word(&table_thermocouple_k[i].adc); + int16_t adc2 = pgm_read_word(&table_thermocouple_k[i + 1].adc); + // Serial.print(i); Serial.print(" "); Serial.print(adc1); Serial.print(" "); Serial.print(adc2); - return TEMP_MIN_TEMP; + if (rawADC >= adc1 && rawADC < adc2) { // in-between tableValue and nextValue + // Approximate temperature via linear interpolation + //float frac = float(rawADC - adc2) / float(adc1 - adc2); + int16_t t1 = pgm_read_word(&table_thermocouple_k[i].temp); + int16_t t2 = pgm_read_word(&table_thermocouple_k[i+1].temp); + // Serial.print(" "); Serial.print(t1); Serial.print(" "); Serial.print(t2); + float tempC = t1 + (float) (rawADC - adc1) * (float(t2 - t1) / float(adc2 - adc1)); // TEMP_TABLE_OFFSET + i + frac; + return tempC; + } + // Serial.println(""); + } + + return TEMP_MIN_TEMP; } float ThermocoupleK:: calcTempCelsius() { _Tcold = ads1118.convertInternalTemp(_raw_cold); _Thot = tempReadtoCelsius(_raw_hot); - //SERIAL_ECHOPGM("ADS1118 TCold "); SERIAL_ECHOLN(_Tcold); - //SERIAL_ECHOPGM("ADS1118 THot "); SERIAL_ECHOLN(_Thot); + //SERIAL_ECHOPGM("ADS1118 TCold "); SERIAL_ECHOLN(_Tcold); + //SERIAL_ECHOPGM("ADS1118 THot "); SERIAL_ECHOLN(_Thot); return _Thot + _Tcold; } - -void ThermocoupleK::setRawCold(int16_t raw_cold) { +void ThermocoupleK::setRawCold(const int16_t raw_cold) { _raw_cold = raw_cold; -} +} -void ThermocoupleK::setRawHot(int16_t raw_hot) { +void ThermocoupleK::setRawHot(const int16_t raw_hot) { _raw_hot = raw_hot; -} -void ThermocoupleK::setTcold(float tcold) { +} +void ThermocoupleK::setTcold(const float tcold) { _Tcold = tcold; } float ThermocoupleK::getTcold() { - return _Tcold ; + return _Tcold; } -void ThermocoupleK::setThot(float thot) { +void ThermocoupleK::setThot(const float thot) { _Thot = thot; } float ThermocoupleK::getThot() { - return _Thot ; + return _Thot; } float ThermocoupleK:: getTempCelsius() { - return _Thot + _Tcold; } diff --git a/Marlin/src/libs/adc/adc_ads1118.h b/Marlin/src/libs/adc/adc_ads1118.h index 7ac4b934b9..e498aa387f 100644 --- a/Marlin/src/libs/adc/adc_ads1118.h +++ b/Marlin/src/libs/adc/adc_ads1118.h @@ -1,6 +1,6 @@ /** * Marlin 3D Printer Firmware - * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * Copyright (c) 2025 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] * * Based on Sprinter and grbl. * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm @@ -22,20 +22,16 @@ #pragma once /** - * Based on Arduino Library for Texas Instruments ADS1118 - 16-Bit Analog-to-Digital Converter with internal Reference and Temperature Sensor + * Based on Arduino Library for Texas Instruments ADS1118 - 16-Bit Analog-to-Digital Converter with internal Reference and Temperature Sensor * https://www.ti.com/product/ADS1118 * https://github.com/ADS1xxx-Series-ADC-Libraries/ADS1118 */ #include "../../inc/MarlinConfigPre.h" -#if ENABLED(HAS_ADS1118) +#define TEMP_SENSOR_ADS1118 -18 - #include - - #define TEMP_SENSOR_ADS1118 -18 - -// ADS config register bits and values: +// ADS config register bits and values: // Bit 15: Single-shot conversion start #define ADS_SS_NOP 0x0000 #define ADS_SS_START 0x8000 @@ -49,9 +45,8 @@ #define INPUT_CHAN_2_G 0x6000 #define INPUT_CHAN_3_G 0x7000 - /// Bits 11-9 ADC PGA gain select bits -/// the gain setting sets the voltage range for the ADC. Full Scale Range +/// the gain setting sets the voltage range for the ADC. Full Scale Range /// voltage is the read value at 0x7FFF (the ADC returns a 16bit integer integer value) /// we use the highest possible gain setting - k-Type thermocouples have a voltage /// difference of ~12mV at 300C @@ -69,8 +64,8 @@ /// Bit 7-5: Data Rate, Sample Frequency select bits (Hz) #define SAMPLE_FREQ_860 0x00E0 #define SAMPLE_FREQ_475 0x00C0 -#define SAMPLE_FREQ_250 0x00A0 -#define SAMPLE_FREQ_128 0x0080 //* default +#define SAMPLE_FREQ_250 0x00A0 +#define SAMPLE_FREQ_128 0x0080 //* default #define SAMPLE_FREQ_64 0x0060 #define SAMPLE_FREQ_32 0x0040 #define SAMPLE_FREQ_16 0x0020 @@ -88,7 +83,7 @@ #define ADS_NOP 0x0000 #define WRITE_CONFIG 0x0002 -/// number of read cycles between cold junction temperature reads +/// Number of read cycles between cold junction temperature reads /// we don't need to read the cold junction temperature every cycle /// because we don't expect it to change much #define TEMP_CHECK_COUNT 120 @@ -98,114 +93,104 @@ #define THERM_CHANNEL_HBP 2 #define THERM_COLD_JUNCTION 3 +typedef struct { + int16_t adc; + int16_t temp; +} ADC_Lookup; - typedef struct { - int16_t adc; - int16_t temp; - } ADC_Lookup; +const static ADC_Lookup table_thermocouple_k[] PROGMEM = { + { -304, -64}, + { -232, -48}, + { -157, -32}, + { -79, -16}, + { 0, 0}, + { 82, 16}, + { 164, 32}, + { 248, 48}, + { 333, 64}, + { 418, 80}, + { 503, 96}, + { 588, 112}, + { 672, 128}, + { 755, 144}, + { 837, 160}, + { 919, 176}, + { 1001, 192}, + { 1083, 208}, + { 1165, 224}, + { 1248, 240}, + { 1331, 256}, + { 1415, 272}, + { 1499, 288}, + { 1584, 304}, + { 1754, 336}, + { 1840, 352}, + { 1926, 368}, + { 2012, 384}, + { 2099, 400} +}; - const static ADC_Lookup PROGMEM table_thermocouple_k[] = { - { -304, -64}, - { -232, -48}, - { -157, -32}, - { -79, -16}, - { 0, 0}, - { 82, 16}, - { 164, 32}, - { 248, 48}, - { 333, 64}, - { 418, 80}, - { 503, 96}, - { 588, 112}, - { 672, 128}, - { 755, 144}, - { 837, 160}, - { 919, 176}, - { 1001, 192}, - { 1083, 208}, - { 1165, 224}, - { 1248, 240}, - { 1331, 256}, - { 1415, 272}, - { 1499, 288}, - { 1584, 304}, - { 1754, 336}, - { 1840, 352}, - { 1926, 368}, - { 2012, 384}, - { 2099, 400} +#define TEMP_TABLE_SIZE (sizeof(table_thermocouple_k) / sizeof(table_thermocouple_k[0])) +#define TEMP_MIN_TEMP 0 +#define TEMP_MAX_TEMP 300 +#define TEMP_TABLE_OFFSET 0 // grados Celsius por índice - }; +class ADS1118 { + public: + static void init(uint8_t cs, uint8_t mosi, uint8_t miso, uint8_t sck); + static void startConversion(const uint8_t pair); // start conversion + static bool ready(); // indicates whether it is already ready to be read + static int16_t read(); // read converted value + static bool busy(); // conversion status + static void loop(); // non‑blocking cycle - #define TEMP_TABLE_SIZE (sizeof(table_thermocouple_k) / sizeof(table_thermocouple_k[0])) - #define TEMP_MIN_TEMP 0 - #define TEMP_MAX_TEMP 300 - #define TEMP_TABLE_OFFSET 0 // grados Celsius por índice + static bool checkDataReady(); + static void startContinuousConversion(const uint8_t channel_pair); + static uint16_t readData(); + static int16_t readChannel(const uint8_t channel); + static uint16_t readConfig (); + static uint16_t readWriteData(const uint16_t config); + + float convertInternalTemp(const int16_t data); + float readInternalTemp(); + + uint16_t config_ADC_SS_CH0 = ADS_SS_START | INPUT_CHAN_0_1| PGA_5_0_256 | SINGLE_SHOT_MODE| SAMPLE_FREQ_128 | ADC_MODE | PULL_UP_ENABLE | WRITE_CONFIG; + uint16_t config_ADC_SS_CH1 = ADS_SS_START | INPUT_CHAN_2_3 | PGA_5_0_256 | SINGLE_SHOT_MODE| SAMPLE_FREQ_128 | ADC_MODE | PULL_UP_ENABLE | WRITE_CONFIG; + uint16_t config_ADC_SS_TEMP = ADS_SS_START | PGA_5_0_256 | SINGLE_SHOT_MODE | SAMPLE_FREQ_128 | TEMP_MODE | PULL_UP_ENABLE | WRITE_CONFIG; + + static uint16_t current_config; + static uint16_t previous_config; + + private: + static void spiTransfer(uint8_t data, uint8_t &resp); + static void writeWord(uint16_t word); + static void readWord(uint16_t &word); + + static uint32_t transfer32 (uint16_t data); + static uint16_t transfer16 (uint16_t data); + static uint8_t transfer8 (uint8_t data); + static void select(); + static void deselect(); - class ADS1118 { - public: - static void init(uint8_t cs, uint8_t mosi, uint8_t miso, uint8_t sck); - static void startConversion(uint8_t pair); // inicia conversión - static bool ready(); // indica si ya se puede leer - static int16_t read(); // lee valor convertido - static bool busy(); // estado de conversión - static void loop(); // ciclo no bloqueante + static void sckHigh(); + static void sckLow(); - static bool checkDataReady(); - static void startContinuousConversion(uint8_t channel_pair); - static uint16_t readData(); - static int16_t readChannel(uint8_t channel); - static uint16_t readConfig (); - static uint16_t readWriteData(uint16_t config); + static uint8_t cs_pin, mosi_pin, miso_pin, sck_pin; + static unsigned long startTime; + static int16_t lastValue; + static int16_t config; - float convertInternalTemp(int16_t data); - float readInternalTemp(); + static bool isBusy; + static uint8_t currentchannel; + //uint16_t configForChannel(const uint8_t channel); + static uint16_t configChannel(const uint8_t channel); + float readVoltage(const uint8_t channel, const float vref); +}; - uint16_t config_ADC_SS_CH0 = ADS_SS_START | INPUT_CHAN_0_1| PGA_5_0_256 | SINGLE_SHOT_MODE| SAMPLE_FREQ_128 | ADC_MODE | PULL_UP_ENABLE | WRITE_CONFIG; - uint16_t config_ADC_SS_CH1 = ADS_SS_START | INPUT_CHAN_2_3 | PGA_5_0_256 | SINGLE_SHOT_MODE| SAMPLE_FREQ_128 | ADC_MODE | PULL_UP_ENABLE | WRITE_CONFIG; - uint16_t config_ADC_SS_TEMP = ADS_SS_START | PGA_5_0_256 | SINGLE_SHOT_MODE | SAMPLE_FREQ_128 | TEMP_MODE | PULL_UP_ENABLE | WRITE_CONFIG; - - static uint16_t current_config ; - static uint16_t previous_config ; - - - private: - static void spiTransfer(uint8_t data, uint8_t &resp); - static void writeWord(uint16_t word); - static void readWord(uint16_t &word); - - static uint32_t transfer32 (uint16_t data); - static uint16_t transfer16 (uint16_t data); - static uint8_t transfer8 (uint8_t data); - - - static void select(); - static void deselect(); - - static void sckHigh(); - static void sckLow(); - - static uint8_t cs_pin, mosi_pin, miso_pin, sck_pin; - static unsigned long startTime; - static int16_t lastValue; - static int16_t config; - - static bool isBusy; - static uint8_t currentchannel; - - uint16_t configForChannel(uint8_t channel); - static uint16_t configChannel(uint8_t channel); - float readVoltage(uint8_t channel, float vref); - - - }; - - extern ADS1118 ads1118; - - class ThermocoupleK { +class ThermocoupleK { public: void init(); float tempReadtoCelsius(int16_t rawADC); @@ -215,17 +200,16 @@ int16_t _raw_cold, _raw_hot; void setRawCold(int16_t raw_cold); - void setRawHot(int16_t raw_hot); + void setRawHot(int16_t raw_hot); void setTcold(float tcold); float getTcold(); void setThot(float thot); - float getThot(); + float getThot(); }; - extern ThermocoupleK thck_0; - extern ThermocoupleK thck_1; +extern ADS1118 ads1118; - -#endif // ENABLED(HAS_ADS1118) \ No newline at end of file +extern ThermocoupleK thck_0; +extern ThermocoupleK thck_1; diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index fbcd51cb5b..2bacb700ce 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -211,7 +211,7 @@ #define TEMP_SENSOR_IS_ADS(n, M) (ENABLED(TEMP_SENSOR_##n##_IS_ADS##M) || (ENABLED(TEMP_SENSOR_REDUNDANT_IS_ADS##M) && REDUNDANT_TEMP_MATCH(SOURCE, E##n))) // ADS1118 -#if HAS_ADS1118 +#if HAS_ADS1118 #include "../libs/adc/adc_ads1118.h" #endif @@ -2632,13 +2632,13 @@ void Temperature::task() { // Adjustable with GAIN and OFFSET from Configuration_adv.h static constexpr celsius_float_t temp_ads1118(const uint8_t e) { - + celsius_float_t temp = 0 ; switch (e) { case 0: temp = thck_0.calcTempCelsius(); - //SERIAL_ECHO("temp ads1118: "); SERIAL_ECHOLN(temp); + //SERIAL_ECHO("temp ads1118: "); SERIAL_ECHOLN(temp); break; case 1: temp = thck_1.calcTempCelsius(); @@ -2683,7 +2683,7 @@ void Temperature::task() { #elif TEMP_SENSOR_0_IS_AD8495 return temp_ad8495(raw); #elif TEMP_SENSOR_0_IS_ADS1118 - return temp_ads1118(e); + return temp_ads1118(e); #else break; #endif @@ -2704,7 +2704,7 @@ void Temperature::task() { #elif TEMP_SENSOR_1_IS_AD8495 return temp_ad8495(raw); #elif TEMP_SENSOR_1_IS_ADS1118 - return temp_ads1118(e); + return temp_ads1118(e); #else break; #endif @@ -2965,22 +2965,22 @@ void Temperature::updateTemperaturesFromRawValues() { // the conversion logic centralized and ISR-light. #if TEMP_SENSOR_IS_ADS(0,1118) #warning "ADS1118 is selected for temp 0" - + temp_hotend[0].setraw(READ_ADS(0)); - // SERIAL_ECHOPGM("ADS1118 Tcold="); - // SERIAL_ECHO(thck_0.getTcold()); + // SERIAL_ECHOPGM("ADS1118 Tcold="); + // SERIAL_ECHO(thck_0.getTcold()); // SERIAL_ECHOPGM(" Thot="); // SERIAL_ECHOLN(thck_0.getThot()); - #endif + #endif #if TEMP_SENSOR_IS_ADS(1,1118) #warning "ADS1118 is selected for temp 1" - + temp_hotend[1].setraw(READ_ADS(1)); - // SERIAL_ECHOPGM("ADS1118 Tcold="); - // SERIAL_ECHO(thck_1.getTcold()); + // SERIAL_ECHOPGM("ADS1118 Tcold="); + // SERIAL_ECHO(thck_1.getTcold()); // SERIAL_ECHOPGM(" Thot="); // SERIAL_ECHOLN(thck_1.getThot()); - #endif + #endif #if HAS_HOTEND HOTEND_LOOP() temp_hotend[e].celsius = analog_to_celsius_hotend(temp_hotend[e].getraw(), e); @@ -3099,14 +3099,14 @@ void Temperature::init() { thck_0.init(); //SERIAL_ECHOLNPGM("ADS1118 start initial conversion for Tcold..."); thck_0.setTcold (ads1118.readInternalTemp()); - - ads1118.current_config = ads1118.config_ADC_SS_TEMP; - ads1118.previous_config = ads1118.current_config; + + ads1118.current_config = ads1118.config_ADC_SS_TEMP; + ads1118.previous_config = ads1118.current_config; //SERIAL_ECHOPGM("ADS1118 Tcold: "); //SERIAL_ECHOLN(thck_0.getTcold()); //ads1118.readConfig(); - - #endif + + #endif // Init (and disable) SPI thermocouples #if TEMP_SENSOR_IS_ANY_MAX_TC(0) && PIN_EXISTS(TEMP_0_CS) @@ -4024,7 +4024,7 @@ void Temperature::disable_all_heaters() { #endif // TEMP_SENSOR_IS_MAX_TC(BED) -#if ENABLED(HAS_ADS1118) +#if HAS_ADS1118 /** * @brief Read ADS Thermocouple temperature. * @@ -4037,13 +4037,13 @@ void Temperature::disable_all_heaters() { */ raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { #define ADS1118_HEAT_INTERVAL 250UL // 250 ms - + //static raw_adc_t ads1118_coldJ_temp_current[2] = { 0, 0 }; //static raw_adc_t ads1118_hotJ_temp_current[2] = { 0, 0 }; - static raw_adc_t ads1118_temp_previous[2] = { 0, 0 }; + static raw_adc_t ads1118_temp_previous[2] = { 0, 0 }; static uint8_t ads1118_errors[2] = { 0, 0 }; - static millis_t next_ads1118_ms[2] = { 0, 0 }; + static millis_t next_ads1118_ms[2] = { 0, 0 }; static raw_adc_t ads_val = TEMP_SENSOR_0_ADS_TMAX; @@ -4052,7 +4052,7 @@ raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { //static millis_t lastmillis ; const millis_t ms = millis(); - //SERIAL_ECHOPGM("ADS1118 elapsed: "); SERIAL_ECHOLN(ms- lastmillis); + //SERIAL_ECHOPGM("ADS1118 elapsed: "); SERIAL_ECHOLN(ms- lastmillis); //lastmillis = ms ; if (PENDING(ms, next_ads1118_ms[hindex]) ) // || !ads1118.checkDataReady() return ads1118_temp_previous[hindex]; // return cached value @@ -4065,7 +4065,7 @@ raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { if (sampleCount < 1) { ads1118.previous_config = ads1118.current_config ; - ads1118.current_config = ads1118.config_ADC_SS_TEMP ; + ads1118.current_config = ads1118.config_ADC_SS_TEMP ; sampleCount++ ; } else if (hindex == 0) @@ -4077,16 +4077,16 @@ raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { ads1118.previous_config = ads1118.current_config ; ads1118.current_config = ads1118.config_ADC_SS_CH1 ; sampleCount = 0 ; - } + } - raw = (int16_t) ads1118.readWriteData(ads1118.current_config); + raw = (int16_t) ads1118.readWriteData(ads1118.current_config); if (ads1118.previous_config == ads1118.config_ADC_SS_TEMP) { //thck_0.setTcold(ads1118.convertInternalTemp(raw)); thck_0.setRawCold(raw); - //SERIAL_ECHOPGM("Last read Raw cold: "); SERIAL_ECHOLN(raw); - //SERIAL_ECHOPGM("TCold "); SERIAL_ECHOLN(thck_0.getTcold()); + //SERIAL_ECHOPGM("Last read Raw cold: "); SERIAL_ECHOLN(raw); + //SERIAL_ECHOPGM("TCold "); SERIAL_ECHOLN(thck_0.getTcold()); } else if (ads1118.previous_config == ads1118.config_ADC_SS_CH0) @@ -4094,10 +4094,10 @@ raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { //ads1118_hotJ_temp_current[hindex] = raw ; //thck_0.setThot(thck_0.tempReadtoCelsius(raw)); thck_0.setRawHot(raw); - //SERIAL_ECHOPGM("Last read Raw hot: "); SERIAL_ECHOLN(raw); - //SERIAL_ECHOPGM("ADS1118 THot "); SERIAL_ECHOLN(thck_0.getThot()); + //SERIAL_ECHOPGM("Last read Raw hot: "); SERIAL_ECHOLN(raw); + //SERIAL_ECHOPGM("ADS1118 THot "); SERIAL_ECHOLN(thck_0.getThot()); } - + // SERIAL_ECHOPGM("ADS1118 State:Read "); SERIAL_ECHOLN(curr_state); SERIAL_ECHOPGM(":"); SERIAL_ECHOLN(raw); @@ -4123,8 +4123,8 @@ raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { ads1118_temp_previous[hindex] = ads_val; // cache value //SERIAL_ECHOPGM("ADS1118 ads_val: "); SERIAL_ECHOLN(ads_val); return ads_val; // return the raw value, it will not be used directly for conversion but for errors, (raw values are stored in thermocouple class) -} -#endif // ENABLED(HAS_ADS1118) +} +#endif // HAS_ADS1118 From 612e17d3c66e76b74fc48c98a5ea368b14dc67ec Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Mon, 17 Nov 2025 19:23:18 -0600 Subject: [PATCH 21/27] format --- Marlin/src/inc/Conditionals-4-adv.h | 4 +-- Marlin/src/libs/adc/adc_ads1118.cpp | 4 +-- Marlin/src/libs/adc/adc_ads1118.h | 2 -- Marlin/src/module/temperature.cpp | 50 ++++++++++++++--------------- 4 files changed, 28 insertions(+), 32 deletions(-) diff --git a/Marlin/src/inc/Conditionals-4-adv.h b/Marlin/src/inc/Conditionals-4-adv.h index 9394aec872..0f5f8ee186 100644 --- a/Marlin/src/inc/Conditionals-4-adv.h +++ b/Marlin/src/inc/Conditionals-4-adv.h @@ -433,7 +433,7 @@ #define TEMP_SENSOR_0_IS_AD595 1 #elif TEMP_SENSOR_0 == -18 #define HAS_ADS1118 1 - #define TEMP_SENSOR_0_IS_ADS1118 1 + #define TEMP_SENSOR_0_IS_ADS1118 1 #define TEMP_SENSOR_0_ADS_TMIN 0 #define TEMP_SENSOR_0_ADS_TMAX 1024 #elif TEMP_SENSOR_0 > 0 @@ -481,7 +481,7 @@ #define TEMP_SENSOR_1_IS_AD595 1 #elif TEMP_SENSOR_1 == -18 #define HAS_ADS1118 1 - #define TEMP_SENSOR_1_IS_ADS1118 1 + #define TEMP_SENSOR_1_IS_ADS1118 1 #define TEMP_SENSOR_1_ADS_TMIN 0 #define TEMP_SENSOR_1_ADS_TMAX 1024 #elif TEMP_SENSOR_1 > 0 diff --git a/Marlin/src/libs/adc/adc_ads1118.cpp b/Marlin/src/libs/adc/adc_ads1118.cpp index c7387fc75b..c8cd812fbf 100644 --- a/Marlin/src/libs/adc/adc_ads1118.cpp +++ b/Marlin/src/libs/adc/adc_ads1118.cpp @@ -259,12 +259,12 @@ ADS1118 ads1118; ThermocoupleK thck_0; ThermocoupleK thck_1; -//#if ENABLED(TEMP_SENSOR_0_IS_ADS1118) +//#if TEMP_SENSOR_0_IS_ADS1118 // #warning "ThcK 0 is enabled" // ThermocoupleK thck_0; //#endif -//#if ENABLED(TEMP_SENSOR_1_IS_ADS1118) +//#if TEMP_SENSOR_1_IS_ADS1118 // #warning "ThcK 1 is enabled" // ThermocoupleK thck_1; //#endif diff --git a/Marlin/src/libs/adc/adc_ads1118.h b/Marlin/src/libs/adc/adc_ads1118.h index e498aa387f..d8555db7a0 100644 --- a/Marlin/src/libs/adc/adc_ads1118.h +++ b/Marlin/src/libs/adc/adc_ads1118.h @@ -29,8 +29,6 @@ #include "../../inc/MarlinConfigPre.h" -#define TEMP_SENSOR_ADS1118 -18 - // ADS config register bits and values: // Bit 15: Single-shot conversion start #define ADS_SS_NOP 0x0000 diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index caa58f7912..ae2caa8843 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -2636,25 +2636,23 @@ void Temperature::task() { // Adjustable with GAIN and OFFSET from Configuration_adv.h static constexpr celsius_float_t temp_ads1118(const uint8_t e) { - - celsius_float_t temp = 0 ; - + celsius_float_t temp = 0; switch (e) { case 0: - temp = thck_0.calcTempCelsius(); - //SERIAL_ECHO("temp ads1118: "); SERIAL_ECHOLN(temp); - break; + temp = thck_0.calcTempCelsius(); + //SERIAL_ECHO("temp ads1118: "); SERIAL_ECHOLN(temp); + break; case 1: - temp = thck_1.calcTempCelsius(); - break; + temp = thck_1.calcTempCelsius(); + break; default: temp = -14.0f; // Fallback to error temperature break; } - return temp ; + return temp; } -#endif +#endif // ANY_THERMISTOR_IS(-18) #if HAS_HOTEND // Derived from RepRap FiveD extruder::getTemperature() @@ -4051,36 +4049,36 @@ raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { static raw_adc_t ads_val = TEMP_SENSOR_0_ADS_TMAX; - static uint8_t sampleCount ; + static uint8_t sampleCount; - //static millis_t lastmillis ; + //static millis_t lastmillis; const millis_t ms = millis(); //SERIAL_ECHOPGM("ADS1118 elapsed: "); SERIAL_ECHOLN(ms- lastmillis); - //lastmillis = ms ; + //lastmillis = ms; if (PENDING(ms, next_ads1118_ms[hindex]) ) // || !ads1118.checkDataReady() return ads1118_temp_previous[hindex]; // return cached value next_ads1118_ms[hindex] = ms + ADS1118_HEAT_INTERVAL; // To do: If there are more hotends enabled, cycle through different channels - int16_t raw ; + int16_t raw; if (sampleCount < 1) { - ads1118.previous_config = ads1118.current_config ; - ads1118.current_config = ads1118.config_ADC_SS_TEMP ; - sampleCount++ ; + ads1118.previous_config = ads1118.current_config; + ads1118.current_config = ads1118.config_ADC_SS_TEMP; + sampleCount++; } else if (hindex == 0) { - ads1118.previous_config = ads1118.current_config ; - ads1118.current_config = ads1118.config_ADC_SS_CH0 ; - sampleCount = 0 ; + ads1118.previous_config = ads1118.current_config; + ads1118.current_config = ads1118.config_ADC_SS_CH0; + sampleCount = 0; } else if (hindex == 1){ - ads1118.previous_config = ads1118.current_config ; - ads1118.current_config = ads1118.config_ADC_SS_CH1 ; - sampleCount = 0 ; + ads1118.previous_config = ads1118.current_config; + ads1118.current_config = ads1118.config_ADC_SS_CH1; + sampleCount = 0; } raw = (int16_t) ads1118.readWriteData(ads1118.current_config); @@ -4095,7 +4093,7 @@ raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { } else if (ads1118.previous_config == ads1118.config_ADC_SS_CH0) { - //ads1118_hotJ_temp_current[hindex] = raw ; + //ads1118_hotJ_temp_current[hindex] = raw; //thck_0.setThot(thck_0.tempReadtoCelsius(raw)); thck_0.setRawHot(raw); //SERIAL_ECHOPGM("Last read Raw hot: "); SERIAL_ECHOLN(raw); @@ -4120,9 +4118,9 @@ raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { } else { // if we add 32767 to raw it will overflow ads1118_errors[hindex] = 0; // reset errors if ok SERIAL_ECHOLNPGM("ADS1118 Warn: Cannot shift adc read from signed to unsigned!"); - ads_val = (raw_adc_t) (raw); // as is ; + ads_val = raw_adc_t(raw); // as is } - //ads_val = (raw_adc_t) 3000; // raw; + //ads_val = raw_adc_t(3000); // raw; ads1118_temp_previous[hindex] = ads_val; // cache value //SERIAL_ECHOPGM("ADS1118 ads_val: "); SERIAL_ECHOLN(ads_val); From fe3037afae5faa6d0b2f319132781dece0d0b4f3 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Tue, 18 Nov 2025 10:06:20 -0600 Subject: [PATCH 22/27] misc ws --- Marlin/src/module/temperature.cpp | 38 +++++++++++++++---------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index ae2caa8843..1a606a0037 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -2965,23 +2965,22 @@ void Temperature::updateTemperaturesFromRawValues() { // internally, and analog_to_celsius_hotend() will retrieve the computed // temperature via thck_0.getThot(). This avoids type overflow and keeps // the conversion logic centralized and ISR-light. - #if TEMP_SENSOR_IS_ADS(0,1118) - #warning "ADS1118 is selected for temp 0" - + #if TEMP_SENSOR_IS_ADS(0, 1118) + #warning "ADS1118 is selected for hotend 0" temp_hotend[0].setraw(READ_ADS(0)); - // SERIAL_ECHOPGM("ADS1118 Tcold="); - // SERIAL_ECHO(thck_0.getTcold()); - // SERIAL_ECHOPGM(" Thot="); - // SERIAL_ECHOLN(thck_0.getThot()); + //SERIAL_ECHOPGM("ADS1118 Tcold="); + //SERIAL_ECHO(thck_0.getTcold()); + //SERIAL_ECHOPGM(" Thot="); + //SERIAL_ECHOLN(thck_0.getThot()); #endif - #if TEMP_SENSOR_IS_ADS(1,1118) - #warning "ADS1118 is selected for temp 1" + #if TEMP_SENSOR_IS_ADS(1, 1118) + #warning "ADS1118 is selected for hotend 1" temp_hotend[1].setraw(READ_ADS(1)); - // SERIAL_ECHOPGM("ADS1118 Tcold="); - // SERIAL_ECHO(thck_1.getTcold()); - // SERIAL_ECHOPGM(" Thot="); - // SERIAL_ECHOLN(thck_1.getThot()); + //SERIAL_ECHOPGM("ADS1118 Tcold="); + //SERIAL_ECHO(thck_1.getTcold()); + //SERIAL_ECHOPGM(" Thot="); + //SERIAL_ECHOLN(thck_1.getThot()); #endif #if HAS_HOTEND @@ -3000,7 +2999,8 @@ void Temperature::updateTemperaturesFromRawValues() { TERN_(HAS_POWER_MONITOR, power_monitor.capture_values()); #if HAS_HOTEND - #define _TEMPDIR(N) (TEMP_SENSOR_IS_ANY_MAX_TC(N) || TEMP_SENSOR_IS_ADS (N,1118) ) ? 0 : TEMPDIR(N), + + #define _TEMPDIR(N) (TEMP_SENSOR_IS_ANY_MAX_TC(N) || TEMP_SENSOR_IS_ADS(N,1118)) ? 0 : TEMPDIR(N), static constexpr int8_t temp_dir[HOTENDS] = { REPEAT(HOTENDS, _TEMPDIR) }; HOTEND_LOOP() { @@ -3084,17 +3084,16 @@ void Temperature::init() { TERN_(PROBING_HEATERS_OFF, paused_for_probing = false); -// #define TEMP_0_CS_PIN 79 // E6 -// #define TEMP_0_SCK_PIN 78 // E2 -// #define TEMP_0_MISO_PIN 80 // E7 -// #define TEMP_0_MOSI_PIN 84 // H2 + //#define TEMP_0_CS_PIN 79 // E6 + //#define TEMP_0_SCK_PIN 78 // E2 + //#define TEMP_0_MISO_PIN 80 // E7 + //#define TEMP_0_MOSI_PIN 84 // H2 #if HAS_ADS1118 ads1118.init(TEMP_0_CS_PIN, TEMP_0_MOSI_PIN, TEMP_0_MISO_PIN, TEMP_0_SCK_PIN); // Initialize the ADS1118, global instance ads1118.readConfig(); #endif - // ADS TC related macros #if TEMP_SENSOR_IS_ADS(0, 1118) #warning "ADS1118 is selected for temp 0" @@ -3107,7 +3106,6 @@ void Temperature::init() { //SERIAL_ECHOPGM("ADS1118 Tcold: "); //SERIAL_ECHOLN(thck_0.getTcold()); //ads1118.readConfig(); - #endif // Init (and disable) SPI thermocouples From a7e4efe6afbc1793eab2223c1f9832d4305391bd Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Mon, 24 Nov 2025 22:47:18 -0600 Subject: [PATCH 23/27] Thermocouple comment --- Marlin/Configuration.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 2d816d9e46..06494fc8e4 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -562,6 +562,7 @@ * ================================================================ * Analog Thermocouple Boards * ================================================================ + * -18 : ADS1118 with Thermocouple, e.g., Mightyboard rev G/H * -4 : AD8495 with Thermocouple * -1 : AD595 with Thermocouple * From 47398119732dd272ce41d3e9f2df09a9b54abe43 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Mon, 24 Nov 2025 22:57:27 -0600 Subject: [PATCH 24/27] filter, test --- Marlin/src/libs/adc/adc_ads1118.cpp | 2 +- Marlin/src/module/temperature.cpp | 159 +++++++++++++--------------- buildroot/tests/BTT_GTR_V1_0 | 2 +- ini/features.ini | 1 + platformio.ini | 1 + 5 files changed, 80 insertions(+), 85 deletions(-) diff --git a/Marlin/src/libs/adc/adc_ads1118.cpp b/Marlin/src/libs/adc/adc_ads1118.cpp index c8cd812fbf..6efbeacaab 100644 --- a/Marlin/src/libs/adc/adc_ads1118.cpp +++ b/Marlin/src/libs/adc/adc_ads1118.cpp @@ -338,4 +338,4 @@ float ThermocoupleK:: getTempCelsius() { } -#endif // HAS_ADS1118_ADC +#endif // HAS_ADS1118 diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index 1a606a0037..a78413cfab 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -210,12 +210,10 @@ #define TEMP_SENSOR_IS_ADS(n, M) (ENABLED(TEMP_SENSOR_##n##_IS_ADS##M) || (ENABLED(TEMP_SENSOR_REDUNDANT_IS_ADS##M) && REDUNDANT_TEMP_MATCH(SOURCE, E##n))) -// ADS1118 #if HAS_ADS1118 #include "../libs/adc/adc_ads1118.h" #endif - #if ENABLED(FILAMENT_WIDTH_SENSOR) #include "../feature/filwidth.h" #endif @@ -4025,6 +4023,7 @@ void Temperature::disable_all_heaters() { #endif // TEMP_SENSOR_IS_MAX_TC(BED) #if HAS_ADS1118 + /** * @brief Read ADS Thermocouple temperature. * @@ -4035,100 +4034,94 @@ void Temperature::disable_all_heaters() { * @param hindex the hotend we're referencing (different channel in ADS1118) * @return integer representing the board's buffer, to be converted later if needed */ -raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { - #define ADS1118_HEAT_INTERVAL 250UL // 250 ms + raw_adc_t Temperature::read_ads1118(const uint8_t hindex/*=0*/) { + #define ADS1118_HEAT_INTERVAL 250UL // 250 ms - //static raw_adc_t ads1118_coldJ_temp_current[2] = { 0, 0 }; - //static raw_adc_t ads1118_hotJ_temp_current[2] = { 0, 0 }; + //static raw_adc_t ads1118_coldJ_temp_current[2] = { 0, 0 }; + //static raw_adc_t ads1118_hotJ_temp_current[2] = { 0, 0 }; - static raw_adc_t ads1118_temp_previous[2] = { 0, 0 }; - static uint8_t ads1118_errors[2] = { 0, 0 }; - static millis_t next_ads1118_ms[2] = { 0, 0 }; + static raw_adc_t ads1118_temp_previous[2] = { 0, 0 }; + static uint8_t ads1118_errors[2] = { 0, 0 }; + static millis_t next_ads1118_ms[2] = { 0, 0 }; - static raw_adc_t ads_val = TEMP_SENSOR_0_ADS_TMAX; + static raw_adc_t ads_val = TEMP_SENSOR_0_ADS_TMAX; - static uint8_t sampleCount; + static uint8_t sampleCount; - //static millis_t lastmillis; + //static millis_t lastmillis; - const millis_t ms = millis(); - //SERIAL_ECHOPGM("ADS1118 elapsed: "); SERIAL_ECHOLN(ms- lastmillis); - //lastmillis = ms; - if (PENDING(ms, next_ads1118_ms[hindex]) ) // || !ads1118.checkDataReady() - return ads1118_temp_previous[hindex]; // return cached value + const millis_t ms = millis(); + //SERIAL_ECHOPGM("ADS1118 elapsed: "); SERIAL_ECHOLN(ms- lastmillis); + //lastmillis = ms; + if (PENDING(ms, next_ads1118_ms[hindex]) ) // || !ads1118.checkDataReady() + return ads1118_temp_previous[hindex]; // return cached value - next_ads1118_ms[hindex] = ms + ADS1118_HEAT_INTERVAL; + next_ads1118_ms[hindex] = ms + ADS1118_HEAT_INTERVAL; - // To do: If there are more hotends enabled, cycle through different channels - int16_t raw; + // To do: If there are more hotends enabled, cycle through different channels + int16_t raw; - if (sampleCount < 1) - { - ads1118.previous_config = ads1118.current_config; - ads1118.current_config = ads1118.config_ADC_SS_TEMP; - sampleCount++; - } - else if (hindex == 0) - { - ads1118.previous_config = ads1118.current_config; - ads1118.current_config = ads1118.config_ADC_SS_CH0; - sampleCount = 0; - } else if (hindex == 1){ - ads1118.previous_config = ads1118.current_config; - ads1118.current_config = ads1118.config_ADC_SS_CH1; - sampleCount = 0; - } - - raw = (int16_t) ads1118.readWriteData(ads1118.current_config); - - if (ads1118.previous_config == ads1118.config_ADC_SS_TEMP) - { - //thck_0.setTcold(ads1118.convertInternalTemp(raw)); - thck_0.setRawCold(raw); - //SERIAL_ECHOPGM("Last read Raw cold: "); SERIAL_ECHOLN(raw); - //SERIAL_ECHOPGM("TCold "); SERIAL_ECHOLN(thck_0.getTcold()); - - } - else if (ads1118.previous_config == ads1118.config_ADC_SS_CH0) - { - //ads1118_hotJ_temp_current[hindex] = raw; - //thck_0.setThot(thck_0.tempReadtoCelsius(raw)); - thck_0.setRawHot(raw); - //SERIAL_ECHOPGM("Last read Raw hot: "); SERIAL_ECHOLN(raw); - //SERIAL_ECHOPGM("ADS1118 THot "); SERIAL_ECHOLN(thck_0.getThot()); - } - - - // SERIAL_ECHOPGM("ADS1118 State:Read "); SERIAL_ECHOLN(curr_state); SERIAL_ECHOPGM(":"); SERIAL_ECHOLN(raw); - - // Handle read error or disconnection : raw = 0x7FFF or 0x8000 (-32768) - if (raw == 0x7FFF || raw == -32768) { - ads1118_errors[hindex]++; - if (ads1118_errors[hindex] > 3) { - SERIAL_ERROR_START(); - SERIAL_ECHOLNPGM("ADS1118 Fault: Conversion error!"); - ads_val = (raw_adc_t)(TEMP_SENSOR_0_ADS_TMAX << 4); // force error + if (sampleCount < 1) { + ads1118.previous_config = ads1118.current_config; + ads1118.current_config = ads1118.config_ADC_SS_TEMP; + sampleCount++; + } + else if (hindex == 0) { + ads1118.previous_config = ads1118.current_config; + ads1118.current_config = ads1118.config_ADC_SS_CH0; + sampleCount = 0; + } + else if (hindex == 1) { + ads1118.previous_config = ads1118.current_config; + ads1118.current_config = ads1118.config_ADC_SS_CH1; + sampleCount = 0; } - } - else if (raw < 32767){ - ads1118_errors[hindex] = 0; // reset errors if ok - ads_val = (raw_adc_t) (((int16_t)raw) + 32768); // raw shift to unsigned int; - } else { // if we add 32767 to raw it will overflow - ads1118_errors[hindex] = 0; // reset errors if ok - SERIAL_ECHOLNPGM("ADS1118 Warn: Cannot shift adc read from signed to unsigned!"); - ads_val = raw_adc_t(raw); // as is - } - //ads_val = raw_adc_t(3000); // raw; - ads1118_temp_previous[hindex] = ads_val; // cache value - //SERIAL_ECHOPGM("ADS1118 ads_val: "); SERIAL_ECHOLN(ads_val); - return ads_val; // return the raw value, it will not be used directly for conversion but for errors, (raw values are stored in thermocouple class) -} + raw = (int16_t) ads1118.readWriteData(ads1118.current_config); + + if (ads1118.previous_config == ads1118.config_ADC_SS_TEMP) { + //thck_0.setTcold(ads1118.convertInternalTemp(raw)); + thck_0.setRawCold(raw); + //SERIAL_ECHOPGM("Last read Raw cold: "); SERIAL_ECHOLN(raw); + //SERIAL_ECHOPGM("TCold "); SERIAL_ECHOLN(thck_0.getTcold()); + + } + else if (ads1118.previous_config == ads1118.config_ADC_SS_CH0) { + //ads1118_hotJ_temp_current[hindex] = raw; + //thck_0.setThot(thck_0.tempReadtoCelsius(raw)); + thck_0.setRawHot(raw); + //SERIAL_ECHOPGM("Last read Raw hot: "); SERIAL_ECHOLN(raw); + //SERIAL_ECHOPGM("ADS1118 THot "); SERIAL_ECHOLN(thck_0.getThot()); + } + + //SERIAL_ECHOPGM("ADS1118 State:Read "); SERIAL_ECHOLN(curr_state); SERIAL_ECHOPGM(":"); SERIAL_ECHOLN(raw); + + // Handle read error or disconnection : raw = 0x7FFF or 0x8000 (-32768) + if (raw == 0x7FFF || raw == -32768) { + ads1118_errors[hindex]++; + if (ads1118_errors[hindex] > 3) { + SERIAL_ERROR_START(); + SERIAL_ECHOLNPGM("ADS1118 Fault: Conversion error!"); + ads_val = (raw_adc_t)(TEMP_SENSOR_0_ADS_TMAX << 4); // force error + } + } + else if (raw < 32767){ + ads1118_errors[hindex] = 0; // reset errors if ok + ads_val = (raw_adc_t) (((int16_t)raw) + 32768); // raw shift to unsigned int; + } else { // if we add 32767 to raw it will overflow + ads1118_errors[hindex] = 0; // reset errors if ok + SERIAL_ECHOLNPGM("ADS1118 Warn: Cannot shift adc read from signed to unsigned!"); + ads_val = raw_adc_t(raw); // as is + } + //ads_val = raw_adc_t(3000); // raw; + + ads1118_temp_previous[hindex] = ads_val; // cache value + //SERIAL_ECHOPGM("ADS1118 ads_val: "); SERIAL_ECHOLN(ads_val); + return ads_val; // return the raw value, it will not be used directly for conversion but for errors, (raw values are stored in thermocouple class) + } + #endif // HAS_ADS1118 - - - /** * Update raw temperatures * diff --git a/buildroot/tests/BTT_GTR_V1_0 b/buildroot/tests/BTT_GTR_V1_0 index 81d079b4f1..e1d782b241 100755 --- a/buildroot/tests/BTT_GTR_V1_0 +++ b/buildroot/tests/BTT_GTR_V1_0 @@ -8,7 +8,7 @@ set -e restore_configs opt_set MOTHERBOARD BOARD_BTT_GTR_V1_0 SERIAL_PORT -1 \ - EXTRUDERS 8 TEMP_SENSOR_1 1 TEMP_SENSOR_2 1 TEMP_SENSOR_3 1 TEMP_SENSOR_4 1 TEMP_SENSOR_5 1 TEMP_SENSOR_6 1 TEMP_SENSOR_7 1 + EXTRUDERS 8 TEMP_SENSOR_1 -18 TEMP_SENSOR_2 1 TEMP_SENSOR_3 1 TEMP_SENSOR_4 1 TEMP_SENSOR_5 1 TEMP_SENSOR_6 1 TEMP_SENSOR_7 1 # Not necessary to enable auto-fan for all extruders to hit problematic code paths opt_set E0_AUTO_FAN_PIN PC10 E1_AUTO_FAN_PIN PC11 E2_AUTO_FAN_PIN PC12 NEOPIXEL_PIN PF13 \ X_DRIVER_TYPE TMC2208 Y_DRIVER_TYPE TMC2130 \ diff --git a/ini/features.ini b/ini/features.ini index 1c10302fb0..bfb933feff 100644 --- a/ini/features.ini +++ b/ini/features.ini @@ -32,6 +32,7 @@ HAS_MOTOR_CURRENT_I2C = SlowSoftI2CMaster build_src_filter=+ LIB_MAX31855 = GadgetAngel MAX31855=https://github.com/GadgetAngel/Adafruit-MAX31855-V1.0.3-Mod-M/archive/dc9cc10ac2.zip LIB_INTERNAL_MAX31865 = build_src_filter=+ +HAS_ADS1118 = build_src_filter=+ NEOPIXEL_LED = adafruit/Adafruit NeoPixel@~1.12.3 build_src_filter=+ I2C_AMMETER = peterus/INA226Lib@1.1.2 diff --git a/platformio.ini b/platformio.ini index df5418cde4..4f8492e073 100644 --- a/platformio.ini +++ b/platformio.ini @@ -85,6 +85,7 @@ default_src_filter = + - - - - ; Library Code + - - - - - From 3c8c2e62235d8f51368698150d81c5e4b28693a1 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Thu, 27 Nov 2025 15:03:43 -0600 Subject: [PATCH 25/27] indent --- Marlin/src/libs/adc/adc_ads1118.cpp | 43 ++++++++++++++--------------- Marlin/src/module/temperature.cpp | 6 ++-- 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/Marlin/src/libs/adc/adc_ads1118.cpp b/Marlin/src/libs/adc/adc_ads1118.cpp index 6efbeacaab..631da363b9 100644 --- a/Marlin/src/libs/adc/adc_ads1118.cpp +++ b/Marlin/src/libs/adc/adc_ads1118.cpp @@ -240,7 +240,7 @@ void ADS1118::deselect() { digitalWrite(cs_pin, HIGH); } void ADS1118::sckHigh() { digitalWrite(sck_pin, HIGH); } void ADS1118::sckLow() { digitalWrite(sck_pin, LOW); } -// Definiciones de variables estáticas +// Static variable definitions uint8_t ADS1118::cs_pin = 0; uint8_t ADS1118::mosi_pin = 0; uint8_t ADS1118::miso_pin = 0; @@ -271,7 +271,7 @@ ThermocoupleK thck_1; void ThermocoupleK::init() {} -// --- Convierte lectura ADC a °C --- +// --- Convert ADC reading to °C --- float ThermocoupleK:: tempReadtoCelsius(const int16_t rawADC) { //Serial.println((int16_t)pgm_read_word(&ThermocoupleK_Lookup[TEMP_TABLE_SIZE - 1])); @@ -280,34 +280,34 @@ float ThermocoupleK:: tempReadtoCelsius(const int16_t rawADC) { if (rawADC < (int16_t) pgm_read_word(&table_thermocouple_k[0].adc)) return TEMP_MIN_TEMP; - // Búsqueda lineal en la tabla (de menor a mayor valor ADC) + // Linear search in the table (from lowest to highest ADC value) for (uint16_t i = 0; i < TEMP_TABLE_SIZE - 1; i++) { - int16_t adc1 = pgm_read_word(&table_thermocouple_k[i].adc); - int16_t adc2 = pgm_read_word(&table_thermocouple_k[i + 1].adc); - // Serial.print(i); Serial.print(" "); Serial.print(adc1); Serial.print(" "); Serial.print(adc2); + int16_t adc1 = pgm_read_word(&table_thermocouple_k[i].adc); + int16_t adc2 = pgm_read_word(&table_thermocouple_k[i + 1].adc); + // Serial.print(i); Serial.print(" "); Serial.print(adc1); Serial.print(" "); Serial.print(adc2); - if (rawADC >= adc1 && rawADC < adc2) { // in-between tableValue and nextValue - // Approximate temperature via linear interpolation - //float frac = float(rawADC - adc2) / float(adc1 - adc2); - int16_t t1 = pgm_read_word(&table_thermocouple_k[i].temp); - int16_t t2 = pgm_read_word(&table_thermocouple_k[i+1].temp); - // Serial.print(" "); Serial.print(t1); Serial.print(" "); Serial.print(t2); - float tempC = t1 + (float) (rawADC - adc1) * (float(t2 - t1) / float(adc2 - adc1)); // TEMP_TABLE_OFFSET + i + frac; - return tempC; - } - // Serial.println(""); + if (rawADC >= adc1 && rawADC < adc2) { // in-between tableValue and nextValue + // Approximate temperature via linear interpolation + //float frac = float(rawADC - adc2) / float(adc1 - adc2); + int16_t t1 = pgm_read_word(&table_thermocouple_k[i].temp); + int16_t t2 = pgm_read_word(&table_thermocouple_k[i+1].temp); + // Serial.print(" "); Serial.print(t1); Serial.print(" "); Serial.print(t2); + float tempC = t1 + (float) (rawADC - adc1) * (float(t2 - t1) / float(adc2 - adc1)); // TEMP_TABLE_OFFSET + i + frac; + return tempC; + } + // Serial.println(""); } return TEMP_MIN_TEMP; } float ThermocoupleK:: calcTempCelsius() { - _Tcold = ads1118.convertInternalTemp(_raw_cold); - _Thot = tempReadtoCelsius(_raw_hot); - //SERIAL_ECHOPGM("ADS1118 TCold "); SERIAL_ECHOLN(_Tcold); - //SERIAL_ECHOPGM("ADS1118 THot "); SERIAL_ECHOLN(_Thot); - return _Thot + _Tcold; + _Tcold = ads1118.convertInternalTemp(_raw_cold); + _Thot = tempReadtoCelsius(_raw_hot); + //SERIAL_ECHOPGM("ADS1118 TCold "); SERIAL_ECHOLN(_Tcold); + //SERIAL_ECHOPGM("ADS1118 THot "); SERIAL_ECHOLN(_Thot); + return _Thot + _Tcold; } void ThermocoupleK::setRawCold(const int16_t raw_cold) { @@ -337,5 +337,4 @@ float ThermocoupleK:: getTempCelsius() { return _Thot + _Tcold; } - #endif // HAS_ADS1118 diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index 2f3e32c86a..351ab45108 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -2629,9 +2629,9 @@ void Temperature::task() { #if ANY_THERMISTOR_IS(-18) -// Conversion for ADS1118 in differential mode (K-type) -// Each LSB bit ≈ 62.5 µV → ~1.5 °C (no calibration). -// Adjustable with GAIN and OFFSET from Configuration_adv.h + // Conversion for ADS1118 in differential mode (K-type) + // Each LSB bit ≈ 62.5 µV → ~1.5 °C (no calibration). + // Adjustable with GAIN and OFFSET from Configuration_adv.h static constexpr celsius_float_t temp_ads1118(const uint8_t e) { celsius_float_t temp = 0; From c16cb3630ceac343ab35fcbb6e9f94f2dde4ee05 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Thu, 27 Nov 2025 16:27:01 -0600 Subject: [PATCH 26/27] pin for test --- buildroot/tests/BTT_GTR_V1_0 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/buildroot/tests/BTT_GTR_V1_0 b/buildroot/tests/BTT_GTR_V1_0 index e1d782b241..4b237c36de 100755 --- a/buildroot/tests/BTT_GTR_V1_0 +++ b/buildroot/tests/BTT_GTR_V1_0 @@ -8,7 +8,8 @@ set -e restore_configs opt_set MOTHERBOARD BOARD_BTT_GTR_V1_0 SERIAL_PORT -1 \ - EXTRUDERS 8 TEMP_SENSOR_1 -18 TEMP_SENSOR_2 1 TEMP_SENSOR_3 1 TEMP_SENSOR_4 1 TEMP_SENSOR_5 1 TEMP_SENSOR_6 1 TEMP_SENSOR_7 1 + EXTRUDERS 8 TEMP_SENSOR_1 1 TEMP_SENSOR_2 1 TEMP_SENSOR_3 1 TEMP_SENSOR_4 1 TEMP_SENSOR_5 1 TEMP_SENSOR_6 1 TEMP_SENSOR_7 1 \ + TEMP_SENSOR_0 -18 TEMP_0_MOSI_PIN PG15 # Not necessary to enable auto-fan for all extruders to hit problematic code paths opt_set E0_AUTO_FAN_PIN PC10 E1_AUTO_FAN_PIN PC11 E2_AUTO_FAN_PIN PC12 NEOPIXEL_PIN PF13 \ X_DRIVER_TYPE TMC2208 Y_DRIVER_TYPE TMC2130 \ From 9e6cc0eabd9a292dac86bb6915666c0e368da1ee Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Thu, 27 Nov 2025 16:39:49 -0600 Subject: [PATCH 27/27] raw = transfer16(0) ? --- Marlin/src/libs/adc/adc_ads1118.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Marlin/src/libs/adc/adc_ads1118.cpp b/Marlin/src/libs/adc/adc_ads1118.cpp index 631da363b9..857f1739c7 100644 --- a/Marlin/src/libs/adc/adc_ads1118.cpp +++ b/Marlin/src/libs/adc/adc_ads1118.cpp @@ -63,9 +63,9 @@ void ADS1118::startConversion(const uint8_t pair) { uint16_t config = 0x858B; // 0b 1000 0101 1000 1011 : SS start, single-ended off, gain ±2.048V, single-shot mode, 128SPS, ADC mode, Pullup enable, Write config switch (pair) { + default: case 0: config |= (0x0 << ADS1118_CH_MASK); currentchannel = 0; break; // AIN0-AIN1 case 1: config |= (0x3 << ADS1118_CH_MASK); currentchannel = 1; break; // AIN2-AIN3 - default: config |= (0x0 << ADS1118_CH_MASK); currentchannel = 0; break; } digitalWrite(cs_pin, LOW); @@ -80,9 +80,8 @@ void ADS1118::startConversion(const uint8_t pair) { bool ADS1118::ready() { if (!isBusy) return true; if (millis() - startTime >= ADS1118_CONV_MS) { - uint16_t raw; digitalWrite(cs_pin, LOW); - transfer16(raw); + uint16_t raw = transfer16(0); digitalWrite(cs_pin, HIGH); lastValue = (int16_t)raw; isBusy = false; @@ -104,9 +103,9 @@ void ADS1118::startContinuousConversion(const uint8_t channel_pair) { // 0x049B: read internal temp uint16_t config = 0x048B; switch (channel_pair) { + default: case 0: config |= (0x0 << ADS1118_CH_MASK); currentchannel = 0; break; // AIN0-AIN1 case 1: config |= (0x3 << ADS1118_CH_MASK); currentchannel = 1; break; // AIN2-AIN3 - default: config |= (0x0 << ADS1118_CH_MASK); currentchannel = 0; break; } digitalWrite(cs_pin, LOW);