SlaHuRa : Slappable Huggable Radio

slappable-huggable-radio.jpgdsc09973.jpg

slahura01-1.jpgslahura01-12.jpg

SlaHuRa or Slappable Huggable Radio is a FM and AM radio that uses an accelerometer (tilt sensor) to change volume and frequency. There are no buttons to press or dials to spin. Tilting the radio from side to side adjusts the frequency. Tilting it from front to back changes the volume.

dsc09978.jpgdsc09904.jpgdsc09898.jpg


SlaHuRa : Slappable Huggable Radio from che-wei wang on Vimeo.
SlaHuRa behaves or misbehaves depending on how you treat it. It likes to be hugged, but once in a while it will misbehave and go off onto a random frequency. To make it behave and again, just slap it to teach it to behave. Likewise, hugging SlaHuRa will promote good behaviour through positive reinforcement.

It “behaves” (stays on the chosen frequency) in direct proportion to how long you “hug” (or hold the radio). The longer you hug it, the longer it will behave. Once you place it back onto a flat surface, it begins to feel axious, and will eventually flip out. If it is behaving “badly” (on a random frequency) you can slap the radio to get it back onto the right frequency.

Version 01


SlaHuRa V01 from che-wei wang on Vimeo.

Version 02
img_0246.jpgimg_0247.jpgimg_0248.jpgimg_0249.jpg

The guts
internal-elev-01.jpg

Arduino Code


int minPulse = 500;
int maxPulse = 2500;
int pulse,pulseR;

long lastPulse = 0;
long resPulse = 0;
long lastAdj=0;
long lastVolAdj=0;
int refreshTime = 20; 

int freq=0;
int vol=0;

int x0, y0, z0; 

int xpos=625;//defalut set to 0 volume
int ypos=512;//default set to middle freq
int zpos=0;

int yposSet=0;

int setFreq;
long timer=0;
long hugTimer=0;
long badTimer=0;
long resTimer=0;
int randomBad=100;

boolean onFreq=false;
boolean freqMem=false;
boolean xTilt=false;
boolean yTilt=false;
boolean zTilt=false;

boolean shaking, tilting;
boolean badness=false;
boolean zero=false;

int hugs=35;

void setup() {
  pinMode(9,OUTPUT);
  pinMode(10,OUTPUT);
  pinMode(11,OUTPUT);
  beginSerial(9600); // Sets the baud rate to 9600
}

void loop() {
  //set zero on tilt sensor
  if(zero==false){
    delay(500);
    setZero();
  }

  int x=analogRead(0)-x0; //reads and represents acceleration X
  int y=analogRead(1)-y0; //reads and represents acceleration Y
  int z=analogRead(2)-z0; //reads and represents acceleration Z
  // int cap=analogRead(5); //capacitive

  // freq adjust
  if(badness==false && millis() - lastAdj >= 6 && millis()-resTimer>=2500.0){
    if (y>50&&y<150) ypos++;
    if (y<-50&&y>-150) ypos--;
    lastAdj=millis();
  }

  // volume adjust
  if(millis()-lastVolAdj>=6){
    if (x>50 && x < 150)  xpos--;
    if (x<-50 && x > -150)  xpos++;
    lastVolAdj=millis();
  }

  //set channel
  if( millis() - timer > 1000.0*(float)(hugs-1) && onFreq==false && badness==false){
    yposSet=ypos;//remember freq
    onFreq=true;
    //Serial.println("freq set");
  }

  //behave badly
  if (millis() - timer >1000.0*(float)hugs && millis()-badTimer>randomBad){
   ypos=ypos+random(-150,150);
    //ypos=random(50,1000);
    //Serial.println("badness");
    badness=true;
    onFreq=false;
    badTimer=millis();
    randomBad=random(300,750); //random timer from 100-1500
  }

  //slapped
  if(badness==true){
    if(y>200 || y<-200 || x>200 || x<-200 || z>200 || z<-200){
      //Serial.println("slapped");
      badness=false;
      ypos=yposSet;
      onFreq=false;
      hugs=10;
      resTimer=millis(); //so slapping doesn't affect reseting to set freq
    }
  }

  int thres=15;
  if(badness==false&& millis()-hugTimer>1000){
    if(x>thres || x<-thres || y>thres || y<-thres){
      hugs=hugs+1;
      timer=millis();
    }
    else{
      hugs=hugs-1;
    }
        hugTimer=millis();
    hugs=constrain(hugs,-1,35);
    //Serial.println(hugs);

  //Serial.print("x");
  //Serial.println(x);
  //Serial.print("y");
  //Serial.println(y);
  //Serial.print("z");
  //Serial.println(z);
  }

  xpos=constrain(xpos,0,1023);
  ypos=constrain(ypos,0,1023);

  vol = xpos*19/10+minPulse;    // convert the analog value
  freq = ypos*19/10+minPulse;    // convert the analog value

    //motor control
  if (millis() - lastPulse >= refreshTime) {
    digitalWrite(9, HIGH);   // Turn the motor on
    delayMicroseconds(vol);       // Length of the pulse sets the motor position
    digitalWrite(9, LOW);    // Turn the motor off
    digitalWrite(10, HIGH);   // Turn the motor on
    delayMicroseconds(freq);       // Length of the pulse sets the motor position
    digitalWrite(10, LOW);    // Turn the motor off
    lastPulse = millis();           // save the time of the last pulse
  }
}

//zero all tilt sensors
void setZero(){
  x0=analogRead(0);
  y0=analogRead(1);
  z0=analogRead(2);
  zero=true;
}