View unanswered posts | View active topics It is currently Wed May 22, 2013 9:13 pm



Reply to topic  [ 6 posts ] 
Silence those Batch 1 Generation 6 electronics.... 
Author Message

Joined: Mon Dec 20, 2010 3:38 pm
Posts: 166
Post Silence those Batch 1 Generation 6 electronics....
I've been playing around today.. and I've managed to impliment an acceptable software fix for the PWM squeel given off by the first batch Gen6 boards..

It involves implementing an M84 gcode in the firmware to disable the steppers when not printing... Tonokips does this and it's very handy.

So... Download your firmware of choice (old optos or new optos)

Open it in Arduino and add the following lines to the process_g_code module:


//turn the steppers off until next use, to silence the PWM squeel
case 84:
digitalWrite(X_ENABLE_PIN, !ENABLE_ON);
digitalWrite(Y_ENABLE_PIN, !ENABLE_ON);
digitalWrite(E_ENABLE_PIN, !ENABLE_ON);



Put them at about line 540 some ways under the M code section:
//find us an m code.
if (gc.seen & GCODE_M)

Once you've installed the patched firmware you can enter M84 in the gcode window in repsnapper to silence the motors... you can make a custom button.. and you can add M84 to the end.gcode in skeinforge or under the end gcode tab in repsnapper so that when the print is finished the motors go silent.

Happy NewYear!

Al...


Sat Jan 08, 2011 11:44 pm
Profile

Joined: Wed Jan 05, 2011 3:45 am
Posts: 33
Post Re: Silence those Batch 1 Generation 6 electronics....
Great stuff araspitfire!

I've added the patch to my github, and confirmed it works (you do need to add an extra break ..)

git://github.com/WebSpider/reprap.git


Sun Jan 09, 2011 4:56 am
Profile

Joined: Fri Dec 31, 2010 3:00 pm
Posts: 74
Post Re: Silence those Batch 1 Generation 6 electronics....
Just to inform you, I've posted on this forum how you have to change the switching freguency so you can eliminate the noise the first batch had...

See:
viewtopic.php?f=19&t=72


Mon Jan 24, 2011 3:58 pm
Profile

Joined: Fri Dec 31, 2010 3:00 pm
Posts: 74
Post Re: Silence those Batch 1 Generation 6 electronics....
So for the firmware fix just add this piece of code between:
"//turn extruder off
*/"

and

"//custom code for temperature control"

in "FiveD_GCode_Interpreter"

Insert this:
"
//turn the steppers off until next use, to silence the PWM squeel
case 84:
digitalWrite(X_ENABLE_PIN, !ENABLE_ON);
digitalWrite(Y_ENABLE_PIN, !ENABLE_ON);
digitalWrite(E_ENABLE_PIN, !ENABLE_ON);
break;
"


Mon Jan 31, 2011 12:20 pm
Profile

Joined: Sun Jan 30, 2011 8:09 pm
Posts: 4
Post Re: Silence those Batch 1 Generation 6 electronics....
BTW this is what my firmware looked like after installing this, I had a hard time following the instructions :)


/**

RepRap GCode interpreter.

IMPORTANT

Before changing this interpreter,read this page:

http://objects.reprap.org/wiki/Mendel_U ... pRapGCodes

*/


#include "configuration.h"
#include "pins.h"
#include "extruder.h"
#include "vectors.h"
#include "cartesian_dda.h"
#include <string.h>

/* bit-flags for commands and parameters */
#define GCODE_G (1<<0)
#define GCODE_M (1<<1)
#define GCODE_P (1<<2)
#define GCODE_X (1<<3)
#define GCODE_Y (1<<4)
#define GCODE_Z (1<<5)
#define GCODE_I (1<<6)
#define GCODE_N (1<<7)
#define GCODE_CHECKSUM (1<<8)
#define GCODE_F (1<<9)
#define GCODE_S (1<<10)
#define GCODE_Q (1<<11)
#define GCODE_R (1<<12)
#define GCODE_E (1<<13)
#define GCODE_T (1<<14)
#define GCODE_J (1<<15)


#define PARSE_INT(ch, str, len, val, seen, flag) \
case ch: \
len = scan_int(str, &val, &seen, flag); \
break;

#define PARSE_LONG(ch, str, len, val, seen, flag) \
case ch: \
len = scan_long(str, &val, &seen, flag); \
break;

#define PARSE_FLOAT(ch, str, len, val, seen, flag) \
case ch: \
len = scan_float(str, &val, &seen, flag); \
break;

