<
>
back to all cubes

Swing Cube

A remote swing. When the lever on one cube goes up, the lever on the other goes down

These cubes are gentle!

Left for the end of the project, we didn't have enough time to try different versions for the mechanical setup. Yair Reshef did a wonderful job, introducing us to the RF24 communication modules, which are perfect for this kind of scenario. The basic concept is simple: each cube's lever has a geared DC-motor and a potentiometer attached to it. This way, we get a closed-loop control (we always know what angle the lever is in, and can run the motor to bring it to the desired angle).

We started playing with a control method called PID (proportional, integral and derivative), which is known to be both accurate and relatively simple to implement. The problem was the mechanical design flaws: the levers touched the edges of their tracks, significantly changing the force needed to get them moving. The outcome was the levers moved around like drunks - not the desired behavior from these cubes.

In the end, we simplified the control by eliminating the integral and derivative part of the algorithm, and this got us the best results. The interesting part is the trick we used for making the connection between the two cubes: each cube's input is the other cubes potentiometer read! This closes the loop between the two cubes, and allows the user to control them both.

Arduino code - download here

/*
  CUBES originally created by the interaction Lab, Holon Institute of Technology for the Design Museum Holon.
  http://interaction.shenkar.ac.il
  This work is licensed under a Creative Commons Attribution 3.0 Unported License

  Swing Cubes by Yair Reshef
*/

// this is the main code of the sketch (swing.ino). There are other files in the ZIP that are needed in order to run the code.

// wirless connection
// based on Example RF Radio Ping Pair
// consider removing "delay(20)" at end of RX() and TX()

#include <SPI.h>
#include "src/nRF24L01.h"
#include "src/RF24.h"
#include "printf.h"


/////////////////// DEBUG ///////////////
#define DEBUG 0 //set to 0 to stop serial output

////////////////////////////////////////////
////////// RF24 ///////////////////////////
////////////////////////////////////////////

RF24 radio(8,9); // Set up nRF24L01 radio on SPI bus plus pins 8 & 9
const int role_pin = A3; // sets the role of this unit in hardware.  

// Topology
// Radio pipe addresses for the 2 nodes to communicate.
const uint64_t pipes[2] = { 
  0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };

#define role_ping_out 1
#define role_pong_back 0
// Role management
const char* role_friendly_name[] = { 
  "invalid", "Ping out", "Pong back"};// The debug-friendly names of those roles
int role;// The role of the current running sketch

int my_potVal, other_potVal; //var for analog pots

///////////////////////////////////////////////////////
////////////////////  Motor   /////////////////////////
///////////////////////////////////////////////////////
//pull this pin HIGH to turn the outputs on and LOW to turn them off
//using PWM on this puin will control speed
int dir1 =3; 
int dir2 =5;  
int potVal, dest,prevPotVal;
boolean newDest=true;

///////////// PID vars //////////////////////
#define pFactor 2.0
#define iFactor 0.0
#define dFactor 0.0 
#define MIN_GAIN 5

//#define pFactor 2.0
//#define iFactor 0.05
//#define dFactor -1.0

unsigned long microsKeep=0;
int tSpeed;
float gain;
float pGain;
float iGain = 0.0;
float dGain;
float error;
float pError = 0;
//////////////////////////////////////////////////
/////////////////////////////////////////////////


void setup(void)
{
  if (DEBUG)
    Serial.begin(57600);

  RF24_setup();

  //  motor setup
    TCCR0B = (TCCR0B&0xf8) | 0x01; //PWM FREQ removes whinning
    TCCR2B = (TCCR2B&0xf8) | 0x01; //PWM FREQ removes whinning
    pinMode(dir1, OUTPUT);
    pinMode(dir2, OUTPUT);

}

void loop(void)
{

  if (role == role_ping_out)   //master
  {
    TX(); 
    dest=other_potVal; //dest = slave position
    move (correct (role, dest));
  }

  if ( role == role_pong_back )//slave (role_pin A3 to ground)
  {
    if (RX()) { 
      dest=other_potVal; //dest = master position
      move (correct (role, dest));
    }
  }
  //move (dest);
}

Parts:

(1x) Arduino Mini Pro 5V

(1x) 10k Potentiometer

(1x) Mini Metal Gearmotor 24:1

(1x) SN754410 Quadruple Half-H Driver

(1x) 10k Resistor

(4x) (1x) 1N914 Fast Switching Diode

(1x) NRF24 Wireless Module

(1x) LD33V Voltage Regulator

(1x) 0.1 uF Capacitors

(1x) 10nF Capacitor

(1x) 7.2V Li-Po Battery

(1x) 5.5/2.1mm Jack Socket