MiniWave ES15 screwdriver + KER toolkit 3d print.

Fusion 360 model

image

https://a360.co/3ZfWJPU “V18 – tested works” is the last tested printed version

image

image

image

this is V15 (Fusion 360 version), the third hole is a teensy bit off , pressure fit

image

image

Version 16+

Swap tray 1 to tray 8 (little bit of glue to over come) but you have to clip these sides a little bit to clear the magnetic locks. it is thin plastic so its easy to do.

image

Arrangement looks like this after the mod, so it removes the screwdriver+tweezers from the base KER only

image

Timelapse print

https://youtu.be/a2AgcULsrTs

image

image

The inner sketches for the holes are correct, i was using larger ones for test fits.

I moved the third hole in v17 to a 46mm from 46.3mm in v16

And just as I printed V16 which seems to work the best, Amazon delivered the PLA i wanted to use…. I guess V17 is getting a run then.

image

this is hatchbox yellow PLA, going to try microcenter in house brand inland gold pla as well, needs a little orange

image

“V18 – tested works”, is the current verified working version from the Fusion360 Link

This is the Inland Gold PLA at the bottommost  (warning inalnd uses cardboard reels)

image

The KER kit is sold as 

KER 128 in 1 Precision Screwdriver Set with Magnetic Driver Kit

I may make some small changes that should reflect in the A360.

Also its currently in slot 8, which is the extension and metal spatula, since slot 1 won’t fit. Will either make a new plate for slot 1 that lets the driver fit, or see if i can adjust so you can move slot 8 to Slot 1 instead

Bambu X1 carbon notes

not much yet as i only had the machine for a day, but keeping notes, as is the way.

Auditing these machines, since they can/are connected to a plain ip addresses in china, have unfettered local network access, no proxy settings, a closed ecosystem and could download and execute arbitrary code without permission and a *lot* of domains they can connect too

FTP

the BambuLabs X1  Carbon currently uses FTP when the SD-CARD is installed, the username is bblc and the access code is  the password , which is stored in

C:\Users\%USERNAME%\AppData\Roaming\BambuStudio

BambuStudio.conf 

It’s in the JSON file, under access_code

  • “access_code”: {
  • }

regular FTP port 21.

if you can’t find the access code, just wireshark with a tcp.port == 21 filter.

the access code appears other places too in the p1p, but i haven’t seen it on the x1c

BambuLabs say they are planning to remove the FTP connection, since they may want something either more secure or just go via their cloud

RFID

the RFID is a mifare classic 1K and doesn’t use any of the std/extended keys, i guess dust off the proxmark time.  not susceptible to NACK

BUILDING THE SLICER

Building the app from github was a bit of a chore, build the deps first then the application (debug mode doesn’t seem to work with the networking plugin dll, will have to check into that a bit more, probably just an incompatibility with name mangle/that dll) the PrusaSlicer github page issues has a lot of notes on the build process.

openssl needs  a windows path / \ compatible perl to build. i just used one from vcpkg

Although the Slicer is open source (since its a fork of PrusaSlicer) the communications for the device  are in a separate library that does all the communications with the cloud service/machine. This is because this allows them to keep the network communications closed source,  the Camera works the same way.

NOTES

internal urls are :-

bambu:///machine?authkey=xxxxxxxxxx&passwd=xxxx&region=us

HARDWARE

back of the 4 way hub, i’ll add better photos.

I like the cute little VOID sticker, is it telling me it is void, it is a portal to another dimension perhaps?

Warranty void stickers are illegal in a lot of places (Definitely Germany and USA) magnusson moss act in the USA

https://www.ftc.gov/news-events/news/press-releases/2018/04/ftc-staff-warns-companies-it-illegal-condition-warranty-coverage-use-specified-parts-or-services

Rockchip RV1126
h5tq4g63efr 4Gb DDR3 SDRAM

KIOXIA  THGBMNG5D1LBAIL VD1216   2140KAE CHINA
https://www.digikey.com/en/products/detail/kioxia-america-inc/thgbmng5d1lbail/9841782
https://pdf1.alldatasheet.com/datasheet-pdf/view/1244282/TOSHIBA/THGBMNG5D1LBAIL.html

https://github.com/yunzhaoyu2050/rockchip_rv1126_rv1109_docs/blob/main/RV1126_RV1109/Rockchip_RV1126_RV1109_Quick_Start_Linux_EN.pdf

https://datasheet.lcsc.com/lcsc/2202131900_SK-HYNIX-H5TQ4G63EFR-RDC_C2803259.pdf

image


image

CPU’s used.

http://www.spintrol.com/index/index/product2/id/25.html

http://www.spintrol.com/index/index/product2/id/23.html

https://jlcpcb.com/partdetail/ZHONGKEWEI-AT8236/C2827823

https://www.alldatasheet.com/datasheet-pdf/pdf/1149566/CHIPSEA/CSU32P10.html

TI Version of the transceiver https://www.ti.com/product/SN75176B

https://www.arrow.com/en/products/tp75176e-sr/3peak

FM 1230 SC

2023-01-14 16_53_27-SharpCap (v4.0.9478, 64 bit) - USB CAMERA  - C__Users_charlie_Desktop_SharpCap C

2023-01-14 16_53_46-SharpCap (v4.0.9478, 64 bit) - USB CAMERA  - C__Users_charlie_Desktop_SharpCap C

3PEAK 75176

