Fighting with computers

Computers are not always friendly.

Sunday, February 22, 2015

3D Tool path generation

I needed for a project to create a parallel finishing tool path similar what many CAM software does. There is nothing wrong with existing CAM software but what fun would be to just buy and use the software.

The basic idea is that you can use a swipe plane across the mesh representing your volume and get the top part of each slice to be the tool path. A similar idea is used for 3D printing, but there the swipe plane is an horizontal one and object is built from the bottom up.

The problem is that you cannot use the slice you just obtain from the mesh as milling bit (or extruded filament if 3D printing) has a non-null dimension. Because of that, just following the contour of the object will create a smaller result than the model.

For 2.5D milling you can do a waterline finishing, doing flat passes on XY-plane. Thus a simple polygon offsetting operation can help you get the part dimensions right. But for 3D milling, the tool compensation becomes more difficult.

The solution I opted for was to perform a mesh offsetting. Three different ideas can be used for the operation:

  1. Facets can be offset following the normal direction.  Mesh becomes full of gaps
  2. Edges can be offset following the a combination of the two normals of the two triangles sharing that edge.
  3. Vertices can be offset too. The question is that what is the better way of combining the normals of the three triangles each vertex shares. 
A quick look at the vertex normals calculation available in Meshlab gives four different methods. Before committing to code anything, a quick test would be welcome. 

I have done a simple test, that proved useful: after calculating vertex normals, I can export the file from Meshlab. Using PLY format instead of STL allows me to output each vertex's normal. If now I do some math with a script I can do the offset and test the result. 

Most time was lost due to a particular "feature" of awk in OSX. Once this was fixed I was able to offset the vertices of the mesh and prepare the correct tool path.

Friday, February 13, 2015

Barcode listings with data

A few weeks ago I mentioned a new tool I created for (allegedly) making my life easier when delivering marked exams to my students. Then I covered the process that happens after the exam. But one key element it was not mentioned is what it needs to do in advance.

For my system I needed a set of labels. My prototype used Code-128 barcode that can handle ASCII code to encode each student email using barcode command-line program for Linux. The only problem with that was the lack of additional information being added to the label, such as the student name.

Looking around I found a very handy tool by AVERY company, that helps you creating labels on-line for all their range of labels. What is even better is the tool will allow you to upload an excel file with data columns, like names and addresses to create a custom listing you designed and export it as PDF (they offer to print it for you to and deliver the labels to your office too).

After some tweaks and, the most difficult part, discovering the reference of my European A4 labels on their site, I get a set of working labels but this time using 2D QR codes that are a bit more reliable than 1D barcodes.

But I was left with a bit of an itch that I should be looking for a way of solving the problem entirely with my own software instead of using an online application, as importing a new list of students required a bit of touching here and there.

Not knowing what could do the job more easily, I turned to the ZXing library I am already using for decoding and I saw there is an encoder too. And given that creating a PDF output seemed to work well for AVERY I decided to do the same, this time using Processing, as it tends to make my life easier than when using Java.


The function above will create a QR code as an image you can later place inside a PDF page following the pattern you want. Going from BufferedImage to PImage took me like one hour to get right, as it seems Processing has been going through different solutions to that in the past, most of them no longer working.

So now I do have a tool that creates the labels from a CSV files with students name and addresses. I am looking forward to use these tools in the coming months.

Saturday, February 07, 2015

Maple Mini looking good

This week I received a real bargain I wanted to test as a better candidate to be able to control several DC motors in closed loop.

I have already tested the STM Nucleo 401 board and I get one 32 bit, signed, hardware encoder input on timer 2 and three more unsigned, 16-bit hardware encoder inputs on other timers. Unfortunately timer 5 was taken by the mbed library I was using. Nucleo is a solid platform and using the cloud IDE actually is not big deal for me.