/* gcode line parse results */
struct GcodeParser
{
unsigned int seen;
int G;
int M;
int T;
float P;
float X;
float Y;
float Z;
float E;
float I;
float J;
float F;
float S;
float R;
float Q;
int Checksum;
long N;
long LastLineNrRecieved;
};


//our command string
char cmdbuffer[COMMAND_SIZE];
char c = '?';
byte serial_count = 0;
boolean comment = false;
FloatPoint fp;
FloatPoint sp;

#define DEBUG_ECHO (1<<0)
#define DEBUG_INFO (1<<1)
#define DEBUG_ERRORS (1<<2)

byte SendDebug = DEBUG_INFO | DEBUG_ERRORS;


// The following three inline functions are used for things like return to 0

inline void specialMoveX(const float& x, const float& feed)
{
sp = where_i_am;
sp.x = x;
sp.f = feed;
qMove(sp);
}

inline void specialMoveY(const float& y, const float& feed)
{
sp = where_i_am;
sp.y = y;
sp.f = feed;
qMove(sp);
}

inline void specialMoveZ(const float& z, const float& feed)
{
sp = where_i_am;
sp.z = z;
sp.f = feed;
qMove(sp);
}

void zeroX()
{
where_i_am.f = SLOW_XY_FEEDRATE;
specialMoveX(where_i_am.x - 5, FAST_XY_FEEDRATE);
specialMoveX(where_i_am.x - 250, FAST_XY_FEEDRATE);
where_i_am.x = 0;
where_i_am.f = SLOW_XY_FEEDRATE;
specialMoveX(where_i_am.x + 1, SLOW_XY_FEEDRATE);
specialMoveX(where_i_am.x - 10, SLOW_XY_FEEDRATE);
where_i_am.x = 0;
}

void zeroY()
{
specialMoveY(where_i_am.y - 5, FAST_XY_FEEDRATE);
specialMoveY(where_i_am.y - 250, FAST_XY_FEEDRATE);
where_i_am.y = 0;
where_i_am.f = SLOW_XY_FEEDRATE;
specialMoveY(where_i_am.y + 1, SLOW_XY_FEEDRATE);
specialMoveY(where_i_am.y - 10, SLOW_XY_FEEDRATE);
where_i_am.y = 0;

}

void zeroZ()
{
where_i_am.f = SLOW_Z_FEEDRATE;
specialMoveZ(where_i_am.z - 0.5, FAST_Z_FEEDRATE);
specialMoveZ(where_i_am.z - 250, FAST_Z_FEEDRATE);
where_i_am.z = 0;
where_i_am.f = SLOW_Z_FEEDRATE;
specialMoveZ(where_i_am.z + 1, SLOW_Z_FEEDRATE);
specialMoveZ(where_i_am.z - 2, SLOW_Z_FEEDRATE);
where_i_am.z = 0;
}

//our feedrate variables.
//float feedrate = SLOW_XY_FEEDRATE;

/* keep track of the last G code - this is the command mode to use
* if there is no command in the current string
*/
int last_gcode_g = -1;

boolean abs_mode = true; //0 = incremental; 1 = absolute

float extruder_speed = 0;

int scan_int(char *str, int *valp);
int scan_float(char *str, float *valp);

GcodeParser gc; /* string parse result */


//init our string processing
inline void init_process_string()
{
serial_count = 0;
comment = false;
}

// Get a command and process it

void get_and_do_command()
{
//read in characters if we got them.
if (Serial.available())
{
c = Serial.read();
blink();
if(c == '\r')
c = '\n';
// Throw away control chars except \n
if(c >= ' ' || c == '\n')
{

//newlines are ends of commands.
if (c != '\n')
{
// Start of comment - ignore any bytes received from now on
if (c == ';')
comment = true;

// If we're not in comment mode, add it to our array.
if (!comment)
cmdbuffer[serial_count++] = c;
}

}
}

// Data runaway?
if(serial_count >= COMMAND_SIZE)
init_process_string();

//if we've got a real command, do it
if (serial_count && c == '\n')
{
// Terminate string
cmdbuffer[serial_count] = 0;

if(SendDebug & DEBUG_ECHO)
{
Serial.print("Echo:");
Serial.println(&cmdbuffer[0]);
}
//process our command!
process_string(cmdbuffer, serial_count);

//clear command.
init_process_string();

// Say we're ready for the next one

if(debugstring[0] != 0 && (SendDebug & DEBUG_INFO))
{
Serial.print("ok ");
Serial.println(debugstring);
debugstring[0] = 0;
} else
Serial.println("ok");
}
}