2023-01-14 16_55_14-SharpCap (v4.0.9478, 64 bit) - USB CAMERA  - C__Users_charlie_Desktop_SharpCap C

 2023-01-14 18_49_36-SharpCap (v4.0.9478, 64 bit) - USB CAMERA  - C__Users_charlie_Desktop_SharpCap C

F330G8BUH5468 Giga

https://www.gigadevice.com/products/microcontrollers/gd32/arm-cortex-m4/mainstream-line/gd32f303-series/

https://www.gigadevice.com/microcontroller/gd32f330g8u6/ 

2023-01-14 16_56_23-SharpCap (v4.0.9478, 64 bit) - USB CAMERA  - C__Users_charlie_Desktop_SharpCap C

the GD’s are popular because of supply chain issues, shorter lead times than the somewhat similar lines from ST Micro

CHIPSEA 32P

https://www.lcsc.com/product-detail/Microcontroller-Units-MCUs-MPUs-SOCs_CHIPSEA-CSU32P10-SOP8_C914988.html

2023-01-14 18_49_10-SharpCap (v4.0.9478, 64 bit) - USB CAMERA  - C__Users_charlie_Desktop_SharpCap C

hall effect

2023-01-14 16_53_46-SharpCap (v4.0.9478, 64 bit) - USB CAMERA  - C__Users_charlie_Desktop_SharpCap C

2023-01-14 18_50_17-SharpCap (v4.0.9478, 64 bit) - USB CAMERA  - C__Users_charlie_Desktop_SharpCap C

filament buffer ( ams hub replaces it)

image

image

image

image

filament displacement, this is spring loaded when the filament passes thru it changes the hall effect sensor state

image

image

image

image

the long magnets are setup to be horizontal , so N E S , so the sensor can determine which direction or no filament

Connectors

https://www.literature.molex.com/SQLImages/kelmscott/Molex/PDF_Images/987651-4661.pdf

Lidar

Haven’t confirmed it yet but the uploaded .3mf contains a 2d image of the first layer expectation this is probably used as the mask for the lidar/first layer inspection

image

April Tags

The codes the printer reads on the plates are 16H5’s 5mmx5mm :-

detection   3:id (16x 5)-25  , hamming 2, margin   24.959 etc

1 border bit
examples

16h5a

BambuNetworkEngine.conf

Rijndael  json  with last machine, username , avatar link , userid/name and tokens.

OpenSSH
nlohman json 
paho mqtt
spdlog
boost
curl
std::fmt

List of domains/ip’s

https://ipinfo.io/47.100.225.51
DevModel.bambu.com https://www.whois.com/whois/bambu.com
DevName.bambu.com
DevSignal.bambu.com
DevConnect.bambu.com
DevBind.bambu.com
bambu-lab.com https://www.whois.com/whois/bambu-lab.com
bambooolab.com https://www.whois.com/whois/bambooolab.com
portal.bambulab.com
cn.mqtt.bambulab.com
api.bambulab.com
us.mqtt.bambulab.com
pre.mqtt.bambu-lab.com
pre.us.bambu-lab.com
bambulab-demo.myshopify.com
portal-qa.bambulab.com
portal-dev.bambu-lab.com
portal-pre.bambu-lab.com
dev.mqtt.bambu-lab.com
pre_us.mqtt.bambu-lab.com
api-us-pre.bambu-lab.com
upgrade-file.bambulab.com
cdn.bambulab.com

BambuLabs X1 Carbon, P1P

EzCad .ezd parsing the pens

My notes on parsing the EZD Cad 2 format and accessing the pen information for regular and Q/MOPA types.

The key part is getBasePtr () + the offset

    1. base = (uint32_t*)(dataBuffer->data() + 0x160 );
    2. dataBuffer->data() + baseOffset + SPEED_MM_OFFSET

start of file + baseOffset + value you want to read/write

These are the offsets
this is a pointer to an offset where the pens/data so baseOffset+this
DATA_PENS_OFFSET ( 0x160 )

offset of the parameter name NAME_OFFSET ( 8UL )
this is the length of the first name of the .ezd i started with
NAME_LENGTH ( 0x10 )

USE_DEFAULT_OFFSET ( 0x0c + 8 ) USE_ON_OFF_OFFSET ( 0x0c ) LOOP_COUNT_OFFSET ( 0x14 ) SPEED_MM_OFFSET ( 0x1c ) POWER_OFFSET ( 0x28 ) FREQUENCY_OFFSET ( 0x34 )

unsigned long here Q_OFFSET ( 0x3c )

double here
Q_OFFSET_2 ( 0x3c+0xa0 ) START_TC_OFFSET ( 0x44 ) LASER_OFF_OFFSET ( 0xCC ) END_TC_OFFSET ( 0x4c ) POLYGON_TC_OFFSET ( 0x54 )

#pragma once

// so far, we no longer need this since it moves
// ezcad version 2.14.11
#define BASE_POINTER (0x27300)

// some test ezd files I found on the web
//#define BASE_POINTER (0x464)

enum {
	COL_PARAMETER = 1,
	COL_RGB = 2,
	COL_DEFAULT = 3,
	COL_ONOFF = 4,
	COL_LOOPCOUNT = 5,
	COL_SPEED_MM = 6,
	COL_POWER = 7,
	COL_FREQUENCY = 8,
	COL_Q = 9,
	COL_START_TC = 10,
	COL_LASER_OFF = 11,
	COL_END_TC = 12,
	COL_POLYGON_TC = 13,
	MAX_COLS = 14
};