But now I have got a Maple Mini for $4 and I have to tell you I am totally sold. It is so much faster compared to an ATMega Arduino that I am positive it can do the work for controlling two DC motors closed-loop and most likely it can do four or more.

The board can handle up to 16 external interrupts, enough for 8 encoders, and it can produce 12 PWM 16-bit resolution outputs (a far cry from 8 bit PWM from Arduino, though I am not sure that will have any impact on the system performance) plus plenty of memory (128K flash, 20K RAM), serial ports and other nice touches.

Like any other Cortex-3 it runs off 3.3V power, which I thought it will be a pain as encoder circuit is rated at 5V, but a quick test revealed encoder seems to be working happily when powered at 3.3V too. That saves me some trouble with interface and gives me more freedom as not all the input pins are 5V tolerant.

Though the Maple family has been around for quite a while (2009) I have never used it before. And my first experience has been a blast too, because the Arduino IDE clone is what they use, so it all seems pretty familiar for long-time Arduino users.

I guess that sooner or later I will need to venture in some of these detailed user manuals for setting some feature on, but for the moment the sample programs and online help are being good enough.

Thursday, January 29, 2015

A better mousetrap so to speak

Once in a while I need to mark exams. Exams do not tend to please students and marking exams is rarely a task anyone enjoys doing. But I cannot change that.

What we do later is what I was trying to change for a while: For some years I have been using Scribd as a platform to make available the marked exams to my students. As I did not have a better tool, I started by doing the scan of the big pile of exams to later make it available as a document they can browse on the web (but not download).

Making all the exams available to all the students is a liability that created me no trouble so far, but I can see privacy concerns plus fear of putting too much information in the hands of the students. To address the privacy concerns I did not made the document visible or public, but private so only those with the secret URL could browse it. On top of that, marked exams were kept available for a couple of weeks before being deleted.

The idea of a student being able to review the whole marking process may not be entirely wrong, as it seems a great exercise of transparency, but it makes most of my colleagues uncomfortable.

Of course I could scan each exam on a different file and later send a copy to each student. But while this approach may be better, it takes a lot of work.

So what I did today was to put together a nice set of tools which help me get a working solution:

  1. ZXing project provides tools for you to create barcodes but mostly for decoding them. It is Java based and it works nicely.
  2. barcode is a linux command-line tool that can easily create a set of barcodes by reading from a textfile (containing names or whatever other info you want to encode).
  3. ImageMagick is a fantastic command-line set of tools for image manipulation
  4. Postfix (or sendmail) can be used to send email alerts to the students (unfortunately my ubuntu version is old and I cannot install new stuff anymore, time to upgrade to next LTS, so I had to make a hack in Java for sending email using SMTP and Sockets). 
What I did was quite a straightforward process:
  1. Once student is turning in the exam, a barcode with his/her email is sticked to the first page of the exam. Several pages of barcodes were created using "barcode" program from the list of emails of the students. Each barcode the text version of the email too for human identification. Code 128 was used.
  2. The big pile of exams is scanned at grayscale 300dpi as a sing PDF file.
  3. PDF file is processed, extracting each page as a bitmap file.
  4. Each bitmap file is processed by ZXing with the option --try_harder so the code is read no matter were on the page it was stuck. 
  5. Once the last page of a lot is detected (as the new one has an email barcode) the sequence of pages of that exam were stored in a special folder on a web server, with a name derived from email value. 
  6. An email containing links to each one of the scanned images of the marked exam stored on a web server are sent to the student (directory listing is not possible in that server, only valid URL are shown).
This way each student gets only his/her exam and they can see what they did wrong or ask for any clarification they may need. On the web server side, the URLs are created in a way the students cannot guess their or others filenames. Being a web server we get feedback of whether a students have checked or not their exams. 

The whole thing process one page per second so my 80 pages exam was done in two minutes, alerts emails included. Now I need like five years to recover the invested effort in creating a tool for saving me time :-)

Monday, January 26, 2015

Sometimes you get lucky, sometimes not

