evildmp / brachiograph Goto Github PK
View Code? Open in Web Editor NEWBrachioGraph is an ultra-cheap (total cost of materials: €14) plotter that can be built with minimal skills.
Home Page: https://www.brachiograph.art
License: MIT License
BrachioGraph is an ultra-cheap (total cost of materials: €14) plotter that can be built with minimal skills.
Home Page: https://www.brachiograph.art
License: MIT License
Power up the Raspberry Pi. Run:
sudo pigpiod
cd BrachioGraph
python3
And then, using the inner_arm and outer_arm length measurements (in cm) that you noted earlier:
from brachiograph import BrachioGraph
bg = BrachioGraph(inner_arm=<inner_arm>, outer_arm=<outer_arm>)
The system will create a BrachioGraph instance and initialise itself, adjusting the motors so that the pen will be at a nominal:
x = -inner_arm
y = outer_arm
And this will correspond to:
the upper arm at -90 degrees, 1500µS pulse-width
the lower arm at 90 degrees to it, 1500µS pulse-width
the lifting motor in the pen up position, 1700µS pulse width
Check the movement
We must make sure that the arms move in the direction we expect. Run:
bg.set_angles(angle_1=-90, angle_2=90)
Once I change the values nothing moves. I triple checked my wiring and even replaced the wires and servos.
I am completely new, and I dont quite understand how to convert my own images, so I can draw them with the plotter.
Do I always have to run the picture through linedraw? How did you create the pictures on the front page? The process is not really clear to me.
Hi, thanks for this great project!
I am having an issue with the base example at https://www.brachiograph.art/ .
I have my plotter set with 3 sg90 servos, with both arms of 8cm, really similar to the default pictures, however, when running the africa
example I am getting an error:
>>> # transform image to json format
>>> from linedraw import *
>>> image_to_json("africa", draw_contours=2, draw_hatch=16)
>>>
>>> # start drawing
>>> from brachiograph import BrachioGraph
>>> inner_arm=8
>>> outer_arm=8
>>> bounds=[2, 2, 12, 12]
>>> bg = BrachioGraph(inner_arm=8, outer_arm=8, bounds=bounds)
>>> bg.plot_file('images/africa.json')
Traceback (most recent call last):
File "<stdin>", line 3, in <module>
File "/home/pi/Projects/BrachioGraph/brachiograph.py", line 164, in plot_file
self.plot_lines(lines=lines, wait=wait, interpolate=interpolate, bounds=bounds, flip=True)
File "/home/pi/Projects/BrachioGraph/brachiograph.py", line 182, in plot_lines
self.xy(x, y, wait=wait, interpolate=interpolate)
File "/home/pi/Projects/BrachioGraph/brachiograph.py", line 439, in xy
(angle_1, angle_2) = self.xy_to_angles(x, y)
File "/home/pi/Projects/BrachioGraph/brachiograph.py", line 608, in xy_to_angles
raise Exception(f"Cannot reach {hypotenuse}; total arm length is {self.INNER_ARM + self.OUTER_ARM}")
Exception: Cannot reach 16.53000294101356; total arm length is 16
If bounds
are specified, why is it trying to get out of it? How can I avoid this? Maybe limiting the image bounds?
Thank you very much!
Dr. Juan C Rodriguez
Hi. I can't tell how to build the mechanism. I can see from the pictures that apparently you just glue the sticks to the motor shaft/arm? But what about the third motor at the pen end? What is the moving part of that motor attached to?
When I try to install pillow using the command provided:
sudo apt install libwebp6 libtiff5 libjbig0 liblcms2-2 libwebpmux3 libopenjp2-7 libzstd1 libwebpdemux2
I get the error message:
"E: Unable to locate package libwebpmux3"
I know that the docs already mention it (https://brachiograph.readthedocs.io/en/latest/explanation/hardware.html#beware-of-fakes), but I thought it can't be that bad, after all I just wanted to try it out.
It turns out that the arms can be moved by more than a centimeter before the gears acturally start turning and as a result any movement smaller than a centimeter is just a wiggly line.
https://video.lw1.at/videos/watch/b6bdccd1-6d72-41a4-bca3-c446ce1b1ce8
So next up I'll try real TowerPro servos with metal gears and hope that I can avoid someone else buying crappy servos.
My apologies if I'd overlook something obvious. I've strictly followed the software installation steps, but when I've created a BrachioGraph, I got a segmentation fault:
pi@raspberrypi:~ $ sudo pigpiod
pi@raspberrypi:~ $ source env/bin/activate
(env) pi@raspberrypi:~ $ cd BrachioGraph/
(env) pi@raspberrypi:~/BrachioGraph $ python
Python 3.7.3 (default, Jul 25 2020, 13:03:44)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
from brachiograph import BrachioGraph
Segmentation fault
(env) pi@raspberrypi:~/BrachioGraph $
The host is running a Raspbian Buster. I appreciate any suggestion on how to get out here, please.
https://help.github.com/en/github/building-a-strong-community/adding-a-license-to-a-repository
It will be more clear for people wanting to contribute (I'm interested in french translation of the doc).
I started up the BrachioGraph program exactly as stated in the instructions. The instructions told me that when I set the arm lengths that it will initialize the arms to the default position, but nothing moved.
The console printed something along the lines of "Connection accepted on socket 5" , "So_KEEPALIVE accepted on socket 5" (for sockets 5 - 8 I think). Not sure what this means, but I ignored it for now.
I tried going through the rest of the commands listed in the docs, and nothing happens with the motors. I thought maybe my wiring was bad, or the motors were too cheap, but I tested them with another program and they work like a charm! So I know its not a wiring or motor problem; I must be doing something wrong with the program. Any suggestions will be much appreciated.
(I am using a raspberry pi 4, NOT a zero)
Hey first I would like to thank you for providing this project. It is really a lot of fun and very educational. :)
Unfortunately, I haven't been able to get any further for several days and even the (detailed) documentation doesn't help at this point.
I am currently calibrating the inner motor (elbow) to get suitable values for servo_2_angle_pws. After inspecting the code I found out that you can add the argument servo=2 to the function bg.calibrate() to calibrate the second motor. But unfortunately the documentation does not provide further information. So far I got only bad values for servo_2_angle_pws, causing the pen to immediately run out of border or sending pulse widths outside the valid range. Therefore I have the following questions:
Hi, I would use brachiograph code to control this SCARA robot; gemoetry seems to be applicable, but in the original project, designer used two 42 stepper motors (nema 17) and a servo for per holder.
This kind of setup will affect cost of plotter, and for sure maybe the usage of a CNC shield ot other to be connected to PI.
Can someone address me to portion of code to change in order to control two stepper motors and a servo instead of 3 servos?
Thank you!
Francesco
This doesn't work:
pi@raspiB:~/BrachioGraph $ python3
Python 3.7.3 (default, Apr 3 2019, 05:39:12)
[GCC 8.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from linedraw import *
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/pi/BrachioGraph/linedraw.py", line 10, in <module>
from PIL import Image, ImageDraw, ImageOps
ModuleNotFoundError: No module named 'PIL'
source: https://brachiograph.readthedocs.io/en/latest/how-to/use-linedraw.html
As adviced I installed: pip3 install opencv-python-headless
before.
But "PIL" = the libary pillow is missing, it has a lot of depencies you have to install before, that means, this has to be done additionally:
sudo apt-get install libjpeg-dev -y
sudo apt-get install zlib1g-dev -y
sudo apt-get install libfreetype6-dev -y
sudo apt-get install liblcms1-dev -y
sudo apt-get install libopenjp2-7 -y
sudo apt-get install libtiff5 -y
sudo pip3 install pillow
Regards
Axel
Hey, I am new to the Raspberry Pi community, and I thought I'd try this as my first project. I am running into a problem where I am trying to create a new Brachiograph instance according to the instructions. The problem comes when I enter:
from brachiograph import BrachioGraph
it returns
Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/home/pi/BrachioGraph/brachiograph.py", line 4, in <module> import readchar ModuleNotFoundError: No module named 'readchar'
.
I assume this has to do with the "readchar" package I downloaded in a previous step, so I tried reinstalling it then creating an instance of brachiograph again, but the same problem occurs. In the virtual environment I installed it using the command:
pip install readchar
Must I redirect the readchar path to a location that the BrachioGraph program can find it? Am I doing something wrong?
Again, I am new to Raspberry pi and Python, so any help would be appreciated!
I haven't seen a previous issue that discusses this, but it seems to be caused by the latter four of these lines in Pen.__init__()
:
Lines 919 to 924 in 57859e1
Is there a specific reason for this (obviously intended) behavior that I'm missing?
Arduino is more popular than PI so why not put code here for Arduino too.
Would it be desirable to add a "remote driver" mode to this, where instead of a Raspberry Pi the servos are connected to an ESP8266 and receive instructions over the network from a computer running the Brachiograph script?
That would also make the machine much cheaper (or much more expensive, depending on your definition, but I assume you need a computer now anyway).
I have run into a syntax error when loading brachiograph.py at line 608.
raise Exception(f"Cannot reach {hypotenuse}; total arm length is {self.INNER_ARM + self.OUTER_ARM}")
The f before the " mark doesn't make sense to me. Is this correct? I see it in several print statements lower down in the code. I am not familiar with this syntax and it was flag as an error when I went to Start up the BrachioGraph
@ from brachiograph import BrachioGraph
Hi, forgive me if this a trivial question (python beginner) but when importing the module:
from brachiograph import BrachioGraph
Traceback (most recent call last):
File "", line 1, in
File "/home/pi/BrachioGraph/brachiograph.py", line 608
raise Exception(f"Cannot reach {hypotenuse}; total arm length is {self.INNER_ARM + self.OUTER_ARM}")
^
SyntaxError: invalid syntax
How can I save everything I typed in python 3, so I do not have to re-install everything, every time I want to use it?
I am completely new to this, so please excuse me if this is not the right way to feedback this. Please advice a better way then!
In this step https://www.brachiograph.art/how-to/calibrate.html when go into bg.drive()
it starts with the values 1800 and 1500. (I think the actual values are still 1500 and 1500 though)
If you use the keyboard to calibrate and write down the value and then initialize it with the values f.e. 1760 and 1470, the starting position is completely off.
`
bg = BrachioGraph(inner_arm=8, outer_arm=8, bounds=[-12, 4, 8, 10])
bg.drive()
1790 1500
`
A simple wiring diagram would be great, for either the servo wiring harness or the breadboard option (where the documentation states the RPi doesn't have enough 5v sources to drive all 3 servos).
Thank you
I am looking for some advice on improving the calibration. The common theme among my prints seems to be the vertical axis is compressed and the horizontal axis is sort of warped towards the shoulder servo. The image below gives an idea.
Any advice on what settings to adjust? I am pasting below my initialization settings.
Currently initializing with:
servo_1_angle_pws1 = [
[-162, 2470],
[-144, 2250],
[-126, 2050],
[-108, 1860],
[ -90, 1690],
[ -72, 1530],
[ -54, 1350],
[ -36, 1190],
[ -18, 1010],
[ 0, 840],
[ 18, 640],
]
servo_2_angle_pws2 = [
[ 0, 660],
[ 18, 840],
[ 36, 1030],
[ 54, 1180],
[ 72, 1340],
[ 90, 1490],
[108, 1640],
[126, 1830],
[144, 2000],
[162, 2200],
[180, 2410],
]
bg = BrachioGraph(
# the lengths of the arms
inner_arm=8,
outer_arm=8,
# the drawing area
bounds=(-7, 4, 7, 13),
# angles in degrees and corresponding pulse-widths for the two arm servos
servo_1_angle_pws=servo_1_angle_pws1,
servo_2_angle_pws=servo_2_angle_pws2,
# pulse-widths for pen up/down
pw_down=500,
pw_up=1500,
)
A short video of BrachioGraph in action would be really helpful to get an idea of the dynamics of the drawing process.
Hi,
I'm thinking about making Brachiograph in other devices, like Arduino, for instance.
As the computer has to be connected to it, it should be "simple" to make a smaller or a not-very-powerful device work.
Anyone tried to achieve something similar?
In order to make this work I'd like to know some details I can't answer by myself at the moment, I hope you can help me with that:
Thanks!
Built the BrachioGraph the other day and the results of the bg.box() function look like this
How do I best troubleshoot what is wrong?
One thing I noticed was that the drive_xy() movements don't seem to match the text descriptions (ie increase x 1 cm, increase y 1cm) it seems possibly flipped?
I get values like (-10,-6) for min/max X and (5,11) for min/max y. All of my servo orientations and wiring match the documentation.
The only difference I can think of is that I am using a RaspberryPi 2Bv1 not a zero.
Anyhow Im pretty excited about this project but not sure how best to troubleshoot it. Im going to start reading through the code to build some understanding.
Hello,
as mentioned above, when I try to plot my first json file (africa.json) from the tutorial I get the following exception:
`
bg = BrachioGraph(inner_arm=8, outer_arm=8, bounds=[-5, 4, 5, 15], servo_1_centre=1460, servo_2_centre=1470)
BrachioGraph.plot_file("africa.json") Traceback (most recent call last):
File "", line 1, in
File "/home/pi/BrachioGraph/brachiograph.py", line 155, in plot_file
wait = wait or self.wait
AttributeError: 'str' object has no attribute 'wait'
`
I love the Lo-Fi nature of this project. Has there been any effort to use 3d printed parts for added stability?
Hey there!
I am new to python and raspberry so I managed to install everything and now trying to test a svg image. I get this output:
BrachioGraph.plot_file("africa.svg")
Traceback (most recent call last):
File "", line 1, in
File "/home/psytel/BrachioGraph/brachiograph.py", line 155, in plot_file
wait = wait or self.wait
AttributeError: 'str' object has no attribute 'wait'
Could someone help me? Thanks a lot :)
cheers
When playing around with drive_xy, I find some locations generate unstable behavior.
https://youtu.be/Dn1bVbstcOw
I also see much more shaky lines in the vertical plane than in the horizontal plane.
I tried isolating the elbow servo to see if it would shake like this alone, but it only seems to happen when assembled.
I'm using SG92 servos which generate more torque than SG90s. Perhaps related?
Using the following testing script
from brachiograph import BrachioGraph
from time import sleep
# The servo_x_degree_ms signs need flipping as my motors
# go in the opposite direction to those in the article
plotter = BrachioGraph(
inner_arm=8.2,
outer_arm=8.85,
servo_1_degree_ms=10,
servo_2_degree_ms=-10,
)
print("Resetting arm position")
plotter.set_angles(angle_1=-90, angle_2=90)
print("Set up complete")
plotter.drive_xy()
and moving around with a,d,l,k I can consistently trigger a math domain error. I think this happens when the hypotenuse
becomes very small or perhaps negative?
Here's the stack trace
Traceback (most recent call last):
File "test.py", line 23, in <module>
plotter.drive_xy()
File "/home/pi/branchiograph/brachiograph.py", line 698, in drive_xy
self.xy(self.current_x, self.current_y)
File "/home/pi/branchiograph/brachiograph.py", line 434, in xy
(angle_1, angle_2) = self.xy_to_angles(x, y)
File "/home/pi/branchiograph/brachiograph.py", line 590, in xy_to_angles
(hypotenuse**2+self.INNER_ARM**2-self.OUTER_ARM**2)/(2*hypotenuse*self.INNER_ARM)
ValueError: math domain error
and here are the values printed during driving the plotter
Resetting arm position
Set up complete
-9.2 8.85
-10.2 8.85
-11.2 8.85
-12.2 8.85
-13.2 8.85
-14.2 8.85
-13.2 8.85
-12.2 8.85
-11.2 8.85
-12.2 8.85
-13.2 8.85
-14.2 8.85
-13.2 8.85
-12.2 8.85
-11.2 8.85
-11.2 9.85
-11.2 10.85
-11.2 11.85
-11.2 12.85
-11.2 13.85
Hi,
I forked the project here to try out different hardware than what is within the documentation.
The main difference is that I am using the SG-5010's instead with the adafruit 16 channel bonnet.
So I removed all the pws logic and went directly from generating the angles to calling the library to drive them.
First problem was it was generating angles as low as -120 for servo 0, and the library will throw an exception if you give it anything outside of 0 - 180, so I added an offset to every call to that first servo. (which I believe messes up the rest calculation?)
After some fiddling with offsets and physical starting positions, I still wasn't able to get it to draw a straight line using .draw_xy() / .box()
So if anyone could give me a heads up of what would be a good idea for starting orientation angles physically and in the code that would be sweet.
I would be happy to post the results of these hardware changes.
Thanks,
Tom
The instructions on the website explain how to invert the movement of the x/y steppers, but not the pen up/down stepper.
Swapping the defaults of pw_up
and pw_down
seemed to do the job, i.e.
# Original BrachioGraph kwargs
pw_up=1500
pw_down=1100
# Flipped BrachioGraphs kwargs
pw_up=1100
pw_down=1500
It'd be nice to include this in the documentation. Or perhaps provide a kwarg like reversed
that flips everything for you if all your steppers are reversed in the same way.
Hi all, I have some issue installing python package under windows7, may I use cygwin in order to install python and python packages needed to the project?
Problems for me are to find correct packages versions that work with 3.7 or 3.8 python versions.
Thank you
Francesco
Sorry if this is a strange question (python beginner), but when I'm importing
from brachiograph import BrachioGraph
it says:
>>> from brachiograph import BrachioGraph Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/home/pi/BrachioGraph/brachiograph.py", line 4, in <module> import readchar ModuleNotFoundError: No module named 'readchar'
And this is very confusing, as I don't know what this means, and I can't find anything answering it.
My second question might be fixed if the first question is resolved, I don't know, but when I put in
bg = BrachioGraph(inner_arm=<8>, outer_arm=<8>)
it gives me an 'invalid syntax' error, pointing to the beginning of '<8>'
Please help!
When I initialise the motors or I set the angles for inner_arm and outer_arm only the elbow motor and pen lifting motors move.
If I use bg.drive_xy() both A,S and K,L move the elbow motor. The shoulder motor does not move.
I've double checked the wiring on the breadboard I'm using and have replaced the wires and motor to the shoulder, which has not solved the issue..
Following the guide, step by step. I've got as far as Create a BrachioGraph instance, when, I get this:
pi@raspberrypi:~ $ sudo pigpiod
pi@raspberrypi:~ $ cd BrachioGraph
pi@raspberrypi:~/BrachioGraph $ python3
Python 3.7.3 (default, Dec 20 2019, 18:57:59)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
from brachiograph import BrachioGraph
Traceback (most recent call last):
File "", line 1, in
File "/home/pi/BrachioGraph/brachiograph.py", line 4, in
import readchar
ModuleNotFoundError: No module named 'readchar'
Obviously, it has to be a logo that the BrachioGraph itself can draw quite well.
The code really ought to have a test suite. I'd like to use pytest, and would welcome any input, or indeed tests.
I would like to gather more information about different servo models to include in the documentation.
If you have built a plotter, please add a note here about what servos you used, and the results you obtained. The code now includes two new methods, BrachioGraph.vertical_lines()
and BrachioGraph.horizontal_lines()
; it might also be useful to include a picture of the results from these.
When I connected the brachio graph to a raspberry pi 1 it accidentally rebooted while the arms were attached. During the boot process the shoulder servo turned rapidly around.
I think this is caused by the fact that the GPIO port 14 is also used for the serial console in a headless setup: https://pinout.xyz/pinout/pin8_gpio14#
A simple solution would be to make the GPIO ports configurable so people can change the shoulder port if they experience similar behavior.
While waiting for my servos to arrive (#29), I looked a bit into where to get nice things to plot from.
While creating lines from images as in linedraw.py
is looking nice, I wanted something more geometric. So I created two scripts that allow creating the lines json format from simple SVG files and from G-code exported with Slic3r. After creating more scripts to minimize travel distance (there is nothing more fun than to optimize the solution to a problem one doesn't have) and creating another one to preview the final plot with turtle graphics, I thought I'd bundle them up for others to use.
https://github.com/Findus23/BrachioGraph-Utils
Sorry for creating a pseudo issue, but due to a lack of a "forum" I think this is the best way to communicate this.
arm_1_centre=-60,
arm_2_centre=90
I don't understand the meaning of this two parameters. How are they different from that
shoulder_motor_angle
elbow_motor_angle
in function xy_to_angles()
?
Please give me some tips, thanks.
Great project. Thanks for sharing your knowledge, experience and results of your hard work :)
I've successfully calibrated servo 1 using bg.calibrate(). The documentation advises "Repeat the process for the other servo.", but does not go into further detail.
How do I switch to servo 2 for the calibration process?
Has anyone attempted drawing curves or circles reliably?
I was imaging creating a 'font' set of shapes matching letters, but this would be best handled with routines for drawing curves/circles as well as straight lines. (vs approximations)
Apologies in that I'm just ignoring the math for the moment.
Whenever I put in the test command bg.test_pattern()
the servos move a little bit and then I get this error:
raceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/pi/BrachioGraph/brachiograph.py", line 332, in test_pattern
self.xy(bounds[0], y, wait, interpolate)
File "/home/pi/BrachioGraph/brachiograph.py", line 475, in xy
self.set_angles(angle_1, angle_2)
File "/home/pi/BrachioGraph/brachiograph.py", line 501, in set_angles
self.set_pulse_widths(pw_1 + self.active_hysteresis_correction_1, pw_2 + self.active_hysteresis_correction_2)
File "/home/pi/BrachioGraph/brachiograph.py", line 548, in set_pulse_widths
self.rpi.set_servo_pulsewidth(14, pw_1)
File "/home/pi/.local/lib/python3.7/site-packages/pigpio.py", line 1677, in set_servo_pulsewidth
self.sl, _PI_CMD_SERVO, user_gpio, int(pulsewidth)))
File "/home/pi/.local/lib/python3.7/site-packages/pigpio.py", line 1009, in _u2i
raise error(error_text(v))
pigpio.error: 'pulsewidth not 0 or 500-2500'
How would I fix this? Would appreciate any help! I am using the ES08MAII servos.
Following the linedraw docs we get the following error in python shell:
>>> from linedraw import *
Cannot import numpy/openCV. Switching to NO_CV mode.
Checking pip lists the following packages:
numpy: 1.19.4
opencv-python-headless 4.5.5.62
pigpio 1.78
Pillow 8.0.1
pip 20.3.4
readchar 2.0.1
tqdm 4.54.0
Is there any specific opencv-python-headless version required?
Thanks.
Hi,
great project!
The documentation "Start up the BrachioGraph" mentions:
Reinitialise your plotter with these values:
bg = BrachioGraph(inner_arm=<inner_arm>, outer_arm=<outer_arm>, bounds=<bounds)
It tooks me some time to find out, that "bounds" has to be declared like this:
bg = BrachioGraph(inner_arm=<inner_arm>, outer_arm=<outer_arm>, bounds=(<bounds>))
Hope that helps!
Does it plot an image or something? I can't find it
Hello,
thanks for the great project!
The docs explain how to vectorize a bitmap. But I do not find, how I can plot an SVG?
Can you give me a hint?
regards,
Hendrik
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.