#define MAX_PEN				( 256 )

#define	DATA_PENS_OFFSET		( 0x160 )	// this is a pointer to an offset where the pens/data is 
#define	NAME_OFFSET			( 8UL )		// offset of the parameter name
#define	NAME_LENGTH			( 0x10 )	// this is the length of the first name of the .ezd i started with
#define USE_DEFAULT_OFFSET		( 0x0c + 8 )
#define USE_ON_OFF_OFFSET		( 0x0c )
#define LOOP_COUNT_OFFSET		( 0x14 )
#define SPEED_MM_OFFSET			( 0x1c )
#define POWER_OFFSET			( 0x28 )
#define FREQUENCY_OFFSET		( 0x34 )
#define Q_OFFSET			( 0x3c )	// unsigned long here
#define Q_OFFSET_2			( 0x3c+0xa0 )	// double here
#define START_TC_OFFSET			( 0x44 )
#define LASER_OFF_OFFSET		( 0xCC )
#define END_TC_OFFSET			( 0x4c )
#define POLYGON_TC_OFFSET		( 0x54 )



class EZD {

public:
	uint16_t	penID;

	// start of pen data
	size_t	basePointer;

	// offset of data after the Parameter string
	uint64_t	baseOffset;

	std::string* dataBuffer = NULL;

	size_t parameter_length;

	~EZD() {
	}
		
	EZD() : baseOffset(0),basePointer(0), penID(0) ,parameter_length(0) {

	}

	EZD(size_t basePtr, uint16_t pen, std::string& data) : EZD() {

		/// whole EZD file
		dataBuffer = &data;

		// start of pen data
		basePointer = basePtr;

		// length of unicode parameter string in bytes
		parameter_length = dataBuffer->at(basePointer + 4);

		// rebases a pointer to after the unicode string .
		// 8 is the offset of the Unicode string
		baseOffset = 
			(size_t)(basePointer + NAME_OFFSET + parameter_length);
		penID = pen;
	}

	// returns the address of the last byte in the block
	size_t EndOfBlock()
	{
		// 0x27c is the size of a block with 0x10 length of the "default" string
		return basePointer + parameter_length + (0x27c - 0x10);
	}

	// these are before the unicode string so are only affected by the basePointer
	void R(uint8_t r) { dataBuffer->at(basePointer) = r; };
	void G(uint8_t g) { dataBuffer->at(basePointer + 1) = g; };
	void B(uint8_t b) { dataBuffer->at(basePointer + 2) = b; };

	uint8_t R() { return dataBuffer->at(basePointer); };
	uint8_t G() { return dataBuffer->at(basePointer + 1); };
	uint8_t B() { return dataBuffer->at(basePointer + 2); };

	uint32_t GetRGB() {
		uint32_t rgb;
		rgb = RGB(R(), G(), B());
		return rgb;

	}

	void SetRGB(uint8_t r, uint8_t g, uint8_t b) {

		R(r);
		G(g);
		B(b);
	}

	void SetRGB(COLORREF r) {
		uint32_t rgb;
		rgb = (uint32_t)r;

		R(GetRValue(rgb));
		G(GetGValue(rgb));
		B(GetBValue(rgb));
	}

	// these are before the unicode string so are only affected by the basePointer
	CString Parameter() {

		// ugly way to do a unicode string...
		std::wstring data;

		// check that we were able to actually read a string length
		ASSERT(parameter_length);
		if (parameter_length == 0) {
			return CString(_T("NA"));
		}

		// resize our string to match
		data.resize(parameter_length);

		// fetch ptr to it
		unsigned char* p = (unsigned char*)dataBuffer->data() + basePointer + 8;
		ASSERT(p);

		// check results
		if (p == 0) {
			return CString(_T("NA"));
		}

		char* d = (char*)data.data();
		ASSERT(d);

		// check results
		if (d == 0) return CString(_T("NA"));

		//copy over string data
		memcpy(
			d,
			p,
			parameter_length
		);

		return CString(data.c_str());
	}

	// these are before the unicode string so are only affected by the basePointer
	std::wstring Parameter(CString value) {

		// ugly way to do a unicode string...
		std::wstring data( value);

		// check that we were able to actually read a string length
		ASSERT(parameter_length);
		if (parameter_length == 0) {
			return std::wstring(_T(""));
		}

		// resize our string to match the length store, its a hassle to rewrite the whole file for this otherwise
		data.resize((parameter_length-1)/2);

		// fetch ptr to it
		unsigned char* p = (unsigned char*)dataBuffer->data() + basePointer + 8;
		ASSERT(p);

		// check results
		if (p == 0) {
			return std::wstring(_T(""));
		}

		char* d = (char*)data.data();
		ASSERT(d);

		// check results
		if (d == 0) return std::wstring(_T(""));

		//copy over string data
		memcpy(
			p,
			d,
			parameter_length
		);

		return data;
	}

	// these are afer the unicode string so are only affected by the basePointer and the length of the unicode string
	uint8_t UseDefault() {
		uint64_t offset = basePointer + USE_DEFAULT_OFFSET + parameter_length;
		uint8_t* b = (uint8_t*)(dataBuffer->data() + offset);
		return *b;
	}

	// only verifys its 0 or 1
	bool UseDefault(uint8_t value) {

		if ((value != 0) && (value != 1)) {
			return false;
		}

		uint64_t offset = basePointer + USE_DEFAULT_OFFSET + parameter_length;
		uint8_t* b = (uint8_t*)(dataBuffer->data() + offset);
		*b = value;

		return true;
	}