I have wasted a fair amount of time today with a problem I solved the way I recommend to others: use a library. I needed to do a polygon offsetting in a program and I used what has worked for me in the past, the Java Topology Suite.

I did my thing and it almost worked perfectly:

However, I noticed a minor artifact once in a while. After some time I found that offset would sometimes did not work well as a weird line would appear crossing (line between to small circles) my beloved pumpkin instead or remaining on the outside (horizontal crossing was expected though).
I as not trying to do a full offset but only of the part whose normals is between 0 and 180 degrees, as this project is related to 3d milling. 

After a few hours of testing it all came down to a defect on the library (as far as I can tell) because with the same input data, but a smaller offset value, the operation was succesful as you can see below:

I was unable to find a proper forum to ask other users about this problem, so I will keep on using this library when the offset values needed are low but I will need to find a better choice for the future. If you know of a good choice I could use in Java I will like to know.

At any rate, here you have the data points in case you want to have a look.



Friday, January 09, 2015

Do more with less

Following my previous post about using an Arduino for controlling a DC motor with an encoder in a closed-loop fashion some people have asked me if one Arduino per motor was not too expensive. Well, if you use an Arduino Pro Mini it can be less than $2 each.

However, I do feel too that maybe we can do better.

The main reason of my initial approach was that I had several signals that need to be handled fast-enough. On one hand, the quadrature encoder of the motor provides two pulsing signals that are used to know the current location of the motor shaft. This is accomplished by counting pulses, if not done fast enough, missed pulses will translate into position errors (and we are going closed-loop instead of using steppers to avoid exactly this same problem).

On the other hand, the motor controller has to be able to receive pulses from the main controller (an Arduino Mega running Marlin) that control the motion of the motor. These pulses can be quite short and frequent (up to 40Khz signal) so motor controller needs to be fast enough not to miss them either.


The first obvious solution was to use the two external interrupts available on the Arduino Pro Mini (or the UNO I was using for development that is equipped with a 328 too). One of the external interrupts will handle one of the encoder signals and the other will handle the "pulse" signal from the motion controller. This way we can be confident that all no pulses of each type will be lost.

However that left me with no choice but to have to use one Arduino per motor, as there were no other interrupts I could use.

Todays test shed some light about an alternative way of doing things. There is a feature on ATMega processors that can trigger an interrupt on pin change for any of the I/O pins selected. My first test was not entirely successful because I forgot to use fast I/O: digitalRead() is not a very fast way of doing things. While not a problem most of the time, it makes interrupt routines to use quite a long time and for fast pulses that means that a second pulse could arrive before we are still reading the first one, leading to missed pulses. Once I fixed this, I can move the carriage very fast without missing pulses.

You can the code I am using below. As usual, I have collected some smart ideas over the 'Net. (Please note the picture above does not represent the system I used the following code with but my initial design posted on youmagine).

#include <PinChangeInt.h>
#include <PinChangeIntConfig.h>

#define encoder0PinA 6
#define encoder0PinB 7

long int encoder0Pos = 0;

void setup(){
  
pinMode(encoder0PinA, INPUT); 
pinMode(encoder0PinB, INPUT); 

PCintPort::attachInterrupt(encoder0PinA, doEncoderMotor0,CHANGE); 
PCintPort::attachInterrupt(encoder0PinB, doEncoderMotor0,CHANGE);

Serial.begin(115200);
  
}

void loop(){
  Serial.println(encoder0Pos);
  delay(200);
}

const int QEM[16] = {0,-1,1,2,1,0,2,-1,-1,2,0,1,2,1,-1,0};    
volatile unsigned char New, Old;
void doEncoderMotor0(){ 
  Old = New;
  New = ((PIND & 128) >>6)  + ((PIND & 64)>>6);         
  encoder0Pos+= QEM [Old * 4 + New];
}


