mirror of
https://github.com/usatiuk/EggbotWireless.git
synced 2025-10-26 16:57:48 +01:00
170 lines
3.8 KiB
C++
170 lines
3.8 KiB
C++
#include <Arduino.h>
|
|
#include <Servo.h>
|
|
#include <Wire.h>
|
|
#include <util/atomic.h>
|
|
#include "Config.h"
|
|
#include "Globals.h"
|
|
#include "common/Commands.h"
|
|
#include "common/Status.h"
|
|
|
|
int curRPM = defRPM;
|
|
bool needAdjust;
|
|
|
|
int calculateDelay(float rpm, int stepsPerRevolution) {
|
|
return ((float)1000 * (float)60) / (rpm * (float)stepsPerRevolution);
|
|
}
|
|
|
|
void adjustRPM() {
|
|
eggStepperRPM = curRPM;
|
|
servoStepperRPM = curRPM;
|
|
if (needAdjust) {
|
|
unsigned int stepsX = servoStepper.getRemainingSteps();
|
|
unsigned int stepsY = eggStepper.getRemainingSteps();
|
|
if (stepsX != 0 && stepsY != 0) {
|
|
if (stepsX > stepsY) {
|
|
eggStepperRPM = (float)curRPM * (float)stepsY / (float)stepsX;
|
|
} else if (stepsY > stepsX) {
|
|
servoStepperRPM = (float)curRPM * (float)stepsX / (float)stepsY;
|
|
}
|
|
}
|
|
}
|
|
eggStepperDelay = calculateDelay(eggStepperRPM, STEPS_PER_REVOLUTION);
|
|
servoStepperDelay = calculateDelay(servoStepperRPM, STEPS_PER_REVOLUTION);
|
|
}
|
|
|
|
Command command;
|
|
|
|
bool newCommand = false;
|
|
bool executing = false;
|
|
|
|
byte rxBuffer[i2cCmdBytes];
|
|
void receiveEvent(int howMany) {
|
|
static int curByte = 0;
|
|
while (Wire.available() > 0) {
|
|
if (!newCommand) {
|
|
char c = Wire.read();
|
|
rxBuffer[curByte] = c;
|
|
curByte++;
|
|
if (curByte == i2cCmdBytes) {
|
|
curByte = 0;
|
|
command.fromBytes(rxBuffer);
|
|
newCommand = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
byte txBuffer[i2cStsBytes];
|
|
Status sts;
|
|
void requestEvent() {
|
|
if (executing || newCommand) {
|
|
sts.type = StatusType::WAIT;
|
|
} else {
|
|
sts.type = StatusType::NEXT;
|
|
}
|
|
|
|
sts.mmS = servoStepper.getPosMm();
|
|
sts.mmE = eggStepper.getPosMm();
|
|
|
|
sts.feedrate = curRPM;
|
|
|
|
sts.pEng = (float)pen.getEngaged();
|
|
|
|
sts.toBytes(txBuffer);
|
|
Wire.write(txBuffer, i2cStsBytes);
|
|
}
|
|
|
|
void execCommand(Command cmd) {
|
|
executing = true;
|
|
|
|
if (cmd.type == CommandType::G01 || cmd.type == CommandType::G00) {
|
|
if (cmd.type == CommandType::G01) {
|
|
needAdjust = true;
|
|
} else {
|
|
needAdjust = false;
|
|
}
|
|
|
|
if (!isnan(cmd.arg1)) {
|
|
servoStepper.moveTo(cmd.arg1);
|
|
}
|
|
|
|
if (!isnan(cmd.arg2)) {
|
|
eggStepper.moveTo(cmd.arg2);
|
|
}
|
|
|
|
if (!isnan(cmd.arg3)) {
|
|
if (cmd.arg3 < 0) {
|
|
pen.engage();
|
|
} else {
|
|
pen.disengage();
|
|
}
|
|
}
|
|
|
|
if (!isnan(cmd.arg4)) {
|
|
curRPM = cmd.arg4;
|
|
}
|
|
|
|
adjustRPM();
|
|
}
|
|
|
|
newCommand = false;
|
|
return;
|
|
}
|
|
|
|
void setup() {
|
|
Serial.begin(115200);
|
|
Wire.begin(8);
|
|
Wire.onReceive(receiveEvent);
|
|
Wire.onRequest(requestEvent);
|
|
Serial.println("Hello!");
|
|
eggStepperRPM = servoStepperRPM = curRPM;
|
|
pinMode(A0, OUTPUT);
|
|
digitalWrite(A0, true);
|
|
OCR2A = 250;
|
|
TCCR2A |= (1 << WGM20) | (1 << CS22);
|
|
TIMSK2 |= (1 << OCIE2A);
|
|
servoStepper.setPos(xLimit);
|
|
pen.init();
|
|
}
|
|
|
|
volatile unsigned int tick = 0;
|
|
volatile bool armed = false;
|
|
|
|
/*
|
|
We use our own timer for more precise timings
|
|
And it ticks only when armed, to ensure
|
|
that steppersRoutine() doesn't skip a single tick
|
|
*/
|
|
ISR(TIMER2_COMPA_vect) {
|
|
if (armed) {
|
|
tick++;
|
|
armed = false;
|
|
}
|
|
}
|
|
|
|
void steppersRoutine() {
|
|
if (!armed) {
|
|
if (tick % adjustDelay == 0) {
|
|
adjustRPM();
|
|
}
|
|
if (tick % eggStepperDelay == 0) {
|
|
eggStepper.doStep();
|
|
}
|
|
if (tick % servoStepperDelay == 0) {
|
|
servoStepper.doStep();
|
|
}
|
|
armed = true;
|
|
}
|
|
if (eggStepper.getRemainingSteps() == 0 &&
|
|
servoStepper.getRemainingSteps() == 0) {
|
|
executing = false;
|
|
}
|
|
}
|
|
|
|
void loop() {
|
|
if (newCommand) {
|
|
execCommand(command);
|
|
}
|
|
steppersRoutine();
|
|
}
|