Jump to content

Heat Soak Macro's


mvdveer

Recommended Posts

Seeing this came up in a previous discussion/thread, I thought I would share what I found and have been using to heat soak the chamber on my Voron 2.4r2 300mm build. 

Must say, still have not achieved putting a heat soak parameter in the Start_print macro with success, but I will keep trying. I have a summary of the thread that I attached as a .txt file for this interested.

This is from the Klipper Discord group:

https://klipper.discourse.group/t/interruptible-heat-soak/1552

I include garethky's repository and Klipper configuration as acknowledgement of his work and is at:

https://github.com/garethky/klipper-voron2.4-config

Statement: I do not know the author or have any affiliation with the author.

Hope this may be of use to someone.

Interuptible Heat soak.txt

Link to comment
Share on other sites

46 minutes ago, rkolbi said:

Thanks for that - can this be called from the Print_Start macro? The one thing I have not ventured into is macro creation. My next learning objective - UNDERSTANDING macros. Currently as a language, I think Latin is easier than Klipper macros 🙂

PS: Your macros to me is extensive but must be honest, as a noob - do not understand them. (Had a look at your repository - impressive work

Edited by mvdveer
Added comment to clarify
Link to comment
Share on other sites

7 hours ago, mvdveer said:

can this be called from the Print_Start macro?

I have been working with this same issue.

[gcode_macro HEAT_SPREAD]
gcode:
  STATUS_STANDBY                  ; turn on LEDs
  G28                             ; home all axes
  G0 Z5 F4000                     ; move Z to 5mm above buildplate
  G0 X60 Y60 F6000                ; move toolhead to center of build plate
  M140 S100                       ; set bed temp to 100C
  M106 S204                       ; turn on part cooling fans at 80%

Calling it as standalone it works great but when called (or ran as commands) within the PRINT_START it will read ahead to the set_bed_temp part and treat it as M190 (wait for bed temp). I have no idea where to change this behavior.

Link to comment
Share on other sites

What exactly do you want in the print start? I just turn the bed on and the nozzle to 170deg, then say it should wait till the chamber thermistor reaches the temp that comes from the slicer, then heating the nozzle to the final temp and everything else.

Link to comment
Share on other sites

1 hour ago, fl0w said:

What exactly do you want in the print start?

I use the part cooling fans above the center of the bed as it heats to speed up the chamber heating. This means that I would like the PRINT_START to allow the homing, moving the toolhead to the center of the build plate and turning on the fans BEFORE turning on the bed heater and waiting for it to reach temperature but this is not the default behavior when calling print_start.

When I print ASA then I get better results leaving the chamber open so I am less concerned with the chamber temperature sensor. I use that for my reference. If I wanted to add a specific heat soak time I could add something like G4 P60000 to add a one minute wait.

Link to comment
Share on other sites

 

So this is my Heat_Soak Macro, I found it somewhere but sadly did not write down who created it in the first place so cannot give credits to them. I modified it by adding the Stealthburner LED Macros and firing up the Nevermore Filter. The Maybe_Home function is from RatOS so maybe you have to go back to Home or G28 there, or you check out RatOS in its DEV Branch on Github as the Voron 2.4 and 0.1 is included now

[gcode_macro CENTER]
description: move Toolhead to centered Position
gcode:
    G0 X150 Y150 Z50 F3500

[gcode_macro HEAT_SOAK]
description: heats the bed for a while

variable_target_temp: 0
variable_stage: None ## heating -> soaking -> done -> None

## in seconds
variable_check_interval: 10
variable_soak_time_remaining: 0
variable_total_time_elapsed: 0

gcode:
    {% set TARGET = params.TARGET | default(0) | float %}
    {% set DURATION = (params.DURATION | default(15) | int) * 60 %} ## minutes to seconds

    SET_GCODE_VARIABLE MACRO=HEAT_SOAK VARIABLE=target_temp         VALUE={ TARGET }
    SET_GCODE_VARIABLE MACRO=HEAT_SOAK VARIABLE=stage               VALUE="'heating'"
    SET_GCODE_VARIABLE MACRO=HEAT_SOAK VARIABLE=soak_time_remaining VALUE={ DURATION }
    SET_GCODE_VARIABLE MACRO=HEAT_SOAK VARIABLE=total_time_elapsed  VALUE=0
    ;; fire up the heateR
    SET_HEATER_TEMPERATURE HEATER=heater_bed TARGET={ TARGET }
    ;; run the fan to circulate air
    SET_FAN_SPEED FAN=Nevermore SPEED=0.65
    ;; put the bed and nozzle where they're a safe distance apart
    STATUS_HOMING
    MAYBE_HOME
    CENTER
    M84 ;; turn off steppers
    STATUS_BUSY
    UPDATE_DELAYED_GCODE ID=heat_soaker DURATION={ check_interval }
    ;; pause the print during heat soak
    PAUSE_BASE

[gcode_macro CANCEL_HEAT_SOAK]
description: cancels an in-progress HEAT_SOAK cycle
gcode:
    SET_GCODE_VARIABLE MACRO=HEAT_SOAK VARIABLE=stage VALUE="'cancel'"
    UPDATE_DELAYED_GCODE ID=heat_soaker DURATION=1
    SET_FAN_SPEED FAN=Nevermore SPEED=0

[delayed_gcode heat_soaker]
; ## debug
; { action_respond_info( printer['gcode_macro HEAT_SOAK'] | tojson )}
gcode:
    {% set heat_soak = printer['gcode_macro HEAT_SOAK'] %}
    ## update total time elapsed
    {% set total_time_elapsed = heat_soak.total_time_elapsed + heat_soak.check_interval %}
    SET_GCODE_VARIABLE MACRO=HEAT_SOAK VARIABLE=total_time_elapsed VALUE={ total_time_elapsed }
    {% set stage = heat_soak.stage %}
    {% if stage == "heating" and printer.heater_bed.temperature >= heat_soak.target_temp %}
        {% set stage = "soaking" %}
    {% endif %}
    {% if stage == "soaking" %}
        ## update soak countdown
        {% set soak_time_remaining = [heat_soak.soak_time_remaining - heat_soak.check_interval, 0] | max %}
        SET_GCODE_VARIABLE MACRO=HEAT_SOAK VARIABLE=soak_time_remaining VALUE={ soak_time_remaining }
        {% if soak_time_remaining == 0 %}
            {% set stage = "done" %}
        {% endif %}
    {% endif %}
    SET_GCODE_VARIABLE MACRO=HEAT_SOAK VARIABLE=stage VALUE="'{ stage }'"
    {% if stage in ("done", "cancel") %}
        {% if stage == "cancel" %}
            {% set stage = "done" %}
            TURN_OFF_HEATERS
            M107 ; turn off fan
            M117 { "soak cancelled after ~%.1fm" | format(total_time_elapsed / 60.0) }
            ;; heat soak was cancelled -- also cancel the print
            CANCEL_PRINT
        {% else %}
            M117 { "soak complete after %.1fm" | format(total_time_elapsed / 60.0) }
            ;; heat soak is complete. Call the complete macro prior to starting the print
            SOAK_COMPLETE
            ;; resume / start the print
            RESUME_BASE
            STATUS_READY
        {% endif %}
        ## reset all state vars, except stage, which may be queried via the api
        SET_GCODE_VARIABLE MACRO=HEAT_SOAK VARIABLE=target_temp         VALUE=0
        SET_GCODE_VARIABLE MACRO=HEAT_SOAK VARIABLE=soak_time_remaining VALUE=0
        SET_GCODE_VARIABLE MACRO=HEAT_SOAK VARIABLE=total_time_elapsed  VALUE=0
    {% else %}
       {% if total_time_elapsed % 90 == 0 %}
            ## output status periodically
            {% if stage == "heating" %}
                M117 { "heating -- %.1fm elapsed" | format(total_time_elapsed / 60.0) }
            {% elif stage == "soaking" %}
                M117 { "soaking -- %.1fm remaining" | format(soak_time_remaining / 60.0) }
            {% endif %}
        {% endif %}
        ## trigger ourselves again
        UPDATE_DELAYED_GCODE ID=heat_soaker DURATION={ heat_soak.check_interval }
        ## dwell for 1ms to prevent from going idle
        G4 P1
    {% endif %}

 

Link to comment
Share on other sites

2 hours ago, atrushing said:

not the default behavior when calling print_start

At least I found the source of my problem and it wasn't Klipper. When Prusa Slicer exports the gcode it adds the following two lines before it applies my print_start gcode:

M190 S100 ; set bed temperature and wait for it to be reached
M104 S255 ; set temperature

Then it calls the PRINT_START.

If I remove the M190 line then my print_start works as expected. Now I just have to solve the Prusa Slicer issue or add a post processing script to remove that line automatically. Maybe I should just upgrade to Super Slicer!

Link to comment
Share on other sites

1 hour ago, atrushing said:

At least I found the source of my problem and it wasn't Klipper. When Prusa Slicer exports the gcode it adds the following two lines before it applies my print_start gcode:

M190 S100 ; set bed temperature and wait for it to be reached
M104 S255 ; set temperature

Then it calls the PRINT_START.

If I remove the M190 line then my print_start works as expected. Now I just have to solve the Prusa Slicer issue or add a post processing script to remove that line automatically. Maybe I should just upgrade to Super Slicer!

In your start gcode in Superslicer/Prusaslicer, add this above your PRINT_START call:

M104 S0 ; Stops PS/SS from sending temp waits separately
M140 S0
PRINT_START <rest of your parameters>

 

  • Thanks 1
Link to comment
Share on other sites

14 hours ago, mvdveer said:

can this be called from the Print_Start macro

 

Print_Start gets divided into two parts.

Non-blocking waiting:
https://github.com/rkolbi/voron2.4/blob/main/MY_V24-350 ADAPTIVE_MESH/ACTIVE/MACRO-WAITING_ROUTINES.cfg
Lines 54 through 117

Print_Start:
https://github.com/rkolbi/voron2.4/blob/main/MY_V24-350 ADAPTIVE_MESH/ACTIVE/MACRO-PRINT_HANDLING.cfg
Lines 44 through 123

PRINT_START:
Lines 64 and 65 save the EXTRUDER_READY and EXTRUDER_TEMP information passed from the start_gcode to the non-blocking waiting routine. Line 70 gets the duration of the soak from the passed start_gcode as SOAK.
Rest of PRINT_START homes and QGL the printer (if desired). Line 97 calls the non-blocking soak routine, passing the SOAK time.  

_PRINT_START2:
Picks up from where PRINT_START left off before the soak, using EXTRUDER_READY and EXTRUDER_TEMP information (lines 104 and 105) that was stored previously.

 

  • Thanks 1
Link to comment
Share on other sites

I simplified mine a bit. 

Relevant snippet from print_start

{% if printer["temperature_fan chamber"].temperature < chambertemp %}
  _HEATSOAK TEMP={bedtemp} MOVE=1                                           # Set up to heat soak if chamber temp is set higher than current reading
  M190 S{bedtemp}                                                           # Set target bed temp & wait for it
  TEMPERATURE_WAIT SENSOR="temperature_fan chamber" MINIMUM={chambertemp}   # Do the actual heat soak wait, until chamber temp is at target
{% else %}
  {% if printer.heater_bed.temperature < (bedtemp-2) %}
    _HEATSOAK TEMP={bedtemp} MOVE=1	        						       # Bed is below target temp, get it heating & safely park toolhead
    M190 S{bedtemp}                                                        # Set bed target temp & wait for it
  {% else %}
    _HEATSOAK TEMP={bedtemp} MOVE=0                                        # Just do a bed heat, no champer temp (open case for PLA)
  {% endif %}
{% endif %}
M106 S0                                                                    # Turn off part cooling fan from heatsoak

Heat soak macro it calls

[gcode_macro _HEATSOAK]
description: Helper: Set up to heat soak printer. Usage: _HEATSOAK [TEMP=temp(110)] [MOVE=move(1)]
gcode:
  {% set temp = params.TEMP|default(110)|int %}
  {% set move = params.MOVE|default(1)|int %}
	
	LED_HEATING
	_PRINT_AR T="Warming up"
	M141 S0                                                 # Turn off exhaust fan
	M140 S{temp}                                            # Heat the bed
	{% if temp >= 100 %}                                    # It's ABS or other high-temp plastic, closed case
		M104 S170                                             # Set hotend to no-ooze temp
		M106 S205                                             # Turn on part fan to 80% for 
		SET_FAN_SPEED FAN=nevermore SPEED=1                   # Turn on Nevermore fans to circulate & accelerate chamber soak
	{% else %}
		M106 S0                                               # Turn off part fan. Open case, no need
		SET_FAN_SPEED FAN=nevermore SPEED=0                   # Make sure Nevermore is off
	{% endif %}
	
	{% if move == 1 %}
		_CG28                                                 # Conditional home
		PARK P=bed                                            # Park toolhead in safe location (center volume)
		LED_HEATING
	{% endif %}

I have SuperSlicer set to pass a target chamber temp for each filament which is passed to print_start. SuperSlicer of course has the M104 & M140 lines @geekandi mentioned. 

So, essentially I send a target chamber temp as my heatsoak parameter. For example PLA sends 0, ABS sends 30. PLA prints skip right to getting things going, ABS waits for the chamber to hit about 30C. It's not interruptible, but that's rare--like I realized I missed something and need to cancel the print. Then I just e-stop the printer and restart it.

I cribbed from the zellneralex Github and modified heavily from there.

  • Like 2
Link to comment
Share on other sites

  • 3 months later...

Hey @claudermilk

Would you mind posting your whole print_start config? I'm trying to replicate your setup but I am not to sure exactly where in my current config I should position your snippet. My current Print_Start is below and it's been very long time since I looked to modify it so I am being overly cautious.

[gcode_macro PRINT_START]

    
gcode:        
    # Parameters
    {% set bedtemp = params.BED|int %}
    {% set hotendtemp = params.HOTEND|int %}
    G32                            ; home all axes
    BED_MESH_CALIBRATE
    G28 Z
    # <insert your routines here>
    G1 X175 Y175 Z150 ; Park Toolhead in center of Build Volume
    M190 S{bedtemp}                                                              ; set & wait for bed temp
    # <insert your routines here>
    M109 S{hotendtemp}                                                           ; set & wait for hotend temp
    # <insert your routines here>
    G92 E0 ; reset extruder
    G1 Z1.0 F3000 ; move z up little to prevent scratching of surface
    G1 X0.1 Y20 Z0.3 F5000.0 ; move to start-line position
    G1 X0.1 Y300.0 Z0.3 F1500.0 E15 ; draw 1st line
    G1 X0.4 Y300.0 Z0.3 F5000.0 ; move to side a little
    G1 X0.4 Y20 Z0.3 F1500.0 E30 ; draw 2nd line
    G92 E0 ; reset extruder
    G1 Z1.0 F3000 ; move z up little to prevent scratching of surface

All the best.

Link to comment
Share on other sites

OK. Just remember--you asked for it. 😜

[gcode_macro PRINT_START]
description: Print Start macro called by slicer start gcode.
gcode:
  # Parameters
  {% set bedtemp = params.BED|default(60)|int %}
  {% set hotendtemp = params.HOTEND|default(215)|int %}
  {% set chambertemp = params.CHAMBER|default(0)|int %}
  {% set flSize = params.SIZE|default("0_0_0_0")|string %} # For adaptive bed mesh OBSOLETE
  {% set _filament = params.FILAMENT|string %}
  {% set user = printer['gcode_macro _USER_VARIABLE'] %}
  {% set filament = printer.save_variables.variables.filament %}

    # Check if filament loaded if sensor on
  {% if not printer.save_variables.variables.filament_loaded|lower == 'true' %}
    {% set filament_detected = false %}
  {% elif printer['filament_switch_sensor runout'].enabled|lower == 'true' %}
    {% set filament_detected = printer['filament_switch_sensor runout'].filament_detected %}
  {% else %}
    {% set filament_detected = true %}
	{% endif %}
  {% if filament_detected %}
    {% if filament.array[filament.index].name != _filament %}
      RESPOND TYPE=error MSG="WARNING! Loaded filament and print file filament mismatch!"
    {% endif %}

    # Turn on webcam if it's off
    # {% if printer.save_variables.variables.webcam_state == 'off' %}
    #   START_WEBCAM
    # {% endif %}

		M141 S0                                                  # Turn off exhaust fan	
    UPDATE_DELAYED_GCODE ID=skirt_fan DURATION=0             # Stop controller fan loop
    SET_FAN_SPEED FAN=controller_fan SPEED=1                 # Turn controller fan on  
		_CG28                                                    # Conditional Home
		G90                                                      # Set to absolute

    {% if printer["temperature_fan chamber"].temperature < chambertemp %}
		  _HEATSOAK TEMP={bedtemp} MOVE=1                        # Set up to heat soak if chamber temp is set higher than current reading
      M190 S{bedtemp}                                        # Set target bed temp & wait for it
      TEMPERATURE_WAIT SENSOR="temperature_fan chamber" MINIMUM={chambertemp}   # Do the actual heat soak wait, until chamber temp is at target
		{% else %}
			{% if printer.heater_bed.temperature < (bedtemp-2) %}
        _HEATSOAK TEMP={bedtemp} MOVE=1	        						# Bed is below target temp, get it heating & safely park toolhead
        M190 S{bedtemp}                                     # Set bed target temp & wait for it
			{% else %}
				_HEATSOAK TEMP={bedtemp} MOVE=0                     # Just do a bed heat, no champer temp (open case for PLA)
			{% endif %}
		{% endif %}
		M106 S0                                                 # Turn off part cooling fan from heatsoak
		
    BED_MESH_CLEAR                                          # Clear old bed mesh
    ### Klicky
    {% if printer['gcode_macro Attach_Probe'] is defined or 'dockable_probe' in printer %}
      ATTACH_PROBE_LOCK                                      # Attach & lock the probe.
    {% endif %}
    ###		
    CLEAN_NOZZLE DOPURGE=0                                   # make sure there's no ooze for Tap, only scrub the nozzle
    Z_TILT_ADJUST                                            # Level bed & re-home Z (part of macro)			
    BED_MESH_CALIBRATE

		LED_HEATING
    G1 X{user.park.center.x} Y{user.park.center.y} Z30 F{user.speed.dock}         # Move tool head to safe distance from bed
    RESPOND MSG="Heating nozzle"
    M106 S205
		M109 S{hotendtemp}                                       # Do final nozzle heat
		CLEAN_NOZZLE                                             # Remove ooze

		### Klicky
    {% if printer['gcode_macro Attach_Probe'] is defined or 'dockable_probe' in printer %}
      CALIBRATE_Z                                            # Get current offset
    {% endif %}
    ###

    ### Obsolete with Tap/Klicky
    {% if user.hw.auto_z_offset_manu %}
		  _SET_PLATE_OFFSET                                     # Add current plate Z offset adjustment
	  {% endif %}

    ### Klicky
    {% if printer['gcode_macro Attach_Probe'] is defined or 'dockable_probe' in printer %}
	    DOCK_PROBE_UNLOCK                                      # Release the probe
    {% endif %}
    ###
	
	  G92 E0                                                   # Reset extruder	
    M83                                                      # Extruder to relative
    G1 E10.0 F3600                                           # Extrude 10mm to account for clean_nozzle retraction
		ADAPTIVE_PURGE                                           # KAMP adaptive purge, used with adaptive bed mesh
		G92 E0                                                   # Reset extruder	
		LED_PRINTING                                             # Prep done, start print
    RESPOND MSG="Printing"
		UPDATE_DELAYED_GCODE ID=_CLEAR_DISPLAY DURATION=1
	{% else %} # no filament loaded
    RESPOND TYPE=error MSG="No filament loaded, print canceled!"
		CANCEL_PRINT
	{% endif %}

Then here's the heatsoak macro.

[gcode_macro _HEATSOAK]
description: Helper: Set up to heat soak printer. Usage: _HEATSOAK [TEMP=temp(110)] [MOVE=move(1)]
gcode:
  {% set temp = params.TEMP|default(110)|int %}
  {% set move = params.MOVE|default(1)|int %}
	
	LED_HEATING
  RESPOND MSG="Warming up"
	M141 S0                                                 # Turn off exhaust fan
	M140 S{temp}                                            # Heat the bed
	{% if temp >= 100 %}                                    # It's ABS or other high-temp plastic, closed case
		M104 S170                                             # Set hotend to no-ooze temp
    M106 S205                                             # Turn on part fan to 80% for 
		SET_FAN_SPEED FAN=nevermore SPEED=1                   # Turn on Nevermore fans to circulate & accelerate chamber soak
	{% else %}
    M106 S0                                               # Turn off part fan. Open case, no need
		SET_FAN_SPEED FAN=nevermore SPEED=0                   # Make sure Nevermore is off
	{% endif %}

	{% if move == 1 %}
		_CG28                                                 # Conditional home
		PARK P=bed                                            # Park toolhead in safe location (center volume)
		LED_HEATING
	{% endif %}

 

  • Like 3
Link to comment
Share on other sites

  • 7 months later...

Hey i have been using this macro for a while now its pretty great thanks for that but i was trying to finagle with it to add a second temperature target for my chamber heater(350 is so fat lol). Anyways i have a very limited knowledge when it come to coding so i could never get it to work can anyone possibly help me out here

Link to comment
Share on other sites

Here's the relevant part of my print_start:

TEMPERATURE_WAIT SENSOR="temperature_fan chamber" MINIMUM={chambertemp}   # Do the actual heat soak wait, until chamber temp is at target

 

Before this I have it wait for the bed to come to temp--if it isn't then the chamber definitely won't be and even if it is, that's irrelevant. Once the bed is to temp, it then starts watching the chamber thermistor for the minimum temperature sent from the Superslicer filament Chamber parameter.

  • Like 1
Link to comment
Share on other sites

  • 2 weeks later...
  • 3 months later...

Lots of good stuff going on in here and I thought you might be able to help me through my issue. I'm doing similar to what others are trying to do where I want to wait until my chamber temp hits a certain temperature before continuing. I first home, then move to the center, turn on the part cooling fan, the heaters, and then I'd like to wait until the chamber temp reaches the set point as passed along by my slicer (Orca). I get the error below. I did fix it to where it is passing the correct value as chamber temp because it now shows MINIMUM=50, but it still says it is Malformed. I've put my Start_Print Macro and a snippet from my printer.cfg file showing that temp sensor below. Any advice on how to fix this?

Screenshot2024-01-28175015.thumb.png.63f32ac3db1be67926e62d782aa46aff.png

 

[gcode_macro START_PRINT]
gcode:
   # Load variables
   {% set bed_temp = params.BED_TEMP|default(40)|int %}
   {% set extruder_temp = params.EXTRUDER_TEMP|default(200)|int %}
   {% set chamber_temp = params.CHAMBER_TEMP|default(0)|int %}
    status_homing #LED Homing
    G28 ; Home all axes
    G1 X125 Y125 F3000
    M106 #Turn part cooling fan on to 100%
    status_heating #LED Heating
    M190 S{bed_temp}
    M104 S{extruder_temp-60}
    #TEMPERATURE_WAIT SENSOR=“temperature_sensor chamber_temp” MINIMUM={chamber_temp} #Wait for the chamber to get hot
    M107 #Turn part cooling fan off.
    status_leveling #LED Z Tilt
    Z_TILT_ADJUST
    status_heating #LED Heating
    M109 S{extruder_temp}
    status_homing #LED Homing
    G28 ; Home all axes
    status_meshing #LED Bed Mesh
    BED_MESH_CALIBRATE 
    status_printing #LED Printing
    LINE_PURGE ; Run purge macro
    status_printing #LED Printing
    #Voron_Purge ; Run purge macro

 

From printer.cfg

[temperature_sensor chamber_temp]
## Chamber Temperature - T1
sensor_type: CMFB103F3950FANT
sensor_pin: PF5
min_temp: 0
max_temp: 100
gcode_id: chamber_th

Link to comment
Share on other sites

Mine looks similar. The only difference being that I've tied my chamber thermistor to my exhaust fan, so it's [temperature_fan chamber] in the printer definitions. I vaguely recall having some issue just defining it separately. Besides, I wanted to link the chamber exhaust up to the chamber temperature anyway.

Link to comment
Share on other sites

6 hours ago, claudermilk said:

Mine looks similar. The only difference being that I've tied my chamber thermistor to my exhaust fan, so it's [temperature_fan chamber] in the printer definitions. I vaguely recall having some issue just defining it separately. Besides, I wanted to link the chamber exhaust up to the chamber temperature anyway.

I think I found it last night looking through Klipper documentation. I think I just need to add [ ] around the MINIMUM={chamber_temp} statement. Haven't had a chance to test that out yet. Should be able to try tonight. 

 

Link to comment
Share on other sites

Adding the brackets didn't work, but I worked through what you have above for your heat soak macros and that is working for me now. I changed some of it fit my naming schemes and what I am using. Thanks for posting your print start information, that was super useful.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...