Hier werden die Unterschiede zwischen zwei Versionen gezeigt.
Beide Seiten der vorigen Revision Vorhergehende Überarbeitung Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
mechatronik:sose24:remote-plotter:code [2024/07/26 00:52] Paul-Hoeft |
mechatronik:sose24:remote-plotter:code [2024/07/31 10:29] (aktuell) TPfoch [Backend] |
||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
======Code====== | ======Code====== | ||
Falls Github spinnt :) | Falls Github spinnt :) | ||
+ | =====Backend===== | ||
+ | <file C++ main.cpp> | ||
+ | #include "DrawRobot.hpp" | ||
- | <file C++ mlzrobo.ino> | + | #define cm |
- | #include "Motor.hpp" | + | |
- | //#define PI 3.14159265358979 | + | |
- | template<typename T1, typename T2> | + | DrawRobot<Arm> robot; |
- | struct Pair | + | |
+ | void setup() | ||
{ | { | ||
- | T1 a; | + | Serial.begin(115200); |
- | T2 b; | + | |
+ | Motor root(AccelStepper(8,4,6,5,7), 4076); | ||
+ | Motor ext(AccelStepper(8,8,9,10,11), 4076); | ||
+ | |||
+ | robot = { | ||
+ | .axies = Arm(11 cm, 11.5 cm, root, ext), | ||
+ | .gantry = Gantry(6, 7) | ||
+ | }; | ||
+ | |||
+ | // robot.axies.moveTo({22.5,0}); | ||
+ | robot.axies.moveTo({11,11.5}); | ||
+ | |||
+ | } | ||
+ | void loop() | ||
+ | { | ||
+ | int cmd = Serial.parseInt(); | ||
+ | switch(cmd){ | ||
+ | case 0:{ | ||
+ | int x = Serial.parseInt(); | ||
+ | int y = Serial.parseInt(); | ||
+ | robot.axies.moveTo({x,y}); | ||
+ | break; | ||
+ | } | ||
+ | case 1: { | ||
+ | int tool = Serial.parseInt(); | ||
+ | robot.gantry.setTool(tool); // ist tool | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | } | ||
+ | </file> | ||
+ | ====Axies==== | ||
+ | <file C++ Axies.hpp> | ||
+ | #pragma once | ||
+ | #include "AccelStepper.h" | ||
+ | #include "MultiStepper.h" | ||
+ | |||
+ | #ifndef PI | ||
+ | #define PI 3.14159265358979 | ||
+ | #endif | ||
+ | |||
+ | struct Point {double x,y;}; | ||
+ | struct Angles {double root, ext;}; | ||
+ | |||
+ | class Axies | ||
+ | { | ||
+ | public: | ||
+ | virtual void moveTo(Point p)=0; | ||
}; | }; | ||
- | struct Point | + | struct Motor |
{ | { | ||
- | double x,y; | + | AccelStepper stepper; |
- | Point(double ix, double iy): x(ix), y(iy) | + | int stepsPerRev=-1; |
- | {} | + | Motor(AccelStepper stepper, int stepsPerRev, int speed=4000): |
- | Point operator-(Point other) | + | stepper(stepper), stepsPerRev(stepsPerRev) |
{ | { | ||
- | return Point(x-other.x, y-other.y); | + | this->stepper.setAcceleration(1000); |
- | } | + | this->stepper.setMaxSpeed(speed); |
- | + | this->stepper.setSpeed(speed); | |
- | Point operator+(Point other) | + | |
- | { | + | |
- | return Point(x+other.x, y+other.y); | + | |
} | } | ||
- | Point operator*(double div) | + | long getSteps(double deg) |
- | { | + | |
- | return Point(x*div, y*div); | + | |
- | } | + | |
- | Point operator/(double div) | + | |
{ | { | ||
- | return Point(x/div, y/div); | + | return deg/360.0*stepsPerRev; |
} | } | ||
}; | }; | ||
- | // std::ostream& operator<<(std::ostream &os, Point p) | ||
- | // { | ||
- | // os << '[' << p.x << ' ' << p.y<<']'; | ||
- | // return os; | ||
- | // } | ||
class Arm | class Arm | ||
{ | { | ||
- | double l1,l2; | + | double rootLen, extLen; |
- | Point current; | + | Motor root, ext; |
- | Motor *m1,*m2; | + | MultiStepper ms; |
public: | public: | ||
- | //arm with the two sections l1,l2. At start both facing upwards | + | Arm(double rootLen, double extLen, Motor root, Motor ext); |
- | template<typename M1, typename M2> | + | void moveTo(Point p); |
- | Arm(double ll1, double ll2, M1 &&m1, M2 &&m2): | + | private: |
- | l1(ll1), l2(ll2), current(0,l1+l2), m1(new M1(m1)), m2(new M2(m2)) | + | |
- | {} | + | |
//calculates the angles of the two sections so the end of the second is at point p | //calculates the angles of the two sections so the end of the second is at point p | ||
- | Pair<double, double> angles(Point p) | + | Angles pointToAngles(Point p); |
- | { | + | }; |
- | double ph2= acos( | + | </file> |
- | (p.x*p.x+p.y*p.y-l1*l1-l2*l2)/ | + | <file C++ Axies.cpp> |
- | (2*l1*l2)); | + | #include "Axies.hpp" |
- | double phi1 = atan2(p.y,p.x) | + | |
- | -atan2(l2*sin(ph2), | + | |
- | (l1+l2*cos(ph2))); | + | |
- | return Pair<double,double>{phi1/PI*180, ph2/PI*180}; | + | Arm::Arm(double rootLen, double extLen, Motor root, Motor ext) : |
- | } | + | rootLen(rootLen), extLen(extLen), ms(), root(root), ext(ext) |
+ | { | ||
+ | ms.addStepper(root.stepper); | ||
+ | ms.addStepper(ext.stepper); | ||
+ | } | ||
- | //goes form current position to point b in a "straight" line by dividing it in s Sections | ||
- | void straightline(Point b, int s) | ||
- | { | ||
- | Point delta=(b-current)/s; | ||
- | //std::cout<< delta<<std::endl; | ||
- | for(int i=0;i<s;i++) | ||
- | { | ||
- | gotoP(current+delta); | ||
- | } | ||
- | } | ||
- | | ||
- | //goes form current to point b | ||
- | void gotoP(Point b) | ||
- | { | ||
- | current=b; | ||
- | auto a = angles(current); | ||
- | m1->setAngle(a.a); | ||
- | m2->setAngle(a.b); | ||
- | | ||
- | } | ||
- | //lift/dops the pen on/off the canvas | + | void Arm::moveTo(Point p) |
- | void shiftPen() | + | { |
- | { | + | Angles angle = pointToAngles(p); // 0-360 |
- | + | Serial.println("Root: " + String(angle.root) + "°->" + String(root.getSteps(angle.root))); | |
- | } | + | Serial.println("Ext: " + String(angle.ext) + "°->" + String(ext.getSteps(angle.root))); |
+ | long pos[2] = {root.getSteps(angle.root), ext.getSteps(angle.ext)}; | ||
+ | ms.moveTo(pos); | ||
+ | ms.runSpeedToPosition(); | ||
+ | } | ||
- | }; | + | Angles Arm::pointToAngles(Point p) |
+ | { | ||
+ | double ph2= acos( | ||
+ | (p.x*p.x+p.y*p.y-rootLen*rootLen-extLen*extLen)/ | ||
+ | (2*rootLen*extLen)); | ||
+ | double phi1 = atan2(p.y,p.x) | ||
+ | -atan2(extLen*sin(ph2), | ||
+ | (rootLen+extLen*cos(ph2))); | ||
- | void setup() | + | return {phi1/PI*180, ph2/PI*180}; |
- | { | + | |
- | // Serial.begin(115200); | + | |
- | // Arm a(1,2, | + | |
- | // MotorStepper(8,9,10,11, 4096), | + | |
- | // MotorServo(A1)); | + | |
- | // Point goal(3,0); | + | |
- | // a.straightline(goal, 3); | + | |
- | Serial.begin(115200); | + | |
- | SmallMotor a(8,9,10,11,2048, 5); | + | |
- | a.setAngle(180); | + | |
- | AccelMotor b(3,2, 300); | + | |
- | b.setAngle(180); | + | |
- | for(int i=0; i<1000;i++){ | + | |
- | a.update(1000); | + | |
- | b.update(1000); | + | |
- | // delay(100); | + | |
- | } | + | |
} | } | ||
- | void loop() | ||
- | { | ||
- | delay(1000); | ||
- | } | ||
- | |||
- | // int main() | ||
- | // { | ||
- | // Arm a(2,1); | ||
- | // Point b(3,0); | ||
- | // a.straightline(b,10); | ||
- | // //auto [phi1, phi2] = a.angles(Point{1,2}); | ||
- | // //std::cout << phi1 << " " << phi2 << std::endl; | ||
- | // } | ||
</file> | </file> | ||
- | <file C++ motor_mtrobo.cpp> | + | ====Gantry==== |
+ | <file C++ Gantry.hpp> | ||
#pragma once | #pragma once | ||
- | #include <math.h> | + | #include <Servo.h> |
- | #ifndef PI | + | |
- | #define PI 3.14159265358979 | + | |
- | #endif | + | |
- | class Motor{ | + | |
- | public: | + | |
- | // return inaccuarrcy | + | |
- | virtual double setAngle(double angle)=0; | + | |
- | virtual double update(int steps)=0; | + | |
- | }; | + | |
- | class StepperMotor : public Motor | + | class Gantry |
{ | { | ||
- | double partial=0; | + | Servo use, // servo for lowering tool |
- | int speed, | + | select;// Servo to switch between tools |
- | stepsPerRev; | + | // ^ currently unused |
- | double target=0; | + | |
- | int current=0; | + | |
- | public: | + | |
- | StepperMotor(int stepsPerRev, int speed=5) | + | |
- | : speed(speed), stepsPerRev(stepsPerRev) | + | |
- | {} | + | |
- | // return inaccuarrcy | + | |
- | double setAngle(double angle) override | + | |
- | { | + | |
- | target = angle*stepsPerRev/360.0; | + | |
- | } | + | |
- | double update(int steps) override | + | |
- | { | + | |
- | double delta = target/steps+partial; | + | |
- | partial = delta-(int)delta; | + | |
- | current+=delta; | + | |
- | stepBy(delta); | + | |
- | return 0; | + | |
- | } | + | |
- | private: | + | |
- | virtual void stepBy(int delta) =0; | + | |
- | }; | + | |
- | #include "Stepper.h" | + | |
- | class SmallMotor : public StepperMotor { | + | |
- | Stepper s; | + | |
public: | public: | ||
- | SmallMotor(int in1, int in2, int in3, int in4, int stepsPerRev, int speed=5) | + | Gantry(int usePin, int selectPin) |
- | : s(stepsPerRev, in1, in2, in3, in4), StepperMotor(stepsPerRev, speed) | + | |
- | { | + | |
- | s.setSpeed(speed); | + | |
- | } | + | |
- | private: | + | |
- | void stepBy(int delta) override | + | |
{ | { | ||
- | Serial.println(delta); | + | use.attach(usePin); |
- | s.step(delta); | + | select.attach(selectPin); |
} | } | ||
+ | enum Tool { | ||
+ | NONE, | ||
+ | PEN | ||
+ | }; | ||
+ | void setTool(Tool tool); | ||
}; | }; | ||
+ | </file> | ||
+ | <file C++ Gantry.cpp> | ||
+ | #include "Gantry.hpp" | ||
- | #include "AccelStepper.h" | + | void Gantry::setTool(Tool tool) |
+ | { | ||
+ | // maybe second servo for tool switch | ||
- | class AccelMotor : public StepperMotor { | + | // dummy implementation |
- | AccelStepper stepper; | + | use.write(180*(tool==PEN)); |
- | public: | + | } |
- | AccelMotor(int stepPin, int dirPin, int stepsPerRev, int speed=1000) | + | </file> |
- | : stepper(1, stepPin, dirPin), StepperMotor(stepsPerRev, speed) | + | |
- | { | + | |
- | stepper.setCurrentPosition(0); | + | |
- | stepper.setMaxSpeed(10000); | + | |
- | stepper.setAcceleration(500); | + | |
- | stepper.setSpeed(500); | + | |
- | } | + | |
- | // double update() override | ||
- | // { | ||
- | // if(stepper.currentPosition() < target) | ||
- | // { | ||
- | // stepper.setSpeed(speed); | ||
- | // stepper.runSpeed(); | ||
- | // } | ||
- | // else if(stepper.currentPosition() > target) | ||
- | // { | ||
- | // stepper.setSpeed(-speed); | ||
- | // stepper.runSpeed(); | ||
- | // } else { | ||
- | // stepper.setSpeed(0); | ||
- | // stepper.runSpeed(); | ||
- | // } | ||
- | // } | ||
- | private: | ||
- | void stepBy(int delta) override | ||
- | { | ||
- | stepper.moveTo(stepper.currentPosition()+delta); | ||
- | stepper.runToPosition(); | ||
- | } | ||
- | }; | ||
- | #include <Servo.h> | ||
- | |||
- | class MotorServo : public Motor { | ||
- | Servo s; | ||
- | uint8_t pin; | ||
- | double currentAngle=0, | ||
- | speed; | ||
- | public: | ||
- | MotorServo(uint8_t pin, double speed=100) : pin(pin), speed(speed) | ||
- | { | ||
- | s.attach(pin); | ||
- | } | ||
- | double setAngle(double angle) override | ||
- | { | ||
- | double dAngle = angle - currentAngle; | ||
- | Serial.println(dAngle); | ||
- | s.write(angle); | ||
- | delay(1000/speed*dAngle); | ||
- | currentAngle=angle; | ||
- | return 0; | ||
- | } | ||
- | double update() {}; | ||
- | }; | ||
- | </file> | ||
=====Frontend===== | =====Frontend===== | ||
- | Dieses Programm ist mithilfe des Tkinter-Moduls geschrieben. Hiermt hat man eine Zeichenoberfläche, welches eine Zeichnung speichern kann als auch die Koordinaten der Zeichnung in der Laufzeit ausgibt und an den Arduino schicken kann. | + | Dieses Programm ist mithilfe des Tkinter-Moduls geschrieben. Hiermt hat man eine Zeichenoberfläche, welche die aktuelle Zeichnung speichern kann als auch die Koordinaten der Zeichnung während Laufzeit ausgibt und an den Arduino schicken kann.(?) |
<file python draw_mtrobo.py> | <file python draw_mtrobo.py> | ||
from tkinter import * | from tkinter import * |