	// these are afer the unicode string so are only affected by the basePointer and the length of the unicode string
	uint8_t OnOff() {
		uint64_t offset = basePointer + USE_ON_OFF_OFFSET + parameter_length;
		uint8_t* b = (uint8_t*)(dataBuffer->data() + offset);
		return *b;
	}

	// only verifys its 0 or 1
	bool OnOff(uint8_t value) {

		if ((value != 0) && (value != 1)) {
			return false;
		}

		uint64_t offset = basePointer + USE_ON_OFF_OFFSET + parameter_length;
		uint8_t* b = (uint8_t*)(dataBuffer->data() + offset);
		*b = value;

		return true;
	}

	uint32_t getBasePtr() {
		uint32_t* base;
		base = (uint32_t*)(dataBuffer->data() + 0x160 );
		return *base;

	}

	uint32_t LoopCount() {
		uint32_t* loop;
		loop = (uint32_t*)(dataBuffer->data() + baseOffset + LOOP_COUNT_OFFSET);
		return (uint32_t)*loop;
	}
	
	bool LoopCount(uint32_t value) {

		if (value < ezdConfig.LoopCountMin || value > ezdConfig.LoopCountMax) {
			return false;
		}

		uint32_t* loop;
		loop = (uint32_t*)(dataBuffer->data() + baseOffset + LOOP_COUNT_OFFSET);
		*loop = value;

		return true;
	}

	double SpeedMM() {
		double* speed;
		speed = (double*)(dataBuffer->data() + baseOffset + SPEED_MM_OFFSET);
		return *speed;
	}

	bool SpeedMM(double val) {
		//reject OOB
		if (val < ezdConfig.SpeedMMMin || val > ezdConfig.SpeedMMMax) {
			return false;
		}

		double* speed;
		speed = (double*)(dataBuffer->data() + baseOffset + SPEED_MM_OFFSET);
		*speed = val;
		return true;
	}

	double Power() {
		double* power;
		power = (double*)(dataBuffer->data() + baseOffset + POWER_OFFSET);
		return *power;
	}

	bool Power(double val) {
		double* power;

		//reject OOB
		if (val <ezdConfig.PowerMin|| val > ezdConfig.PowerMax) {
			return false;
		}

		power = (double*)(dataBuffer->data() + baseOffset + POWER_OFFSET);
		*power = val;
		return true;
	}

	double Frequency() {
		uint32_t* frequency;
		frequency = (uint32_t*)(dataBuffer->data() + baseOffset + FREQUENCY_OFFSET);
		return (double)(*frequency) / 1000.0;
	}

	bool Frequency(double val) {

		//reject OOB
		if (val < ezdConfig.FrequencyMin || val > ezdConfig.FrequencyMax) {
			return false;
		}

		uint32_t* frequency;
		frequency = (uint32_t*)(dataBuffer->data() + baseOffset + FREQUENCY_OFFSET);
		uint32_t t = (uint32_t)(val * 1000.0);
		(*frequency) = t;

		return true;
	}

	int32_t StartTC() {
		int32_t* temp;
		temp = (int32_t*)(dataBuffer->data() + baseOffset + START_TC_OFFSET);

		return *temp;
	}

	bool StartTC(int32_t val) {
		//reject OOB
		if (val < ezdConfig.StartTCMin || val > ezdConfig.StartTCMax) {
			return false;
		}
		
		int32_t* temp;
		temp = (int32_t*)(dataBuffer->data() + baseOffset + START_TC_OFFSET);
		*temp = val;
		
		return true;
	}

	uint32_t LaserOff() {
		uint32_t* temp;
		temp = (uint32_t*)(dataBuffer->data() + baseOffset + LASER_OFF_OFFSET);

		return *temp;
	}

	bool LaserOff(uint32_t val) {
		//reject OOB
		if (val < ezdConfig.LaserOffMin || val > ezdConfig.LaserOffMax) {
			return false;
		}


		uint32_t* temp;
		temp = (uint32_t*)(dataBuffer->data() + baseOffset + LASER_OFF_OFFSET);
		*temp = val;

		return true;
	}

	uint32_t EndTC() {
		uint32_t* temp;
		temp = (uint32_t*)(dataBuffer->data() + baseOffset + END_TC_OFFSET);

		return *temp;
	}

	bool EndTC(uint32_t val) {
		//reject OOB
		if (val < ezdConfig.EndTCMin || val > ezdConfig.EndTCMax) {
			return false;
		}

		uint32_t* temp;
		temp = (uint32_t*)(dataBuffer->data() + baseOffset + END_TC_OFFSET);
		*temp = val;

		return true;

	}

	uint32_t PolygonTC() {
		uint32_t* temp;
		temp = (uint32_t*)(dataBuffer->data() + baseOffset + POLYGON_TC_OFFSET);

		return *temp;
	}

	bool PolygonTC(uint32_t val) {
		//reject OOB
		if (val < ezdConfig.PolygonTCMin|| val > ezdConfig.PolygonTCMax) {
			return false;
		}

		uint32_t* temp;
		temp = (uint32_t*)(dataBuffer->data() + baseOffset + POLYGON_TC_OFFSET);
		*temp = val;

		return true;
	}

