Dies ist eine alte Version des Dokuments!
Falls Github spinnt :)
#include "Motor.hpp" //#define PI 3.14159265358979 template<typename T1, typename T2> struct Pair { T1 a; T2 b; }; struct Point { double x,y; Point(double ix, double iy): x(ix), y(iy) {} Point operator-(Point other) { return Point(x-other.x, y-other.y); } Point operator+(Point other) { return Point(x+other.x, y+other.y); } Point operator*(double div) { return Point(x*div, y*div); } Point operator/(double div) { return Point(x/div, y/div); } }; // std::ostream& operator<<(std::ostream &os, Point p) // { // os << '[' << p.x << ' ' << p.y<<']'; // return os; // } class Arm { double l1,l2; Point current; Motor *m1,*m2; public: //arm with the two sections l1,l2. At start both facing upwards template<typename M1, typename M2> Arm(double ll1, double ll2, M1 &&m1, M2 &&m2): 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 Pair<double, double> angles(Point p) { double ph2= acos( (p.x*p.x+p.y*p.y-l1*l1-l2*l2)/ (2*l1*l2)); 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}; } //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 shiftPen() { } }; void setup() { // 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; // }
#pragma once #include <math.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 { double partial=0; int speed, stepsPerRev; 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: SmallMotor(int in1, int in2, int in3, int in4, int stepsPerRev, int speed=5) : s(stepsPerRev, in1, in2, in3, in4), StepperMotor(stepsPerRev, speed) { s.setSpeed(speed); } private: void stepBy(int delta) override { Serial.println(delta); s.step(delta); } }; #include "AccelStepper.h" class AccelMotor : public StepperMotor { AccelStepper stepper; public: AccelMotor(int stepPin, int dirPin, int stepsPerRev, int speed=1000) : 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() {}; };
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.
from tkinter import * class Point: def __init__(self, x, y, color="black"): self.x = x self.y = y self.color = color class GUI: def __init__(self): #gneral attributes self.last = None self.points = [] #tkinter stuff self.widget_bgc = "black" self.widget_fgc = "lawn green" self.draw_color = "back" self.window = Tk() self.window.geometry("500x550") self.window.title("Frontend") self.window.config(bg=self.widget_bgc) self.canvas = Canvas(self.window, height=475, width=465) self.canvas.place(x=15, y=15) # self.canvas.bind("<B1-Motion>", self.draw) self.canvas.bind("<Button-1>", self.draw_dot) self.canvas.bind("<ButtonRelease-1>", self.reset_last) self.clear_btn = Button(self.window, text="clear", command=self.clear_canvas, bg=self.widget_bgc, fg=self.widget_fgc) self.clear_btn.place(x=15, y=510) self.export_btn = Button(self.window, text="export", command=self.export, bg=self.widget_bgc, fg=self.widget_fgc) self.export_btn.place(x=55, y=510) self.import_btn = Button(self.window, text="import", command=self.import_, bg=self.widget_bgc, fg=self.widget_fgc) self.import_btn.place(x=105, y=510) self.size = IntVar() self.size.set(7) self.slider = Scale(self.window, from_=1, to=20, tickinterval=0, orient=HORIZONTAL, variable=self.size, bg=self.widget_bgc, fg=self.widget_fgc, highlightbackground=self.widget_fgc) self.slider.place(x=375, y=505) self.window.mainloop() def clear_canvas(self): self.canvas.delete("all") self.points.clear() def export(self): f = open("export.txt", "w") result = "" for point in self.points: if point == "DONE": result += "DONE\n" else: result += str(point[0]) + "|" + str(point[1]) + "\n" f.write(result) f.close() def import_(self): self.canvas.delete("all") f = open("export.txt", "r") content = f.readlines() f.close() last = None for i, line in enumerate(content): line = line.replace("\n", "") if line == "DONE": last = None else: coords = line.split("|") x = int(coords[0]) y = int(coords[1]) if last: self.canvas.create_line(x, y, last[0] , last[1], width=self.size.get(), fill = "black", capstyle=ROUND, joinstyle=BEVEL) if i == len(content) or content[i+1] == "DONE\n": self.canvas.create_line(x, y, x, y, width=self.size.get(), fill = "black", capstyle=ROUND, joinstyle=BEVEL) last = (x, y) def reset_last(self, event): if self.last: self.canvas.create_line(self.last.x, self.last.y, event.x , event.y, width=self.size.get(), fill = "black", capstyle=ROUND, joinstyle=BEVEL) self.last = None self.points.append("DONE") print("PEN UP") def draw_dot(self, event): print("LINE START", event.x, event.y) print("PEN DOWN") if self.last == None: self.points.append((event.x, event.y)) self.last = Point(event.x, event.y) def draw(self, event): print(event.x, event.y) if self.last: self.points.append((event.x, event.y)) self.canvas.create_line(self.last.x, self.last.y, event.x, event.y, width= self.size.get(), fill = self.last.color, capstyle=ROUND, joinstyle=BEVEL) self.last = Point(event.x, event.y) g = GUI()