int parse_string(struct GcodeParser * gc, char instruction[ ], int size)
{
int ind;
int len; /* length of parameter argument */

gc->seen = 0;

len=0;
/* scan the string for commands and parameters, recording the arguments for each,
* and setting the seen flag for each that is seen
*/
for (ind=0; ind<size; ind += (1+len))
{
len = 0;
switch (instruction[ind])
{
PARSE_INT('G', &instruction[ind+1], len, gc->G, gc->seen, GCODE_G);
PARSE_INT('M', &instruction[ind+1], len, gc->M, gc->seen, GCODE_M);
PARSE_INT('T', &instruction[ind+1], len, gc->T, gc->seen, GCODE_T);
PARSE_FLOAT('S', &instruction[ind+1], len, gc->S, gc->seen, GCODE_S);
PARSE_FLOAT('P', &instruction[ind+1], len, gc->P, gc->seen, GCODE_P);
PARSE_FLOAT('X', &instruction[ind+1], len, gc->X, gc->seen, GCODE_X);
PARSE_FLOAT('Y', &instruction[ind+1], len, gc->Y, gc->seen, GCODE_Y);
PARSE_FLOAT('Z', &instruction[ind+1], len, gc->Z, gc->seen, GCODE_Z);
PARSE_FLOAT('I', &instruction[ind+1], len, gc->I, gc->seen, GCODE_I);
PARSE_FLOAT('J', &instruction[ind+1], len, gc->J, gc->seen, GCODE_J);
PARSE_FLOAT('F', &instruction[ind+1], len, gc->F, gc->seen, GCODE_F);
PARSE_FLOAT('R', &instruction[ind+1], len, gc->R, gc->seen, GCODE_R);
PARSE_FLOAT('Q', &instruction[ind+1], len, gc->Q, gc->seen, GCODE_Q);
PARSE_FLOAT('E', &instruction[ind+1], len, gc->E, gc->seen, GCODE_E);
PARSE_LONG('N', &instruction[ind+1], len, gc->N, gc->seen, GCODE_N);
PARSE_INT('*', &instruction[ind+1], len, gc->Checksum, gc->seen, GCODE_CHECKSUM);
default:
break;
}
}
}