Update: I have not had much luck with two motors per Arduino. I can make it work for low speeds but eventually the interrupt service routines use up all the processor time and the system becomes unstable. I guess it can be done if motors have lower resolution encoders or have a lower RPMs.

However, I have learned that Maple Mini has an ARM processor that includes four timers that can handle one encoder each. This may be a better platform, specially if you can get it for $4 on Aliexpress.

Wednesday, December 31, 2014

Closed-loop DC motor to act as a stepper motor

One of the things that I hate the most about 3D printing is that these machines are usually working in open loop and, sometimes, a tiny error happens that ruins a long print. Most 3D printers use one or more stepper motors to move each axis. Steppers are a good solution to the problem, they are easy to control and have lots of torque (compared to similar sized DC motors) but they may skip a step occasionally. The problem then is the print head is no longer where it is supposed to be but slightly off. From there on the print is misaligned and most likely will be useless.

Any type of motor can be equipped with an encoder to check its location at any time. However that adds an additional cost to the equipment and requires extra software to handle this new information.

One idea that has been mentioned many times in RepRap forums is that if steppers were replaced by DC motors with encoders that will allow the accurate position control that offer the steppers, the machines could be made more reliable and, perhaps, cheaper. However, it is difficult to beat the simplicity and elegance of a stepper-based bot and this idea has not gone further that some tests. (Actually, DC motors were used early on by RepRap machines and replaced by steppers for the extruder but only with an on-off control and not closed-loop).

Only recently, it seems a commercial manufacturer (that is not to be mentioned here) started using a closed-loop system for their extruder motor with the idea of providing a better output quality.

I was curious about this same idea, but given that steppers can be bought for $10 each and the driver electronics for a couple of bucks now, it was unclear whether a closed-loop around a DC motor with encoder could be built cheaply enough. After seeing an ad on Aliexpress I bought five DC motors with encoder to give the idea a go.

In order to control a [brushed] DC motor you need an H-bridge electronics and a micro-controller that will perform the control logic, including a PID control loop. Given that I was planning to replace steppers, the first test seemed to create such a system that could replace one stepper and do the test on a working 3D printer before going further.

Unfortunately, the motor driver I selected, a $1 L9110S off eBay, caught fire while trying to adjust the PID loop gain. This chip does not have a thermal shutdown circuit and the capacitor they put at the output will cause the chip to destroy itself if polarity is changed fast enough (as when your motor oscillates around the set point when you have an unstable control loop).  Next driver was $2 L298 and this one is working nicely with the small motor I use.


This motor I am using is likely not well suited for driving the axis of a 3D printer unless it is geared down a bit, but it is cheaper than a stepper and it includes the encoder (though I had to create a hood to cover it). The L298 is a dual H-bridge chip, so it could be used to control two motors. But my initial idea is to just have one motor per Arduino board, as this way I can use the two external interrupt pins, one for one of the encoder inputs and the other for the step input. The software is to be interfaced to a regular 3D printer controller by means of the STEP and DIR[ection] pins like a regular stepper driver.  For the moment I am not supporting the ENA[ble] pin but that would be easy to do if needed. The software includes a PID loop that tries the motor location to be always at the desired location (that will be changed by the action of the STEP and DIR pins above). Besides, the software is reporting the current location and target each second through the serial port. It also allows a new target location to be set through the serial port. Do not use any end of line marker for that, just the plain integer number of the new location.

I have created this software by merging several pieces found on the net, like the servostrap project, the Arduino PID and Autotune PID libraries (though I failed to make the latter work properly). 

Next step is to gear down the motor to use it on the x-axis of my Prusa i3. But that will take a still a while. Though I have found this other motor with a built-in driver and encoder that might be a better, higher-power motor.

Other people are using a faster processor to do the whole printer out of DC motors. It is amazing how cheap 32bits processors have become :-)

This is my first print using this contraption on the x-axis of my home Prusa i3:


I had to create this part for the mechanical attachment.