MarlinFirmware / Marlin

Marlin is an optimized firmware for RepRap 3D printers based on the Arduino platform. Many commercial 3D printers come with Marlin installed. Check with your vendor if you need source code for your specific machine.
https://marlinfw.org
GNU General Public License v3.0
16.28k stars 19.24k forks source link

bugfix 2.0.x: Occasional hotend temperature glitch when printing #11323

Closed gloomyandy closed 6 years ago

gloomyandy commented 6 years ago

Description

I've recently been seeing drops in temperature during printing. My hotend temperature will be set at say 200 and will be being maintained at that +/- a few degrees. However from time to time I will see a reading of around 176.

I've spent some time digging into this by adding some debug code into the temperature.cpp file. What I see is that normally over a period of a second or so the min and max raw ADC readings for the temperature sensor are 86/87 however from time to time I get a range of 86/937. Digging into this further I added code to record the min and max time from the call to start the ADC to reading it. Normally these values are around 944/1140 uS. However when I get the above "odd" reading I get a minimum period of only 28uS. My understanding is that the Atmega 2560 ADC conversion time minimum is around 100uS so I suspect this is what is causing the glitch. My guess is that at times other interrupt routines are delaying the start of the ADC conversion resulting in the short conversion time.

This will almost certainly be Arduino specific and probably depends upon what options you have enabled (and hence how long the other interrupt calls run for).

I'm going to add code to ensure that there is always a minimum delta of 100uS between successive calls to the temperature interrupt routine. But is there a better way to fix this?

Steps to Reproduce

Run a print job and closely monitor the hotend temperature reports.

Expected behavior:

Temperature should remain constant within a few degrees of the set point

Actual behavior:

Temperature occasionally drops by 25 or so degrees.

Additional Information

Configuration files are here: https://github.com/gloomyandy/Marlin/tree/bugfix-2.0.x/Marlin

boelle commented 6 years ago

this is a little more than a "glitch" or spike

sure its not a thermistor that has one leg in the coffin?

AnHardt commented 6 years ago

@brucehvn What processor do you use? The above 'patch' does only work for the AVR-processors. If i'v seen it right the other platforms all do use analogRead() storing in a variable to get the value later and fake the conversion ready test. Because analogRead() is busy waiting for the result this should work nicely, but is poisoning the timing.

Got surprising results. Testet the duration of analogRead()

// MEGA   time per ADC sample = 112.0000000000µs =   8.9285717010 Khz
// DUE    time per ADC sample =   4.0000000000µs = 250.0000000000 Khz 30 times faster
// F429ZI time per ADC sample =  53.0000000000µs =  18.8679245283 Khz 2,113207547169811 times faster That's disappointing

For the MEGA this is the expected bad value. For good reason we don't use anologRead() at the AVRs, but start the conversion and pick up the result later. At the DUE analoRead() is about 30 times faster. So we can probably use it. The F429ZI is an 180MHz ARM and for that surprisingly slow in analogeRead() with stm32duino/Arduino_Core_STM32 kernel.

How does your board perform?

const int analogInPin = A0;
int sensorValue = 0;
void setup() {
  Serial.begin(9600);
  while (!Serial) {}; // wait for serial port to connect. Needed for native USB port only
}

#define NSAMPLES 100000

void loop() {
  unsigned long time1 = micros();
  for (long long i = NSAMPLES; i >= 0; i--)
    sensorValue += analogRead(analogInPin);
  unsigned long time2 = micros();
  Serial.print("time per ADC sample = ");
  double msps = (time2 - time1) / (NSAMPLES);
  Serial.print(msps ,10);
  Serial.print("µs = ");
  Serial.print(1000.0/msps,10);
  Serial.println(" Khz");
  delay(2);
}

// MEGA   time per ADC sample = 112.0000000000µs =   8.9285717010 Khz
// DUE    time per ADC sample =   4.0000000000µs = 250.0000000000 Khz 30 times faster
// F429ZI time per ADC sample =  53.0000000000µs =  18.8679245283 Khz 2,113207547169811 times faster That's disapointing
ejtagle commented 6 years ago

@AnHardt : Not all 32bit processors have integrated fast ADC converters. Some of them could be using a ramp based (delta) ADC, that are quite precise, but very slow...

brucehvn commented 6 years ago

@AnHardt I'm using the typical Mega 2560 AVR with Ramps 1.4. I've just installed the latest bugfix-2.0.x code and will give it a try first before pursuing this any further.

brucehvn commented 6 years ago

@boelle I would tend to agree with you except I've completely replaced the heater block with the latest e3d v6 heater block with the thermistor cartridge assembly. It could be a problem with that, but I saw the same behavior with the old heater block and thermistor, so if it's hardware related, it would probably be something with the analog functionality of the ramps or mega board. I had another issue where the z motors were turning a little bit when a retract/unretract was executed. I spent 2 days swapping out all the hardware, ramps, mega, lcd display, etc., only to find out it was a firmware issue that was being worked on. So nowadays, I check the firmware first, then move on to the hardware if needed.

AnHardt commented 6 years ago

@ejtagle Got some more numbers.

// MEGA/UNO/NANO time per ADC sample = 112.0000000000µs =   8.9285717010 Khz
// DUE           time per ADC sample =   4.0000000000µs = 250.0000000000 Khz
// ESP32         time per ADC sample =   9.0000000000µs = 111.1111111111 Khz
// Teensy++ 2.0  time per ADC sample =  60.0000000000µs =  16.6666666667 Khz
// Teensy 3.5    time per ADC sample =   8.0000000000µs = 125.0000000000 Khz
// Teensy 3.6    time per ADC sample =   6.0000000000µs = 166.6666666667 Khz
// STM32F401RE   time per ADC sample =  56.0000000000µs =  17.8571428571 Khz
// STM32F411RE   time per ADC sample =  53.0000000000µs =  18.8679245283 Khz
// STM32F429ZI   time per ADC sample =  53.0000000000µs =  18.8679245283 Khz 

The STM32s ADCs are fast - 1Msample/s should be reachable with the right use. It's the current implementation of analogRead() what takes that long (stm32duino/Arduino_Core_STM32 kernel). For every analogRead() the ADC is - completely set up, start a calibration, wait for calibration, start a single measurement, wait for measurement, shut down ADC.

ejtagle commented 6 years ago

@AnHardt : That is the problem with Arduino core--- It is a general purpose framework, and when trying to get maximum performance from the hw, it starts to interfere. All the digitalXXX() and analogXXX() functions reinitialize everything, just in case, so they are pretty slow. And that is the reason of the fastio.h macros.

I guess that if analogXXX() functions are getting in the way of performance, they should be reimplemented (hey!, performing an ADC conversion is not that hard at all ... ;)

(And BTW, yes, i HATE polling on embeded systems... on STM we should be doing it the same way than in AVR, using an state machine...)

github-actions[bot] commented 4 years ago

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.