New Version Sprinter V2
- Look Vorward Funktion - - Stepper Control with Timer 1 - SOFT PWM for Extruder heating --> Free Timer 1 - G2 / G3 Command for arc real arc - Baudrate 250 kbaud - M30 Command delete file on SD Card - Text moved to flash to free RAM - M203 Command for Temp debugging
This commit is contained in:
parent
8d17b09475
commit
76bbfb39ae
9 changed files with 2912 additions and 1061 deletions
|
|
@ -9,11 +9,12 @@
|
|||
// Gen6 = 5,
|
||||
// Sanguinololu up to 1.1 = 6
|
||||
// Sanguinololu 1.2 and above = 62
|
||||
// Gen 7 @ 16MHZ only= 7
|
||||
// Teensylu (at90usb) = 8
|
||||
// Gen 3 Plus = 21
|
||||
// gen 3 Monolithic Electronics = 22
|
||||
// Gen3 PLUS for TechZone Gen3 Remix Motherboard = 23
|
||||
#define MOTHERBOARD 62
|
||||
#define MOTHERBOARD 62
|
||||
|
||||
//// Thermistor settings:
|
||||
// 1 is 100k thermistor
|
||||
|
|
@ -26,14 +27,16 @@
|
|||
#define THERMISTORHEATER 1
|
||||
#define THERMISTORBED 1
|
||||
|
||||
//// Calibration variables
|
||||
// X, Y, Z, E steps per unit - Metric Prusa Mendel with Wade extruder:
|
||||
float axis_steps_per_unit[] = {80, 80, 3200/1.25,700};
|
||||
// Metric Prusa Mendel with Makergear geared stepper extruder:
|
||||
//float axis_steps_per_unit[] = {80,80,3200/1.25,1380};
|
||||
//// Calibration variables --> CHECK THIS VALUES FOR YOUR PRINTER !!!
|
||||
// X, Y, Z, E steps per unit - Metric Prusa Mendel with Wade extruder and alu pulleys:
|
||||
#define _AXIS_STEP_PER_UNIT {64, 64, 3200/1.25,766}
|
||||
|
||||
// Metric Prusa Mendel with Makergear geared stepper extruder and printet pulleys:
|
||||
//#define _AXIS_STEP_PER_UNIT {80,80,3200/1.25,1380}
|
||||
|
||||
// MakerGear Hybrid Prusa Mendel:
|
||||
// Z axis value is for .9 stepper(if you have 1.8 steppers for Z, you need to use 2272.7272)
|
||||
//float axis_steps_per_unit[] = {104.987, 104.987, 4545.4544, 1487};
|
||||
//#define _AXIS_STEP_PER_UNIT {104.987, 104.987, 4545.4544, 1487}
|
||||
|
||||
//// Endstop Settings
|
||||
#define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors
|
||||
|
|
@ -45,17 +48,18 @@ const bool Y_ENDSTOP_INVERT = false;
|
|||
const bool Z_ENDSTOP_INVERT = false;
|
||||
|
||||
// This determines the communication speed of the printer
|
||||
#define BAUDRATE 115200
|
||||
//#define BAUDRATE 115200
|
||||
#define BAUDRATE 250000
|
||||
|
||||
// Comment out (using // at the start of the line) to disable SD support:
|
||||
#define SDSUPPORT
|
||||
// Uncomment to make Sprinter run init.g from SD on boot
|
||||
|
||||
// Uncomment to make run init.g from SD on boot
|
||||
//#define SDINITFILE
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
//// ADVANCED SETTINGS - to tweak parameters
|
||||
|
||||
#include "thermistortables.h"
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
// For Inverting Stepper Enable Pins (Active Low) use 0, Non Inverting (Active High) use 1
|
||||
#define X_ENABLE_ON 0
|
||||
|
|
@ -70,10 +74,10 @@ const bool DISABLE_Z = true;
|
|||
const bool DISABLE_E = false;
|
||||
|
||||
// Inverting axis direction
|
||||
const bool INVERT_X_DIR = false;
|
||||
const bool INVERT_X_DIR = true;
|
||||
const bool INVERT_Y_DIR = false;
|
||||
const bool INVERT_Z_DIR = true;
|
||||
const bool INVERT_E_DIR = false;
|
||||
const bool INVERT_E_DIR = true;
|
||||
|
||||
//// ENDSTOP SETTINGS:
|
||||
// Sets direction of endstops when homing; 1=MAX, -1=MIN
|
||||
|
|
@ -83,15 +87,19 @@ const bool INVERT_E_DIR = false;
|
|||
|
||||
const bool min_software_endstops = false; //If true, axis won't move to coordinates less than zero.
|
||||
const bool max_software_endstops = true; //If true, axis won't move to coordinates greater than the defined lengths below.
|
||||
const int X_MAX_LENGTH = 200;
|
||||
const int Y_MAX_LENGTH = 200;
|
||||
const int Z_MAX_LENGTH = 100;
|
||||
|
||||
//Max Length for Prusa Mendel, check the ways of your axis and set this Values
|
||||
const int X_MAX_LENGTH = 165;
|
||||
const int Y_MAX_LENGTH = 181;
|
||||
const int Z_MAX_LENGTH = 90;
|
||||
|
||||
//// MOVEMENT SETTINGS
|
||||
const int NUM_AXIS = 4; // The axis order in all axis related arrays is X, Y, Z, E
|
||||
float max_feedrate[] = {200000, 200000, 240, 500000};
|
||||
float homing_feedrate[] = {1500,1500,120};
|
||||
bool axis_relative_modes[] = {false, false, false, false};
|
||||
|
||||
#define _MAX_FEEDRATE {24000, 24000, 180, 2700} // (400,400,3,45) mm/sec --> Array Unit = mm / min
|
||||
#define _HOMING_FEEDRATE {1500,1500,120} // ( 25, 25,2) mm/sec --> Array Unit = mm / min
|
||||
|
||||
#define _AXIS_RELATIVE_MODES {false, false, false, false}
|
||||
|
||||
// Min step delay in microseconds. If you are experiencing missing steps, try to raise the delay microseconds, but be aware this
|
||||
// If you enable this, make sure STEP_DELAY_RATIO is disabled.
|
||||
|
|
@ -107,29 +115,88 @@ bool axis_relative_modes[] = {false, false, false, false};
|
|||
//// Acceleration settings
|
||||
#ifdef RAMP_ACCELERATION
|
||||
// X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot.
|
||||
float max_start_speed_units_per_second[] = {25.0,25.0,0.2,10.0};
|
||||
long max_acceleration_units_per_sq_second[] = {1000,1000,50,10000}; // X, Y, Z and E max acceleration in mm/s^2 for printing moves or retracts
|
||||
long max_travel_acceleration_units_per_sq_second[] = {500,500,50,500}; // X, Y, Z max acceleration in mm/s^2 for travel moves
|
||||
#define _ACCELERATION 2000 // Normal acceleration mm/s^2
|
||||
#define _RETRACT_ACCELERATION 7000 // Normal acceleration mm/s^2
|
||||
#define _MAX_XY_JERK (20.0*60)
|
||||
#define _MAX_Z_JERK (0.4*60)
|
||||
#define _MAX_START_SPEED_UNITS_PER_SECOND {25.0,25.0,0.2,10.0}
|
||||
#define _MAX_ACCELERATION_UNITS_PER_SQ_SECOND {500,500,50,500} // X, Y, Z and E max acceleration in mm/s^2 for printing moves or retracts
|
||||
#define _MAX_TRAVEL_ACCELERATION_UNITS_PER_SQ_SECOND {500,500,50,500} // X, Y, Z max acceleration in mm/s^2 for travel moves
|
||||
#endif
|
||||
|
||||
|
||||
// Machine UUID
|
||||
// This may be useful if you have multiple machines and wish to identify them by using the M115 command.
|
||||
// By default we set it to zeros.
|
||||
char uuid[] = "00000000-0000-0000-0000-000000000000";
|
||||
//#define _DEF_CHAR_UUID "00000000-0000-0000-0000-000000000000"
|
||||
#define _DEF_CHAR_UUID "55841315-4681-1640-0000-260479000000"
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
//// Planner buffer Size
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
// The number of linear motions that can be in the plan at any give time
|
||||
// if the SD Card need to much memory reduce the Values for Plannerpuffer (base of 2)
|
||||
#ifdef SDSUPPORT
|
||||
#define BLOCK_BUFFER_SIZE 16
|
||||
#define BLOCK_BUFFER_MASK 0x0f
|
||||
#else
|
||||
#define BLOCK_BUFFER_SIZE 16
|
||||
#define BLOCK_BUFFER_MASK 0x0f
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
//// SETTINGS FOR ARC FUNCTION (Command G2/G2)
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
// Arc interpretation settings:
|
||||
//Step to split a cirrcle in small Lines
|
||||
#define MM_PER_ARC_SEGMENT 1
|
||||
//After this count of steps a new SIN / COS caluclation is startet to correct the circle interpolation
|
||||
#define N_ARC_CORRECTION 25
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
//// HEATERCONTROL AND PID PARAMETERS
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
//Testfunction to adjust the Hotend temperatur in case of Printingspeed
|
||||
//If the Printer print slow the Temp is going to AUTO_TEMP_MIN
|
||||
//At the moment this Value dont change the targettemp from the Hotend
|
||||
//The result of this function is only send with the Temperaturerequest to the host
|
||||
//#define AUTOTEMP
|
||||
#ifdef AUTOTEMP
|
||||
#define AUTO_TEMP_MAX 240
|
||||
#define AUTO_TEMP_MIN 205
|
||||
#define AUTO_TEMP_FACTOR 0.025
|
||||
#define AUTOTEMP_OLDWEIGHT 0.98
|
||||
#endif
|
||||
|
||||
//// AD595 THERMOCOUPLE SUPPORT UNTESTED... USE WITH CAUTION!!!!
|
||||
|
||||
//// PID settings:
|
||||
// Uncomment the following line to enable PID support. This is untested and could be disastrous. Be careful.
|
||||
//#define PIDTEMP 1
|
||||
#define PIDTEMP 1
|
||||
#ifdef PIDTEMP
|
||||
//Sanguinololu 1.2 and above, the PWM Output Hotend Timer 1 is used for the Hardware PWM
|
||||
//but in this Software use Timer1 for the Stepperfunction so it is not possible to use the "analogWrite" function.
|
||||
//This Soft PWM use Timer 2 with 400 Hz to drive the PWM for the hotend
|
||||
#define PID_SOFT_PWM
|
||||
|
||||
//Measure the MIN/MAX Value of the Hotend Temp and show it with
|
||||
//Command M601 / Command M602 Reset the MIN/MAX Value
|
||||
//#define DEBUG_HEATER_TEMP
|
||||
|
||||
//PID Controler Settings
|
||||
#define PID_INTEGRAL_DRIVE_MAX 80 // too big, and heater will lag after changing temperature, too small and it might not compensate enough for long-term errors
|
||||
#define PID_PGAIN 2560 //256 is 1.0 // value of X means that error of 1 degree is changing PWM duty by X, probably no need to go over 25
|
||||
#define PID_PGAIN 2048 //256 is 1.0 // value of X means that error of 1 degree is changing PWM duty by X, probably no need to go over 25
|
||||
#define PID_IGAIN 64 //256 is 1.0 // value of X (e.g 0.25) means that each degree error over 1 sec (2 measurements) changes duty cycle by 2X (=0.5) units (verify?)
|
||||
#define PID_DGAIN 4096 //256 is 1.0 // value of X means that around reached setpoint, each degree change over one measurement (half second) adjusts PWM by X units to compensate
|
||||
#define PID_DGAIN 2048 //256 is 1.0 // value of X means that around reached setpoint, each degree change over one measurement (half second) adjusts PWM by X units to compensate
|
||||
|
||||
// magic formula 1, to get approximate "zero error" PWM duty. Take few measurements with low PWM duty and make linear fit to get the formula
|
||||
#define HEATER_DUTY_FOR_SETPOINT(setpoint) ((int)((187L*(long)setpoint)>>8)-27) // for my makergear hot-end: linear fit {50,10},{60,20},{80,30},{105,50},{176,100},{128,64},{208,128}
|
||||
// for my makergear hot-end: linear fit {50,10},{60,20},{80,30},{105,50},{176,100},{128,64},{208,128}
|
||||
#define HEATER_DUTY_FOR_SETPOINT(setpoint) ((int)((187L*(long)setpoint)>>8)-27)
|
||||
// magic formula 2, to make led brightness approximately linear
|
||||
#define LED_PWM_FOR_BRIGHTNESS(brightness) ((64*brightness-1384)/(300-brightness))
|
||||
#endif
|
||||
|
|
@ -140,20 +207,23 @@ char uuid[] = "00000000-0000-0000-0000-000000000000";
|
|||
// How often should the heater check for new temp readings, in milliseconds
|
||||
#define HEATER_CHECK_INTERVAL 500
|
||||
#define BED_CHECK_INTERVAL 5000
|
||||
|
||||
// Comment the following line to enable heat management during acceleration
|
||||
#define DISABLE_CHECK_DURING_ACC
|
||||
#ifndef DISABLE_CHECK_DURING_ACC
|
||||
// Uncomment the following line to disable heat management during moves
|
||||
//#define DISABLE_CHECK_DURING_MOVE
|
||||
#endif
|
||||
|
||||
// Uncomment the following line to disable heat management during travel moves (and extruder-only moves, eg: retracts), strongly recommended if you are missing steps mid print.
|
||||
// Probably this should remain commented if are using PID.
|
||||
// It also defines the max milliseconds interval after which a travel move is not considered so for the sake of this feature.
|
||||
#define DISABLE_CHECK_DURING_TRAVEL 1000
|
||||
|
||||
//// Temperature smoothing - only uncomment this if your temp readings are noisy (Gen6 without EvdZ's 5V hack)
|
||||
//#define SMOOTHING
|
||||
#define SMOOTHING
|
||||
//#define SMOOTHFACTOR 16 //best to use a power of two here - determines how many values are averaged together by the smoothing algorithm
|
||||
#define SMOOTHFACTOR 2 //best to use a power of two here - determines how many values are averaged together by the smoothing algorithm
|
||||
|
||||
//// Experimental watchdog and minimal temp
|
||||
// The watchdog waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature
|
||||
|
|
@ -188,13 +258,22 @@ char uuid[] = "00000000-0000-0000-0000-000000000000";
|
|||
//#define CONTROLLERFAN_PIN 23 //Pin used for the fan to cool controller, comment out to disable this function
|
||||
#define CONTROLLERFAN_SEC 60 //How many seconds, after all motors were disabled, the fan should run
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// DEBUGING
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
|
||||
//Uncomment this to see on the host if a wrong or unknown Command is recived
|
||||
//Only for Testing !!!
|
||||
//#define SEND_WRONG_CMD_INFO
|
||||
|
||||
// Uncomment the following line to enable debugging. You can better control debugging below the following line
|
||||
//#define DEBUG
|
||||
#ifdef DEBUG
|
||||
//#define DEBUG_PREPARE_MOVE //Enable this to debug prepare_move() function
|
||||
//#define DEBUG_BRESENHAM //Enable this to debug the Bresenham algorithm
|
||||
//#define DEBUG_RAMP_ACCELERATION //Enable this to debug all constant acceleration info
|
||||
//#define DEBUG_MOVE_TIME //Enable this to time each move and print the result
|
||||
//#define DEBUG_MOVE_TIME //Enable this to time each move and print the result
|
||||
//#define DEBUG_HEAT_MGMT //Enable this to debug heat management. WARNING, this will cause axes to jitter!
|
||||
//#define DEBUG_DISABLE_CHECK_DURING_TRAVEL //Debug the namesake feature, see above in this file
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -2,52 +2,9 @@
|
|||
// Licence: GPL
|
||||
#include <WProgram.h>
|
||||
#include "fastio.h"
|
||||
|
||||
extern "C" void __cxa_pure_virtual();
|
||||
void __cxa_pure_virtual(){};
|
||||
void get_command();
|
||||
void process_commands();
|
||||
|
||||
void manage_inactivity(byte debug);
|
||||
void setup_acceleration();
|
||||
|
||||
void manage_heater();
|
||||
|
||||
#if defined HEATER_USES_THERMISTOR
|
||||
#define temp2analogh( c ) temp2analog_thermistor(c,temptable,NUMTEMPS)
|
||||
#define analog2temp( c ) analog2temp_thermistor(c,temptable,NUMTEMPS)
|
||||
#elif defined HEATER_USES_AD595
|
||||
#define temp2analogh( c ) temp2analog_ad595(c)
|
||||
#define analog2temp( c ) analog2temp_ad595(c)
|
||||
#elif defined HEATER_USES_MAX6675
|
||||
#define temp2analogh( c ) temp2analog_max6675(c)
|
||||
#define analog2temp( c ) analog2temp_max6675(c)
|
||||
#endif
|
||||
|
||||
#if defined BED_USES_THERMISTOR
|
||||
#define temp2analogBed( c ) temp2analog_thermistor((c),bedtemptable,BNUMTEMPS)
|
||||
#define analog2tempBed( c ) analog2temp_thermistor((c),bedtemptable,BNUMTEMPS)
|
||||
#elif defined BED_USES_AD595
|
||||
#define temp2analogBed( c ) temp2analog_ad595(c)
|
||||
#define analog2tempBed( c ) analog2temp_ad595(c)
|
||||
#elif defined BED_USES_MAX6675
|
||||
#define temp2analogBed( c ) temp2analog_max6675(c)
|
||||
#define analog2tempBed( c ) analog2temp_max6675(c)
|
||||
#endif
|
||||
|
||||
#if defined (HEATER_USES_THERMISTOR) || defined (BED_USES_THERMISTOR)
|
||||
int temp2analog_thermistor(int celsius, const short table[][2], int numtemps);
|
||||
int analog2temp_thermistor(int raw,const short table[][2], int numtemps);
|
||||
#endif
|
||||
|
||||
#if defined (HEATER_USES_AD595) || defined (BED_USES_AD595)
|
||||
int temp2analog_ad595(int celsius);
|
||||
int analog2temp_ad595(int raw);
|
||||
#endif
|
||||
|
||||
#if defined (HEATER_USES_MAX6675) || defined (BED_USES_MAX6675)
|
||||
int temp2analog_max6675(int celsius);
|
||||
int analog2temp_max6675(int raw);
|
||||
#endif
|
||||
|
||||
#if X_ENABLE_PIN > -1
|
||||
#define enable_x() WRITE(X_ENABLE_PIN, X_ENABLE_ON)
|
||||
|
|
@ -78,12 +35,78 @@ int analog2temp_max6675(int raw);
|
|||
#define disable_e() ;
|
||||
#endif
|
||||
|
||||
#define X_AXIS 0
|
||||
#define Y_AXIS 1
|
||||
#define Z_AXIS 2
|
||||
#define E_AXIS 3
|
||||
|
||||
|
||||
// This struct is used when buffering the setup for each linear movement "nominal" values are as specified in
|
||||
// the source g-code and may never actually be reached if acceleration management is active.
|
||||
typedef struct {
|
||||
// Fields used by the bresenham algorithm for tracing the line
|
||||
long steps_x, steps_y, steps_z, steps_e; // Step count along each axis
|
||||
|
||||
long step_event_count; // The number of step events required to complete this block
|
||||
volatile long accelerate_until; // The index of the step event on which to stop acceleration
|
||||
volatile long decelerate_after; // The index of the step event on which to start decelerating
|
||||
volatile long acceleration_rate; // The acceleration rate used for acceleration calculation
|
||||
unsigned char direction_bits; // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h)
|
||||
|
||||
#ifdef ADVANCE
|
||||
long advance_rate;
|
||||
volatile long initial_advance;
|
||||
volatile long final_advance;
|
||||
float advance;
|
||||
#endif
|
||||
|
||||
// Fields used by the motion planner to manage acceleration
|
||||
float speed_x, speed_y, speed_z, speed_e; // Nominal mm/minute for each axis
|
||||
float nominal_speed; // The nominal speed for this block in mm/min
|
||||
float millimeters; // The total travel of this block in mm
|
||||
float entry_speed;
|
||||
float acceleration; // acceleration mm/sec^2
|
||||
|
||||
// Settings for the trapezoid generator
|
||||
long nominal_rate; // The nominal step rate for this block in step_events/sec
|
||||
volatile long initial_rate; // The jerk-adjusted step rate at start of block
|
||||
volatile long final_rate; // The minimal rate at exit
|
||||
long acceleration_st; // acceleration steps/sec^2
|
||||
volatile char busy;
|
||||
} block_t;
|
||||
|
||||
|
||||
void FlushSerialRequestResend();
|
||||
void ClearToSend();
|
||||
|
||||
void showString (PGM_P s);
|
||||
|
||||
void manage_inactivity(byte debug);
|
||||
|
||||
|
||||
void get_coordinates();
|
||||
void prepare_move();
|
||||
void linear_move(unsigned long steps_remaining[]);
|
||||
void do_step(int axis);
|
||||
void prepare_arc_move(char isclockwise);
|
||||
void plan_buffer_line(float x, float y, float z, float e, float feed_rate);
|
||||
|
||||
void kill(byte debug);
|
||||
|
||||
void check_axes_activity();
|
||||
void plan_init();
|
||||
void st_init();
|
||||
void tp_init();
|
||||
void plan_buffer_line(float x, float y, float z, float e, float feed_rate);
|
||||
void plan_set_position(float x, float y, float z, float e);
|
||||
void st_wake_up();
|
||||
void st_synchronize();
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
void log_message(char* message);
|
||||
void log_bool(char* message, bool value);
|
||||
void log_int(char* message, int value);
|
||||
void log_long(char* message, long value);
|
||||
void log_float(char* message, float value);
|
||||
void log_uint(char* message, unsigned int value);
|
||||
void log_ulong(char* message, unsigned long value);
|
||||
#endif
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
143
Sprinter/arc_func.cpp
Normal file
143
Sprinter/arc_func.cpp
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
arc_func.c - high level interface for issuing motion commands
|
||||
Part of Grbl
|
||||
|
||||
Copyright (c) 2009-2011 Simen Svale Skogsrud
|
||||
Copyright (c) 2011 Sungeun K. Jeon
|
||||
|
||||
Grbl 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.
|
||||
|
||||
Grbl 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 Grbl. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <avr/pgmspace.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "Configuration.h"
|
||||
#include "Sprinter.h"
|
||||
|
||||
// The arc is approximated by generating a huge number of tiny, linear segments. The length of each
|
||||
// segment is configured in settings.mm_per_arc_segment.
|
||||
void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8_t axis_1,
|
||||
uint8_t axis_linear, float feed_rate, float radius, uint8_t isclockwise)
|
||||
{
|
||||
// int acceleration_manager_was_enabled = plan_is_acceleration_manager_enabled();
|
||||
// plan_set_acceleration_manager_enabled(false); // disable acceleration management for the duration of the arc
|
||||
float center_axis0 = position[axis_0] + offset[axis_0];
|
||||
float center_axis1 = position[axis_1] + offset[axis_1];
|
||||
float linear_travel = target[axis_linear] - position[axis_linear];
|
||||
float extruder_travel = target[E_AXIS] - position[E_AXIS];
|
||||
float r_axis0 = -offset[axis_0]; // Radius vector from center to current location
|
||||
float r_axis1 = -offset[axis_1];
|
||||
float rt_axis0 = target[axis_0] - center_axis0;
|
||||
float rt_axis1 = target[axis_1] - center_axis1;
|
||||
|
||||
// CCW angle between position and target from circle center. Only one atan2() trig computation required.
|
||||
float angular_travel = atan2(r_axis0*rt_axis1-r_axis1*rt_axis0, r_axis0*rt_axis0+r_axis1*rt_axis1);
|
||||
if (angular_travel < 0) { angular_travel += 2*M_PI; }
|
||||
if (isclockwise) { angular_travel -= 2*M_PI; }
|
||||
|
||||
float millimeters_of_travel = hypot(angular_travel*radius, fabs(linear_travel));
|
||||
if (millimeters_of_travel == 0.0) { return; }
|
||||
uint16_t segments = floor(millimeters_of_travel/MM_PER_ARC_SEGMENT);
|
||||
/*
|
||||
// Multiply inverse feed_rate to compensate for the fact that this movement is approximated
|
||||
// by a number of discrete segments. The inverse feed_rate should be correct for the sum of
|
||||
// all segments.
|
||||
if (invert_feed_rate) { feed_rate *= segments; }
|
||||
*/
|
||||
float theta_per_segment = angular_travel/segments;
|
||||
float linear_per_segment = linear_travel/segments;
|
||||
float extruder_per_segment = extruder_travel/segments;
|
||||
|
||||
/* Vector rotation by transformation matrix: r is the original vector, r_T is the rotated vector,
|
||||
and phi is the angle of rotation. Based on the solution approach by Jens Geisler.
|
||||
r_T = [cos(phi) -sin(phi);
|
||||
sin(phi) cos(phi] * r ;
|
||||
|
||||
For arc generation, the center of the circle is the axis of rotation and the radius vector is
|
||||
defined from the circle center to the initial position. Each line segment is formed by successive
|
||||
vector rotations. This requires only two cos() and sin() computations to form the rotation
|
||||
matrix for the duration of the entire arc. Error may accumulate from numerical round-off, since
|
||||
all double numbers are single precision on the Arduino. (True double precision will not have
|
||||
round off issues for CNC applications.) Single precision error can accumulate to be greater than
|
||||
tool precision in some cases. Therefore, arc path correction is implemented.
|
||||
|
||||
Small angle approximation may be used to reduce computation overhead further. This approximation
|
||||
holds for everything, but very small circles and large mm_per_arc_segment values. In other words,
|
||||
theta_per_segment would need to be greater than 0.1 rad and N_ARC_CORRECTION would need to be large
|
||||
to cause an appreciable drift error. N_ARC_CORRECTION~=25 is more than small enough to correct for
|
||||
numerical drift error. N_ARC_CORRECTION may be on the order a hundred(s) before error becomes an
|
||||
issue for CNC machines with the single precision Arduino calculations.
|
||||
|
||||
This approximation also allows mc_arc to immediately insert a line segment into the planner
|
||||
without the initial overhead of computing cos() or sin(). By the time the arc needs to be applied
|
||||
a correction, the planner should have caught up to the lag caused by the initial mc_arc overhead.
|
||||
This is important when there are successive arc motions.
|
||||
*/
|
||||
// Vector rotation matrix values
|
||||
float cos_T = 1-0.5*theta_per_segment*theta_per_segment; // Small angle approximation
|
||||
float sin_T = theta_per_segment;
|
||||
|
||||
float arc_target[4];
|
||||
float sin_Ti;
|
||||
float cos_Ti;
|
||||
float r_axisi;
|
||||
uint16_t i;
|
||||
int8_t count = 0;
|
||||
|
||||
// Initialize the linear axis
|
||||
arc_target[axis_linear] = position[axis_linear];
|
||||
|
||||
// Initialize the extruder axis
|
||||
arc_target[E_AXIS] = position[E_AXIS];
|
||||
|
||||
for (i = 1; i<segments; i++)
|
||||
{ // Increment (segments-1)
|
||||
|
||||
if (count < N_ARC_CORRECTION) //25 pieces
|
||||
{
|
||||
// Apply vector rotation matrix
|
||||
r_axisi = r_axis0*sin_T + r_axis1*cos_T;
|
||||
r_axis0 = r_axis0*cos_T - r_axis1*sin_T;
|
||||
r_axis1 = r_axisi;
|
||||
count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Arc correction to radius vector. Computed only every N_ARC_CORRECTION increments.
|
||||
// Compute exact location by applying transformation matrix from initial radius vector(=-offset).
|
||||
cos_Ti = cos(i*theta_per_segment);
|
||||
sin_Ti = sin(i*theta_per_segment);
|
||||
r_axis0 = -offset[axis_0]*cos_Ti + offset[axis_1]*sin_Ti;
|
||||
r_axis1 = -offset[axis_0]*sin_Ti - offset[axis_1]*cos_Ti;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
// Update arc_target location
|
||||
arc_target[axis_0] = center_axis0 + r_axis0;
|
||||
arc_target[axis_1] = center_axis1 + r_axis1;
|
||||
arc_target[axis_linear] += linear_per_segment;
|
||||
arc_target[E_AXIS] += extruder_per_segment;
|
||||
|
||||
//showString(PSTR("sec:"));
|
||||
//Serial.println(i);
|
||||
plan_buffer_line(arc_target[X_AXIS], arc_target[Y_AXIS], arc_target[Z_AXIS], arc_target[E_AXIS], feed_rate);
|
||||
|
||||
}
|
||||
// Ensure last segment arrives at target location.
|
||||
//showString(PSTR("Last sec\r\n"));
|
||||
plan_buffer_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], target[E_AXIS], feed_rate);
|
||||
|
||||
// plan_set_acceleration_manager_enabled(acceleration_manager_was_enabled);
|
||||
}
|
||||
|
||||
32
Sprinter/arc_func.h
Normal file
32
Sprinter/arc_func.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
arc_func.h - high level interface for issuing motion commands
|
||||
Part of Grbl
|
||||
|
||||
Copyright (c) 2009-2011 Simen Svale Skogsrud
|
||||
Copyright (c) 2011 Sungeun K. Jeon
|
||||
|
||||
Grbl 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.
|
||||
|
||||
Grbl 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 Grbl. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef arc_func_h
|
||||
#define arc_func_h
|
||||
|
||||
// Execute an arc in offset mode format. position == current xyz, target == target xyz,
|
||||
// offset == offset from current xyz, axis_XXX defines circle plane in tool space, axis_linear is
|
||||
// the direction of helical travel, radius == circle radius, isclockwise boolean. Used
|
||||
// for vector transformation direction.
|
||||
void mc_arc(float *position, float *target, float *offset, unsigned char axis_0, unsigned char axis_1,
|
||||
unsigned char axis_linear, float feed_rate, float radius, unsigned char isclockwise);
|
||||
|
||||
#endif
|
||||
574
Sprinter/heater.cpp
Normal file
574
Sprinter/heater.cpp
Normal file
|
|
@ -0,0 +1,574 @@
|
|||
/*
|
||||
Reprap heater funtions based on Sprinter
|
||||
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/*
|
||||
This softwarepart for Heatercontrol is based on Sprinter
|
||||
big thanks to kliment (https://github.com/kliment/Sprinter)
|
||||
*/
|
||||
|
||||
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
#include "heater.h"
|
||||
#include "fastio.h"
|
||||
#include "pins.h"
|
||||
#include "Sprinter.h"
|
||||
|
||||
|
||||
|
||||
// Manage heater variables. For a thermistor or AD595 thermocouple, raw values refer to the
|
||||
// reading from the analog pin. For a MAX6675 thermocouple, the raw value is the temperature in 0.25
|
||||
// degree increments (i.e. 100=25 deg).
|
||||
|
||||
int target_raw = 0;
|
||||
int target_temp = 0;
|
||||
int current_raw = 0;
|
||||
int current_raw_maxval = -32000;
|
||||
int current_raw_minval = 32000;
|
||||
int tt_maxval;
|
||||
int tt_minval;
|
||||
int target_bed_raw = 0;
|
||||
int current_bed_raw = 0;
|
||||
unsigned long previous_millis_heater, previous_millis_bed_heater, previous_millis_monitor;
|
||||
|
||||
#ifdef PIDTEMP
|
||||
int g_heater_pwm_val = 0;
|
||||
|
||||
unsigned char PWM_off_time = 0;
|
||||
unsigned char PWM_out_on = 0;
|
||||
|
||||
int temp_iState = 0;
|
||||
int temp_dState = 0;
|
||||
int prev_temp = 0;
|
||||
int pTerm;
|
||||
int iTerm;
|
||||
int dTerm;
|
||||
//int output;
|
||||
int error;
|
||||
int heater_duty = 0;
|
||||
const int temp_iState_min = 256L * -PID_INTEGRAL_DRIVE_MAX / PID_IGAIN;
|
||||
const int temp_iState_max = 256L * PID_INTEGRAL_DRIVE_MAX / PID_IGAIN;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef AUTOTEMP
|
||||
float autotemp_max=AUTO_TEMP_MAX;
|
||||
float autotemp_min=AUTO_TEMP_MIN;
|
||||
float autotemp_factor=AUTO_TEMP_FACTOR;
|
||||
int autotemp_setpoint=0;
|
||||
bool autotemp_enabled=true;
|
||||
#endif
|
||||
|
||||
#ifndef HEATER_CURRENT
|
||||
#define HEATER_CURRENT 255
|
||||
#endif
|
||||
|
||||
#ifdef SMOOTHING
|
||||
uint32_t nma = 0;
|
||||
#endif
|
||||
|
||||
#ifdef WATCHPERIOD
|
||||
int watch_raw = -1000;
|
||||
unsigned long watchmillis = 0;
|
||||
#endif
|
||||
|
||||
#ifdef MINTEMP
|
||||
int minttemp = temp2analogh(MINTEMP);
|
||||
#endif
|
||||
|
||||
#ifdef MAXTEMP
|
||||
int maxttemp = temp2analogh(MAXTEMP);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define HEAT_INTERVAL 250
|
||||
#ifdef HEATER_USES_MAX6675
|
||||
unsigned long max6675_previous_millis = 0;
|
||||
int max6675_temp = 2000;
|
||||
|
||||
int read_max6675()
|
||||
{
|
||||
if (millis() - max6675_previous_millis < HEAT_INTERVAL)
|
||||
return max6675_temp;
|
||||
|
||||
max6675_previous_millis = millis();
|
||||
|
||||
max6675_temp = 0;
|
||||
|
||||
#ifdef PRR
|
||||
PRR &= ~(1<<PRSPI);
|
||||
#elif defined PRR0
|
||||
PRR0 &= ~(1<<PRSPI);
|
||||
#endif
|
||||
|
||||
SPCR = (1<<MSTR) | (1<<SPE) | (1<<SPR0);
|
||||
|
||||
// enable TT_MAX6675
|
||||
WRITE(MAX6675_SS, 0);
|
||||
|
||||
// ensure 100ns delay - a bit extra is fine
|
||||
delay(1);
|
||||
|
||||
// read MSB
|
||||
SPDR = 0;
|
||||
for (;(SPSR & (1<<SPIF)) == 0;);
|
||||
max6675_temp = SPDR;
|
||||
max6675_temp <<= 8;
|
||||
|
||||
// read LSB
|
||||
SPDR = 0;
|
||||
for (;(SPSR & (1<<SPIF)) == 0;);
|
||||
max6675_temp |= SPDR;
|
||||
|
||||
// disable TT_MAX6675
|
||||
WRITE(MAX6675_SS, 1);
|
||||
|
||||
if (max6675_temp & 4)
|
||||
{
|
||||
// thermocouple open
|
||||
max6675_temp = 2000;
|
||||
}
|
||||
else
|
||||
{
|
||||
max6675_temp = max6675_temp >> 3;
|
||||
}
|
||||
|
||||
return max6675_temp;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef PID_SOFT_PWM
|
||||
|
||||
void init_Timer2_softpwm(void)
|
||||
{
|
||||
// This is a simple SOFT PWM with 500 Hz for Extruder Heating
|
||||
|
||||
|
||||
TIFR2 = (1 << TOV2); // clear interrupt flag
|
||||
TCCR2B = (1 << CS22) | (1 << CS20); // start timer (ck/128 prescalar)
|
||||
TCCR2A = (1 << WGM21); // CTC mode
|
||||
OCR2A = 128; // We want to have at least 30Hz or else it gets choppy
|
||||
TIMSK2 = (1 << OCIE2A); // enable timer2 output compare match interrupt
|
||||
|
||||
}
|
||||
|
||||
|
||||
ISR(TIMER2_COMPA_vect)
|
||||
{
|
||||
|
||||
|
||||
if(g_heater_pwm_val < 2)
|
||||
{
|
||||
#if LED_PIN > -1
|
||||
WRITE(LED_PIN,LOW);
|
||||
#endif
|
||||
WRITE(HEATER_0_PIN,LOW);
|
||||
PWM_out_on = 0;
|
||||
OCR2A = 128;
|
||||
}
|
||||
else if(g_heater_pwm_val > 253)
|
||||
{
|
||||
#if LED_PIN > -1
|
||||
WRITE(LED_PIN,HIGH);
|
||||
#endif
|
||||
WRITE(HEATER_0_PIN,HIGH);
|
||||
PWM_out_on = 1;
|
||||
OCR2A = 128;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if(PWM_out_on == 1)
|
||||
{
|
||||
|
||||
#if LED_PIN > -1
|
||||
WRITE(LED_PIN,LOW);
|
||||
#endif
|
||||
WRITE(HEATER_0_PIN,LOW);
|
||||
PWM_out_on = 0;
|
||||
OCR2A = PWM_off_time;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
#if LED_PIN > -1
|
||||
WRITE(LED_PIN,HIGH);
|
||||
#endif
|
||||
WRITE(HEATER_0_PIN,HIGH);
|
||||
PWM_out_on = 1;
|
||||
|
||||
if(g_heater_pwm_val > 253)
|
||||
{
|
||||
OCR2A = 253;
|
||||
PWM_off_time = 2;
|
||||
}
|
||||
else if(g_heater_pwm_val < 2)
|
||||
{
|
||||
OCR2A = 2;
|
||||
PWM_off_time = 253;
|
||||
}
|
||||
else
|
||||
{
|
||||
OCR2A = g_heater_pwm_val;
|
||||
PWM_off_time = 255 - g_heater_pwm_val;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void manage_heater()
|
||||
{
|
||||
|
||||
//Temperatur Monitor for repetier
|
||||
if((millis() - previous_millis_monitor) > 250 )
|
||||
{
|
||||
previous_millis_monitor = millis();
|
||||
if(manage_monitor <= 1)
|
||||
{
|
||||
showString(PSTR("MTEMP:"));
|
||||
Serial.print(millis());
|
||||
if(manage_monitor<1)
|
||||
{
|
||||
showString(PSTR(" "));
|
||||
Serial.print(analog2temp(current_raw));
|
||||
showString(PSTR(" "));
|
||||
Serial.print(target_temp);
|
||||
showString(PSTR(" "));
|
||||
Serial.println(heater_duty);
|
||||
}
|
||||
#if THERMISTORBED!=0
|
||||
else
|
||||
{
|
||||
showString(PSTR(" "));
|
||||
Serial.print(analog2tempBed(current_bed_raw));
|
||||
showString(PSTR(" "));
|
||||
Serial.print(analog2tempBed(target_bed_raw));
|
||||
showString(PSTR(" "));
|
||||
if(READ(HEATER_1_PIN))
|
||||
Serial.println(255);
|
||||
else
|
||||
Serial.println(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
// ENDE Temperatur Monitor for repetier
|
||||
|
||||
if((millis() - previous_millis_heater) < HEATER_CHECK_INTERVAL )
|
||||
return;
|
||||
|
||||
previous_millis_heater = millis();
|
||||
|
||||
#ifdef HEATER_USES_THERMISTOR
|
||||
current_raw = analogRead(TEMP_0_PIN);
|
||||
#ifdef DEBUG_HEAT_MGMT
|
||||
log_int("_HEAT_MGMT - analogRead(TEMP_0_PIN)", current_raw);
|
||||
log_int("_HEAT_MGMT - NUMTEMPS", NUMTEMPS);
|
||||
#endif
|
||||
// When using thermistor, when the heater is colder than targer temp, we get a higher analog reading than target,
|
||||
// this switches it up so that the reading appears lower than target for the control logic.
|
||||
current_raw = 1023 - current_raw;
|
||||
#elif defined HEATER_USES_AD595
|
||||
current_raw = analogRead(TEMP_0_PIN);
|
||||
#elif defined HEATER_USES_MAX6675
|
||||
current_raw = read_max6675();
|
||||
#endif
|
||||
|
||||
//MIN / MAX save to display the jitter of Heaterbarrel
|
||||
if(current_raw > current_raw_maxval)
|
||||
current_raw_maxval = current_raw;
|
||||
|
||||
if(current_raw < current_raw_minval)
|
||||
current_raw_minval = current_raw;
|
||||
|
||||
#ifdef SMOOTHING
|
||||
if (!nma) nma = SMOOTHFACTOR * current_raw;
|
||||
nma = (nma + current_raw) - (nma / SMOOTHFACTOR);
|
||||
current_raw = nma / SMOOTHFACTOR;
|
||||
#endif
|
||||
|
||||
#ifdef WATCHPERIOD
|
||||
if(watchmillis && millis() - watchmillis > WATCHPERIOD)
|
||||
{
|
||||
if(watch_raw + 1 >= current_raw)
|
||||
{
|
||||
target_temp = target_raw = 0;
|
||||
WRITE(HEATER_0_PIN,LOW);
|
||||
|
||||
#ifdef PID_SOFT_PWM
|
||||
g_heater_pwm_val = 0;
|
||||
#else
|
||||
analogWrite(HEATER_0_PIN, 0);
|
||||
#if LED_PIN>-1
|
||||
WRITE(LED_PIN,LOW);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
watchmillis = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//If tmp is lower then MINTEMP stop the Heater
|
||||
//or it os better to deaktivate the uutput PIN or PWM ?
|
||||
#ifdef MINTEMP
|
||||
if(current_raw <= minttemp)
|
||||
target_temp = target_raw = 0;
|
||||
#endif
|
||||
|
||||
#ifdef MAXTEMP
|
||||
if(current_raw >= maxttemp)
|
||||
{
|
||||
target_temp = target_raw = 0;
|
||||
|
||||
#if (ALARM_PIN > -1)
|
||||
WRITE(ALARM_PIN,HIGH);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (TEMP_0_PIN > -1) || defined (HEATER_USES_MAX6675) || defined (HEATER_USES_AD595)
|
||||
#ifdef PIDTEMP
|
||||
|
||||
int current_temp = analog2temp(current_raw);
|
||||
error = target_temp - current_temp;
|
||||
int delta_temp = current_temp - prev_temp;
|
||||
|
||||
prev_temp = current_temp;
|
||||
pTerm = ((long)PID_PGAIN * error) / 256;
|
||||
const int H0 = min(HEATER_DUTY_FOR_SETPOINT(target_temp),HEATER_CURRENT);
|
||||
heater_duty = H0 + pTerm;
|
||||
|
||||
if(error < 30)
|
||||
{
|
||||
temp_iState += error;
|
||||
temp_iState = constrain(temp_iState, temp_iState_min, temp_iState_max);
|
||||
iTerm = ((long)PID_IGAIN * temp_iState) / 256;
|
||||
heater_duty += iTerm;
|
||||
}
|
||||
|
||||
int prev_error = abs(target_temp - prev_temp);
|
||||
int log3 = 1; // discrete logarithm base 3, plus 1
|
||||
|
||||
if(prev_error > 81){ prev_error /= 81; log3 += 4; }
|
||||
if(prev_error > 9){ prev_error /= 9; log3 += 2; }
|
||||
if(prev_error > 3){ prev_error /= 3; log3 ++; }
|
||||
|
||||
dTerm = ((long)PID_DGAIN * delta_temp) / (256*log3);
|
||||
heater_duty += dTerm;
|
||||
heater_duty = constrain(heater_duty, 0, HEATER_CURRENT);
|
||||
|
||||
#ifdef PID_SOFT_PWM
|
||||
g_heater_pwm_val = heater_duty;
|
||||
#else
|
||||
analogWrite(HEATER_0_PIN, heater_duty);
|
||||
|
||||
#if LED_PIN>-1
|
||||
analogWrite(LED_PIN, constrain(LED_PWM_FOR_BRIGHTNESS(heater_duty),0,255));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
if(current_raw >= target_raw)
|
||||
{
|
||||
WRITE(HEATER_0_PIN,LOW);
|
||||
#if LED_PIN>-1
|
||||
WRITE(LED_PIN,LOW);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITE(HEATER_0_PIN,HIGH);
|
||||
#if LED_PIN > -1
|
||||
WRITE(LED_PIN,HIGH);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if(millis() - previous_millis_bed_heater < BED_CHECK_INTERVAL)
|
||||
return;
|
||||
|
||||
previous_millis_bed_heater = millis();
|
||||
|
||||
#ifndef TEMP_1_PIN
|
||||
return;
|
||||
#endif
|
||||
|
||||
#if TEMP_1_PIN == -1
|
||||
return;
|
||||
#else
|
||||
|
||||
#ifdef BED_USES_THERMISTOR
|
||||
|
||||
current_bed_raw = analogRead(TEMP_1_PIN);
|
||||
|
||||
#ifdef DEBUG_HEAT_MGMT
|
||||
log_int("_HEAT_MGMT - analogRead(TEMP_1_PIN)", current_bed_raw);
|
||||
log_int("_HEAT_MGMT - BNUMTEMPS", BNUMTEMPS);
|
||||
#endif
|
||||
|
||||
// If using thermistor, when the heater is colder than targer temp, we get a higher analog reading than target,
|
||||
// this switches it up so that the reading appears lower than target for the control logic.
|
||||
current_bed_raw = 1023 - current_bed_raw;
|
||||
#elif defined BED_USES_AD595
|
||||
current_bed_raw = analogRead(TEMP_1_PIN);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef MINTEMP
|
||||
if(current_bed_raw >= target_bed_raw || current_bed_raw < minttemp)
|
||||
#else
|
||||
if(current_bed_raw >= target_bed_raw)
|
||||
#endif
|
||||
{
|
||||
WRITE(HEATER_1_PIN,LOW);
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITE(HEATER_1_PIN,HIGH);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONTROLLERFAN_PIN
|
||||
controllerFan(); //Check if fan should be turned on to cool stepper drivers down
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#if defined (HEATER_USES_THERMISTOR) || defined (BED_USES_THERMISTOR)
|
||||
int temp2analog_thermistor(int celsius, const short table[][2], int numtemps)
|
||||
{
|
||||
int raw = 0;
|
||||
byte i;
|
||||
|
||||
for (i=1; i<numtemps; i++)
|
||||
{
|
||||
if (table[i][1] < celsius)
|
||||
{
|
||||
raw = table[i-1][0] +
|
||||
(celsius - table[i-1][1]) *
|
||||
(table[i][0] - table[i-1][0]) /
|
||||
(table[i][1] - table[i-1][1]);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Overflow: Set to last value in the table
|
||||
if (i == numtemps) raw = table[i-1][0];
|
||||
|
||||
return 1023 - raw;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined (HEATER_USES_AD595) || defined (BED_USES_AD595)
|
||||
int temp2analog_ad595(int celsius)
|
||||
{
|
||||
return celsius * 1024 / (500);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined (HEATER_USES_MAX6675) || defined (BED_USES_MAX6675)
|
||||
int temp2analog_max6675(int celsius)
|
||||
{
|
||||
return celsius * 4;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined (HEATER_USES_THERMISTOR) || defined (BED_USES_THERMISTOR)
|
||||
int analog2temp_thermistor(int raw,const short table[][2], int numtemps) {
|
||||
int celsius = 0;
|
||||
byte i;
|
||||
|
||||
raw = 1023 - raw;
|
||||
|
||||
for (i=1; i<numtemps; i++)
|
||||
{
|
||||
if (table[i][0] > raw)
|
||||
{
|
||||
celsius = table[i-1][1] +
|
||||
(raw - table[i-1][0]) *
|
||||
(table[i][1] - table[i-1][1]) /
|
||||
(table[i][0] - table[i-1][0]);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Overflow: Set to last value in the table
|
||||
if (i == numtemps) celsius = table[i-1][1];
|
||||
|
||||
return celsius;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined (HEATER_USES_AD595) || defined (BED_USES_AD595)
|
||||
int analog2temp_ad595(int raw)
|
||||
{
|
||||
return raw * 500 / 1024;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined (HEATER_USES_MAX6675) || defined (BED_USES_MAX6675)
|
||||
int analog2temp_max6675(int raw)
|
||||
{
|
||||
return raw / 4;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONTROLLERFAN_PIN
|
||||
unsigned long lastMotor = 0; //Save the time for when a motor was turned on last
|
||||
unsigned long lastMotorCheck = 0;
|
||||
|
||||
void controllerFan()
|
||||
{
|
||||
if ((millis() - lastMotorCheck) >= 2500) //Not a time critical function, so we only check every 2500ms
|
||||
{
|
||||
lastMotorCheck = millis();
|
||||
|
||||
if(!READ(X_ENABLE_PIN) || !READ(Y_ENABLE_PIN) || !READ(Z_ENABLE_PIN) || !READ(E_ENABLE_PIN)) //If any of the drivers are enabled...
|
||||
{
|
||||
lastMotor = millis(); //... set time to NOW so the fan will turn on
|
||||
}
|
||||
|
||||
if ((millis() - lastMotor) >= (CONTROLLERFAN_SEC*1000UL) || lastMotor == 0) //If the last time any driver was enabled, is longer since than CONTROLLERSEC...
|
||||
{
|
||||
WRITE(CONTROLLERFAN_PIN, LOW); //... turn the fan off
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITE(CONTROLLERFAN_PIN, HIGH); //... turn the fan on
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
119
Sprinter/heater.h
Normal file
119
Sprinter/heater.h
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
Reprap heater funtions based on Sprinter
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/*
|
||||
This softwarepart for Heatercontrol is based on Sprinter
|
||||
big thanks to kliment (https://github.com/kliment/Sprinter)
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "Configuration.h"
|
||||
#include "thermistortables.h"
|
||||
|
||||
#if defined HEATER_USES_THERMISTOR
|
||||
#define temp2analogh( c ) temp2analog_thermistor(c,temptable,NUMTEMPS)
|
||||
#define analog2temp( c ) analog2temp_thermistor(c,temptable,NUMTEMPS)
|
||||
#elif defined HEATER_USES_AD595
|
||||
#define temp2analogh( c ) temp2analog_ad595(c)
|
||||
#define analog2temp( c ) analog2temp_ad595(c)
|
||||
#elif defined HEATER_USES_MAX6675
|
||||
#define temp2analogh( c ) temp2analog_max6675(c)
|
||||
#define analog2temp( c ) analog2temp_max6675(c)
|
||||
#endif
|
||||
|
||||
#if defined BED_USES_THERMISTOR
|
||||
#define temp2analogBed( c ) temp2analog_thermistor((c),bedtemptable,BNUMTEMPS)
|
||||
#define analog2tempBed( c ) analog2temp_thermistor((c),bedtemptable,BNUMTEMPS)
|
||||
#elif defined BED_USES_AD595
|
||||
#define temp2analogBed( c ) temp2analog_ad595(c)
|
||||
#define analog2tempBed( c ) analog2temp_ad595(c)
|
||||
#elif defined BED_USES_MAX6675
|
||||
#define temp2analogBed( c ) temp2analog_max6675(c)
|
||||
#define analog2tempBed( c ) analog2temp_max6675(c)
|
||||
#endif
|
||||
|
||||
#if defined (HEATER_USES_THERMISTOR) || defined (BED_USES_THERMISTOR)
|
||||
int temp2analog_thermistor(int celsius, const short table[][2], int numtemps);
|
||||
int analog2temp_thermistor(int raw,const short table[][2], int numtemps);
|
||||
#endif
|
||||
|
||||
#if defined (HEATER_USES_AD595) || defined (BED_USES_AD595)
|
||||
int temp2analog_ad595(int celsius);
|
||||
int analog2temp_ad595(int raw);
|
||||
#endif
|
||||
|
||||
#if defined (HEATER_USES_MAX6675) || defined (BED_USES_MAX6675)
|
||||
int temp2analog_max6675(int celsius);
|
||||
int analog2temp_max6675(int raw);
|
||||
#endif
|
||||
|
||||
|
||||
extern int target_raw;
|
||||
extern int target_temp;
|
||||
extern int current_raw;
|
||||
extern int current_raw_maxval;
|
||||
extern int current_raw_minval;
|
||||
extern int tt_maxval;
|
||||
extern int tt_minval;
|
||||
extern int target_bed_raw;
|
||||
extern int current_bed_raw;
|
||||
extern unsigned long previous_millis_heater, previous_millis_bed_heater;
|
||||
extern unsigned char manage_monitor;
|
||||
|
||||
#ifdef PIDTEMP
|
||||
extern int g_heater_pwm_val;
|
||||
|
||||
extern unsigned char PWM_off_time;
|
||||
extern unsigned char PWM_out_on;
|
||||
|
||||
extern int temp_iState;
|
||||
extern int temp_dState;
|
||||
extern int prev_temp;
|
||||
extern int pTerm;
|
||||
extern int iTerm;
|
||||
extern int dTerm;
|
||||
extern int error;
|
||||
extern int heater_duty;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef AUTOTEMP
|
||||
extern float autotemp_max;
|
||||
extern float autotemp_min;
|
||||
extern float autotemp_factor;
|
||||
extern int autotemp_setpoint;
|
||||
extern bool autotemp_enabled;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef SMOOTHING
|
||||
extern uint32_t nma;
|
||||
#endif
|
||||
|
||||
#ifdef WATCHPERIOD
|
||||
extern int watch_raw;
|
||||
extern unsigned long watchmillis;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef PID_SOFT_PWM
|
||||
void init_Timer2_softpwm(void);
|
||||
#endif
|
||||
|
||||
void manage_heater();
|
||||
|
|
@ -637,20 +637,20 @@
|
|||
#define X_STEP_PIN 15
|
||||
#define X_DIR_PIN 21
|
||||
#define X_MIN_PIN 18
|
||||
#define X_MAX_PIN -2
|
||||
#define X_MAX_PIN -2
|
||||
|
||||
#define Y_STEP_PIN 22
|
||||
#define Y_DIR_PIN 23
|
||||
#define Y_MIN_PIN 19
|
||||
#define Y_MAX_PIN -1
|
||||
|
||||
#define Z_STEP_PIN 3
|
||||
#define Z_DIR_PIN 2
|
||||
#define Z_STEP_PIN 3
|
||||
#define Z_DIR_PIN 2
|
||||
#define Z_MIN_PIN 20
|
||||
#define Z_MAX_PIN -1
|
||||
|
||||
#define E_STEP_PIN 1
|
||||
#define E_DIR_PIN 0
|
||||
#define E_STEP_PIN 1
|
||||
#define E_DIR_PIN 0
|
||||
|
||||
#define LED_PIN -1
|
||||
|
||||
|
|
@ -663,30 +663,79 @@
|
|||
#define HEATER_0_PIN 13 // (extruder)
|
||||
|
||||
#ifdef SANGUINOLOLU_V_1_2
|
||||
|
||||
#define HEATER_1_PIN 12 // (bed)
|
||||
#define X_ENABLE_PIN 14
|
||||
#define Y_ENABLE_PIN 14
|
||||
#define Z_ENABLE_PIN 26
|
||||
#define E_ENABLE_PIN 14
|
||||
|
||||
#define HEATER_1_PIN 12 // (bed)
|
||||
#define X_ENABLE_PIN 14
|
||||
#define Y_ENABLE_PIN 14
|
||||
#define Z_ENABLE_PIN 26
|
||||
#define E_ENABLE_PIN 14
|
||||
#else
|
||||
|
||||
#define HEATER_1_PIN 14 // (bed)
|
||||
#define X_ENABLE_PIN -1
|
||||
#define Y_ENABLE_PIN -1
|
||||
#define Z_ENABLE_PIN -1
|
||||
#define E_ENABLE_PIN -1
|
||||
|
||||
#define HEATER_1_PIN 14 // (bed)
|
||||
#define X_ENABLE_PIN -1
|
||||
#define Y_ENABLE_PIN -1
|
||||
#define Z_ENABLE_PIN -1
|
||||
#define E_ENABLE_PIN -1
|
||||
#endif
|
||||
|
||||
#define TEMP_0_PIN 7 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 33 extruder)
|
||||
#define TEMP_1_PIN 6 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 34 bed)
|
||||
#define SDPOWER -1
|
||||
#define SDSS 31
|
||||
#define SDPOWER -1
|
||||
#define SDSS 31
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Gen7 pin assignment
|
||||
*
|
||||
****************************************************************************************/
|
||||
|
||||
#if MOTHERBOARD == 7
|
||||
#define KNOWN_BOARD 1
|
||||
|
||||
#if !defined(__AVR_ATmega644P__) && !defined(__AVR_ATmega1284P__) && !defined(__AVR_ATmega644__)
|
||||
#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu.
|
||||
#endif
|
||||
//x axis pins
|
||||
#define X_STEP_PIN 19
|
||||
#define X_DIR_PIN 18
|
||||
#define X_ENABLE_PIN -1
|
||||
#define X_MIN_PIN 7
|
||||
#define X_MAX_PIN 6
|
||||
|
||||
//y axis pins
|
||||
#define Y_STEP_PIN 23
|
||||
#define Y_DIR_PIN 22
|
||||
#define Y_ENABLE_PIN -1
|
||||
#define Y_MIN_PIN 5
|
||||
#define Y_MAX_PIN 2
|
||||
|
||||
//z axis pins
|
||||
#define Z_STEP_PIN 26
|
||||
#define Z_DIR_PIN 25
|
||||
#define Z_ENABLE_PIN 24
|
||||
#define Z_MIN_PIN 1
|
||||
#define Z_MAX_PIN 0
|
||||
|
||||
//extruder pins
|
||||
#define E_STEP_PIN 28
|
||||
#define E_DIR_PIN 27
|
||||
#define E_ENABLE_PIN -1
|
||||
#define TEMP_0_PIN 1 // Extruder
|
||||
#define HEATER_0_PIN 4 // Extruder
|
||||
#define HEATER_1_PIN 3 // Bed
|
||||
|
||||
|
||||
#define SDPOWER -1
|
||||
#define SDSS -1
|
||||
#define LED_PIN -1
|
||||
#define TEMP_1_PIN 2 //Bed
|
||||
#define FAN_PIN -1
|
||||
#define PS_ON_PIN 15
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Teensylu 0.7 pin assingments (ATMEGA90USB)
|
||||
* Requires the Teensyduino software with Teensy2.0++ selected in arduino IDE!
|
||||
|
|
|
|||
76
Sprinter/speed_lookuptable.h
Normal file
76
Sprinter/speed_lookuptable.h
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
#ifndef SPEED_LOOKUPTABLE_H
|
||||
#define SPEED_LOOKUPTABLE_H
|
||||
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
uint16_t speed_lookuptable_fast[256][2] PROGMEM = {
|
||||
{ 62500, 55556}, { 6944, 3268}, { 3676, 1176}, { 2500, 607}, { 1893, 369}, { 1524, 249}, { 1275, 179}, { 1096, 135},
|
||||
{ 961, 105}, { 856, 85}, { 771, 69}, { 702, 58}, { 644, 49}, { 595, 42}, { 553, 37}, { 516, 32},
|
||||
{ 484, 28}, { 456, 25}, { 431, 23}, { 408, 20}, { 388, 19}, { 369, 16}, { 353, 16}, { 337, 14},
|
||||
{ 323, 13}, { 310, 11}, { 299, 11}, { 288, 11}, { 277, 9}, { 268, 9}, { 259, 8}, { 251, 8},
|
||||
{ 243, 8}, { 235, 7}, { 228, 6}, { 222, 6}, { 216, 6}, { 210, 6}, { 204, 5}, { 199, 5},
|
||||
{ 194, 5}, { 189, 4}, { 185, 4}, { 181, 4}, { 177, 4}, { 173, 4}, { 169, 4}, { 165, 3},
|
||||
{ 162, 3}, { 159, 4}, { 155, 3}, { 152, 3}, { 149, 2}, { 147, 3}, { 144, 3}, { 141, 2},
|
||||
{ 139, 3}, { 136, 2}, { 134, 2}, { 132, 3}, { 129, 2}, { 127, 2}, { 125, 2}, { 123, 2},
|
||||
{ 121, 2}, { 119, 1}, { 118, 2}, { 116, 2}, { 114, 1}, { 113, 2}, { 111, 2}, { 109, 1},
|
||||
{ 108, 2}, { 106, 1}, { 105, 2}, { 103, 1}, { 102, 1}, { 101, 1}, { 100, 2}, { 98, 1},
|
||||
{ 97, 1}, { 96, 1}, { 95, 2}, { 93, 1}, { 92, 1}, { 91, 1}, { 90, 1}, { 89, 1},
|
||||
{ 88, 1}, { 87, 1}, { 86, 1}, { 85, 1}, { 84, 1}, { 83, 0}, { 83, 1}, { 82, 1},
|
||||
{ 81, 1}, { 80, 1}, { 79, 1}, { 78, 0}, { 78, 1}, { 77, 1}, { 76, 1}, { 75, 0},
|
||||
{ 75, 1}, { 74, 1}, { 73, 1}, { 72, 0}, { 72, 1}, { 71, 1}, { 70, 0}, { 70, 1},
|
||||
{ 69, 0}, { 69, 1}, { 68, 1}, { 67, 0}, { 67, 1}, { 66, 0}, { 66, 1}, { 65, 0},
|
||||
{ 65, 1}, { 64, 1}, { 63, 0}, { 63, 1}, { 62, 0}, { 62, 1}, { 61, 0}, { 61, 1},
|
||||
{ 60, 0}, { 60, 0}, { 60, 1}, { 59, 0}, { 59, 1}, { 58, 0}, { 58, 1}, { 57, 0},
|
||||
{ 57, 1}, { 56, 0}, { 56, 0}, { 56, 1}, { 55, 0}, { 55, 1}, { 54, 0}, { 54, 0},
|
||||
{ 54, 1}, { 53, 0}, { 53, 0}, { 53, 1}, { 52, 0}, { 52, 0}, { 52, 1}, { 51, 0},
|
||||
{ 51, 0}, { 51, 1}, { 50, 0}, { 50, 0}, { 50, 1}, { 49, 0}, { 49, 0}, { 49, 1},
|
||||
{ 48, 0}, { 48, 0}, { 48, 1}, { 47, 0}, { 47, 0}, { 47, 0}, { 47, 1}, { 46, 0},
|
||||
{ 46, 0}, { 46, 1}, { 45, 0}, { 45, 0}, { 45, 0}, { 45, 1}, { 44, 0}, { 44, 0},
|
||||
{ 44, 0}, { 44, 1}, { 43, 0}, { 43, 0}, { 43, 0}, { 43, 1}, { 42, 0}, { 42, 0},
|
||||
{ 42, 0}, { 42, 1}, { 41, 0}, { 41, 0}, { 41, 0}, { 41, 0}, { 41, 1}, { 40, 0},
|
||||
{ 40, 0}, { 40, 0}, { 40, 0}, { 40, 1}, { 39, 0}, { 39, 0}, { 39, 0}, { 39, 0},
|
||||
{ 39, 1}, { 38, 0}, { 38, 0}, { 38, 0}, { 38, 0}, { 38, 1}, { 37, 0}, { 37, 0},
|
||||
{ 37, 0}, { 37, 0}, { 37, 0}, { 37, 1}, { 36, 0}, { 36, 0}, { 36, 0}, { 36, 0},
|
||||
{ 36, 1}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 1},
|
||||
{ 34, 0}, { 34, 0}, { 34, 0}, { 34, 0}, { 34, 0}, { 34, 1}, { 33, 0}, { 33, 0},
|
||||
{ 33, 0}, { 33, 0}, { 33, 0}, { 33, 0}, { 33, 1}, { 32, 0}, { 32, 0}, { 32, 0},
|
||||
{ 32, 0}, { 32, 0}, { 32, 0}, { 32, 0}, { 32, 1}, { 31, 0}, { 31, 0}, { 31, 0},
|
||||
{ 31, 0}, { 31, 0}, { 31, 0}, { 31, 1}, { 30, 0}, { 30, 0}, { 30, 0}, { 30, 0},
|
||||
};
|
||||
|
||||
uint16_t speed_lookuptable_slow[256][2] PROGMEM = {
|
||||
{ 62500, 12500}, { 50000, 8334}, { 41666, 5952}, { 35714, 4464}, { 31250, 3473}, { 27777, 2777}, { 25000, 2273}, { 22727, 1894},
|
||||
{ 20833, 1603}, { 19230, 1373}, { 17857, 1191}, { 16666, 1041}, { 15625, 920}, { 14705, 817}, { 13888, 731}, { 13157, 657},
|
||||
{ 12500, 596}, { 11904, 541}, { 11363, 494}, { 10869, 453}, { 10416, 416}, { 10000, 385}, { 9615, 356}, { 9259, 331},
|
||||
{ 8928, 308}, { 8620, 287}, { 8333, 269}, { 8064, 252}, { 7812, 237}, { 7575, 223}, { 7352, 210}, { 7142, 198},
|
||||
{ 6944, 188}, { 6756, 178}, { 6578, 168}, { 6410, 160}, { 6250, 153}, { 6097, 145}, { 5952, 139}, { 5813, 132},
|
||||
{ 5681, 126}, { 5555, 121}, { 5434, 115}, { 5319, 111}, { 5208, 106}, { 5102, 102}, { 5000, 99}, { 4901, 94},
|
||||
{ 4807, 91}, { 4716, 87}, { 4629, 84}, { 4545, 81}, { 4464, 79}, { 4385, 75}, { 4310, 73}, { 4237, 71},
|
||||
{ 4166, 68}, { 4098, 66}, { 4032, 64}, { 3968, 62}, { 3906, 60}, { 3846, 59}, { 3787, 56}, { 3731, 55},
|
||||
{ 3676, 53}, { 3623, 52}, { 3571, 50}, { 3521, 49}, { 3472, 48}, { 3424, 46}, { 3378, 45}, { 3333, 44},
|
||||
{ 3289, 43}, { 3246, 41}, { 3205, 41}, { 3164, 39}, { 3125, 39}, { 3086, 38}, { 3048, 36}, { 3012, 36},
|
||||
{ 2976, 35}, { 2941, 35}, { 2906, 33}, { 2873, 33}, { 2840, 32}, { 2808, 31}, { 2777, 30}, { 2747, 30},
|
||||
{ 2717, 29}, { 2688, 29}, { 2659, 28}, { 2631, 27}, { 2604, 27}, { 2577, 26}, { 2551, 26}, { 2525, 25},
|
||||
{ 2500, 25}, { 2475, 25}, { 2450, 23}, { 2427, 24}, { 2403, 23}, { 2380, 22}, { 2358, 22}, { 2336, 22},
|
||||
{ 2314, 21}, { 2293, 21}, { 2272, 20}, { 2252, 20}, { 2232, 20}, { 2212, 20}, { 2192, 19}, { 2173, 18},
|
||||
{ 2155, 19}, { 2136, 18}, { 2118, 18}, { 2100, 17}, { 2083, 17}, { 2066, 17}, { 2049, 17}, { 2032, 16},
|
||||
{ 2016, 16}, { 2000, 16}, { 1984, 16}, { 1968, 15}, { 1953, 16}, { 1937, 14}, { 1923, 15}, { 1908, 15},
|
||||
{ 1893, 14}, { 1879, 14}, { 1865, 14}, { 1851, 13}, { 1838, 14}, { 1824, 13}, { 1811, 13}, { 1798, 13},
|
||||
{ 1785, 12}, { 1773, 13}, { 1760, 12}, { 1748, 12}, { 1736, 12}, { 1724, 12}, { 1712, 12}, { 1700, 11},
|
||||
{ 1689, 12}, { 1677, 11}, { 1666, 11}, { 1655, 11}, { 1644, 11}, { 1633, 10}, { 1623, 11}, { 1612, 10},
|
||||
{ 1602, 10}, { 1592, 10}, { 1582, 10}, { 1572, 10}, { 1562, 10}, { 1552, 9}, { 1543, 10}, { 1533, 9},
|
||||
{ 1524, 9}, { 1515, 9}, { 1506, 9}, { 1497, 9}, { 1488, 9}, { 1479, 9}, { 1470, 9}, { 1461, 8},
|
||||
{ 1453, 8}, { 1445, 9}, { 1436, 8}, { 1428, 8}, { 1420, 8}, { 1412, 8}, { 1404, 8}, { 1396, 8},
|
||||
{ 1388, 7}, { 1381, 8}, { 1373, 7}, { 1366, 8}, { 1358, 7}, { 1351, 7}, { 1344, 8}, { 1336, 7},
|
||||
{ 1329, 7}, { 1322, 7}, { 1315, 7}, { 1308, 6}, { 1302, 7}, { 1295, 7}, { 1288, 6}, { 1282, 7},
|
||||
{ 1275, 6}, { 1269, 7}, { 1262, 6}, { 1256, 6}, { 1250, 7}, { 1243, 6}, { 1237, 6}, { 1231, 6},
|
||||
{ 1225, 6}, { 1219, 6}, { 1213, 6}, { 1207, 6}, { 1201, 5}, { 1196, 6}, { 1190, 6}, { 1184, 5},
|
||||
{ 1179, 6}, { 1173, 5}, { 1168, 6}, { 1162, 5}, { 1157, 5}, { 1152, 6}, { 1146, 5}, { 1141, 5},
|
||||
{ 1136, 5}, { 1131, 5}, { 1126, 5}, { 1121, 5}, { 1116, 5}, { 1111, 5}, { 1106, 5}, { 1101, 5},
|
||||
{ 1096, 5}, { 1091, 5}, { 1086, 4}, { 1082, 5}, { 1077, 5}, { 1072, 4}, { 1068, 5}, { 1063, 4},
|
||||
{ 1059, 5}, { 1054, 4}, { 1050, 4}, { 1046, 5}, { 1041, 4}, { 1037, 4}, { 1033, 5}, { 1028, 4},
|
||||
{ 1024, 4}, { 1020, 4}, { 1016, 4}, { 1012, 4}, { 1008, 4}, { 1004, 4}, { 1000, 4}, { 996, 4},
|
||||
{ 992, 4}, { 988, 4}, { 984, 4}, { 980, 4}, { 976, 4}, { 972, 4}, { 968, 3}, { 965, 3},
|
||||
};
|
||||
|
||||
#endif
|
||||
Loading…
Reference in a new issue