Malyan M200 3D printer

aka Monoprice Select Mini V2, MP Select Mini, ProFab Mini, PrimaCreator P120


There’s a manual on the SD card called manual.pdf

setup WiFi

The Maylan m200 has Smart Config. This means that it can receive WiFi credentials ‘over the air’ (texas instruments cc3000EspTouch). On iOS you can install ‘MP 3D Printer WiFi Connect’. You need to select the ‘Move’ menu on the printer and hold the push button down for a couple of seconds to get into Smart Config mode. Then the app can send the WiFi credentials. Then the printer will display it’s IP address on its screen.

“The ESP8266 doesn’t support 5 GHz. The user will have to make sure their phone is connected to a 2.4 GHz AP so ESP Touch can sniff the packets.”

Web UI

  • http://IPaddress


telnet / netcat

you can use telnet or netcat on port 23 to get a direct TCP connection to the printer.

nc 23
# > G28
# < ok N0 P15 B15

get status

REST API for single commands

home (G28):

start print, cancel print, emergency stop

function start_p() {
    url: "set?code=M565",
    cache: false
  }).done(function(html) {});

function cancel_p() {
    url: "set?cmd={P:X}",
    cache: false
  }).done(function(html) {});

$('#eStop').click(function() {
        url: "set?code=M112\nM999",
        cache: false
    }).done(function(html) {
        $('#gCodeLog').append("<br>M112; Emergency Stop!");
        gCodeLog.scrollTop = gCodeLog.scrollHeight;
        alert('Emergency Stop Sent! You will have to cycle power on the printer to get communications back up.');



you can communicate using a websocket:

Machine / firmware info and config

(the display shows: V35.115.2) V35 = Motion Controller Version 115.2 = UI/LCD Controller Version


NAME. Malyan	VER: 3.5	MODEL: M200	HW: HH02
BUILD: May 18 2017 20:24:25


echo:Steps per unit:
echo:  M92 X93.00 Y93.00 Z1097.50 E97.00
echo:Maximum feedrates (mm/s):
echo:  M203 X150.00 Y150.00 Z1.50 E50.00
echo:Maximum Acceleration (mm/s2):
echo:  M201 X800 Y800 Z20 E10000
echo:Accelerations: P=printing, R=retract and T=travel
echo:  M204 P3000.00 R3000.00 T3000.00
echo:Advanced variables:
S=Min feedrate (mm/s),
T=Min travel feedrate (mm/s),
B=minimum segment time (ms),
X=maximum XY jerk (mm/s),
Z=maximum Z jerk (mm/s),
E=maximum E echo:  M205 S0.00 T0.00 B20000 X20.00 Z0.40 E5.00
echo:Home offset (mm):
echo:  M206 X0.00 Y0.00 Z0.00
echo:Invert axis: M562 XYZE
echo:PID settings:
echo:  M301 P20.00 I0.02 D250.00 C100.00 L20
echo:  M304 P10.00 I0.02 D305.40
echo:Filament settings: Disabled
echo:  M200 D1.75
echo:  M200 D0


the uploaded file is stored on the SD card as ‘cache.gc’

function upload() {
  var blob = new Blob([$("textarea").val()]);
  var reader = new FileReader();

  reader.onload = function(event){   // this function is triggered once a call to readAsDataURL returns
      var fd = new FormData();
      fd.append('fname', 'doodle.g');
          type: 'POST',
          url: '/upload',
          data: fd,
          processData: false,
          contentType: false
      }).done(function(data) {
  reader.readAsDataURL(blob); // trigger the read from the reader...


function get(cmd) {
 $.get(cmd,function(successData) { console.log(cmd+": "+successData)} ); 

function start() {

function home() {

function stop() {

function status() {

start gcode for the demo print ‘cat.gcode’ on the SD card

M109 S195.000000
;Sliced at: Wed 15-06-2016 08:14:50
;Basic settings: Layer height: 0.2 Walls: 1.2 Fill: 20
;Print time: 2 hours 29 minutes
;Filament used: 7.45m 22.0g
;Filament cost: None
;M190 S0 ;Uncomment to add your own bed temperature line
;M109 S195 ;Uncomment to add your own temperature line
G21        ;metric values
G90        ;absolute positioning
M82        ;set extruder to absolute mode
M107       ;start with the fan off
G28 X0 Y0  ;move X/Y to min endstops
G28 Z0     ;move Z to min endstops
G1 Z15.0 F6000 ;move the platform down 15mm
G92 E0                  ;zero the extruded length
G1 F200 E3              ;extrude 3mm of feed stock
G92 E0                  ;zero the extruded length again
G1 F6000
;Put printing message on LCD screen
M117 Printing...

;Layer count: 299
G0 F6000 X43.681 Y44.418 Z0.300
G1 F1200 X44.482 Y43.662 E0.13738
G1 X44.847 Y43.323 E0.19951
G1 X45.818 Y42.600 E0.35050
G1 X46.870 Y41.930 E0.50606


(M109 S195\nG21\nG90\nM82\nM107\nG28 X0 Y0\nG28 Z0\nG1 Z15.0 F6000\nG92 E0\nG1 F200 E3\nG92 E0\nG1 F6000\n)

end gcode for the demo print ‘cat.gcode’ on the SD card

G1 F6000 E7440.46357
G0 X54.969 Y63.344 Z64.948
;End GCode
M104 S0                     ;extruder heater off
M140 S0                     ;heated bed heater off (if you have it)
G91                                    ;relative positioning
G1 E-1 F300                            ;retract the filament a bit before lifting the nozzle, to release some of the pressure
G1 Z+0.5 E-5 X-20 Y-20 F6000 ;move Z up a bit and retract filament even more
G28 X0 Y0                              ;move X/Y to min endstops, so the head is out of the way
M84                         ;steppers off
G90                         ;absolute positioning

Malyan’s wiki

Malyan’s firmware sourcecode on github

Malyan on Alibaba

optimal layer heights

Layer Height (mm)
0.04375 (results may vary)*

Available Commands

P:X Cancel print
P:H Homing
P:P Pause print
P:R Resume print
P:M Print cache.gc

C:T0000 Set T0 temperature
C:P000  Set hotbed temperature

e:e Return printing status
e:M Return mac address

J:X Moves the X-Axis
J:Y Moves the Y-Axis
J:Z Moves the Z-Axis
S:I List files on the microSD card
V   Displays firmware versions on LCD
W   Deletes WiFi SSID and password

Download from remote server

M564 IPADDRESS/file.gcode   # download file from server
M565 IPADDRESS/file.gcode   # download and print
not working test:
not working test:
I received a new firmware version (v158.2) from Malyan where this problem is solved :
Now this works: ``

Testing Doodle3D Sketch on Malyan M200


rsync -av /Users/rick/Documents/Doodle3D/doodle3d-client/www/


Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept"

firmware Update method:

Motion conroller Copy update.bin to clean formatted microSD card. Create empty file named “fcupdate.flg”. Insert card and power on printer to update.


not tried yet{V:}

SD card

  • The SDCard that came with the printer is formatted FAT16 and has about 128MB.
  • I tried with a Transcend Premium 300x 16GB card formatted FAT32. The display shows: “No files”
  • I tried to format it exFAT but same result.
  • I tried to resize SD card to 4GB FAT using Windows DISKPART: Same result.
  • according to Monoprice website: “Note: If you choose to purchase an SD card, please make sure that it is not labeled HC (High Capacity) as it may not be compatible with the printer. This means that the card must be smaller than 4GB in size.”. My 16GB card has the HC label. May be this is a problem even when it’s resized to a smaller capacity.
  • next attempt: Use Disk Utility to create a diskimage from the original SD card to another (2GB) SD-card. It downsizes this card. They should be identical now but the printer still reports ‘No files’.
  • related reddit thread
  • backup sd card:
    sudo dd if=/dev/disk3 of=~/printer.img
    sudo dd if=~/printer.img of=/dev/disk3

Monoprice Select Mini 3D Printer KB

reverse engineering UI board

ESP touch / Smart Config


(8 megabytes) / (500 kbps) = 2.13333333 minutes

(8 MB) / (20 (KB / s)) = 6.66666667 minutes

forget wifi{W:}

auto print

‘auto00.g’ should start when holding knob on mainmenu. Not tested yet.

rename cache.gc to something else

M566 newname.gc


websocket test

<form id="frmConnect" action="#" onsubmit="connect(txtIP.value)">
  <input type="text" placeholder="ip address" id="txtIP" value=""/>
  <input type="submit" id="btnConnect" value="Connect"/>

<form id="frmSend" action="#" onsubmit="send(txtCmd.value)" hidden>
  <input type="text" placeholder="command" id="txtCmd"/>
  <input type="submit" value="Send"/>

<textarea cols="60" rows="20" id="txtLog"></textarea>


var ws;

function connect(ip) {
  ws = new WebSocket("ws://"+ip+":81");
  ws.onmessage = function (event) {
    txtLog.value+="< " +;
  ws.onopen = function () {
    frmConnect.hidden = true;
    frmSend.hidden = false;
    txtLog.value += "Connected to " + ip + "\n";

function send(cmd) {
  if (ws) ws.send(cmd);
  txtLog.value += "> " + cmd + "\n";;


Access-Control-Allow-Origin - test script

<!DOCTYPE html>
<title>Malyan M200 CORS problem</title>
  <input type="text" id="ip" placeholder="ip address">
  <button onclick="inquiry(ip.value)">Inquiry</button>
  function inquiry(ip) {
    var xhr = new XMLHttpRequest();
    xhr.onload = function() { 
    };'GET', 'http://' + ip + '/inquiry');


raw communication codes

commands and responses are send both ways at 500kbps (gcode with 8 databits, control commands with 7 databits?) gcode data is uploaded with 8 databits.

{P:X} cancel
{C:T0000} set nozzle temp
{C:P000} set bed temp
{S:I} inquiry? / sd init?
{S:L} sd list?

{B:0} ?

{FILE:MM_support test.gcode}

{T1:000/000} temp nozzle
{TP:017/000} temp bed
{TQ:025P} progress
{TT:000001} ???

response when uploading looks like 6bits data: {h01}{h01}{h01}{h01}{h01}{h01}{h01}{h01}{h01}{h01}{h01}{h01}{h01};{h13}{h19}{h13}:{h1B}{h07}{h1D}0{h12}{h14}{h05}{h04}=

‘bricked’ after updating motion controller:

Fix on OSX (replace # by correct value):

diskutil list
diskutil info disk#
sudo diskutil unmount /dev/disk#
sudo newfs_msdos -F 32 -v 3DPRINTER -b 512 /dev/disk#
diskutil mount disk#
diskutil info disk#

First my File System was MS-DOS FAT16 and Allocation Block Size was 16384 Bytes Now it is MS-DOS FAT32 with Allocation Block Size 512 Bytes. Thanks to MatthewUpp.