	uint32_t Q() {
		uint32_t* temp;
		double* temp1;
		temp = (uint32_t*)(dataBuffer->data() + baseOffset + Q_OFFSET);
		temp1 = (double*)(dataBuffer->data() + baseOffset + Q_OFFSET_2);

		return *temp;
	}

	bool Q(uint32_t val) {

		//reject OOB
		if (ezdConfig.QMin < 0 || val > ezdConfig.QMax) {
			return false;
		}

		uint32_t* temp;
		double* temp1;

		temp = (uint32_t*)(dataBuffer->data() + baseOffset + Q_OFFSET);
		temp1 = (double*)(dataBuffer->data() + baseOffset + Q_OFFSET_2);

		*temp = val;
		*temp1 = double(val);

		return true;
	}
};

decode .upd files

just a very quick post on how to decode a chinese laser cutter firmware update file 644 etc

#include <iostream>
#include <fstream>
#include <vector>

uint8_t decode(uint8_t updByte)
{
     return (((uint8_t)(updByte – 1) ^ 0x88) << 7) |
         (( uint8_t)((updByte – 1) ^ 0x88) >> 7) |
         ((updByte – 1) ^ 0x88) & 0x7E;
}

int main(int argc, char* argv[])
{
     if (argc < 3) {
         return -1;
     }

    std::ifstream updFile(argv[1], std::ios::binary | std::ios::ate);
     std::streamsize size = updFile.tellg();
     updFile.seekg(0, std::ios::beg);

    std::vector<char> buffer(size);
     if (updFile.read(buffer.data(), size))
     {
         std::cout << “loaded ” << buffer.size() << std::endl;
         for (size_t i = 0; i < buffer.size(); i++ ) {
             buffer[i] = decode(buffer[i]);
         }

        auto outputFile = std::fstream(argv[2], std::ios::out | std::ios::binary);
         outputFile.write((char*)buffer.data(), buffer.size());
         outputFile.close();
     }
}

Super Mini Mini 2 – TC motor part 2

Finally done with all my trips over the seas. So had time to pull apart the SMM2 and get to the second motor and inspect it.

it came pretty dirty, and i guess i didn’t clean off that drywall as well as thought, and that stuff isn’t good so cleaned that up first

then remove all the bolts on the top, not the door ones on the side though,they’re obviously not part of the top though, the enclosure will still in place when the top is removed.

image

i am pretty sure the previous owners just hosed it down with the green stuff. But we can see the same motor OEM but this time it has sealed brushes, don’t know why they used sealed on this one and not the other!

image

reasons as why not to use this style of molex connector in a place it can get contaminated. chips inside the connector, coolant you name it, so wrapped it.

image

the umbrella door opening mech gets a lot of swarf under it too, so good place to put on a cleaning schedule

close up showing the internal part of the connector has been contaminated.image

under this wheel the chips were getting bunched up so i cleaned it out

image

this is where the cables for the motor and sensors enter the steel tube frame, the bulkhead protecting ring had fallen out and it just wouldn’t stay in place, i pressed it in here in this picture but it just fell out again. this is meant to stop the edge of the metal slowing eating away at the insulation on the wiring since it’ll move/vibrate so its worth improving it. the haas one just wouldn’t lock into place, either a sloppy fit or it wore out

image

removing the access panel on the  steel tube to get access to the connectors. neither of these were tight and the left one was a tad cross threaded and the cable was loose and moved so wasn’t really sealed , also no gasket/seal on the panel so the coolant can get inside, as you can see here. sloppy fit on the bulkhead again. not a huge deal but could be better.

image

just like the green from swamp thing, it gets everywhere.

image

rear of panel

image

motor type SPG LS series LS85E82K-A06. haas part no 32-1875

image

image

and apparently after this i didn’t take more pictures though i thought i had..

the brushes on this motor have o ring seals so they were fine inside, all we did was clean up excess coolant and chips from everywhere feasible and then put it back together, no real issues there, add a gasket to that access panel. cover up the molex connectors for the sensor with some self annealing tape etc.

two!

image

also finally managed to get an CSMD NGC from eBay for a decent amount less than the list price from Haas. i have no idea what goes on with pricing on eBay, but i regularly see these go for 2x or more the list price from Haas for used ones… ($1600) maybe there is some secret Haas charge but we did get a HFO quote for it at that price. so who knows, but apparently you can arbitrage CSMDs on eBay. More on that later (the csmd not the arbitrage )

image

haas super mini mill 2 ngc tool changer carousel motor

hello,

don’t use tool 1 during testing the carousel, use tool 2

the folks that had our SMM2 with only 300 hours before us didn’t do the best job of keeping it clean and used some wacky looking coolants.

we noticed that the tool change was a bit sloppy/noisy and looking around people just said that is just Haas, but eventually while I was in the UK it failed with a lot of serious looking warnings 9847 etc that if you looked up talked about firmware mismatches but looking into it, it was basically just saying that the motor was on, but didn’t seem to be drawing current.

oh dear.

image

so pulled apart the machine, removed the access panel to the changer , lifted out the motor and looked at the brushes. they were contaminated so cleaned it up, put it back and seemed to be better.

when i got back to the USA a week or so later we noticed the tool change was throwing a quick alarm during a tool change.

so today we pulled it apart again

this motor being disconnected, throws an 858 ATC carousel motor electrical fault

cover off

image

there are some interesting design choices in here.

removed wiring, tool #1 connector wire is marked as tool #1, t.c mark isn’t marked as t.c. mark.

image

