TinyG does Spirograph

TinyG Executing Gcode

I’ve been working on the C code for TinyG for 2 years now and I still feel like a rank newbie. The more I get into the domain the more I find that I just don’t know. This weekend I was refactoring a part of the planner to get rid of a bug in some complex feedhold cases. As I got into it further I realized more of the implications that the fundamental variables in CNC (Gcode) are really just time and position.  This is obvious if you look at the math for the motion equations – the base equation is V = dr/dt  – velocity is the derivative of position (r) over time (t), and further derivatives on down to acceleration, jerk, (then snap, crackle and pop! Really. I’m not making this up.)

What was not obvious is how this manifests itself in Gcode and in the underlying motor controller code. First off, Gcode is typically stated as position and velocity, aka feed rate. So G1 F500 X100 Y100 Z-5 moves X, Y and Z from some starting position, say (0,0,0), to (100,100,-5) at a velocity of 500 mm per minute (or perhaps inches per minute, depending). This is the most common way to generate gcode.

But this gets really complicated when you add rotary axes. What exactly does G1 F500 X100 Y100 Z-5 A3600 B1800 mean? Kramer says what that is in the Gcode “Gold Source” specification (NIST RS274/NGCv3, section 2.1.2.5) on Feed Rate. You can read more about that here if you want: Gcode Language Support – Feed Rates and Traverse Rates, but in short, feed rate is a complicated mashup of linear and rotary motion that somehow gets all the axes in the move to the right end point at the right time.

So it’s really just position and time, when it’s all said and done. My *real* machinist friends tell me that this is why machine generated Gcode for complicated machining centers is often produced using Inverse Time Mode – where the F word is interpreted as time, not as velocity. That way you con’t have to mess with these crazy transformations, you just tell the machine where to be, when.

I discovered a while ago that this has ramifications in the controller code. Basically, you want to ditch velocity as a variable as soon as you can, and do all your computation in time and position. These need to stay accurate or errors will creep into the work. Velocity, acceleration, jerk?   Not so much. Errors here are much more forgiving.

Another implication is that there is a quanta for time, or a Planck’s constant for the controller. It’s not 5.391 x 10(-44)th like in the real world, it’s the minimum interpolation interval that the firmware/hardware system can sustain. In EMC2 this is about 1 millisecond. In TinyG it’s closer to 2.5 milliseconds. This is the minimum update time that you can change the parameters for the motor drivers, or the update rate. If you go faster than this you won’t be able to compute the next update in time and the system will fail. Likewise there is a minimum quanta for position, which is basically how far an axis moves for one step (or for one microstep if you don’t really care about the increased relative error that introduces – microsteps are not perfect).

So the whole system needs to be constructed around these limits.  Thinking about the problem this way opens up a bunch of new possibilities. Like easier ways of doing splining, or better ways of coordinating axes in parallel robots. Or how to coordinate many-axis machines working in the same space – think multiple adaptive exclusion regions all competing for access to the same endpoints or regions.

 

 

 

 

 

 

While this is not exactly the norm CNC, embeded, laser cutting post here.  I am posting how to compile and write C code to run directly on Andorid.

  • Download the Android NDK .
  • Extract it to where ever you like.  I put it (/Applications/eclipse/android-ndk-r7b)
  • Open a terminal and cd to where you put it.
  • Then run the build script: (android-5 is gingerbread)
/build/tools/make-standalone-toolchain.sh --platform=android-5 --install-dir=/tmp/my-android-toolchain

 

Now that you have your toolchain built.. (insane easy!  thx google) its time to test it out.

#include 
void main(){
printf("hello world!\n");
}

Here is out little program to test out our new arm toolchain.
Lets compile it with:

./arm-linux-androideabi-gcc -o hello hello.c

If all goes well you should have a arm executable named hello in the same directory.

Running file on hello should in fact show us our binary is of ARM architecture!

hello: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), not stripped

Here is the arm-linux-objdump output from hello: (-d is the disassemble flag)

./arm-linux-androideabi-objdump -d hello
 
hello:     file format elf32-littlearm
Disassembly of section .plt:
 
