— vince120 (@TiFr_Vince) October 13, 2019
— vince120 (@TiFr_Vince) October 13, 2019
Collé ! pic.twitter.com/vmrcZwNbSy
— vince120 (@TiFr_Vince) October 13, 2019
robinHood (./32) :
sympa :')
ça me fais penser que j'avais dumpé le protocole et réimplémenté un outil de contrôle des graveuses laser entrée de gamme chinoises, faudrait que je le termine
using namespace std;
int serial = 0;
static volatile int abordPrint = 0;
int endPrinting = 0;
u32 printx, printy;
void onmoved( void );
namespace zap {
union pixel {
u32 raw;
struct {
u8 x;
u8 ymore:4;
u8 xmore:4;
u8 y;
u8 color;
};
};
void pixelSet( pixel ** pp, int px, int py, u8 c ){
static int contigus = 0;
int color = 255 - c;
pixel * p = *pp;
if( color ){
color = ( ( color * ( 100 + colorBoost ) ) / 100 );
if( color > 0xff ) color = 0xff;
}
if( color < trimWhite ){ contigus=0; return; }
u8 x = px & 0xff,
xmore = ( px >> 8 ) & 0x0f,
y = py & 0xff,
ymore = ( py >> 8 ) & 0x0f
;
p->raw = 0;
p->x = x; p->xmore = xmore;
p->y = y; p->ymore = ymore;
p->color = color;
if( ++contigus == fakePixel ){
p++;
p->raw = 0;
p->x = x; p->xmore = xmore;
p->y = y; p->ymore = ymore;
contigus=0;
}
*pp = p + 1;
}
pixel * img2b( u8 * img, int sx, int sy, int * nb ){
*nb = 0;
int size = sx * sy; if( !size ) return 0;
u8 *i = img;
pixel *out = (pixel*)malloc( size * 2 * sizeof( pixel ) ), *p=out;
if( !out ) return 0;
int x=0, y=0;
while( 1 ){
while( x != sx )
pixelSet( &p, x++, y, *i++ );
x--;
if( ++y == sy ) break;
i += sx;
while( x != -1 )
pixelSet( &p, x--, y, *i-- );
x++;
i += sx;
if( ++y == sy ) break;
};
*nb = p - out;
return out;
}
}; // /zap
u8 * png2img(const char* file, int*width , int*height){
png_byte color_type;
png_byte bit_depth;
png_structp png_ptr;
png_infop info_ptr;
png_bytep * row_pointers;
char header[8];
/* open file and test for it being a png */
FILE *fp = fopen(file, "rb");
if (!fp) return 0;
fread(header, 1, 8, fp);
if(png_sig_cmp((const unsigned char*)header, 0, 8)) return 0;
/* initialize stuff */
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if(!png_ptr) return 0;
info_ptr = png_create_info_struct(png_ptr);
if(!info_ptr) return 0;
if(setjmp(png_jmpbuf(png_ptr))) return 0;
png_init_io(png_ptr, fp);
png_set_sig_bytes(png_ptr, 8);
png_read_info(png_ptr, info_ptr);
*width = png_get_image_width(png_ptr, info_ptr);
*height = png_get_image_height(png_ptr, info_ptr);
color_type = png_get_color_type(png_ptr, info_ptr);
bit_depth = png_get_bit_depth(png_ptr, info_ptr);
if(bit_depth == 16)
png_set_strip_16(png_ptr);
if(color_type == PNG_COLOR_TYPE_PALETTE)
png_set_palette_to_rgb(png_ptr);
// PNG_COLOR_TYPE_GRAY_ALPHA is always 8 or 16bit depth.
if(color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
png_set_expand_gray_1_2_4_to_8(png_ptr);
if(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
png_set_tRNS_to_alpha(png_ptr);
// These color_type don't have an alpha channel then fill it with 0xff.
if(color_type == PNG_COLOR_TYPE_RGB ||
color_type == PNG_COLOR_TYPE_GRAY ||
color_type == PNG_COLOR_TYPE_PALETTE)
png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER);
if(color_type == PNG_COLOR_TYPE_GRAY ||
color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
png_set_gray_to_rgb(png_ptr);
png_read_update_info(png_ptr, info_ptr);
row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * *height);
if( !row_pointers ) return 0;
for (int y=0; y<*height; y++){
row_pointers[y] = (png_byte*) malloc(png_get_rowbytes(png_ptr,info_ptr));
if( !row_pointers[y] ) return 0;
}
png_read_image(png_ptr, row_pointers);
fclose(fp);
u8 * img = (u8*)malloc( *width * *height ), *i = img;
if( !img ) return 0;
int x, y;
for( y = 0 ; y < *height ; y++){
png_byte* row = row_pointers[y];
for( x = 0; x < *width; x++) {
*i++ = row[x * 4];
}
free(row);
}
free(row_pointers);
return img;
}
int set_interface_attribs(int fd, int speed){
struct termios tty;
if (tcgetattr(fd, &tty) < 0) {
printf("Error from tcgetattr: %s\n", strerror(errno));
return -1;
}
cfsetospeed(&tty, (speed_t)speed);
cfsetispeed(&tty, (speed_t)speed);
tty.c_cflag |= (CLOCAL | CREAD); /* ignore modem controls */
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8; /* 8-bit characters */
tty.c_cflag &= ~PARENB; /* no parity bit */
tty.c_cflag &= ~CSTOPB; /* only need 1 stop bit */
tty.c_cflag &= ~CRTSCTS; /* no hardware flowcontrol */
/* setup for non-canonical mode */
tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
tty.c_oflag &= ~OPOST;
/* fetch bytes as they become available */
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 1;
if (tcsetattr(fd, TCSANOW, &tty) != 0) {
printf("Error from tcsetattr: %s\n", strerror(errno));
return -1;
}
return 0;
}
int openSerial( const char * portname ){
int fd;
fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC);
if (fd < 0) return 0;
/* baudrate 115200, 8 bits, no parity, 1 stop bit */
set_interface_attribs(fd, B115200);
return fd;
}
int serialWriteNoLog(int serial, u8 * data, int length){
int l = write(serial, data, length);
//printf("write %u bytes\n",length);
tcdrain( serial );
return l;
}
int serialWriteLog(int serial, u8 * data, int length){
int l = write(serial, data, length);
//printf("write %u bytes\n",length);
int i = 0; while(i != length){
printf("%02x ",data[i]);
i++;
if( !(i % 16) ) printf("\n");
}
printf("\n");
if(length < 20){ i = 0; while(i != length) printf("%c",data[i++]); printf("\n"); }
tcdrain( serial );
return l;
}
int serialWrite(int serial, u8 * data, int length){
int l = write(serial, data, length);
//printf("write %u bytes\n",length);
//int i = 0; while(i != length) printf("%02x",data[i++]); printf("\n");
//if(length < 20){ i = 0; while(i != length) printf("%c",data[i++]); printf("\n"); }
tcdrain( serial );
return l;
}
int serialWriteS( int serial, const char * string ){
return serialWrite( serial, (u8*)string, strlen( string ) );
}
float laserPower = 0, laserTime = 0, *currentEngraverPSend = 0;
zap::pixel * pixelsData = 0; u32 pixelsDataLength = 0; u32 totalBytes = 0;
u8 empty[ 1024 ];
int imgwidth = 0, imgheight = 0;
void onready( void );
u32 bleft = 1024*3;
u32 started = 0;
void processCommand( char command, u32 argsNb, char * args ){
if( !argsNb ) return;
char *a = args; // first arg
/*
printf("process command %c",command);
for( u32 n=0;n<argsNb;n++ )
printf(" %s",&args[n*ARGS_MAX_LENGTH]);
printf("\n");
*/
switch( command ){
case 'B':
if( *a == '2' ){
printf("* unknow B2 request data command");
abordPrint = 1;
break;
}
if( *a != '1' ) break;
switch( a[1] ){
case '0': // B10
printf("< hello !\n");
break;
case 0: // B1
//printf("< engraver request some data !\n");
if( !started ){
//reset
printf("< resume ?\n> eof !\n");
serialWriteS( serial, "$33" );
/*serialWrite( serial, empty, 1024 );
wait(300);
serialWrite( serial, empty, 1024 );
wait(300);
serialWrite( serial, empty, 1024 );
wait(300);
serialWriteS( serial, "$33" );
wait(300);
serialWriteS( serial, "$32" );
wait(300);*/
//sleep(1);
/*serialWrite( serial, empty, 1024 );
sleep(1);
serialWriteS( serial, "$33" );
sleep(1);
printf("> abord\n");
serialWriteS( serial, "$32" );
sleep(2);
printf("> hello ???\n");
serialWriteS( serial, "$40" );*/
//printf("> reset\n");
//serialWriteS( serial, "$42" );
//sleep(2);
// serialWriteS( serial, "$42" );
break;
}
if( !pixelsData || !pixelsDataLength ){
if(bleft < 1024){
// eof
printf("> eof\n");
serialWriteS( serial, "$33" );
break;
}
bleft -= 1024;
printf("> send %u empty pixels\n",256);
serialWrite( serial, empty, 1024 );
break;
}
if(bleft > 1024) bleft -= 1024; else bleft = 0;
if( pixelsDataLength >= 256 ){
pixelsDataLength -= 256;
serialWrite( serial, (u8*)pixelsData, 1024 );
pixelsData = &pixelsData[256];
//printf("> send %u pixels\n",256);
//printf(">>");
} else {
/*u8 bf[ 1024 ];
u32 i=0;
for(;i<pixelsDataLength;i++)
*(u32*)&bf[i*4] = pixelsData[i].raw;
*/
//printf("> send %u pixels\n",pixelsDataLength);
//printf( ">>" );
serialWrite( serial, (u8*)pixelsData, pixelsDataLength*4 );
/* zap::pixel * p = pixelsData;
int x, y;
for( y = 0; y < imgheight; y++ ){
for( x = 0; x < imgwidth; x++ ){
printf( "%08x ", p->raw );
p++;
}
printf("\n");
}
p = pixelsData;
for( y = 0; y < imgheight; y++ ){
for( x = 0; x < imgwidth; x++ ){
printf( "%02x ", p->color );
p++;
}
printf("\n");
}
*/
pixelsDataLength = 256 - pixelsDataLength;
//printf("> send %u empty pixels\n",pixelsDataLength);
serialWriteNoLog( serial, empty, pixelsDataLength*4 );
pixelsDataLength = 0;
pixelsData = 0;
}
printf( "<< %u / %u >>\n", totalBytes - pixelsDataLength*4, totalBytes );
break;
}
break;
case 'F':
switch( *a ){
case '8':
currentEngraverPSend = &laserPower;
break;
case '9':
currentEngraverPSend = &laserTime;
break;
case '1':
if( a[1] == '1' ){ // F11, moved
printf("< moved to start position\n");
onmoved();
}
break;
case '2':
switch( a[1] ){
case '0':
printf("< starting !\n");
break;
case '2':
if( started ){
printf("< done\n");
endPrinting = 1;
break;
}
printf("< aborded\n> hello ?\n");
serialWriteS(serial, "$40");
//printf("< %s\n", started ? "done" : "aborded");
//endPrinting = started;
break;
case '3':
printf("< eof\n");
break;
default:
printf("< F2%c\n",a[1]);
break;
}
break;
default:
printf("< F%c%c\n",*a,a[1]);
break;
}
break;
case 'P':
if( !currentEngraverPSend ) return;
*currentEngraverPSend = strtof(a,0);
printf("< %s : %f\n", currentEngraverPSend == &laserPower ? "power" : "time", *currentEngraverPSend);
if( currentEngraverPSend == &laserTime ){
char * aa = a;
while(*aa && *aa != '-') aa++;
if( *aa ){
// bad start ?
printf("< resume ?\n");
//onready();
// resend hello ?
printf("> abord\n");
serialWriteS( serial, "$32" );
}
}
currentEngraverPSend = 0;
break;
case 'c':
printf("< ready !\n");
//onready();
if( imgwidth < 96 && imgheight < 96 ){
{ u8 * bf = (u8*)pixelsData;
int i = 0;
while(i != imgwidth * imgheight * 4){
printf("%s%02x ",i%4?KNRM:KGRN,bf[i]);
//printf( "%08x ", p->raw );
i++;
if( !(i % 16) ) printf("\n");
}
}
printf("%s\n",KNRM);
/*{ zap::pixel * bf = pixelsData;
int i = 0;
while(i != imgwidth * imgheight){
printf("%02x ",bf[i].color);
i++;
if( !(i % imgwidth) ) printf("\n");
}
}
printf("\n");*/
}
//wait(400);
onready();
break;
default:
printf("*** unknow command %c %u\n",command,argsNb);
break;
}
}
char * pumpCommand( char *bf, char * end ){
char *p = bf;
// jump to next command
while( (*p < 'A' || *p > 'Z') && p != end && *p != 'c' ){
printf("skip %u, %2x, %c\n",*p,*p,*p);
p++; // skip all for command
}
if( p == end ) return 0; // not found
char command = *p++;//, *data = p;
// until end or another command, space arg separator
u32 argsNb = 0, arg = 0;
char args[MAX_ARGS*ARGS_MAX_LENGTH], *argp = args;
while( p != end && !( *p > 'A' && *p < 'Z' ) ){
//printf("%c",*p);
if( *p == ' ' ){
if( arg ){
argsNb++;
argp = &args[ argsNb*ARGS_MAX_LENGTH ]; arg=0;
}
} else {
*argp++ = *p; *argp=0; // copy arg char
arg++;
}
p++;
};
if( arg ) argsNb++;
if( !argsNb ) return 0;
char * rtn = p == end ? 0 : p;
processCommand( command, argsNb, args );
return rtn;
}
void onready( void ){
wait(400);
serialWriteS(serial,"$8 P1.000"); // power 100%
wait(400);
serialWriteS(serial,"$9 P1.000"); // time 100%
printx = ( 1600 - imgwidth ) / 2;
printy = ( 1600 - imgheight ) / 2;
//printx = printy = 0;
printf("> move to %u %u\n",printx,printy);
char bf[64];
sprintf(bf, "$25 P%u %u", printx, printy);
wait(400);
serialWriteS( serial, bf );
started = 1;
}
void onmoved( void ){
if( !started ) return;
//printf("set power & time\n");
/*
wait(500);
serialWriteS(serial,"$8 P1.000"); // power 90%
wait(500);
serialWriteS(serial,"$9 P1.000"); // time 100%
*/
wait(500);
printf("> start engraving\n");
char bf[64];
sprintf(bf, "$30 P%u %u P2", printx, printy);
//printf("%s\n",bf);
serialWriteS( serial, bf );
}
void onctrlc( int sig )
{
if( !( serial ) ) return;
//ioctl( serial, TIOCSTI, "releasing" ); // unblock read
abordPrint = 1;
}
int main(int argc, char const *argv[]) {
int width, height, nbpx;
//struct sigaction act;
//memset (&act, '\0', sizeof(act));
//act.sa_handler = intHandler;
//act.sa_sigaction = &onctrlc;
//act.sa_flags = SA_SIGINFO;
signal( SIGINT, onctrlc );
// load png into a 8b raw buffer
u8 * img = png2img( argv[1], &width, &height );
if( !img ){
printf("cannot load picture\n");
return 0;
}
// convert picture to laser "pixels" bytecode buffer
zap::pixel *pixels = zap::img2b( img, width, height, &nbpx );
pixelsData = pixels; pixelsDataLength=/*width*height*/nbpx; totalBytes = pixelsDataLength*4;
imgwidth = width;
imgheight = height;
free( img ); // no more need picture buffer
if( !pixels ) return 0;
printf( "* loaded picture, %ix%i, %u px\n", width, height, nbpx );
// open serial port
const char *port = "/dev/ttyUSB0";
serial = openSerial( port );
if( !serial ){
free( pixels );
printf("* no engraver found or accessible on %s\n", port);
return 0;
}
printf("* connected on %s\n", port);
// hello
printf("> hello ?\n");
serialWriteS( serial, "$40" );
memset( empty, 0, 1024 );
char bf[ serialBfLength ];
while(1){
wait( 50 ); // 20 fps
if( abordPrint ){ // ctrl-C ?
printf("\n%sabord!%s\n",KRED,KNRM);
serialWriteS(serial, "$32");
sleep(2); // abord
//printf("reset!\n");
//serialWriteS(serial, "$42");
//sleep(2); // reset
break; // bye
}
int l;
ioctl( serial, FIONREAD, &l);
if( l ){
l = read( serial, bf, serialBfLength - 1 );
if( !l ) continue; // nothing to read
}
char *b = bf, *end = bf + l;
while( b ) b = pumpCommand( b, end );
if( endPrinting ) break;
};
free( pixels );
//serialWriteS(serial, "$42"); sleep(1); // reset
close(serial);
return 0;
}
vince (./26) :Le pb de ça c'est que ça ne permet que de la gravure et qu'au final ça se limite à de la 2D extrudéEngraving: from CAD to CNC using free softwareLuigi Findanno MakesI was looking for a metallic protractor to mount on my DIY antenna rotator and I was sure chinese suppliers was the answer. As I found some interesting objects, thay had some limitations: too big o…
trouvé sur touiteur grâce à squalyl
vince (./11) :J'ai refait la pièce pour ajouter un Z max (il n'y avait que zmin) parce que manifestement le cycle de homing avec lasergrbl a besoin des deux fins de courses
Grâce à squalyl j'ai la possibilité de faire du homing sur ma CNC, mais il manquait un interrupteur sur Z, j'ai donc refait la pièce qui tient la fraise...
Modifs :
- ajout d'un emplacement pour l'interrupteur de fin de course + ses vis+ une sortie pour le fil
- ajout d'un renfort pour la vis de serrage de l'outil
- ajout d'un emplacement pour une rondelle au niveau de la vis de serrage de l'outil
A droite la version d'origine, à gauche la version modifiée.
C'est la première impression, il a fallu en faire une autre :
- les dimensions des vis pour l'interrupteur sont trop short
- il manque un mm pour la largeur de l'outil fraise (pour le laser c'est bon par contre)
- la rondelle que j'ai en stock est plus épaisse que le trou prévu pour elle
- j'ai mesuré le diamètre de la mauvaise vis au moment de prévoir le trou pour la vis de serrage, je l'ai vu au moment du montage
A part ça, les trous de la colonne (roulements à bille) et del'axe vis sans fin sont nickels...
Et ma version est plus lourde, je pense que la différence de matériau n'explique pas tout et que c'est la valeur d'infill de la pièce d'origine qui était plus basse que la mienne (je suis à 50% d'infill)