//Read the string and execute instructions
void process_string(char instruction[], int size)
{
//the character / means delete block... used for comments and stuff.
if (instruction[0] == '/')
return;

float fr;
bool axisSelected;

fp.x = 0.0;
fp.y = 0.0;
fp.z = 0.0;
fp.e = 0.0;
fp.f = 0.0;

//get all our parameters!
parse_string(&gc, instruction, size);


// Do we have lineNr and checksums in this gcode?
if((bool)(gc.seen & GCODE_CHECKSUM) | (bool)(gc.seen & GCODE_N))
{
// Check that if recieved a L code, we also got a C code. If not, one of them has been lost, and we have to reset queue
if( (bool)(gc.seen & GCODE_CHECKSUM) != (bool)(gc.seen & GCODE_N) )
{
if(SendDebug & DEBUG_ERRORS)
Serial.println("Serial Error:Recieved a LineNr code without a Checksum code or Checksum without LineNr");
FlushSerialRequestResend();
return;
}
// Check checksum of this string. Flush buffers and re-request line of error is found
if(gc.seen & GCODE_CHECKSUM) // if we recieved a line nr, we know we also recieved a Checksum, so check it
{
// Calc checksum.
byte checksum = 0;
byte count=0;
while(instruction[count] != '*')
checksum = checksum^instruction[count++];
// Check checksum.
if(gc.Checksum != (int)checksum)
{
if(SendDebug & DEBUG_ERRORS)
Serial.println("Serial Error: checksum mismatch");
FlushSerialRequestResend();
return;
}
// Check that this lineNr is LastLineNrRecieved+1. If not, flush
if(!( (bool)(gc.seen & GCODE_M) && gc.M == 110)) // unless this is a reset-lineNr command
if(gc.N != gc.LastLineNrRecieved+1)
{
if(SendDebug & DEBUG_ERRORS)
Serial.println("Serial Error: LineNr is not the last lineNr+1");
FlushSerialRequestResend();
return;
}
//If we reach this point, communication is a succes, update our "last good line nr" and continue
gc.LastLineNrRecieved = gc.N;
}
}


/* if no command was seen, but parameters were, then use the last G code as
* the current command
*/
if ((!(gc.seen & (GCODE_G | GCODE_M | GCODE_T))) && ((gc.seen != 0) && (last_gcode_g >= 0)))
{
/* yes - so use the previous command with the new parameters */
gc.G = last_gcode_g;
gc.seen |= GCODE_G;
}

// Deal with emergency stop as No 1 priority

if ((gc.seen & GCODE_M) && (gc.M == 112))
shutdown();

//did we get a gcode?
if (gc.seen & GCODE_G)
{
last_gcode_g = gc.G; /* remember this for future instructions */
fp = where_i_am;
if (abs_mode)
{
if (gc.seen & GCODE_X)
fp.x = gc.X;
if (gc.seen & GCODE_Y)
fp.y = gc.Y;
if (gc.seen & GCODE_Z)
fp.z = gc.Z;
if (gc.seen & GCODE_E)
fp.e = gc.E;
}
else
{
if (gc.seen & GCODE_X)
fp.x += gc.X;
if (gc.seen & GCODE_Y)
fp.y += gc.Y;
if (gc.seen & GCODE_Z)
fp.z += gc.Z;
if (gc.seen & GCODE_E)
fp.e += gc.E;
}

// Get feedrate if supplied - feedrates are always absolute???
if ( gc.seen & GCODE_F )
fp.f = gc.F;

// Process the buffered move commands first
// If we get one, return immediately

switch (gc.G)
{
//Rapid move
case 0:
fr = fp.f;
fp.f = FAST_XY_FEEDRATE;
qMove(fp);
fp.f = fr;
return;

// Controlled move; -ve coordinate means zero the axis
case 1:
qMove(fp);
return;

//go home. If we send coordinates (regardless of their value) only zero those axes
case 28:
axisSelected = false;
if(gc.seen & GCODE_X)
{
zeroX();
axisSelected = true;
}
if(gc.seen & GCODE_Y)
{
zeroY();
axisSelected = true;
}
if(gc.seen & GCODE_Z)
{
zeroZ();
axisSelected = true;
}
if(!axisSelected)
{
zeroX();
zeroY();
zeroZ();
}
where_i_am.f = SLOW_XY_FEEDRATE; // Most sensible feedrate to leave it in

return;


default:
break;
}

// Non-buffered G commands
// Wait till the buffer q is empty first

while(!qEmpty()) delay(WAITING_DELAY);
//delay(2*WAITING_DELAY); // For luck
switch (gc.G)
{

//Dwell
case 4:
delay((int)(gc.P + 0.5));
break;

//Inches for Units
case 20:
setUnits(false);
break;

//mm for Units
case 21:
setUnits(true);
break;

//Absolute Positioning
case 90:
abs_mode = true;
break;

//Incremental Positioning
case 91:
abs_mode = false;
break;

//Set position as fp
case 92:
setPosition(fp);
break;

default:
if(SendDebug & DEBUG_ERRORS)
{
Serial.print("huh? G");
Serial.println(gc.G, DEC);
FlushSerialRequestResend();
}
}
}




//find us an m code.
if (gc.seen & GCODE_M)
{
// Wait till the q is empty first
while(!qEmpty()) delay(WAITING_DELAY);
//delay(2*WAITING_DELAY);
switch (gc.M)
{


case 0:
shutdown();
break;
/*
case 1:
//todo: optional stop
break;

case 2:
//todo: program end
break;
*/

// Now, with E codes, there is no longer any idea of turning the extruder on or off.
// (But see valve on/off below.)

/*
//turn extruder on, forward
case 101:
ex[extruder_in_use]->setDirection(1);
ex[extruder_in_use]->setSpeed(extruder_speed);
break;

//turn extruder on, reverse
case 102:
ex[extruder_in_use]->setDirection(0);
ex[extruder_in_use]->setSpeed(extruder_speed);
break;

//turn extruder off

*/

//turn the steppers off until next use, to silence the PWM squeel
case 84:
digitalWrite(X_ENABLE_PIN, !ENABLE_ON);
digitalWrite(Y_ENABLE_PIN, !ENABLE_ON);
digitalWrite(E_ENABLE_PIN, !ENABLE_ON);
break;

//custom code for temperature control
case 104:
if (gc.seen & GCODE_S)
{
ex[extruder_in_use]->setTemperature((int)gc.S);
}
break;

//custom code for temperature reading
case 105:
Serial.print("T:");
Serial.print(ex[extruder_in_use]->getTemperature());
Serial.print(" B:");
Serial.println(ex[0]->getBedTemperature());
break;

//turn fan on
case 106:
ex[extruder_in_use]->setCooler(255);
break;

//turn fan off
case 107:
ex[extruder_in_use]->setCooler(0);
break;


// Set the temperature and wait for it to get there
case 109:
ex[extruder_in_use]->setTemperature((int)gc.S);
ex[extruder_in_use]->waitForTemperature();
break;
// Starting a new print, reset the gc.LastLineNrRecieved counter
case 110:
if (gc.seen & GCODE_N)
{
gc.LastLineNrRecieved = gc.N;
if(SendDebug & DEBUG_INFO)
Serial.println("DEBUG:LineNr set");
}
break;
case 111:
SendDebug = gc.S;
break;
case 112: // STOP!
{
int a=50;
while(a--)
{blink(); delay(50);}
}
cancelAndClearQueue();
break;

// If there's an S field, use that to set the PWM, otherwise use the pot.
case 108:
case 113:
#if MOTHERBOARD > 1
if (gc.seen & GCODE_S)
ex[extruder_in_use]->setPWM((int)(255.0*gc.S + 0.5));
else
ex[extruder_in_use]->usePotForMotor();
#endif
break;

//custom code for returning current coordinates
case 114:
Serial.print("C: X");
Serial.print(where_i_am.x);
Serial.print(" Y");
Serial.print(where_i_am.y);
Serial.print(" Z");
Serial.print(where_i_am.z);
Serial.print(" E");
Serial.println(where_i_am.e);
break;


// TODO: make this work properly
case 116:
ex[extruder_in_use]->waitForTemperature();
break;

// The valve (real, or virtual...) is now the way to control any extruder (such as
// a pressurised paste extruder) that cannot move using E codes.

// Open the valve
case 126:
ex[extruder_in_use]->valveSet(true, (int)(gc.P + 0.5));
break;

// Close the valve
case 127:
ex[extruder_in_use]->valveSet(false, (int)(gc.P + 0.5));
break;

case 140:
if (gc.seen & GCODE_S)
{
ex[0]->setBedTemperature((int)gc.S);
}
break;

case 141: //TODO: set chamber temperature
break;

case 142: //TODO: set holding pressure
break;

default:
if(SendDebug & DEBUG_ERRORS)
{
Serial.print("Huh? M");
Serial.println(gc.M, DEC);
FlushSerialRequestResend();
}
}



}

// Tool (i.e. extruder) change?

if (gc.seen & GCODE_T)
{
while(!qEmpty()) delay(WAITING_DELAY);
//delay(2*WAITING_DELAY);
newExtruder(gc.T);
}
}