000082d4 :
    82d4:	e52de004 	push	{lr}		; (str lr, [sp, #-4]!)
    82d8:	e59fe004 	ldr	lr, [pc, #4]	; 82e4 
    82dc:	e08fe00e 	add	lr, pc, lr
    82e0:	e5bef008 	ldr	pc, [lr, #8]!
    82e4:	00001158 	.word	0x00001158
    82e8:	e28fc600 	add	ip, pc, #0	; 0x0
    82ec:	e28cca01 	add	ip, ip, #4096	; 0x1000
    82f0:	e5bcf158 	ldr	pc, [ip, #344]!
    82f4:	e28fc600 	add	ip, pc, #0	; 0x0
    82f8:	e28cca01 	add	ip, ip, #4096	; 0x1000
    82fc:	e5bcf150 	ldr	pc, [ip, #336]!
 
Disassembly of section .text:
 
00008300 :
    8300:	e1a0000d 	mov	r0, sp
    8304:	e3a01000 	mov	r1, #0	; 0x0
    8308:	e28f2004 	add	r2, pc, #4	; 0x4
    830c:	e28f3004 	add	r3, pc, #4	; 0x4
    8310:	eafffff7 	b	82f4 
    8314:	ea000005 	b	8330 
    8318:	0000935c 	.word	0x0000935c
    831c:	00009364 	.word	0x00009364
    8320:	0000936c 	.word	0x0000936c
    8324:	00009374 	.word	0x00009374
    8328:	e1a00000 	.word	0xe1a00000
    832c:	e1a00000 	.word	0xe1a00000
 
00008330 :
    8330:	e92d4800 	push	{fp, lr}
    8334:	e28db004 	add	fp, sp, #4	; 0x4
    8338:	e59f300c 	ldr	r3, [pc, #12]	; 834c 
    833c:	e08f3003 	add	r3, pc, r3
    8340:	e1a00003 	mov	r0, r3
    8344:	ebffffe7 	bl	82e8 
    8348:	e8bd8800 	pop	{fp, pc}
    834c:	0000000c 	.word	0x0000000c

There we see our ARM registers (r’s) doing their thing. Admittedly I am still getting used to looking at arm assembly.

So now that we know this is the right arch we can push this up to our device via adb.  adb is included in the Android SDK download.

./adb push /tmp/my-android-toolchain/bin/hello /data/hello

This will upload the arm binary hello to the /data/hello location. Note you must have your phone connected (or emulator.. duh right?)
Once this is uploaded we will use adb again to get a shell on the phone/tablet/whatever.

adb shell
#

This returns us to a blank shell. I personally like bash so I toss out a bash command and drop right into the bash shell.
From here we make the hello file executable and run it!

chmod +x /data/hello
/data/hello

Which gives us:

localhost / # /data/hello 
Hello Worldlocalhost / #

There we have it! C code without any official Java interfaces to the NDK. Pretty cool.  As a afterthought I did this all from OSX.  So any specific Windows questions on how to do the same I will not be able to assist with.  Better just “read the docs” from google on that.
Anyhow this post is mainly for me to keep around for my records on how to do this in the future.

 

Quick update… Been working on a grblShield case as of late.  Its close to being done.  I will release the laser cut files soon.  However, very soon we will be offering a full on “grblShield kit” which will include a preloaded arduino running the latest version of grbl and a laser cut case.  Here is a cardboard early prototype..

 

grblShield Case

Cardboard Prototype

 

DSC_8203.JPG

Notice the upside down logo.. Whoops!

 

 

 

 

 

 

 

 

 

2011 has been a busy year at Synthetos. We launched the grblshield in March and TinyG in September.  Here’s an update on both.

grblshield has gotten a lot of interest this year. We are almost sold out of our second production run and need to do another at the start of the new year.  There have been some great projects using grblshield and we’ve gotten some excellent feedback. Here’s a really cool CNC mill conversion.

grblShield v2 Production

TinyG has been through a lot of development this year.  Some highlights:

  • Version 6 hardware released
  • Support for rotary axes – now does 6 axes – XYZ and ABC
  • Advanced acceleration and cornering algorithms using constant-jerk planning
  • Feedhold and cycle-start
  • Status reports provide position and velocity feedback in JSON format
  • Lots of debugging and shakedown. It’s pretty solid now.

TinyG v6

Another thing that’s happened over the year is that TinyG and grbl projects continue to coordinate on algorithms, interfaces, etc. Simen Skogsrud started the grbl project and brought it to grbl 0.6.  We worked closely with Simen to ensure grblshield compatibility. Since about mid-year 2011 Simen has been focused on some really interesting Ruby development as you can see from his github.  Sonny Jeon (chamnit) has been carrying the grbl codebase forward. We’ve been recommending that anyone using grblshield use Sonny’s fork. It fixes a number of issues in earlier releases, has advanced cornering and feedholds. We’ve coordinated the use of characters and interfaces so that controllers can be compatible with either system.

At this point TinyG is pretty complete as a basic CNC controller, but there is always more that can be done.  Look for more interesting developments in 2012, including a control console – and compatibility with many that are being developed, backlash compensation, feed overrides, and laser support (PWM channels). We are very interested in your requirements so please comment on this post if you have ideas.

Alden and Riley

 
1/8 Plexiglass

I was reading Make:’s Blog and I saw the entry on laser cutting wood to make it bendable (see SNIJLAB). See here. I set out to see if it was possible to laser cut plexiglass in the same way. To my surprise it works pretty good! You can see for yourself the results.

I also created a 20″x3″ version in 1/8 red plexiglass. This took about 45minutes of cutting. You can see a video of how flexible it is.

 

TinyG Pre-Release

TinyG pre-release is available finally.  Alden has been putting a TON of time into working out bugs here and there.  Right now you can get your own TinyG from the synstore.  But be warned this is a pre-release.  There will be updates.  TinyG currently does not have a bootloader on it.  So what does that mean?  Well, you need a AVR ISP MKII programmer. (Others might work but we know this one does) to update your TinyG boards.  We are offering another service here shortly.  If you purchase a TinyG board and would like a firmware update on it, just send it in and cover the shipping (to and from) and we will update if for you for free.

 

We also have added the .156″ stepper motor connector kits to the synstore.  You can get them here.  They make life much easier when trying to interface your motors to TinyG or grblShield.

 

 
Heat Sink Kit

Heat Sink Kit

We recently added a new product to the syn webstore.  Its a 4 pack stepper driver heat sink kit.  These are not needed with TinyG or grblShield when using motors up to about 2 amps per winding.  However at 2 – 2.5 amps you really should be using at least the heat sinks and possibly a fan as well.  You can pick them up for $5.99 for the first month.  After which the price returns to normal $6.99.

 

We are using these heat sinks for the v90 Probotix mill we have. We have some beefy stepper motors on this machine. These little heat sinks help get that extra out of the drivers.

 

We’re very excited here at Synthetos about getting avr-xboot running on TinyG. In preparation for general release of TinyG (mid-August) we have incorporated Alex Forencich’s xboot onto the chip. This allows people to download new versions of the TinyG firmware using AVRdude directly into the USB port. That’s right, no programmer is needed, so no Atmel AVRISP2 to buy.

This post describes how to get xboot onto an Atmel xmega using AVRStudio4. If you are looking for instructions to reflash TinyG, go here.

Getting xboot onto an Atmel xmega chip

It’s really quite easy to create and program an xmega boot loader from AVRStudio4 once you understand the moving parts. The avr-xboot github has really good documentation which if you read it and understand it you should have no problem getting xboot to work. I did the former but less the latter, so I had a few dead ends. Here are step-by-step instructions how to get the boot loader running via AS4.

Notes on AVRStudio, OSs and programmers: AVRStudio4 is the last version before Atmel went to AVRstudio5. I’ve run betas of AVRStudio5 but have backed off due to some bugs I’ve encountered. This post uses AS4 – mostly because I trust it more at this point. The steps may also work on AS5, but I have not tried it. Both AS4 and AS5 are Windows only. I run XP as a VMWare virtual machine on a Mac OSX machine and have encountered no problems with this configuration. Installing AS4 requires first installing WinAVR, then the AVRStudio, then the latest service pack they have. The latest versions are WinAVR-20100110, AS4.18, and SP3. I use an Atmel AVRISP MKii programmer. These are available from Mouser Electronics (& others) for $34. The programmer must support PDI programming to program the xmegas. TinyAVRs and similar will not work on xmegas.

Moving Parts

  • The Xmegas have 3 programmable flash regions; the application section, the application table section, and the boot section. The application section starts at location 0×00000, with the application table section located at the end of the section. The boot section starts immediately after the application table section. This is location 0×40000 on the xmega256 chips. In addition to the flash regions, you can also program EEPROM, fuses, and lock bits.
  • The boot loader must reside in the boot section as running the boat loader erases and overwrites the application section(s), and the chip won’t erase the section you are currently running in for obvious reasons.
  • The xmegas have a fuse called BOOTRST that must be set to Boot Loader Reset so the chip starts up in the boot area. This fuse needs to be programmed, too.
AVRStudio4 Instructions
  1. Setup and configure an xboot project in AS4
    1. Download the code from the avr-xboot github
    2. Open a new AVR GCC project in the downloaded project directory. Name the Project “xboot”. Do not create a folder or an initial file. Navigate to the downloaded project directory to set the location. Hit Next.
    3. Select your chip. Hit Finish.
    4. Right click “Source Files” in the left hand project pane. Select “Add Existing Source Files”. Select all files that show up (eeprom_driver.c —> xboot.c). The .S is considered a source.
    5. Right click “Header Files” in the left hand project pane and do the same.
    6. Click the “Project” tab, “Configuration Options”. Select “Use External Makefile” and navigate to the Makefile in the project directory. (See Note 1)
  2. Configure and build the xboot code
    1. Edit the Makefile according to the xboot instructions in section “2.1 Configure”. You will find the Makefile under “Other Files” (or you may need to add it to Other Files). You will need to set the MCU and the CPU frequency (TinyG uses F_CPU = 32000000).
    2. Configure xboot.h according to section “3.0 Configure” which I won’t repeat here. I had to change the UART to C0 which is the device TinyG uses for the USB port. You may also want to find a free LED so the boot loader can signal its state. If you are running a rev A or B xmega you may need to enable #define USE_AVR1008_EEPROM – see Atmel app note AVR1008 for details.
    3. Build the code (You can ignore the warning “xboot.c:55: warning: ‘i’ may be used uninitialized in this function” – or go into xboot.c, initialize i, and rebuild like I did).
    4. Checking the compile messages shows a .text section starting at address 0×40000 – for the xmega256 – your part may be different, but should not be 0×00000 (See Note 2)
  3. Program the target chip
    1. Fire up the programmer – which must be one of the ones compatible with the xmega PDI programming protocol, such as the AVRISP mkii.
    2. From the Program tab, program the flash using xboot.hex as the Input HEX File. The xboot makefile outputs 2 hex files: xboot.hex and xboot-boot.hex. You want xboot.hex
    3. From the Fuses tab, set the BOOTRST fuse to Boot Loader Reset. Hit the “Program” button before leaving this screen.
  4. Check it out
    1. At this point the boot loader should be on the chip in the boot section.
    2. Hit reset on your target board the indicator LED should light and the loader should accept commands.
    3. If you type S to the UART shortly after reset it should respond with xBoot++ indicating that the boot loader is alive (and your baud rates are set correctly).
    4. If you connect AVRdude while in boot mode it should connect (See section 2).
Notes:
  1. There is a post on AVRfreaks that advises using Configuration Options to set the memory region to the flash region. I did not find this to be necessary. Nor did I find setting F_CPU in the configure dialog, as both of these are taken care of by the makefile provided with xboot. All we are doing with Configuration Options is telling AS4 to use a different makefile, so all other settings are going to be ignored – as they are what AS4 uses to create its own makefile.
  2. The xboot.hex file starts with the line  :020000024000BC – or similar if you are using something other than a 256kb part. This is a segment offset record which locates the subsequent hex records to the base of the boot section; 0×40000 in the case of the xmega256. The “4000″ field in the “02 4000 BC” portion is the offset / 16 – which is why its missing the last zero.Your offset will be 1000 for a 64kb part, 2000 for a 128kb part, etc., but should never be 0000.  The AVR programmer is smart enough to skip over the parts of flash it is not programming, so the chip programs very fast – given that the boot loader is a small program. Looks like the AS4 programmer does not go through the rest of the memory as it appears AVRdude does.

Jun 242011
 

Recently I moved. Which means that Synthetos moved :) We have been super busy packing/un-packing (or read squandering prime making/hacking weather). However, Alden (My partner) has been hacking away at the TinyG code base. However, moving was a very very good thing! The new Synthetos Workshop is not 3400 sqft. (1700 sqft. x 2 floors). I have tossed in a few PRE-SETUP images of the workshop. I will post some more when everything is setup. Just note that we are not gone. We will be back making cool procjects (BIG ONES) soon!



 

Here at Synthetos we came up with the idea of using the grblShield to control a wirebot. A wirebot (or “cable robot”) is the same type of robot as the SkyCam that sports stadiums use to fly video cameras over the field. We plan on using this robot setup to control some really cool Halloween decorations!  However the uses are many. Riley’s son wants a TIE Fighter flying around the ceiling in his room. Using the grblShield and three stepper motors, some braided fishing line and some odds and ends we get our WireBot. Check out the Make:Project here to find step by step instructions.  Below is an explanation of the setup and the math.

Intro

The wirebot has the following components – from the top layer to the bottom:

  1. A Python program that reads Gcode files, transforms X,Y and Z them into wirebot coordinates and sends commands to…
  2. grbl. Which is a 3 axis CNC controller running on the Arduino hardware.
  3. grblshield plugs into the Arduino and provides 3 stepper controllers which drive…
  4. three motors the control the string lengths needed to position the wirebot.

Setting up the motors

The working volume of the wirebot is a triangular solid defined by the three motor positions: left vertex, right vertex, and rear vertex (v1, v2, and v3). The useful working volume where the coordinates are relatively linear is somewhat smaller than the full triangle, and is roughly the cylinder that fits within the volume. So when setting up a wirebot you want to chose vertex locations to get a good working volume. While the robot can move outside the working volume, the coordinates get very distorted very fast. They stay pretty linear inside the working volume.

Chose a good space to work in (like an open porch), and mount the motors at the vertices, probably along the ceiling of the porch. For best results the string should come off the spool pointing roughly towards the center, but any reasonable angle will do. We wound the strings so they feed off the top of the spools. Here’s a picture of the wirebot test rig (considerably smaller than the porch!).

When you mount the motors it’s easiest if they are all “pointing the same way”, i.e. the shafts are all pointing clockwise or counterclockwise around the circle. If one motor is reversed from the others you will need to invert the polarity of that motor either at the plug (electrically) or by using the grbl polarity setting (see: http://www.synthetos.com/wiki/index.php?title=Using_the_grblShield)

Configuring the vertices

The wirebot coordinate system has an X, Y, Z origin (0,0,0) in the middle of the volume. Positive X moves to the right, positive Y moves towards the back, and positive Z moves up.

To set up the vertices determine the position of each vertex relative to the origin. Measure the vertex offset in X (left/right), Y (backwards/forwards) and Z (up/down) dimensions from an origin point in the center of the volume. Measure from the origin to the center of each spool. So if the above diagram represents an 8 foot cube the coordinates will look something like this (in inches):

v1 = (x1, y1, z1) = ( -48″,  -48″,  48″ )         left vertex motor

v2 = (x2, y2, z2) = (  48″,  -48″,  48″ )        right vertex motor

v3 = (x3, y3, z3) = (   0″,    48″,  48″ )         rear vertex motor

These offsets are entered into the Python program. The above example assumes the vertices are all at the same height, but they don’t have to be. Just enter the actual height from the origin. The example also assumes that the rear vertex is half way between the left and right in X (centered), but it doesn’t have to be. The positions of the vertices are somewhat arbitrary, assuming you don’t reduce the working volume too much.

Wirebot inverse kinematics math

The math is actually very simple once you realize that all you need to do is compute the line lengths (distances) between the target position and the vertices. The line lengths are the cartesian distances defined by the following equations.

L1 = sqrt((x1-x)^2 + (y1-y)^2 + (z1-x)^2)

L2 = sqrt((x2-x)^2 + (y2-y)^2 + (z1-x)^2)

L3 = sqrt((x3-x)^2 + (y1-y)^2 + (z1-x)^2)

Where (x1,y1,z1)… are the vertex positions and (x,y,z) is the target position.

Rather than modifying the grbl code to perform the inverse kinematics, we cheat and do the transformation beforehand using a Python program. The Python program transforms the X,Y,Z coordinates you input to produce Gcode that produces the right string lengths from the grblshield.The Python takes the actual X, Y and Z coordinates and transforms them to L1, L2, and L3 values before sending them to grbl/grblshield.  The L1 length is fed to grbl/grblshield as the Gcode “X” coordinate, L2 as the “Y”, and L3 as the Z.

Here is a video of it moving the ping pong ball in a spoke like pattern.

© 2012 Synthetos Blog Suffusion theme by Sayontan Sinha

Bad Behavior has blocked 179 access attempts in the last 7 days.