removed the motor from the housing

image

very steely.

image

baldor motor,. spg assembly https://spgmotor.net/bs-series/#1561724885376-8af2aff5-cb26e609-82cd0c42-a4318461-c59ceb77-0fe8467c-de89

image

pepperl fuchs

NBB4-12M45-Z5-0.3MM sensors

image

yep


Get to the brushes!

remove this cover, flat blade should come out easily.

image

image

fun stuff, it is not sealed , nor is meant to be by the manufacturer even though this is a custom one for haas ( seems to be, different ratio and they run it at 160V)

20211002_161250

egads

image

brush is all gunked up

image


the new dune is looking good, but low budget sandworms

20211002_161506

i did order a couple of replacement brushes, but they’re not really right since its just the carbon side with no provision for the wire, not a big deal since the brush itself is the same length as the new one and looks fine.

cleaned up the brush, and put it back ( added some teflon tape on retainer)

lets take a look at the other brush

image

interesting, totally fine no damage,  no corrosion.

when the motor is mounted, the dirty brush is on the inside where the green rectangle is

image

most of the box this is all in is “sealed”, gasket on the front, sealed wiring… except there is a ruddy great slot and bearing as part of the tool changer mech right next to the brush, so no we know why its contaminated on that side only….  why not rotate the motor 90o so the brushes aren’t exposed to the grease and coolant, after thought?

a plate over this with an indent for the nut/bolt would have been great too, and would have kept chips and coolant etc out of this mechanism,

some photos of the offending part, you can see the grease, coolant and chips

image

the nasty brush is right next to the nut, and we cleaned up the inside of the cabinet a lot , it was a lot worse.

image

a temp fix while we decide what to do about it long term, the teflon tape will help and i wrapped the motor with some aluminum tape

image

so if you get tool change errors, or a sloppy tool change where it feels like it doesn’t engage well or the motor just sounds funky, check that motor and brush, , it might just need a good cleaning.

measured 21 ohms on the motor after cleaning. (haas specs 5 to 20 ohms)

note correct placement of wiring at the front of the motor versus behind it

image

next we are going to pull out the shuttle motor and check it, that does not look fun to remove.

also this is a fun fella.

image

image

hello onsemi/fairchild ?

cheers

Teknik Quickset V6.3.8 under Windows 10

Update: Teknik have updated the app with these fixes and released V6.4.0 they accidentally included a readme that is actually a copy of the exe again as a txt file. so I let them know and they’re fixing it too but confirmed V6.4.0 works as expected on Windows 10

I’d recently added Windows 10 to  my main since it has a lot of nice stuff, wsl2/sandboxing etc. and as much as I like windows 7 it is time for a dual boot setup.

Anyway for the projects I am currently working on, so far only the Teknik QuickSet software failed to install/run.

The failure is from an .OCX file from a third party that allows them to use Hotkeys that get processed before VBA etc sees them.

How to fix it

Step 1. Download and install quickset 6.3 from Teknik.

It’ll tell you a OCX failed to register, ignore it in the popup and it will continue the install process.

Step 2. Grab this zip archive and extract it https://www.desaware.com/support/downloads/spyworks/signedcomponents.zip

Step 3. Replace the files in the Quickset folders with the files from this zip.

Step 4. Open up an elevated CMD prompt (Run as administrator)

image

Step 5. Go to the folder where quickset DLLs are (default location below)

cd “C:\Program Files (x86)\Teknic\Quickset 6.3”
regsvr32 DWSHK80.OCX
exit

We’re done with the command prompt now.

That should be it. QuickSet will now run as expected.

image

teknic servos and servo drivers

This is a W I P and will be adding to it as time permits, also as we do discovery and get it working.

We picked up a few teknic 2311 servos and controllers from ebay, the eclipse, sst and control point trajectory planner. The plan is to convert all our existing machines that use steppers into servos. Starting the journey with a HF Mini Lathe conversion its easy to handle and if you slam it into itself during tuning (which will likely happen) then its not going to do a lot of damage to itself or anyone else, since its tiny in comparison to our other Lathe/machines. Plus it is neat to have a small CNC lathe.

Prolog

Teknic make nice gear, they sell their ClearCore controller which is a neat little dev box, as well as ClearPath servos  that are stepper replacements that take step/dir and then translate all that into the proper servo movements for a brushless motor.

Since we managed to get a good deal on the servo drives and motors we decided to venture into the world of tuning Teknic servos.

Teknic support is basically two levels :-

one:  buy 100s or 100s of units a year of the eclipse and we’ll remotely tune and help
two: buy a clearpath

Which is fair enough.

There is also no auto tune feature and no hardware monitor port on Eclipse drives, the SSTs have them but are older tech. ClearPaths have auto tune, which is a fine choice, but at first you might be how do i get the fine control i’m looking for out of step/dir that i do from –/+ 10V

From best we can tell, you download the QuickSet software for your controller, load a windows .ini style config for your drive/motor setup if there is one and start from there. If there is no config for your setup you start off with the basic parameters of the motor from the datasheet and start PID style tuning on it, first on the bench with no load. Then with the load you are planning to drive.

Since Teknic won’t help us (after all we did buy from eBay we’re on our own) and we want to have interoperability between our motion controllers (tinyg/kflop) and the eclipse/servo drives.

Sounds easy enough…..

Quickset Software

The QuickSet software has an RS232 connection to the driver that can read back the various monitor signals from the driver (some drivers have a hardware monitor line you can connect a scope too, the help docs muddle the descriptions so you spend a while looking for the non existing port, even looking for a TLC5615C 10 bit DAC convertor on the main board, so far haven’t found it. These folks really like TI.

The are two versions of QuickSet we’re using 6.3 since 5.x doesn’t handle our drive, the SST version is called SST-QuickSet.

First thing we did was head to duckduckgo and search for “how to tune teknic servos” etc , lots of ClearPath examples, nothing on the separates. What about examples of the scope traces or what you should expect to see ( beyond the normal PID style tuning or <1 1 >1 style stuff ). Nope, how about anything at all?

Nothing. Maybe someone else can find a page detailing how it works but couldn’t find a thing.

Since we had the basic unloaded motor setup finished the next step was to load it and measuring tracking errors. Poking around the software, found “Tracking (Mtr) Dir) [F3]” etc.

Noting that some of the functions have short cut keys for setup,  F3/F4/F5  Kv tune Setup (shift F1) we figured that these would be the ones to use and setup first.  each shortcut changes a few parameters and setups the scopes and stimulus generator into  the right modes.

Tracking error still seems to evade though, we think  we’re looking at it.But not sure, i’ve looked thru the apps help section and its not great. The tune mode help sections go in circles, literally.

Searching the help section finally took us to a page that says

image

Phone support whats this ? I didn’t see anything obvious in the app. I did note the  Advanced section in the options page being greyed out so filled that for later investigation.

In the initial motor setup phase there is a shortcut keypress you have to do to enable editing the basic motor parameters. it’s ctrl+shift+M 

So i could look at the Registered Hotkeys, or i could say do Phone? ctrl+Shift+P ?

image

ControlPoint basic interface

image

Standalone phone support window

image

This fun box

image

I feel like one of the Hackers in the movies now where i guessed the password in one try. But really turns out I’m just one of those hackers that tried the obvious thing first and it worked “password123” etc. This may even be documented somewhere.

But now we can set a bar  showing the Direction tracking Error

image

It enables a tonne of other settings too.

For the ControlBasic scripting there is an old windows help format file that is a hassle to read, so just convert it to a modern one (HelpNDoc does it well)

For now we’ve got the motor moving back and forth with a slight “feels like a step” motion when using step/dir that might be the style of pulses from the TinyG we used to test, or its a setup error in the drive.

Using QuickSet the motor moves great, and its crazy torquey.

We initially tuned Kv then KP/Ki etc as discussed in the help section.

inital runs

Hardware setup

Most of the connections are molex, we lucked out that the eBay seller supplied cut and uncut cables. Also orderd spares from Arrow. SST and Eclipse here

Molex

0039012180 https://www.arrow.com/en/products/0039012180/molex
0039012200 https://www.arrow.com/en/products/0039012200/molex
0039000039 https://www.arrow.com/en/products/0039000039/molex
0050579405 https://www.arrow.com/en/products/0050579405/molex
0039012060 https://www.arrow.com/en/products/0039012060/molex
0016020119 https://www.arrow.com/en/products/0016020119/molex

TE

1-480698-0 https://www.arrow.com/en/products/1-480698-0/te-connectivity
1376348-1 https://www.arrow.com/en/products/1376348-1/te-connectivity

https://www.teknic.com/files/downloads/E2-3L_manual.pdf All listed in  here on page  73

Also DB25 male needed

RS232 tx/rx to the host used a usb adapter and it worked fine.  Pins 2 and 3 on the DB-25

Drive enable , have to ground that. Watch out for the drive jumping into life if its badly configured or such Pin 4 DB-25

Supply +5v power for the logic board  Pin 20 DB-25

Pin 21 DB-25 is GND

Supply a solid 75VDC from a power supply designed for servos, they don’t play well with most SMPS, the toridials with a full wave rectifier and a few caps do well. Molex 4 Pin

Wire up motors and controllers per datasheet.

Also add step/dir for later testing. you don’t need it for the initial tune

image

Thats about it.

Notes

These are just mostly notes to ourselves. Some of the values have changed

Links

https://www.teknic.com/files/product_info/E2-3L_r1.5.pdf

https://www.teknic.com/files/product_info/N23_Industrial_Grade_Motors.pdf

https://www.teknic.com/files/downloads/Teknic_SSt_System_Manual_Rev3.8.pdf

https://www.artisantg.com/info/Teknic_SSt_1500_301_Manual_2016122792438.pdf

https://www.teknic.com/downloads/

OK Keyboard version 2(3) part 1

Another blog entry which is incomplete so I will keep adding to it as my schedule allows.

This is technically the third revision of the One Key Per GPIO Keyboard OKPGK since there is an APA102 2020 and a SK6812 version of the original. I’m still using the APA102 2020s. I added thicker traces, USB C and a few more caps to help with the very last LED in the chain, i can hopefully double the speed the LEDs are updated, though they’re fast as it is and we’ll run into the limits of the LED itself hopefully, if not already there.

This isn’t an article about the creation of they keyboard, its more of a board log/process thing.

Switches and LEDS

image

Added bluetooth with the MDBT 50 module

image

Setting it up for the PNP

image

I like to put the boards in the orientation they end up on the PNP if possible.

Building the BOM with BOM-XS.ulp

image

Prepping for export to the Neoden4 Software NEODEN-4.ulp

image

BOM-Xs.ulp for getting a parts list and order together

image

