Fighting with computers

Computers are not always friendly.

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.


Tuesday, November 25, 2014

Loading TinyG2 in the Arduino DUE

I have been intrigued for a while with TinyG controller and their S-shaped speed
curves. It is an
evolution from simpler trapezoidal speed patterns used by GRBL software and by most 3D printer firmwares out there too.

However, TinyG (besides a South Korean music group) is not designed to work on a regular Arduino but over more powerful Atmel processors, the XMega series. While the software is open source, it does not help if you do not have the right processor. But lately I am giving a course where I have borrowed an Arduino DUE, which happens to be supported by TinyG project too.

Uploading the code has been a bit of challenge, partly due to my attempt of using a USB cable with broken data wires (I did not know that as I use it for charging my cellphone). But even with a good cable, the upload process, at least using OSX was a bit of a challenge. It all comes down to a not entirely cooked script from their github.

As I am not familiar with ARM development conventions, I see there is a binary file that I can download, but it is a .elf file. Apparently, the uploader program, bossac, cannot handle the .elf file for reasons I do not understand. It needs a binary file instead, and that can be obtained with an obscure command (at least for me): arm-none-eabi-objcopy -O binary tinyg.elf  tinyg.bin

Once I have got the binary file, I can upload the code happily with command bossac  -e -w -v -b tinyg.bin -R

However, the built-in script from the git, DueFromOSX.sh failed miserably on my computer.

As usual, my downloading of Arduino IDE that was required, 1.5.8 version, was not successful at first as the Java 7 version is apparently not the one that I have installed but Java 6. Nothing that could not be fixed downloading the right one. But I was surprised how tricky the process has been as a whole.

Unfortunately I have run out of time for testing the DUE with grbl shield on my ShapeOko to see if there is a big difference from its older brother GRBL. Maybe another future post.

Update

For Linux, I did not have much luck with the direct usage of bossac command, however I was puzzled at how Arduino IDE will work flawlessly in Linux while still it was using bossac. So I realized the culprit was the need of a previous setting the port to 1200 bps to reset the board and clear the memory, this is the command that worked for me to upload code to the Arduino DUE from Linux command line:
stty -F /dev/ttyACM0 1200; sleep 1;  bossac --port=ttyACM0 -U false -e -w -v -b TinyG2.bin -R

Thursday, November 13, 2014

Another one bitten by the bug

While I have been doing electronics since I was a kid I never owned an oscilloscope before. At a local meeting of Arduino users a colleague mentioned me there was a very good offer of a four channel sampling oscilloscope. Not that I need to use it very often but I was curious enough to see how instruments have evolved lately I decided it was about time to have my own scope so it was kind of a birthday gift I bought to myself (if that makes any sense).

First thing I have measured, just because it's right next to me is the the ringing of my 3D printer's hotend PID regulator output. It has been mentioned voltages can get pretty high over there in RAMPS boards and boy, that is true. At around a 50-volt spike is produced when the load is switched off. And the real value can only be appreciated if you freeze the sampled signal and expand widely the time axis, as the spike duration is below 1us. I guess total energy is so small the MOSFET is not really damaged (as it has been sitting there for three years now without stop working). Values in the order of micro Joules seems to be safe as the STB55NF06L is avalanche tested and the single pulse avalanche energy is 300mJ.

This second image shows the moment the heated bed of my printer is switched off. It shows how the highest peak is actually triggering the avalanche mode in the MOSFET (avalanche voltage is rated 60V).

Friday, October 10, 2014

VFD control with Arduino using RS485 link

Variable Frequency Drives (VFD) allow the control of spindles so speed can accurately be controlled and a detailed acceleration profile for the spindle and reverse rotation can all be handled. In essence a VFD is an three phase inverter for three-phase AC motor.

I am using a popular (I mean cheap) Chinese VFD and though the reference manual is not great, I could see there is a built-in RS-485 port. I usually control the start, stop and speed selection using the keyboard on the unit but I thought it will be more useful if I could control everything from the same Arduino is doing our CNC table control.

Some cheap RS-485 off eBay and some lines of code later, I can start, stop and change the speed from an Arduino. What a cool thing to have!




Some configuration of your VFD are needed before you can use it like that.  You need to set PD163=1 (I am using address 1 in the code). PD=164=1 (for setting serial to 9600bps) and PD165=0 (for using ASCII and 8N1 character format). On top of that, you need to set PD001=2 (for commands being provided through the communications port). 

Please note that doing that may interfere with your existing controls using external terminals, so be careful as that might make your emergency or external stop buttons to stop working. The built-in stop button still will stop the spindle but you need to power-cycle the VFD for accepting new start commands over the serial port.