Friday, January 31, 2014

Interrupt-based sketch for Adafruit coin acceptor

Some time ago I bought this coin acceptor. Programming it to accept 4 different types of coins is convoluted, but quite ingenious, and works exactly as the spec sheet indicates, without glitches. Surprising for such a complex task, considering that the user interface consists of 3 buttons and two 7-segment LED displays.
After setting it up, the mechanism identifies each coin type reliably, even providing user-friendly feedback (showing on the LED display the number of impulses sent over the COIN/white wire), very helpful for debugging.

Now onto actually using it. Adafruit's graciously provided the "Piggy bank" sample project,  including the Arduino sketch as well. The sketch however, counts the impulses simply in the loop() function. That may work fine in that particular setup, with just the coin acceptor (1 coin type nonetheless) and the LCD display. If you want to add more hardware (printer, buttons, bluetooth, SD card, LEDs etc), you need a smarter, hardware-independent, way to count the impulses from the coin acceptor. Naturally, that involves interrupts.

I present below a snapshot of my interrupt-based sketch, tested in a more complex hardware setup. The COIN wire is connected to D2, attached to interrupt INT0. Function coinISR() gets called for each impulse from the coin acceptor. A coin is recognized when a train of expected number of impulses is received in a sequence.


#define COIN_PIN 2

void setup()
{
  // Debugging output
  Serial.begin(9600);

  // set up the LCD's number of rows and columns:
  lcd.begin(16, 2);

  Serial.println("Ready...");
  
  pinMode(COIN_PIN, INPUT);
  attachInterrupt(0, coinISR, RISING);  // COIN wire connected to D2;
}


// total amount of money collected;
float money = 0.0;

// gets incremented by the ISR;
// gets reset when coin was recognized (after train of pulses ends);
volatile int pulses = 0;
volatile long timeLastPulse = 0;


// executed for every pulse;
void coinISR()
{
  pulses++;
  timeLastPulse = millis();
}


void loop()
{
  lcd.setCursor(0,0);
  lcd.print("Please put coins");
  lcd.setCursor(0,1);
  lcd.print("PAID $");
  lcd.print(money);

  long timeFromLastPulse = millis() - timeLastPulse;
  if (pulses > 0 && timeFromLastPulse > 200)
  {
    // sequence of pulses stopped; determine the coin type;
    if (pulses == 2)
    {
      Serial.println("Received dime (2 pulses)");
      money += .1;
    }
    else if (pulses == 5)
    {
      Serial.println("Received quarter (5 pulses)");
      money += .25;
    }
    else if (pulses == 10)
    {
      Serial.println("Received looney (10 pulses)");
      money += 1.0;
    }
    else if (pulses == 15)
    {
      Serial.println("Received tooney (15 pulses)");
      money += 2.0;
    }
    else
    {
      Serial.print("Unknown coin: ");
      Serial.print(pulses);
      Serial.println(" pulses");
    }

    pulses = 0;
  }
}


Wednesday, January 22, 2014

Geiger Counter remixed

One of the requirements I consider important when designing a device is the ability to repair it, in case it breaks down. This means that the device should be easy to dis-assemble into its components, ideally without using a soldering iron. To achieve this goal, I usually tend to use headers and sockets for connecting the boards between them. I also try to place the buttons/switches etc. directly on the board, eventually sticking out through holes in the panel, rather than using their panel-mount equivalents connected to the board with wires.

The main reason I called one of my latest device "ugly" in a recent post was because I could not meet this requirement (well, I did not design the whole thing either). Essentially, that particular Geiger counter is very difficult to fix. Accessing to the FTDI header to re-program the Arduino Mini is also challenging. If, for some reason, the LiPo charger breaks down, the replacement miniature board would require drilling, then trace-cutting, then some wires to be soldered to the traces. I would rather throw it away then go through the (still undocumented) exercise again.

Considering all of the above, I designed a Geiger counter board shaped and dimensioned as the original Arduino, so it can fit in the Arduino enclosure from Adafruit, together with the 16x2 LCD display. The schematic is based on BroHogan's DIYGeigerCounter, to which I added the LiPo charger (with USB miniB socket) and a toggle switch for power on/off.


It does not get much simpler than this. The Geiger counter board is screwed to the half case, together with the display. With the case closed, the "free-floating" Geiger tube and the LiPo battery are held in place pretty well without additional fasteners, just by being pressed against each other.


There are 2 LEDs soldered to the bottom side of the PCB: one indicates LiPo charging, the other is the radiation indicator. This being another reason the enclosure needs to be transparent or translucent (it's not only for showing off the simple yet elegant internals :).

The 3V3 LCD display is connected to the board with a pair of 6-wire ribbon cable which can be easily unplugged if necessary. Sketches are uploaded to the ATmega328 (SMD) through the 6-pin FTDI connector, from Arduino IDE (as a matter of fact, I uploaded the release 10.2 of the DIYGeigerCounter software by BroHogan).

There is enough room in the enclosure to fit a second SI-29 Geiger tube in parallel (electrically) with the existing one, for better sensitivity.
The counter works perfectly with the bigger SBM-20 tube as well, but it is a bit challenging to fit that inside without some compromises.

The bottom cover of the enclosure does not require any modification (e.g. filing, drilling); one opening is still used for the (now smaller) USB connector, the other (originally designed for the power jack) is re-purposed for the power toggle switch.


Note that the miniB USB connector is only used for charging the battery and not for uploading sketches or for USB serial communication.

It would be very nice if this stylish enclosure gets re-designed for the 128x64 OLED display.

Monday, January 13, 2014

Chumby Nixie clock

With my limited (read "non-existent") crafting resources (e.g. space, tools), the easiest way to enclose my Arduinix clock was by recycling my late Chumby's shell. Things almost magically fit together, with minimal thinking and work. I was able to cram inside the box a hand-wired Wiseduino with an Arduinix-remix shield and a 4-tube board.


The old Wiseduino would have come in handy if I had any left. I made one using the protoshield from Sparkfun, which also has a connector for the Bluetooth JY-MCU module. Beside the ATmega328, this pseudo-Wiseduino board includes a DS1307 with coin backup battery and a 7805 voltage regulator.

The tube board is attached with screws to an empty board that plugs in the Arduinix-remixed shield. (Note that one reason for "remixing" Arduinix was to re-arrange the parts sticking out, namely the mosfet and the capacitors, so that it allows another shield to be stacked on top.)


The clock has no user button (I glued the original snooze button on top, would have required extra work to re-use it), so the time is set through the bluetooth interface, similarly to my other Arduino Nixie clock.


The sketch (compiled with Arduino 1.0.4) is available here. Note that, unlike the original Arduinix sample sketch, the nixie-driving code is now using interrupts. This decouples the display logic from the clock functionality, also allowing for the addition of a buzzer alarm.

Friday, January 3, 2014

Custom enclosure for Wise Clock 4

John, aka broHogan, the creator of DIYGeigerKit, skillfully built a nice enclosure for his Wise Clock 4, a potential inspiration to others. From his email:

The case is made from Cocobolo (rosewood) from a slab I bought in Costa Rica. The splines are ebony. In about a year it will turn a nice deep red.


It's really not this brown,


more like this.
Buttons also cocobolo. Holes drilled in the ends go over pushbuttons.


The router jig used to cut the slots for the splines.


And this reminds me of a joke. How do you double the value of a Jugo car? You fill up the tank. Got it? :)

Thanks John, I really appreciate it.