Major update

imported some improvements from user "bartebor"
- fixed some timing issues
- added button-support via #ifdefine
- worked on penarm-shaking-bug
- restructured some codesegments
This commit is contained in:
cocktailyogi
2015-05-05 22:27:01 +02:00
parent 269591d8d0
commit 6505252c20
6 changed files with 264 additions and 180 deletions

View File

@@ -18,44 +18,55 @@ Thanks to my wife and my daughter for their patience. :-)
1 collision control via penMin/penMax
2 implement homing sequence via microswitch or optical device
*/
#include "AccelStepper.h"
//#include "libs\AccelStepper.h" // nice lib from http://www.airspayce.com/mikem/arduino/AccelStepper/
#include "AccelStepper.h" // nice lib from http://www.airspayce.com/mikem/arduino/AccelStepper/
#include <Servo.h>
#include "SerialCommand.h" //nice lib from Stefan Rado, https://github.com/kroimon/Arduino-SerialCommand
#include <avr/eeprom.h>
#include "button.h"
#define initSting "EBBv13_and_above Protocol emulated by Eggduino-Firmware V1.4"
//Rotational Stepper
#define initSting "EBBv13_and_above Protocol emulated by Eggduino-Firmware V1.6"
//Rotational Stepper:
#define step1 11
#define dir1 10
#define enableRotMotor 9
#define rotMicrostep 16 //MicrostepMode, only 1,2,4,8,16 allowed, because of Integer-Math in this Sketch
//Pen Stepper
//Pen Stepper:
#define step2 8
#define dir2 7
#define enablePenMotor 6
#define penMicrostep 16 //MicrostepMode, only 1,2,4,8,16 allowed, because of Integer-Math in this Sketch
//Servo
#define servoPin 3
// PRG button
#define prgButton 2
// pen up/down button
#define penToggleButton 12
// motors enable button
#define motorsButton 4
#define servoPin 3 //Servo
// EXTRAFEATURES - UNCOMMENT TO USE THEM -------------------------------------------------------------------
// #define prgButton 2 // PRG button
// #define penToggleButton 12 // pen up/down button
// #define motorsButton 4 // motors enable button
// #define CommandSMQB
//-----------------------------------------------------------------------------------------------------------
#define penUpPosEEAddress ((uint16_t *)0)
#define penDownPosEEAddress ((uint16_t *)2)
#define debounceDelay 50
//make Objects
AccelStepper rotMotor(1, step1, dir1);
AccelStepper penMotor(1, step2, dir2);
Servo penServo;
SerialCommand SCmd;
// Variables... be careful, by messing around here, evrything has a reason and crossrelations...
//create Buttons
#ifdef prgButton
Button prgButtonToggle(prgButton, setprgButtonState);
#endif
#ifdef penToggleButton
Button penToggle(penToggleButton, doTogglePen);
#endif
#ifdef motorsButton
Button motorsToggle(motorsButton, toggleMotors);
#endif
// Variables... be careful, by messing around here, everything has a reason and crossrelations...
int penMin=0;
int penMax=0;
int penUpPos=5; //can be overwritten from EBB-Command SC
@@ -72,46 +83,8 @@ Thanks to my wife and my daughter for their patience. :-)
uint8_t penStepCorrection = 16/penMicrostep ; //devide EBB-Coordinates by this factor to get EGGduino-Steps
float rotSpeed=0;
float penSpeed=0; // these are local variables for Function SteppermotorMove-Command, but for performance-reasons it will be initialized here
int motorsEnabled = 0;
typedef void (*ActionCb)(void);
class Button {
public:
Button(byte p, ActionCb a): debounce(0), state(1), lastState(1), action(a), pin(p) {};
void check() {
byte b = digitalRead(pin);
long t = millis();
if (b != lastState) {
debounce = t;
}
if ((t - debounce) > debounceDelay) {
if (b != state) {
state = b;
if (!state) {
(*action)();
}
}
}
lastState = b;
}
private:
long debounce;
byte state:1;
byte lastState:1;
byte pin;
ActionCb action;
};
Button penToggle(penToggleButton, doTogglePen);
Button motorsToggle(motorsButton, toggleMotors);
boolean motorsEnabled = 0;
void setup() {
Serial.begin(9600);
makeComInterface();
@@ -119,9 +92,22 @@ void setup() {
}
void loop() {
SCmd.readSerial();
penToggle.check();
motorsToggle.check();
if( 0 == digitalRead(prgButton))
prgButtonState = 1;
if ( penMotor.distanceToGo() || rotMotor.distanceToGo() ) {
penMotor.runSpeedToPosition(); // Moving.... moving... moving....
rotMotor.runSpeedToPosition();
}
SCmd.readSerial();
#ifdef penToggleButton
penToggle.check();
#endif
#ifdef motorsButton
motorsToggle.check();
#endif
#ifdef prgButton
prgButtonToggle.check();
#endif
}

View File

@@ -5,7 +5,9 @@ void makeComInterface(){
SCmd.addCommand("SC",stepperModeConfigure);
SCmd.addCommand("SP",setPen);
SCmd.addCommand("SM",stepperMove);
SCmd.addCommand("SMQB",stepperMoveQueryButton); // composite function enabling smooth movement
#ifdef CommandSMQB
SCmd.addCommand("SMQB",stepperMoveQueryButton); // composite function enabling smooth movement
#endif
SCmd.addCommand("SE",ignore);
SCmd.addCommand("TP",togglePen);
SCmd.addCommand("PO",ignore); //Engraver command, not implemented, gives fake answer
@@ -32,8 +34,8 @@ void queryPen() {
void queryButton() {
Serial.print(String(prgButtonState) +"\r\n");
prgButtonState = 0;
sendAck();
prgButtonState = 0;
}
void queryLayer() {
@@ -87,109 +89,60 @@ void stepperMove() {
uint16_t duration=0; //in ms
int penStepsEBB=0; //Pen
int rotStepsEBB=0; //Rot
while ( penMotor.distanceToGo() || rotMotor.distanceToGo() ) {
penMotor.runSpeedToPosition(); // Moving.... moving... moving....
rotMotor.runSpeedToPosition();
}
if (!parseSMArgs(&duration, &penStepsEBB, &rotStepsEBB)) {
sendError();
return;
}
if ( (penStepsEBB==0) && (rotStepsEBB==0) ) {
delay(duration);
sendAck();
return;
}
doMove(duration, penStepsEBB, rotStepsEBB);
sendAck();
}
void stepperMoveQueryButton() {
uint16_t duration=0; //in ms
int penStepsEBB=0; //Pen
int rotStepsEBB=0; //Rot
if (!parseSMArgs(&duration, &penStepsEBB, &rotStepsEBB)) {
sendError();
return;
}
if ( (penStepsEBB==0) && (rotStepsEBB==0) ) {
delay(duration);
queryButton();
//sendAck();
return;
}
// sending ACK before actual move to allow buffering
queryButton();
doMove(duration, penStepsEBB, rotStepsEBB);
//sendAck();
}
bool parseSMArgs(uint16_t *duration, int *penStepsEBB, int *rotStepsEBB) {
char *arg1;
char *arg2;
char *arg3;
arg1 = SCmd.next();
if (arg1 != NULL) {
*duration = atoi(arg1);
arg2 = SCmd.next();
}
if (arg2 != NULL) {
*penStepsEBB = atoi(arg2);
arg3 = SCmd.next();
}
if (arg3 != NULL) {
*rotStepsEBB = atoi(arg3);
return true;
}
#ifdef CommandSMQB
void stepperMoveQueryButton() {
uint16_t duration=0; //in ms
int penStepsEBB=0; //Pen
int rotStepsEBB=0; //Rot
return false;
}
if (!parseSMArgs(&duration, &penStepsEBB, &rotStepsEBB)) {
sendError();
return;
}
void doMove(uint16_t duration, int penStepsEBB, int rotStepsEBB) {
motorsOn();
if ( (penStepsEBB==0) && (rotStepsEBB==0) ) {
delay(duration);
queryButton();
return;
}
if( (1 == rotStepCorrection) && (1 == penStepCorrection) ){ // if coordinatessystems are identical
//set Coordinates and Speed
rotMotor.move(rotStepsEBB);
rotMotor.setSpeed( abs( (float)rotStepsEBB * (float)1000 / (float)duration ) );
penMotor.move(penStepsEBB);
penMotor.setSpeed( abs( (float)penStepsEBB * (float)1000 / (float)duration ) );
} else {
//incoming EBB-Steps will be multiplied by 16, then Integer-maths is done, result will be divided by 16
// This make thinks here really complicated, but floating point-math kills performance and memory, believe me... I tried...
long rotSteps = ( (long)rotStepsEBB * 16 / rotStepCorrection) + (long)rotStepError; //correct incoming EBB-Steps to our microstep-Setting and multiply by 16 to avoid floatingpoint...
long penSteps = ( (long)penStepsEBB * 16 / penStepCorrection) + (long)penStepError;
// sending ACK before actual move to allow buffering
queryButton();
doMove(duration, penStepsEBB, rotStepsEBB);
}
#endif
int rotStepsToGo = (int) (rotSteps/16); //Calc Steps to go, which are possible on our machine
int penStepsToGo = (int) (penSteps/16);
rotStepError = (long)rotSteps - ((long) rotStepsToGo * (long)16); // calc Position-Error, if there is one
penStepError = (long)penSteps - ((long) penStepsToGo * (long)16);
long temp_rotSpeed = ((long)rotStepsToGo * (long)1000 / (long)duration ); // calc Speed in Integer Math
long temp_penSpeed = ((long)penStepsToGo * (long)1000 / (long)duration ) ;
float rotSpeed= (float) abs(temp_rotSpeed); // type cast
float penSpeed= (float) abs(temp_penSpeed);
//set Coordinates and Speed
rotMotor.move(rotStepsToGo); // finally, let us set the target position...
rotMotor.setSpeed(rotSpeed); // and the Speed!
penMotor.move(penStepsToGo);
penMotor.setSpeed( penSpeed );
}
while ( penMotor.distanceToGo() || rotMotor.distanceToGo() ) {
penMotor.runSpeedToPosition(); // Moving.... moving... moving....
rotMotor.runSpeedToPosition();
}
}
void setPen(){
int cmd;
int value;
char *arg;
while ( penMotor.distanceToGo() || rotMotor.distanceToGo() ) {
penMotor.runSpeedToPosition(); // Moving.... moving... moving....
rotMotor.runSpeedToPosition();
}
arg = SCmd.next();
if (arg != NULL) {
cmd = atoi(arg);
@@ -202,7 +155,6 @@ void setPen(){
case 1:
penServo.write(penDownPos);
penState=penDownPos;
//Serial.println("case 1");
break;
default:
@@ -212,14 +164,14 @@ void setPen(){
char *val;
val = SCmd.next();
if (val != NULL) {
value = atoi(val);
// Serial.println("delayvalue");
delay(value);
sendAck();
}
if (val==NULL && arg !=NULL)
delay(500);
sendAck();
value = atoi(val);
sendAck();
delay(value);
}
if (val==NULL && arg !=NULL) {
sendAck();
delay(500);
}
// Serial.println("delay");
if (val==NULL && arg ==NULL)
sendError();
@@ -228,16 +180,19 @@ void setPen(){
void togglePen(){
int value;
char *arg;
while ( penMotor.distanceToGo() || rotMotor.distanceToGo() ) {
penMotor.runSpeedToPosition(); // Moving.... moving... moving....
rotMotor.runSpeedToPosition();
}
arg = SCmd.next();
if (arg != NULL)
value = atoi(arg);
else
value = 500;
doTogglePen();
delay(value);
sendAck();
doTogglePen();
sendAck();
delay(value);
}
void doTogglePen() {
@@ -289,26 +244,6 @@ void enableMotors(){
}
}
void motorsOff() {
digitalWrite(enableRotMotor, HIGH);
digitalWrite(enablePenMotor, HIGH);
motorsEnabled = 0;
}
void motorsOn() {
digitalWrite(enableRotMotor, LOW) ;
digitalWrite(enablePenMotor, LOW) ;
motorsEnabled = 1;
}
void toggleMotors() {
if (motorsEnabled) {
motorsOff();
} else {
motorsOn();
}
}
void stepperModeConfigure(){
int cmd;
int value;

View File

@@ -6,9 +6,18 @@ void initHardware(){
pinMode(enableRotMotor, OUTPUT);
pinMode(enablePenMotor, OUTPUT);
pinMode(prgButton, INPUT_PULLUP);
pinMode(penToggleButton, INPUT_PULLUP);
pinMode(motorsButton, INPUT_PULLUP);
#ifdef prgButton
pinMode(prgButton, INPUT_PULLUP);
#endif
#ifdef penToggleButton
pinMode(penToggleButton, INPUT_PULLUP);
#endif
#ifdef motorsButton
pinMode(motorsButton, INPUT_PULLUP);
#endif
rotMotor.setMaxSpeed(2000.0);
rotMotor.setAcceleration(10000.0);
@@ -41,3 +50,90 @@ void inline sendError(){
Serial.print("unknown CMD\r\n");
}
void motorsOff() {
digitalWrite(enableRotMotor, HIGH);
digitalWrite(enablePenMotor, HIGH);
motorsEnabled = 0;
}
void motorsOn() {
digitalWrite(enableRotMotor, LOW) ;
digitalWrite(enablePenMotor, LOW) ;
motorsEnabled = 1;
}
void toggleMotors() {
if (motorsEnabled) {
motorsOff();
} else {
motorsOn();
}
}
bool parseSMArgs(uint16_t *duration, int *penStepsEBB, int *rotStepsEBB) {
char *arg1;
char *arg2;
char *arg3;
arg1 = SCmd.next();
if (arg1 != NULL) {
*duration = atoi(arg1);
arg2 = SCmd.next();
}
if (arg2 != NULL) {
*penStepsEBB = atoi(arg2);
arg3 = SCmd.next();
}
if (arg3 != NULL) {
*rotStepsEBB = atoi(arg3);
return true;
}
return false;
}
void doMove(uint16_t duration, int penStepsEBB, int rotStepsEBB) {
if (!motorsEnabled) {
motorsOn();
}
if( (1 == rotStepCorrection) && (1 == penStepCorrection) ){ // if coordinatessystems are identical
//set Coordinates and Speed
rotMotor.move(rotStepsEBB);
rotMotor.setSpeed( abs( (float)rotStepsEBB * (float)1000 / (float)duration ) );
penMotor.move(penStepsEBB);
penMotor.setSpeed( abs( (float)penStepsEBB * (float)1000 / (float)duration ) );
} else {
//incoming EBB-Steps will be multiplied by 16, then Integer-maths is done, result will be divided by 16
// This make thinks here really complicated, but floating point-math kills performance and memory, believe me... I tried...
long rotSteps = ( (long)rotStepsEBB * 16 / rotStepCorrection) + (long)rotStepError; //correct incoming EBB-Steps to our microstep-Setting and multiply by 16 to avoid floatingpoint...
long penSteps = ( (long)penStepsEBB * 16 / penStepCorrection) + (long)penStepError;
int rotStepsToGo = (int) (rotSteps/16); //Calc Steps to go, which are possible on our machine
int penStepsToGo = (int) (penSteps/16);
rotStepError = (long)rotSteps - ((long) rotStepsToGo * (long)16); // calc Position-Error, if there is one
penStepError = (long)penSteps - ((long) penStepsToGo * (long)16);
long temp_rotSpeed = ((long)rotStepsToGo * (long)1000 / (long)duration ); // calc Speed in Integer Math
long temp_penSpeed = ((long)penStepsToGo * (long)1000 / (long)duration ) ;
float rotSpeed= (float) abs(temp_rotSpeed); // type cast
float penSpeed= (float) abs(temp_penSpeed);
//set Coordinates and Speed
rotMotor.move(rotStepsToGo); // finally, let us set the target position...
rotMotor.setSpeed(rotSpeed); // and the Speed!
penMotor.move(penStepsToGo);
penMotor.setSpeed( penSpeed );
}
/*
while ( penMotor.distanceToGo() || rotMotor.distanceToGo() ) {
penMotor.runSpeedToPosition(); // Moving.... moving... moving....
rotMotor.runSpeedToPosition();
}
*/
}
void setprgButtonState(){
prgButtonState = 1;
}

View File

@@ -3,7 +3,7 @@ Eggduino
Arduino Firmware for Eggbot / Spherebot with Inkscape-Integration
Version 1.4s
Version 1.6
tested with Inkscape Portable 0.91, Eggbot Extension and patched eggbot.py
Regards: Eggduino-Firmware by Joachim Cerny, 2015
@@ -17,6 +17,7 @@ Features:
- No collision-detection!!
- Supported Servos: At least one type ;-) I use Arduino Servo-Lib with TG9e- standard servo.
- Full Arduino-Compatible. I used an Arduino Uno
- Button-support (3 buttons)
Tested and fully functional with Inkscape.

View File

@@ -1,3 +1,10 @@
05.05.2015 v1.6
imported some improvements from user "bartebor"
fixed some timing issues
added button-support via #ifdefine
worked on penarm-shaking-bug
restructured some codesegments
29.03.2015 v1.4
added prototype for PRG-Button support. somebody has to test it. Connect pushbutton between Pin2 und GND.
disabled ccordinate transform for 16-microstepping, because Inkscape sends in 16-microstepping, as well.

59
button.h Normal file
View File

@@ -0,0 +1,59 @@
/*
* button.h
*
* Created: 04.05.2015 21:38:42
* Author: Yogi
*/
#ifndef __BUTTON_H__
#define __BUTTON_H__
#include <Arduino.h>
#define debounceDelay 50
typedef void (*ActionCb)(void);
class Button
{
private:
long debounce;
byte state:1;
byte lastState:1;
byte pin;
ActionCb action;
Button( const Button &c );
Button& operator=( const Button &c );
public:
Button(byte p, ActionCb a): debounce(0), state(1), lastState(1), action(a), pin(p) {} ;
void check() {
byte b = digitalRead(pin);
long t = millis();
if (b != lastState) {
debounce = t;
}
if ((t - debounce) > debounceDelay) {
if (b != state) {
state = b;
if (!state) {
(*action)();
}
}
}
lastState = b;
};
}; //button
#endif //__BUTTON_H__