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.