Augmented reality sandbox control box updated
January 28, 2018 19 Comments
I constructed a couple of these control boxes for my ARsandbox project using Arduino Micro and Adafruit Feather 32u4. The main goal is to make the interaction between a user and the software more intuitive. The two flashing buttons add and remove water from the simulation, which is pretty nice. I wanted to add another feature, to move the elevation up and down. Say you have a lot of sand in the box but you want to display some “water”. You have to remove a lot of sand (time consuming) from the box or edit a config file (near impossible for an average user). On the other hand, if I can change the base plane location in the calculation, I can achieve the above goal without removing sand or editing files. With help of the original developer Dr. Oliver Kreylos, I started messing with the source code. It took me a day to understand what I could do to change the base plane and how to do it. I ended up creating a tool to manipulate the plane. Now that the plane can be moved, I added a rotary encoder to the control box to emulate the keyboard keys assigned to move the plane. Voila!
The photo gallery above shows 5 shots of different elevation values. You can clearly see the “sea” on bottom right is shrinking after each turn of the knob.
Here is a short video. I was slowly raising the elevation so more and more land became above water. Then I quickly returned the land back into water:
Here is a photo of the inside of the box:
I added a breakout board for rotary encoder and buttons. It’s very tightly sandwiched between the two buttons. There is no space between the board and the buttons, not even a fraction of millimeter. I don’t know how these pieces just managed to fit. Here is the breakout board:
I made this a while ago as an interface for my phi-panels LCD backpacks. This breakout board is pretty simple. There are two encoder channels and one shaft button, plus six push buttons, which I am not using. I just connected to the encoder channels, shaft button, and the common. I had to cut off a strip on the right side of the board to fit into the box. I was using my phi_interfaces library to read the encoder and emulate a button push if the encoder is rotated one way, another button if the encoder is rotated the other way. I didn’t assign any function for the shaft button. I am thinking that I should use it to switch between elevation adjustment and water speed adjustment. If you want one, I have a few available, with rotary encoders (I don’t have knobs). Leave me a message. I’ll break off a strip of the board so it will fit in the same box I’m using. Otherwise, you can get it printed yourself if you know how to do that. Here is the design file in EAGLE CAD:
If you know how to design boards, you can easily I haven’t updated the Adafruit Feature 32u4 version but will probably design a new printed circuit board so assembling will be easier, and not involving cutting off part of a board. Some code in case anyone wants to replicate it.
[code language=”cpp” collapse=”true”]
/*
* Credit: Dr. John Liu
* Purpose: This sketch emulates keyboard keys "1" and "2" with two push buttons with LEDs. It also flashes the LEDs
* If a rotary encoder is present, it will emulate ‘5’ and ‘6’ if you rotate the encoder’s shaft. This combined with my modification on ARsandbox source code will shift color mapping up and down.
* This version uses p-channel mosfets and open drain with 10Kohm pull-up to 5V to control LEDs with the 3.3V Adafruit Feather32u4.
* Notes: On Adafruit Feather 32u4, pin 9 is connected to battery sensing voltage divider.
* 2018-01-28
* Visit http://liudr.wordpress.com for more information
*/
#include "Keyboard.h"
#include
#define USING_MICRO
#ifdef USING_MICRO
const int button_1=2; // 11 for Adafruit feather 32u4, 2 for Arduino Micro;
const int button_2=3; // 10 for Adafruit feather 32u4, 3 for Arduino Micro
const int EncoderChnA=7;
const int ChnCommon=8;
const int EncoderChnB=9;
const int ShaftBtn=10;
const int EncoderDetent=18;
#endif
#ifdef USING_FEATHER
const int button_1=11; // 11 for Adafruit feather 32u4, 2 for Arduino Micro;
const int button_2=10; // 10 for Adafruit feather 32u4, 3 for Arduino Micro
#endif
const int led_1=6;
const int led_2=5;
const unsigned long led_on_ms=300;
const unsigned long led_off_ms=1700;
const unsigned int button_1_key=’1′; //KEY_LEFT_ARROW;
const unsigned int button_2_key=’2′; //KEY_RIGHT_ARROW;
const unsigned int UpKeyOut=’5′;
const unsigned int DownKeyOut=’6′;
int prev_1=HIGH;
int prev_2=HIGH;
int led_stat=LOW;
unsigned long prev_1_ms=0;
unsigned long prev_2_ms=0;
unsigned long blink_timer_0_ms=0;
unsigned long blink_timer_1_ms=0;
int debounce_ms=25;
char mapping[]={‘U’,’D’}; // This is a rotary encoder so it returns U for up and D for down on the dial.
phi_rotary_encoders MyEncoder(mapping, EncoderChnA, EncoderChnB, EncoderDetent);
//multiple_button_input* dial1=&my_encoder1;
void setup()
{
// make pin 2 an input and turn on the
// pullup resistor so it goes high unless
// connected to ground:
pinMode(button_1, INPUT_PULLUP);
pinMode(button_2, INPUT_PULLUP);
pinMode(led_1,OUTPUT);
pinMode(led_2,OUTPUT);
pinMode(ChnCommon,OUTPUT);
digitalWrite(led_1,LOW);
digitalWrite(led_2,LOW);
digitalWrite(ChnCommon,LOW); // Using this pin as ground since some prototypes don’t have enough gnd pins.
Keyboard.begin();
blink_timer_0_ms=millis();
}
void loop()
{
unsigned char ch=MyEncoder.getKey(); // Rotary encoder emulates two buttons.
if (ch==mapping[0])
{
Keyboard.write(UpKeyOut);
}
else if (ch==mapping[1])
{
Keyboard.write(DownKeyOut);
}
switch (led_stat)
{
case LOW:
if (millis()-blink_timer_0_ms>led_on_ms)
{
blink_timer_0_ms=millis();
led_stat=HIGH;
pinMode(led_1,INPUT); // Open drain to let pull-up resistor pull drain to 5V.
pinMode(led_2,INPUT); // Open drain to let pull-up resistor pull drain to 5V.
}
break;
case HIGH:
if (millis()-blink_timer_0_ms>led_off_ms)
{
blink_timer_0_ms=millis();
led_stat=LOW;
pinMode(led_1,OUTPUT); // Pull drain to GND.
pinMode(led_2,OUTPUT); // Pull drain to GND
}
break;
}
if ((digitalRead(button_1) == HIGH)&&(prev_1==LOW))
{
if (millis()-prev_1_ms>debounce_ms)
{
prev_1_ms=millis();
Keyboard.release(button_1_key);
//Serial.println("1 released");
}
prev_1=HIGH;
}
if ((digitalRead(button_1) == LOW)&&(prev_1==HIGH))
{
if (millis()-prev_1_ms>debounce_ms)
{
prev_1_ms=millis();
Keyboard.press(button_1_key);
//Serial.println("1 pressed");
}
prev_1=LOW;
}
if ((digitalRead(button_2) == HIGH)&&(prev_2==LOW))
{
if (millis()-prev_2_ms>debounce_ms)
{
prev_2_ms=millis();
Keyboard.release(button_2_key);
//Serial.println("2 released");
}
prev_2=HIGH;
}
if ((digitalRead(button_2) == LOW)&&(prev_2==HIGH))
{
if (millis()-prev_2_ms>debounce_ms)
{
prev_2_ms=millis();
Keyboard.press(button_2_key);
//Serial.println("2 pressed");
}
prev_2=LOW;
}
}
[/code]
Here is the instruction of the software update:
Instruction
Here is the link to the two files you need for the update:
Without my button box, you can still use keyboards such as 5 and 6 to invoke the feature.