At this point its worth going back over the schematic and making sure you’re using the same device for parts that are used more than once. The 10K resistors didn’t get grouped since I used one device from the sparkfun lbr and one from microbuilder. Which happened because I imported the Bluetooth module from another one of my designs.

After using the replace feature of Eagle they are now properly grouped. Adding ATTRIBUTES from Mouser and Digikey parts helps a lot here, we normally try to use a common library where the footprints are verified and the attributes already exist. The more  data you can add here, the less work you have to do when you start to buy/build.

image

 

Prepping the Pick and Place

Magnetic bars hold it place and am using the fixed board method here.

image

Cataloging Parts

I decide to catalogue all the parts on the PNP since it has been a while since we did a run, which took a while! All the reels photographed and documented, it is so much easier to do as you’re going along. We usually keep the NSL default stack updated in the default ULP but as you change the reels you can export/import the previous stack from each different setup so there is a .USS file that is usually newer than the default stack, and we’re still working out what our default stack is.

I made a Google Sheet so we can track the changes, I plan to tie this into the export scripts so it builds up either a USS or the default stack automatically from this spreadsheet.

image

Fiducials

Next is setting up the fiducials, basically what I’m doing is locating where the fiducuals are physically on the PNP, then look at where eagle thinks they are, then using the difference between the two points (x1-x2) (y1-y2) and entering that into the Eagle Export section, which means the board is placed at the correct physical location. The machine then will run the auto fiducial finder and adjust everything automatically for any small differences during mounting or such.

I have yet to annotate this video.

Doing that gives me the XY offset for this, and entering the Xd/Yd into the X and Y boxes the outputted CSV file will contain the physical coordinates on the PNP. I’d have taken more photos of the process, but the fish pump in the PNP gets annoying to listen too (and they’re all in the video linked above)

image

Some of the components don’t fit in reels so I’ll make  a custom tray..

One of the issues we have with lack of storage space is sometimes its easier to buy new components than find them, especially if it is tiny parts. Placed an order for the CPUs and also picked up a few extra MBDT50 with the external antenna and a suitable antenna, ended up being arrow and mouser, can never seem to find an order that is from one place. It’ll also give an opportunity to check the antennas with the VNA which is always fun.

 

Another App

I threw together a quick MFC application that OAuths to the Google Sheets API and can pull the data down, then we write the USS file to the local folder for the Eagle ULP to use. I’d liked to have embedded it all into the ULP but the Oauth part is trickier there.  Alternatively publishing the sheet to the Web and then just get/json etc but I prefer this since its a two way process.

image

The idea here is you can keep a master spreadsheet with the state of the current Pick and Place setup. Data can also be edited here and pushed back to the spreadsheet. For different machines, can have different spreadsheets.

The push back is for things like Nozzle ID and X and Y of pickup, place/pickup height etc which is often fine tuned on the machine.

I haven’t pulled the images yet, not sure if I will. Rather than getting crazy on support applications I want MVP (Minimum Viable Product) the idea is to cut down spent in preparation

May also output a script that updates or adds ATTRIBUTES for the OEM Part numbers in the sch/brd file.

stick-vise XY table

Finally got around to creating a XY table for the stick vise to use with the eakins digital inspection camera. This is just a quick write up.

The idea is it can scan the larger PCB, and overlay the routes etc.

Here it is, for test fitment I just 3d printed the mounts. I’ll cut them out of metal later.

20200606_191403
20200606_191323
2020-06-06 19_44_11-Linear Rail 50mm _ 100mm _ 150mm_ 200mm Linear Stage Actuator with Square Linear

The https://www.stickvise.com/ adapter

https://a360.co/2AHRemu

Adapter to  connect the two linear rails’ together.

https://a360.co/3h5zYIC

I picked up the rails off eBay/aliexpress but i wanted a longer 150mm so I grabbed another from Amazon, these things are available everywhere

2020-06-06 19_33_46-Autodesk Fusion 360
2020-06-06 19_21_37-Autodesk Fusion 360
2020-06-06 19_21_20-Autodesk Fusion 360

stick vise adapter.

2020-06-06 19_34_38-Autodesk Fusion 360
2020-06-06 19_22_21-Autodesk Fusion 360
2020-06-06 19_22_02-Autodesk Fusion 360

All the bolts are M3 I used are 10mm length.

The nut version

which bolts thru from this side.

I made the countersinks 5mm on the first plate I made ( not pictured), then hot welded an M3 threaded insert into the plastic, on the metal one i’d have just put an M3 nut in there.

To drive it i’m using  the Polulu  Tic’s https://www.pololu.com/category/212/tic-stepper-motor-controllers they don’t seem to have a dual one, or chainable so its two USBs at the moment.

that us more or less it. 3D print or mill the plates, attach the stick vise to the first plate, then the stick vise+plate to the first linear rail, then put the nuts or inserts on the second plates two holes (spaced 20mm ) and then bolt the second plate to the second longer linear rail with four M3 10mms, put the first shorter linear rail on top of the second, and use two M3 10mm bolts to hold it in place.

this is the overlay of the tracks on the pcb, pre XY. so now the plan is to  move the pcb around and have the tracks around.

2020-06-06 19_46_40-Dr Terrible's House of Bloggable – Stuff i posted - Brave

I’ll do a more detailed write up when its up and running in measuretwice. there were some notes in this post

https://charliex2.wordpress.com/2020/01/14/eakins-camera-hackery-pokery-and-the-legend-of-measuretwice/