Benutzer-Werkzeuge

Webseiten-Werkzeuge


Seitenleiste

mechatronik:sose24:remote-plotter:code

Dies ist eine alte Version des Dokuments!




Inhaltsverzeichnis

Code

Falls Github spinnt :)

Arduino Code

mlzrobo.ino
#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;
// }

Motor

motor_mtrobo.cpp
#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() {};
};

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.

draw_mtrobo.py
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()
mechatronik/sose24/remote-plotter/code.1721948028.txt.gz · Zuletzt geändert: 2024/07/26 00:53 von Paul-Hoeft