int scan_float(char *str, float *valp, unsigned int *seen, unsigned int flag)
{
float res;
int len;
char *end;

res = (float)strtod(str, &end);

len = end - str;

if (len > 0)
{
*valp = res;
*seen |= flag;
}
else
*valp = 0;

return len; /* length of number */
}

int scan_int(char *str, int *valp, unsigned int *seen, unsigned int flag)
{
int res;
int len;
char *end;

res = (int)strtol(str, &end, 10);
len = end - str;

if (len > 0)
{
*valp = res;
*seen |= flag;
}
else
*valp = 0;

return len; /* length of number */
}

int scan_long(char *str, long *valp, unsigned int *seen, unsigned int flag)
{
long res;
int len;
char *end;

res = strtol(str, &end, 10);
len = end - str;

if (len > 0)
{
*valp = res;
*seen |= flag;
}
else
*valp = 0;

return len; /* length of number in ascii world */
}

void setupGcodeProcessor()
{
gc.LastLineNrRecieved = -1;
}

void FlushSerialRequestResend()
{
char buffer[100]="Resend:";
ltoa(gc.LastLineNrRecieved+1, buffer+7, 10);
Serial.flush();
Serial.println(buffer);
}


Mon Jan 31, 2011 1:19 pm
Profile

Joined: Wed Dec 29, 2010 7:22 pm
Posts: 8
Post Re: Silence those Batch 1 Generation 6 electronics....
For full silence you can add the same to the bottom of setup() in FiveD_GCode_Interpreter.pde. As such:

Code:
  digitalWrite(X_ENABLE_PIN, !ENABLE_ON);
  digitalWrite(Y_ENABLE_PIN, !ENABLE_ON);
  digitalWrite(Z_ENABLE_PIN, !ENABLE_ON);
  digitalWrite(E_ENABLE_PIN, !ENABLE_ON);


Around line 386. This will make it start silent, or go silent when you exit repsnapper.


Thu Feb 03, 2011 8:31 pm
Profile
Display posts from previous:  Sort by  
Reply to topic   [ 6 posts ] 

Who is online

Users browsing this forum: No registered users and 0 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.