MiniPOV Mercury switch sensor firmware for waving

by corwin on Fri Sep 12, 2008 1:53 pm

Hello!

I looked all over the internet and couldn't find the code for a MiniPOV ATtiny2313 firmware which would allow text to always read FORWARDS when waving the miniPOV. A simple mercury switch ($2 at RadioShack, JayCar etc.) attached to the Sensor port (Pin 6) and GND, and oriented in the direction of waving, allows the miniPOV to detect direction and reverse the image on the reverse stroke. Here is my source code, modified from the original largeimage.c file.

Test it out! Either add "mercury.hex" lines in your miniPOV makefile, or just copy the contents above straight into an existing file :)

Have fun! Comments and suggestions welcome :)



Code: Select all | TOGGLE FULL SIZE
// mercury.c 13.08.2008 by Corwin Willys
// for LadyAda MiniPOV
//
// Modified version of largeimage.c to utilise a
// simple mercury switch to make the displayed
// text constantly FORWARD in two dimensions regardless
// of wave direction - no more backward text
// on the reverse swing wave!
//
// SETUP
// - Install a mercury switch on Sensor / Pin6 to GND
// - Line up mercury switch with the swing direction of your MiniPOV
// - Install this firmware and test:
// - If text is always backwards, adjust SETUP setting further down in
//   this file!!


#include <avr/io.h>      // this contains all the IO port definitions
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/pgmspace.h>
#include <util/delay.h>

void delay_ms( uint16_t milliseconds)
{
   for( ; milliseconds > 0; milliseconds--)
   {
      _delay_ms( 1);
   }
}

#define TIMER1_PRESCALE_1 1
#define TIMER1_PRESCALE_8 2
#define TIMER1_PRESCALE_64 3
#define TIMER1_PRESCALE_256 4
#define TIMER1_PRESCALE_1024 5


// We use these macros because binary constants arent always supported. ugh.
#define HEX__(n) 0x##n##UL
#define B8__(x) ((x&0x0000000FLU)?1:0)  \
               +((x&0x000000F0LU)?2:0)  \
               +((x&0x00000F00LU)?4:0)  \
               +((x&0x0000F000LU)?8:0)  \
               +((x&0x000F0000LU)?16:0) \
               +((x&0x00F00000LU)?32:0) \
               +((x&0x0F000000LU)?64:0) \
               +((x&0xF0000000LU)?128:0)
#define B8(d) ((unsigned char)B8__(HEX__(d)))


// store all the image data in program memory (ROM)
// instead of RAM (the default)


// START OF IMAGE DATA

const uint8_t large_image[] PROGMEM = {

B8(00000000),
B8(00000000),
B8(00000000),
B8(00000000),
B8(00000000),
B8(01111100),
B8(10000010),
B8(10000010),
B8(10000010),
B8(01000110),
B8(00000000),
B8(00000000),
B8(01110000),
B8(10001000),
B8(10001000),
B8(10001000),
B8(01110000),
B8(00000000),
B8(00000000),
B8(10001000),
B8(11111000),
B8(10010000),
B8(10001000),
B8(00001000),
B8(00000000),
B8(00001000),
B8(01111000),
B8(10001000),
B8(01100000),
B8(10001000),
B8(01111000),
B8(00001000),
B8(00000000),
B8(10001000),
B8(10001000),
B8(11111010),
B8(10000000),
B8(10000000),
B8(00000000),
B8(10001000),
B8(11111000),
B8(10010000),
B8(00001000),
B8(10001000),
B8(11110000),
B8(10000000),
B8(00000000),
B8(00000000),
B8(00000000),
B8(00000000),
B8(00000000),
B8(00000000),


};

// END OF IMAGE DATA


// special pointer for reading from ROM memory
PGM_P largeimage_p PROGMEM = large_image;

#define NUM_ELEM(x) (sizeof (x) / sizeof (*(x)))
int imagesize = NUM_ELEM(large_image);



// this function is called when timer1 compare matches OCR1A
uint8_t j = 0;
int k = 0;
SIGNAL( SIG_TIMER1_COMPA ) {
  if (j >= imagesize)
  {
      if  (bit_is_clear(PIND, 2))  // going one direction
         k = 0;
      else
         k = 1;                   // going in the other direction
      
   j = 0;
   }


  // read the image data from ROM
  if (k >= 1)               // if k=1 then the switch is either open or not present
 
 
  //                --------SETUP---------
  //
  // Just swap the two PORTB lines below depending on how
  // the PCB mercury switch is mounted - you should aim to get
  // all text forwards and not all backwards
 
 
   PORTB = pgm_read_byte(largeimage_p + imagesize - j - 1);   // reversing the image
 
  else                     // if k=0 the switch is present and closed to ground
 
   PORTB = pgm_read_byte(largeimage_p + j);            // normal direction
 
 
  j++;
}

int main(void) {

  DDRB = 0xFF;                  // set all 8 pins on port B to outputs
  DDRD = 0xFB;                  // one input on pin D2, this pin reads Corwins Mercury
  PORTD = 0x04;                 // turn on pullup on pin D2

  /*
    the frequency of the interrupt overflow is determined by the
    prescaler and overflow value.
    freq = clock_frequency / ( 2 * prescaler * overflow_val)
    where prescaler can be 1, 8, 64, 256, or 1024
    clock_freq is 8MHz
    and overflow_val is 16bit

    the overflow value is placed in OCR1A, the prescale is set in TCCR1B
    so for example:
    A good POV frequency is around 400Hz
    desired freq = 400Hz
    clock freq = 8MHz
    8MHz / (400Hz * 2) = 10000
    since 10000 is less than 655536 (largest 16 bit number)
    OCR1A = 10000 and the prescale is 1
  */


  TCCR1B = (1 << WGM12) | TIMER1_PRESCALE_1;
  OCR1A = (uint16_t)10000;  //MODIFIED BY CORWIN TO UP SPEED AFTER MERCURY CHANGES

  TIMSK |= 1 << OCIE1A;   // Output Compare Interrupt Enable (timer 1, OCR1A)

  sei();                 // Set Enable Interrupts

  while (1);
}


Enjoy.
Last edited by corwin on Sat Sep 13, 2008 3:48 am, edited 1 time in total.
corwin
 
Posts: 7
Joined: Fri Sep 12, 2008 1:30 pm

by magician13134 on Fri Sep 12, 2008 9:20 pm

Does Radioshack really sell mercury switches? Anyway, great work, this is neat, can't wait to try it out
User avatar
magician13134
 
Posts: 1119
Joined: Wed Jun 13, 2007 8:17 am
Location: Ann Arbor

by adafruit on Sat Sep 13, 2008 1:17 am

did you get it to work? i found that 'tilt ball' switches bounced a bit too much
User avatar
adafruit
 
Posts: 11638
Joined: Thu Apr 06, 2006 3:21 pm
Location: nyc

by The_Don125 on Sat Sep 13, 2008 2:05 am

I do wonder if an accelerometer such as this one would work:
http://www.sparkfun.com/commerce/produc ... cts_id=252

Since it outputs analog, and runs off of 3.3V, it would work well. I'm thinking all that would need to be done is to tie either the x or y direction to the sensor line. Looks like it will output 0V if going in one direction, and 3.3V in the other, which would let it behave as a sensor.

edit:
Thought about it some more, and realized this wouldn't work. You'd only be accelerating for probably the first half to 2/3 of the swing, then decelerating for the rest. The sensor would pick up the deceleration and switch the text halfway through the swing, so not a good idea.

Though now another thought hits me, if you know it will only be used for handheld purposes, you can time it so that it waits a few milliseconds after sensing before switching text direction, and then hope that the switch occurs in the time when the POV is moving too slow for the effect to work at either end of the swing.

Of course, all of this is made impractical by the fact that the linked sensor costs more than the minipov itself.
The_Don125
 
Posts: 373
Joined: Tue Mar 06, 2007 10:51 pm
Location: Illinois

by corwin on Sat Sep 13, 2008 4:08 am

ladyada wrote:did you get it to work? i found that 'tilt ball' switches bounced a bit too much

The mercury switch works excellent! For hand wave speeds anyway. The conductive liquid is very "heavy" and viscous so it doesn't bounce. Just a small fix needed to the code above (now edited), changed the backwards display code: PORTB = pgm_read_byte(largeimage_p + imagesize - j - 1);

The_Don125 wrote:Thought about it some more, and realized this wouldn't work. You'd only be accelerating for probably the first half to 2/3 of the swing, then decelerating for the rest. The sensor would pick up the deceleration and switch the text halfway through the swing, so not a good idea.

This is not actually a problem at all. See my code above, it checks direction only between cycles and then runs through a whole image - doesn't switch the text halfway through the swing :)

Though the accelerometer could be great cause you could get the text to be stationary as well! With my cheapo mercury switch, I need to get a regular swing rhythm , otherwise the text seems to "scroll" back and forth.

However looking at the hall effect code by another poster, it takes some time to sync up properly, so maybe a hand swing accelerometer would be overkill. This $2 solution is awesome enough for me.

Link for photo of my mercury switch: http://www.jaycar.com.au/productView.asp?ID=SM1035
corwin
 
Posts: 7
Joined: Fri Sep 12, 2008 1:30 pm

by wiregr on Mon Sep 22, 2008 3:34 pm

Wow, great job! I was just looking for a way to do this exact thing, and your solution seems a lot simpler than what I was planning to try :D

My plan was to use an accelerometer, but I didn't want to have to add too much extra circuitry. Since the accelerometer outputs 1.5v at rest, and more/less depending on the axis of movement I was planning to try and use the analog comparator on the ATtiny to detect which direction it was moving in. I could see this being a pain though, because I would have to move some of the LEDs to another port complicating things a bit.

My ultimate goal is to make a pair of gloves with the LEDs in the palm and the circuitry on the back. Of course it figures that I didn't check the forums until after I already ordered my parts, but oh well :) It gives me an excuse to play around with some new toys.
wiregr
 
Posts: 3
Joined: Mon Sep 22, 2008 12:52 pm
Location: Reno, NV

Re: MiniPOV Mercury switch sensor firmware for waving

by corwin on Thu Oct 09, 2008 10:45 am

Good luck with your accelerometer project! Let us know how it goes. I think your planned solution will still be better, as you should be able to use the comparator to judge speed as well (not just direction), possibly avoiding the stretch/shrink effect when waving at different speeds when your arms get tired :)
corwin
 
Posts: 7
Joined: Fri Sep 12, 2008 1:30 pm

Re: MiniPOV Mercury switch sensor firmware for waving

by wiregr on Thu Oct 09, 2008 1:29 pm

The more I think about it, I would probably have to switch over to another microcontroller that has an ADC if I really wanted to take full advantage of the accelerometer. The analog comparator method would only let me know if the voltage was greater/less than the reference, so in effect I think it would just be a very expensive mercury switch :)

I did end up building a hand mounted minipov using the mercury switch and your code and it worked great! Thanks again for posting everything!
wiregr
 
Posts: 3
Joined: Mon Sep 22, 2008 12:52 pm
Location: Reno, NV

Re: MiniPOV Mercury switch sensor firmware for waving

by sparr on Thu Dec 25, 2008 4:06 am

Thanks for the inspiration. I couldn't easily find a mercury switch, so I ended up with some enclosed ball tilt switches, but they are un-bouncy enough that it works ok as long as I am very abrupt at the end of the swing. I ended up modifying my font-based code instead of the original firmware. Instead of changing direction only at the end of the word, I change j++ to increment/decrement depending on the switch, so it changes mid-letter, this seems more fluid to me.
sparr
 
Posts: 196
Joined: Tue Nov 04, 2008 4:21 pm

Re: MiniPOV Mercury switch sensor firmware for waving

by corwin on Fri Jan 09, 2009 2:26 am

It would be good to see a photo (or video?) of how it looks changing mid-letter..... I'm having trouble picturing it in my mind. And yes personally I use a font-based code as well to allow easier image modification (but the one posted is simpler to understand).

Any photography people with tips on how to take a good shot of these things? :)

Cheers!

Corwin
corwin
 
Posts: 7
Joined: Fri Sep 12, 2008 1:30 pm

Re: MiniPOV Mercury switch sensor firmware for waving

by Seamus on Fri Jan 09, 2009 2:46 am

corwin wrote:Any photography people with tips on how to take a good shot of these things? :)

I'm not a photography person, it isn't the greatest photo, and it isn't even a "real" MiniPOV, but...

Image

This was a learning project with the Arduino, and I only have so much room in front of my mirror, so this was the easiest way to see what it looked like.

I set my camera (Panasonic FZ-7) up on a tripod, with a 1-second exposure, and a 10-second timer. I focused on the spot where I would be standing, made sure the unit was running, then hit the shutter, walked over to where I had the camera pointing, and got ready. Ten seconds later, as the shutter opened, I waved it once across my body at a moderate speed and stopped at the end of the arc.

Yes, it took several tries to get the exposure and scan speed right, and even then I didn't get it pointing right at the camera, as you can see the elevation in my arc. It would have been a lot faster and easier if I'd had someone else operating the camera, but I eventually got something acceptable.
I make things.
Sometimes I break things too.
...because variety is good.
User avatar
Seamus
 
Posts: 40
Joined: Sun Nov 23, 2008 1:18 am
Location: Upstate SC

Re: MiniPOV Mercury switch sensor firmware for waving

by pomprocker on Sat Feb 21, 2009 9:12 pm

Where can I find this mercury tilt switch in the US? Radio Shack doesn't have them, and I can't find it on mouser.

EDIT:

Would any of these from my local electronics place work?

http://www.action-electronics.com/switches.htm#Mercury
pomprocker
 
Posts: 44
Joined: Wed Dec 17, 2008 11:29 pm
Location: Mission Viejo, CA

Re: MiniPOV Mercury switch sensor firmware for waving

by wiregr on Tue Feb 24, 2009 8:30 pm

Either one of the switches at the site you posted should work just fine. I used that same kind of mercury switch in my minipov, and it worked like a charm.
wiregr
 
Posts: 3
Joined: Mon Sep 22, 2008 12:52 pm
Location: Reno, NV

Re: MiniPOV Mercury switch sensor firmware for waving

by corwin on Wed Apr 01, 2009 10:29 am

Yep that is the type of mercury switch you need. Just line up it's long axis with the direction of your waving, use the firmware above, and you're good to go. You can add code for font-based string setting if you want, makes it easier to change the text by hand :)
corwin
 
Posts: 7
Joined: Fri Sep 12, 2008 1:30 pm

Re: MiniPOV Mercury switch sensor firmware for waving

by pomprocker on Sun Apr 05, 2009 12:36 am

I noticed neither mouser or digikey sells the mercury switch. Is there a reason for this? is it because it is not ROHS compliant?
pomprocker
 
Posts: 44
Joined: Wed Dec 17, 2008 11:29 pm
Location: Mission Viejo, CA