Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
M
MarlinKimbra
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
machinery
MarlinKimbra
Commits
03152a21
Commit
03152a21
authored
Sep 03, 2015
by
MagoKimbra
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add PID_EXTRUSION_RATE
parent
c9fc2819
Changes
8
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
193 additions
and
88 deletions
+193
-88
changelog.md
Documentation/changelog.md
+1
-0
Configuration_Feature.h
MarlinKimbra/Configuration_Feature.h
+5
-0
Marlin_main.cpp
MarlinKimbra/Marlin_main.cpp
+27
-4
Marlin_main.h
MarlinKimbra/Marlin_main.h
+4
-1
configuration_store.cpp
MarlinKimbra/configuration_store.cpp
+56
-31
language.h
MarlinKimbra/language.h
+2
-0
temperature.cpp
MarlinKimbra/temperature.cpp
+96
-50
temperature.h
MarlinKimbra/temperature.h
+2
-2
No files found.
Documentation/changelog.md
View file @
03152a21
### Version 4.2.0
### Version 4.2.0
*
Add PID Extrusion Rate Kc in percent.
*
New configuration systems (Now you can create a separate file with all configuration and use it in you FW update)
*
New configuration systems (Now you can create a separate file with all configuration and use it in you FW update)
*
New namings for file
*
New namings for file
*
Added more documentation inside configuration file
*
Added more documentation inside configuration file
...
...
MarlinKimbra/Configuration_Feature.h
View file @
03152a21
...
@@ -169,11 +169,16 @@
...
@@ -169,11 +169,16 @@
// is more then PID_FUNCTIONAL_RANGE then the PID will be shut off and the heater will be set to min/max.
// is more then PID_FUNCTIONAL_RANGE then the PID will be shut off and the heater will be set to min/max.
#define PID_FUNCTIONAL_RANGE 10 // degC
#define PID_FUNCTIONAL_RANGE 10 // degC
#define PID_INTEGRAL_DRIVE_MAX PID_MAX // Limit for the integral term
#define PID_INTEGRAL_DRIVE_MAX PID_MAX // Limit for the integral term
// this adds an experimental additional term to the heating power, proportional to the extrusion speed.
// if Kc is chosen well, the additional required power due to increased melting should be compensated.
//#define PID_ADD_EXTRUSION_RATE
#define LPQ_MAX_LEN 50
// HotEnd{HE0,HE1,HE2,HE3}
// HotEnd{HE0,HE1,HE2,HE3}
#define DEFAULT_Kp {40, 40, 40, 40} // Kp for E0, E1, E2, E3
#define DEFAULT_Kp {40, 40, 40, 40} // Kp for E0, E1, E2, E3
#define DEFAULT_Ki {07, 07, 07, 07} // Ki for E0, E1, E2, E3
#define DEFAULT_Ki {07, 07, 07, 07} // Ki for E0, E1, E2, E3
#define DEFAULT_Kd {60, 60, 60, 60} // Kd for E0, E1, E2, E3
#define DEFAULT_Kd {60, 60, 60, 60} // Kd for E0, E1, E2, E3
#define DEFAULT_Kc {100, 100, 100, 100} // heating power = Kc * (e_speed)
/***********************************************************************/
/***********************************************************************/
...
...
MarlinKimbra/Marlin_main.cpp
View file @
03152a21
...
@@ -195,7 +195,7 @@
...
@@ -195,7 +195,7 @@
* M250 - Set LCD contrast C<contrast value> (value 0..63)
* M250 - Set LCD contrast C<contrast value> (value 0..63)
* M280 - Set servo position absolute. P: servo index, S: angle or microseconds
* M280 - Set servo position absolute. P: servo index, S: angle or microseconds
* M300 - Play beep sound S<frequency Hz> P<duration ms>
* M300 - Play beep sound S<frequency Hz> P<duration ms>
* M301 - Set PID parameters P I
and D
* M301 - Set PID parameters P I
D and C
* M302 - Allow cold extrudes, or set the minimum extrude S<temperature>.
* M302 - Allow cold extrudes, or set the minimum extrude S<temperature>.
* M303 - PID relay autotune S<temperature> sets the target temperature. (default target temperature = 150C)
* M303 - PID relay autotune S<temperature> sets the target temperature. (default target temperature = 150C)
* M304 - Set bed PID parameters P I and D
* M304 - Set bed PID parameters P I and D
...
@@ -489,6 +489,10 @@ unsigned long printer_usage_seconds;
...
@@ -489,6 +489,10 @@ unsigned long printer_usage_seconds;
boolean
chdkActive
=
false
;
boolean
chdkActive
=
false
;
#endif
#endif
#if ENABLED(PIDTEMP) && ENABLED(PID_ADD_EXTRUSION_RATE)
int
lpq_len
=
20
;
#endif
//===========================================================================
//===========================================================================
//================================ Functions ================================
//================================ Functions ================================
//===========================================================================
//===========================================================================
...
@@ -5899,25 +5903,44 @@ inline void gcode_M226() {
...
@@ -5899,25 +5903,44 @@ inline void gcode_M226() {
#if ENABLED(PIDTEMP)
#if ENABLED(PIDTEMP)
/**
/**
* M301: Set PID parameters P I D
* M301: Set PID parameters P I D (and optionally C, L)
*
* P[float] Kp term
* I[float] Ki term (unscaled)
* D[float] Kd term (unscaled)
*
* With PID_ADD_EXTRUSION_RATE:
*
* C[float] Kc term
* L[float] LPQ length
*/
*/
inline
void
gcode_M301
()
{
inline
void
gcode_M301
()
{
// multi-hotend PID patch: M301 updates or prints a single hotend's PID values
// multi-hotend PID patch: M301 updates or prints a single hotend's PID values
// default behaviour (omitting E parameter) is to update for hotend 0 only
// default behaviour (omitting E parameter) is to update for hotend 0 only
int
e
=
code_seen
(
'
E
'
)
?
code_value
()
:
0
;
// hotend being updated
int
e
=
code_seen
(
'
H
'
)
?
code_value
()
:
0
;
// hotend being updated
if
(
e
<
HOTENDS
)
{
// catch bad input value
if
(
e
<
HOTENDS
)
{
// catch bad input value
if
(
code_seen
(
'P'
))
PID_PARAM
(
Kp
,
e
)
=
code_value
();
if
(
code_seen
(
'P'
))
PID_PARAM
(
Kp
,
e
)
=
code_value
();
if
(
code_seen
(
'I'
))
PID_PARAM
(
Ki
,
e
)
=
scalePID_i
(
code_value
());
if
(
code_seen
(
'I'
))
PID_PARAM
(
Ki
,
e
)
=
scalePID_i
(
code_value
());
if
(
code_seen
(
'D'
))
PID_PARAM
(
Kd
,
e
)
=
scalePID_d
(
code_value
());
if
(
code_seen
(
'D'
))
PID_PARAM
(
Kd
,
e
)
=
scalePID_d
(
code_value
());
#if ENABLED(PID_ADD_EXTRUSION_RATE)
if
(
code_seen
(
'C'
))
PID_PARAM
(
Kc
,
e
)
=
code_value
();
if
(
code_seen
(
'L'
))
lpq_len
=
code_value
();
NOMORE
(
lpq_len
,
LPQ_MAX_LEN
);
#endif
updatePID
();
updatePID
();
ECHO_SMV
(
OK
,
"e:"
,
e
);
ECHO_SMV
(
OK
,
"e:"
,
e
);
ECHO_MV
(
" p:"
,
PID_PARAM
(
Kp
,
e
));
ECHO_MV
(
" p:"
,
PID_PARAM
(
Kp
,
e
));
ECHO_MV
(
" i:"
,
unscalePID_i
(
PID_PARAM
(
Ki
,
e
)));
ECHO_MV
(
" i:"
,
unscalePID_i
(
PID_PARAM
(
Ki
,
e
)));
ECHO_EMV
(
" d:"
,
unscalePID_d
(
PID_PARAM
(
Kd
,
e
)));
ECHO_MV
(
" d:"
,
unscalePID_d
(
PID_PARAM
(
Kd
,
e
)));
#if ENABLED(PID_ADD_EXTRUSION_RATE)
ECHO_MV
(
" c:"
,
PID_PARAM
(
Kc
,
e
));
#endif
ECHO_E
;
}
}
else
{
else
{
ECHO_LM
(
ER
,
MSG_INVALID_EXTRUDER
);
ECHO_LM
(
ER
,
MSG_INVALID_EXTRUDER
);
...
...
MarlinKimbra/Marlin_main.h
View file @
03152a21
...
@@ -10,7 +10,6 @@ void idle(bool ignore_stepper_queue = false);
...
@@ -10,7 +10,6 @@ void idle(bool ignore_stepper_queue = false);
void
manage_inactivity
(
bool
ignore_stepper_queue
=
false
);
void
manage_inactivity
(
bool
ignore_stepper_queue
=
false
);
void
FlushSerialRequestResend
();
void
FlushSerialRequestResend
();
void
ok_to_send
();
void
ok_to_send
();
...
@@ -172,6 +171,10 @@ extern int fanSpeed;
...
@@ -172,6 +171,10 @@ extern int fanSpeed;
extern
void
IDLE_OOZING_retract
(
bool
retracting
);
extern
void
IDLE_OOZING_retract
(
bool
retracting
);
#endif
#endif
#if ENABLED(PIDTEMP) && ENABLED(PID_ADD_EXTRUSION_RATE)
extern
int
lpq_len
;
#endif
#if ENABLED(FWRETRACT)
#if ENABLED(FWRETRACT)
extern
bool
autoretract_enabled
;
extern
bool
autoretract_enabled
;
extern
bool
retracted
[
EXTRUDERS
];
// extruder[n].retracted
extern
bool
retracted
[
EXTRUDERS
];
// extruder[n].retracted
...
...
MarlinKimbra/configuration_store.cpp
View file @
03152a21
...
@@ -29,10 +29,10 @@
...
@@ -29,10 +29,10 @@
*
*
*/
*/
#define EEPROM_VERSION "V2
4
"
#define EEPROM_VERSION "V2
5
"
/**
/**
* V2
4
EEPROM Layout:
* V2
5
EEPROM Layout:
*
*
* ver
* ver
* M92 XYZ E0 ... axis_steps_per_unit X,Y,Z,E0 ... (per extruder)
* M92 XYZ E0 ... axis_steps_per_unit X,Y,Z,E0 ... (per extruder)
...
@@ -77,10 +77,11 @@
...
@@ -77,10 +77,11 @@
* M145 S2 F gumPreheatFanSpeed
* M145 S2 F gumPreheatFanSpeed
*
*
* PIDTEMP:
* PIDTEMP:
* M301 E0 PID Kp[0], Ki[0], Kd[0]
* M301 E0 PIDC Kp[0], Ki[0], Kd[0], Kc[0]
* M301 E1 PID Kp[1], Ki[1], Kd[1]
* M301 E1 PIDC Kp[1], Ki[1], Kd[1], Kc[1]
* M301 E2 PID Kp[2], Ki[2], Kd[2]
* M301 E2 PIDC Kp[2], Ki[2], Kd[2], Kc[2]
* M301 E3 PID Kp[3], Ki[3], Kd[3]
* M301 E3 PIDC Kp[3], Ki[3], Kd[3], Kc[3]
* M301 L lpq_len
*
*
* PIDTEMPBED:
* PIDTEMPBED:
* M304 PID bedKp, bedKi, bedKd
* M304 PID bedKp, bedKi, bedKd
...
@@ -199,13 +200,19 @@ void Config_StoreSettings() {
...
@@ -199,13 +200,19 @@ void Config_StoreSettings() {
EEPROM_WRITE_VAR
(
i
,
gumPreheatFanSpeed
);
EEPROM_WRITE_VAR
(
i
,
gumPreheatFanSpeed
);
#if ENABLED(PIDTEMP)
#if ENABLED(PIDTEMP)
for
(
int
e
=
0
;
e
<
HOTENDS
;
e
++
)
{
for
(
int
h
=
0
;
h
<
HOTENDS
;
h
++
)
{
EEPROM_WRITE_VAR
(
i
,
PID_PARAM
(
Kp
,
e
));
EEPROM_WRITE_VAR
(
i
,
PID_PARAM
(
Kp
,
h
));
EEPROM_WRITE_VAR
(
i
,
PID_PARAM
(
Ki
,
e
));
EEPROM_WRITE_VAR
(
i
,
PID_PARAM
(
Ki
,
h
));
EEPROM_WRITE_VAR
(
i
,
PID_PARAM
(
Kd
,
e
));
EEPROM_WRITE_VAR
(
i
,
PID_PARAM
(
Kd
,
h
));
EEPROM_WRITE_VAR
(
i
,
PID_PARAM
(
Kc
,
h
));
}
}
#endif
#endif
#if DISABLED(PID_ADD_EXTRUSION_RATE)
int
lpq_len
=
20
;
#endif
EEPROM_WRITE_VAR
(
i
,
lpq_len
);
#if ENABLED(PIDTEMPBED)
#if ENABLED(PIDTEMPBED)
EEPROM_WRITE_VAR
(
i
,
bedKp
);
EEPROM_WRITE_VAR
(
i
,
bedKp
);
EEPROM_WRITE_VAR
(
i
,
bedKi
);
EEPROM_WRITE_VAR
(
i
,
bedKi
);
...
@@ -336,13 +343,19 @@ void Config_RetrieveSettings() {
...
@@ -336,13 +343,19 @@ void Config_RetrieveSettings() {
EEPROM_READ_VAR
(
i
,
gumPreheatFanSpeed
);
EEPROM_READ_VAR
(
i
,
gumPreheatFanSpeed
);
#if ENABLED(PIDTEMP)
#if ENABLED(PIDTEMP)
for
(
int8_t
e
=
0
;
e
<
HOTENDS
;
e
++
)
{
for
(
int8_t
h
=
0
;
h
<
HOTENDS
;
h
++
)
{
EEPROM_READ_VAR
(
i
,
PID_PARAM
(
Kp
,
e
));
EEPROM_READ_VAR
(
i
,
PID_PARAM
(
Kp
,
h
));
EEPROM_READ_VAR
(
i
,
PID_PARAM
(
Ki
,
e
));
EEPROM_READ_VAR
(
i
,
PID_PARAM
(
Ki
,
h
));
EEPROM_READ_VAR
(
i
,
PID_PARAM
(
Kd
,
e
));
EEPROM_READ_VAR
(
i
,
PID_PARAM
(
Kd
,
h
));
EEPROM_READ_VAR
(
i
,
PID_PARAM
(
Kc
,
h
));
}
}
#endif // PIDTEMP
#endif // PIDTEMP
#if DISABLED(PID_ADD_EXTRUSION_RATE)
int
lpq_len
;
#endif
EEPROM_READ_VAR
(
i
,
lpq_len
);
#if ENABLED(PIDTEMPBED)
#if ENABLED(PIDTEMPBED)
EEPROM_READ_VAR
(
i
,
bedKp
);
EEPROM_READ_VAR
(
i
,
bedKp
);
EEPROM_READ_VAR
(
i
,
bedKi
);
EEPROM_READ_VAR
(
i
,
bedKi
);
...
@@ -420,14 +433,15 @@ void Config_ResetDefault() {
...
@@ -420,14 +433,15 @@ void Config_ResetDefault() {
float
tmp6
[]
=
DEFAULT_Kp
;
float
tmp6
[]
=
DEFAULT_Kp
;
float
tmp7
[]
=
DEFAULT_Ki
;
float
tmp7
[]
=
DEFAULT_Ki
;
float
tmp8
[]
=
DEFAULT_Kd
;
float
tmp8
[]
=
DEFAULT_Kd
;
float
tmp9
[]
=
DEFAULT_Kc
;
#endif // PIDTEMP
#endif // PIDTEMP
#if ENABLED(HOTEND_OFFSET_X) && ENABLED(HOTEND_OFFSET_Y)
#if ENABLED(HOTEND_OFFSET_X) && ENABLED(HOTEND_OFFSET_Y)
float
tmp
9
[]
=
HOTEND_OFFSET_X
;
float
tmp
10
[]
=
HOTEND_OFFSET_X
;
float
tmp1
0
[]
=
HOTEND_OFFSET_Y
;
float
tmp1
1
[]
=
HOTEND_OFFSET_Y
;
#else
#else
float
tmp9
[]
=
{
0
};
float
tmp10
[]
=
{
0
};
float
tmp10
[]
=
{
0
};
float
tmp11
[]
=
{
0
};
#endif
#endif
for
(
int8_t
i
=
0
;
i
<
3
+
EXTRUDERS
;
i
++
)
{
for
(
int8_t
i
=
0
;
i
<
3
+
EXTRUDERS
;
i
++
)
{
...
@@ -459,14 +473,14 @@ void Config_ResetDefault() {
...
@@ -459,14 +473,14 @@ void Config_ResetDefault() {
else
else
max_e_jerk
[
i
]
=
tmp5
[
max_i
-
1
];
max_e_jerk
[
i
]
=
tmp5
[
max_i
-
1
];
#if HOTENDS > 1
#if HOTENDS > 1
max_i
=
sizeof
(
tmp
9
)
/
sizeof
(
*
tmp9
);
max_i
=
sizeof
(
tmp
10
)
/
sizeof
(
*
tmp10
);
if
(
i
<
max_i
)
if
(
i
<
max_i
)
hotend_offset
[
X_AXIS
][
i
]
=
tmp
9
[
i
];
hotend_offset
[
X_AXIS
][
i
]
=
tmp
10
[
i
];
else
else
hotend_offset
[
X_AXIS
][
i
]
=
0
;
hotend_offset
[
X_AXIS
][
i
]
=
0
;
max_i
=
sizeof
(
tmp1
0
)
/
sizeof
(
*
tmp10
);
max_i
=
sizeof
(
tmp1
1
)
/
sizeof
(
*
tmp11
);
if
(
i
<
max_i
)
if
(
i
<
max_i
)
hotend_offset
[
Y_AXIS
][
i
]
=
tmp1
0
[
i
];
hotend_offset
[
Y_AXIS
][
i
]
=
tmp1
1
[
i
];
else
else
hotend_offset
[
Y_AXIS
][
i
]
=
0
;
hotend_offset
[
Y_AXIS
][
i
]
=
0
;
#endif // HOTENDS > 1
#endif // HOTENDS > 1
...
@@ -535,11 +549,15 @@ void Config_ResetDefault() {
...
@@ -535,11 +549,15 @@ void Config_ResetDefault() {
#endif
#endif
#if ENABLED(PIDTEMP)
#if ENABLED(PIDTEMP)
for
(
int8_t
e
=
0
;
e
<
HOTENDS
;
e
++
)
{
for
(
int8_t
h
=
0
;
h
<
HOTENDS
;
h
++
)
{
Kp
[
e
]
=
tmp6
[
e
];
Kp
[
h
]
=
tmp6
[
h
];
Ki
[
e
]
=
scalePID_i
(
tmp7
[
e
]);
Ki
[
h
]
=
scalePID_i
(
tmp7
[
h
]);
Kd
[
e
]
=
scalePID_d
(
tmp8
[
e
]);
Kd
[
h
]
=
scalePID_d
(
tmp8
[
h
]);
Kc
[
h
]
=
tmp9
[
h
];
}
}
#if ENABLED(PID_ADD_EXTRUSION_RATE)
lpq_len
=
20
;
// default last-position-queue size
#endif
// call updatePID (similar to when we have processed M301)
// call updatePID (similar to when we have processed M301)
updatePID
();
updatePID
();
#endif // PIDTEMP
#endif // PIDTEMP
...
@@ -752,12 +770,19 @@ void Config_ResetDefault() {
...
@@ -752,12 +770,19 @@ void Config_ResetDefault() {
ECHO_LM
(
DB
,
"PID settings:"
);
ECHO_LM
(
DB
,
"PID settings:"
);
}
}
#if ENABLED(PIDTEMP)
#if ENABLED(PIDTEMP)
for
(
int
e
=
0
;
e
<
HOTENDS
;
e
++
)
{
for
(
int
h
=
0
;
h
<
HOTENDS
;
h
++
)
{
ECHO_SMV
(
DB
,
" M301 E"
,
e
);
ECHO_SMV
(
DB
,
" M301 H"
,
h
);
ECHO_MV
(
" P"
,
PID_PARAM
(
Kp
,
e
));
ECHO_MV
(
" P"
,
PID_PARAM
(
Kp
,
h
));
ECHO_MV
(
" I"
,
unscalePID_i
(
PID_PARAM
(
Ki
,
e
)));
ECHO_MV
(
" I"
,
unscalePID_i
(
PID_PARAM
(
Ki
,
h
)));
ECHO_EMV
(
" D"
,
unscalePID_d
(
PID_PARAM
(
Kd
,
e
)));
ECHO_MV
(
" D"
,
unscalePID_d
(
PID_PARAM
(
Kd
,
h
)));
}
#if ENABLED(PID_ADD_EXTRUSION_RATE)
ECHO_MV
(
" C"
,
PID_PARAM
(
Kc
,
h
));
#endif
ECHO_E
;
}
#if ENABLED(PID_ADD_EXTRUSION_RATE)
ECHO_SMV
(
DB
,
" M301 L"
,
lpq_len
);
#endif
#endif
#endif
#if ENABLED(PIDTEMPBED)
#if ENABLED(PIDTEMPBED)
ECHO_SMV
(
DB
,
" M304 P"
,
bedKp
);
// for compatibility with hosts, only echos values for E0
ECHO_SMV
(
DB
,
" M304 P"
,
bedKp
);
// for compatibility with hosts, only echos values for E0
...
...
MarlinKimbra/language.h
View file @
03152a21
...
@@ -179,6 +179,7 @@
...
@@ -179,6 +179,7 @@
#define MSG_KP " Kp: "
#define MSG_KP " Kp: "
#define MSG_KI " Ki: "
#define MSG_KI " Ki: "
#define MSG_KD " Kd: "
#define MSG_KD " Kd: "
#define MSG_KC " Kc: "
#define MSG_B "B:"
#define MSG_B "B:"
#define MSG_T "T:"
#define MSG_T "T:"
#define MSG_AT "@:"
#define MSG_AT "@:"
...
@@ -191,6 +192,7 @@
...
@@ -191,6 +192,7 @@
#define MSG_PID_DEBUG_PTERM " pTerm "
#define MSG_PID_DEBUG_PTERM " pTerm "
#define MSG_PID_DEBUG_ITERM " iTerm "
#define MSG_PID_DEBUG_ITERM " iTerm "
#define MSG_PID_DEBUG_DTERM " dTerm "
#define MSG_PID_DEBUG_DTERM " dTerm "
#define MSG_PID_DEBUG_CTERM " cTerm "
#define MSG_INVALID_EXTRUDER_NUM " - Invalid extruder number !"
#define MSG_INVALID_EXTRUDER_NUM " - Invalid extruder number !"
#define MSG_HEATER_BED "bed"
#define MSG_HEATER_BED "bed"
...
...
MarlinKimbra/temperature.cpp
View file @
03152a21
This diff is collapsed.
Click to expand it.
MarlinKimbra/temperature.h
View file @
03152a21
...
@@ -62,12 +62,12 @@ extern float current_temperature_bed;
...
@@ -62,12 +62,12 @@ extern float current_temperature_bed;
#endif
#endif
#if ENABLED(PIDTEMP)
#if ENABLED(PIDTEMP)
extern
float
Kp
[
HOTENDS
],
Ki
[
HOTENDS
],
Kd
[
HOTENDS
];
extern
float
Kp
[
HOTENDS
],
Ki
[
HOTENDS
],
Kd
[
HOTENDS
]
,
Kc
[
HOTENDS
]
;
#define PID_PARAM(param, e) param[e] // use macro to point to array value
#define PID_PARAM(param, e) param[e] // use macro to point to array value
#endif
#endif
#if ENABLED(PIDTEMPBED)
#if ENABLED(PIDTEMPBED)
extern
float
bedKp
,
bedKi
,
bedKd
;
extern
float
bedKp
,
bedKi
,
bedKd
;
#endif
#endif
#if ENABLED(PIDTEMP) || ENABLED(PIDTEMPBED)
#if ENABLED(PIDTEMP) || ENABLED(PIDTEMPBED)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment