Augmented reality sandbox control box updated

This slideshow requires JavaScript.

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.

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.


/*
 * 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 https://liudr.wordpress.com for more information
 */
#include "Keyboard.h"
#include <phi_interfaces.h>
#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;
  }
}

5 Responses to Augmented reality sandbox control box updated

  1. Hi, great project! Excuse me, could you kindly point me to the code in the SARndbox code that changes the base level? I tried changing the distance in the BoxLayout.txt file but I didn’t see any change. I’d appreciate your help, thanks!

    • liudr says:

      Luis,
      I have not posted my code update yet. It’s been a while but I think I have all my steps written down somewhere. You need to know how to compile code in order to make this change. I’m not sure I can support all requests of how to compile code. Anyway, do you have a button box made out of arduino like the one I posted the details and code? Using computer keyboard is only good for tests. Once kids get a hold of the keyboard, you’ll be sorry you had the keyboard out. Sand will clog keys if they aren’t banging on them already. Pressing the escape will quit sandbox also.

      • mascorella says:

        Hey! I’ve been looking for the same thing.. I’m comfortable compiling the code and be happy to work through any issues. This would be fantastic! I have the various buttons built and some basic interactivity happening, but the ability to change the height would be awesome.

        Thanks!

      • liudr says:

        I need some time to gather my notes together. Will get back to you soon.

      • mascorella says:

        Than you – that’s brilliant!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: