Esteem Engine: A Maker Blog

This video demonstrates another breakthrough with the Garden Weeding Robot that allows the user to  wirelessly control the robot via a graphic interface. Here is the code used in both Arduino and Processing.

Arduino Code

#include <AFMotor.h>

AF_DCMotor motor1(1, MOTOR12_64KHZ); // create motor #2, 64KHz pwm
AF_DCMotor motor2(2, MOTOR12_64KHZ); // create motor #2, 64KHz pwm
AF_DCMotor motor3(3, MOTOR12_64KHZ); // create motor #2, 64KHz pwm
AF_DCMotor motor4(4, MOTOR12_64KHZ); // create motor #2, 64KHz pwm

char val; // variable to receive data from the serial port

void setup() {

  Serial.begin(9600);       // start serial communication at 9600bps

  motor1.setSpeed(100);     // set the speed to 100
  motor2.setSpeed(100);     // set the speed to 100
  motor3.setSpeed(100);     // set the speed to 100
  motor4.setSpeed(100);     // set the speed to 100
}

void loop() {

  if( Serial.available() )       // if data is available to read
  {
    val = Serial.read();         // read it and store it in ‘val’
  }

  if( val == ‘F’ )               // if ‘F’ was received, move robot forward
  {
    motor1.run(FORWARD);     
    motor2.run(FORWARD);     
    motor3.run(FORWARD);     
    motor4.run(FORWARD);   
  }

   if( val == ‘B’ )               // if ‘B’ was received, move robot backward
  {
    motor1.run(BACKWARD);     
    motor2.run(BACKWARD);     
    motor3.run(BACKWARD);     
    motor4.run(BACKWARD);   
  }



  if( val == ‘R’ )               // if ‘R’ was received, turn robot to the right
  {
    motor1.run(FORWARD);     
    motor2.run(BACKWARD);     
    motor3.run(BACKWARD);     
    motor4.run(FORWARD);   
  }

   if( val == ‘L’ )               // if ‘L’ was received, turn robot to the left
  {
    motor1.run(BACKWARD);     
    motor2.run(FORWARD);     
    motor3.run(FORWARD);     
    motor4.run(BACKWARD);   
  }


   if( val == ‘J’ )               // if ‘J’ was received, stop the robot
  {
    motor1.run(RELEASE);     
    motor2.run(RELEASE);     
    motor3.run(RELEASE);     
    motor4.run(RELEASE);   
  }


}

Here’s the code for Processing:


//import class to set up serial connection with wiring board
import processing.serial.*;

Serial port;

color currentcolor;

CircleButton circle1, circle2, circle3, circle4;
RectButton rect1, rect2;

boolean locked = false;

void setup()
{
  size(400, 400);
  smooth();

  color baseColor = color(102);
  currentcolor = baseColor;


  // List all the available serial ports in the output pane.
  // You will need to choose the port that the Wiring board is
  // connected to from this list. The first port in the list is
  // port #0 and the third port in the list is port #2.
  println(Serial.list());

  // Open the port that the Wiring board is connected to (in this case 1
  // which is the second open port in the array)
  // Make sure to open the port at the same speed Wiring is using (9600bps)
  port = new Serial(this, Serial.list()[0], 9600);

  // Define and create circle button
  color buttoncolor = color(204);
  color highlight = color(153);
  ellipseMode(CENTER);
  circle1 = new CircleButton(95, 110, 24, buttoncolor, highlight);

  // Define and create circle button
  buttoncolor = color(204);
  highlight = color(153);
  circle2 = new CircleButton(170, 110, 24, buttoncolor, highlight);

  // Define and create circle button
  buttoncolor = color(153);
  highlight = color(102);
  circle3 = new CircleButton(130, 150, 24, buttoncolor, highlight);

  // Define and create circle button
  buttoncolor = color(140);
  highlight = color(112);
  circle4 = new CircleButton(130, 75, 24, buttoncolor, highlight);

  // Define and create rectangle button
  buttoncolor = color(102);
  highlight = color(51);
  rect1 = new RectButton(113, 90, 40, buttoncolor, highlight);


}

void draw()
{
  background(162);
  stroke(255);
  update(mouseX, mouseY);
  circle1.display();
  circle2.display();
  circle3.display();
  circle4.display();
  rect1.display();

}

void update(int x, int y)
{
  if(locked == false) {
    circle1.update();
    circle2.update();
    circle3.update();
    circle4.update();
    rect1.update();
  }
  else {
    locked = false;
  }

  if(mousePressed) {
    if(circle1.pressed()) {
      currentcolor = circle1.basecolor;
      port.write(‘L’);
    }
    else if(circle2.pressed()) {
      currentcolor = circle2.basecolor;
      port.write(‘R’);
    }
    else if(circle3.pressed()) {
      currentcolor = circle3.basecolor;
      port.write(‘B’);
    }
    else if(circle4.pressed()) {
      currentcolor = circle3.basecolor;
      port.write(‘F’);
    } 
    else if(rect1.pressed()) {
      currentcolor = rect1.basecolor;
      port.write(‘J’);
    }

  }
}


class Button
{
  int x, y;
  int size;
  color basecolor, highlightcolor;
  color currentcolor;
  boolean over = false;
  boolean pressed = false;  

  void update()
  {
    if(over()) {
      currentcolor = highlightcolor;
    }
    else {
      currentcolor = basecolor;
    }
  }

  boolean pressed()
  {
    if(over) {
      locked = true;
      return true;
    }
    else {
      locked = false;
      return false;
    }   
  }

  boolean over()
  {
    return true;
  }

  boolean overRect(int x, int y, int width, int height)
  {
    if (mouseX >= x && mouseX <= x+width &&
      mouseY >= y && mouseY <= y+height) {
      return true;
    }
    else {
      return false;
    }
  }

  boolean overCircle(int x, int y, int diameter)
  {
    float disX = x - mouseX;
    float disY = y - mouseY;
    if(sqrt(sq(disX) + sq(disY)) < diameter/2 ) {
      return true;
    }
    else {
      return false;
    }
  }

}

class CircleButton extends Button
{
  CircleButton(int ix, int iy, int isize, color icolor, color ihighlight)
  {
    x = ix;
    y = iy;
    size = isize;
    basecolor = icolor;
    highlightcolor = ihighlight;
    currentcolor = basecolor;
  }

  boolean over()
  {
    if( overCircle(x, y, size) ) {
      over = true;
      return true;
    }
    else {
      over = false;
      return false;
    }
  }

  void display()
  {
    stroke(255);
    fill(currentcolor);
    ellipse(x, y, size, size);
  }
}

class RectButton extends Button
{
  RectButton(int ix, int iy, int isize, color icolor, color ihighlight)
  {
    x = ix;
    y = iy;
    size = isize;
    basecolor = icolor;
    highlightcolor = ihighlight;
    currentcolor = basecolor;
  }

  boolean over()
  {
    if( overRect(x, y, size, size) ) {
      over = true;
      return true;
    }
    else {
      over = false;
      return false;
    }
  }

  void display()
  {
    stroke(255);
    fill(currentcolor);
    rect(x, y, size, size);
  }
}


Both sets of code were pieced together from other examples, tutorials and a lot of trial and error….so there’s likely a more efficient way to write it. The next goal is to post the Processing graphic interface on a website and control the robot from any internet enabled computer in the world.  

Garden Weeding Robot Progress - Joystick Control

Happy to report a personal breakthrough of the Garden Weeding Robot.

image

In addition to successfully using an Xbee module to transmit wireless keystroke commands between a computer and the robot, I managed to replace the keystroke commands with more intuitive joystick movements. Using a Parrallax 2 axis joystick and a lot of trial and error, I managed to cobble together the following code that will translate forward movement of the joystick into forward movement of the robot:

#include <AFMotor.h>

int UD = 0;
int LR = 0;

AF_DCMotor motor1(1, MOTOR12_64KHZ); // create motor #2, 64KHz pwm
AF_DCMotor motor2(2, MOTOR12_64KHZ); // create motor #2, 64KHz pwm
AF_DCMotor motor3(3, MOTOR12_64KHZ); // create motor #2, 64KHz pwm
AF_DCMotor motor4(4, MOTOR12_64KHZ); // create motor #2, 64KHz pwm

const int threshold = 600;   // an arbitrary threshold level that’s in the range of the analog input

void setup() {
  Serial.begin(9600);           // set up Serial library at 9600 bps
  Serial.println(“Motor test!”);

  motor1.setSpeed(100);     // set the speed to 100
  motor2.setSpeed(100);     // set the speed to 100
  motor3.setSpeed(100);     // set the speed to 100
  motor4.setSpeed(100);     // set the speed to 100
}

void loop() {
  int UD = analogRead(A0);
  int LR = analogRead(A1);

 
  Serial.print(“UD = “);
  Serial.print(UD, DEC);
  Serial.print(“, LR = “);
  Serial.println(LR, DEC);  
  delay(200);

  {
  if (UD > threshold) {
     motor1.run(FORWARD);      // turn it on going forward
     motor2.run(FORWARD);      // turn it on going forward
     motor3.run(FORWARD);      // turn it on going forward
     motor4.run(FORWARD);      // turn it on going forward
  }
  else {
     motor1.run(RELEASE);      // turn off
     motor2.run(RELEASE);      // turn off
     motor3.run(RELEASE);      // turn off
     motor4.run(RELEASE);      // turn off

  }

  }

}


Given how popular the J-bot kit and 2 axis joystick are and how many youtube videos demonstrations of the two devices are out there, I was amazed to find little to no code documentation for these demonstrations…perhaps I’m not looking hard enough.

While my code is quite simple and doesn’t even include turning, reverse or multi-speed functions, it is very satisfying to be able to fuse a number of independent code function together in pursuit of a long term goal.

Next up is combining joystick control with wireless communiciation to create a remote control.

Some tangible progress on the On-Air light project

Earlier, I posted about the electronics overhaul of the old Ibanez artstar and have since managed to get everything working and back in the guitar. Attaching the input jack was relatively easy — the jack could be pulled into place by tying a washer to the end of some picture hanging wire and pulling the wire/jack up through its hole in the guitar.

The bridge tone pot (closest to the jack) was more tricky. I struggled to find a method of attaching the wire securely to the pot to pull through its hole. After several failed attempts with tying picture wire to the pot I finally settled on soldering the top of the pot knob and tying some brass wire around the solder. The other pots were close enough to the f-hole to do by hand.

Finally, the Gibson pickup selector was too short to peek through the hole on the Ibanez guitar. Luckily, the original selector was still functional and was relatively easy to swap out.

A while back, I started to document an attempt replace the electronics in my electric guitar (sans the pickups). Here are the latest photos before the insterting the pots, jack and pickup selector back into the guitar. Though technically successful, here are some lessons from project:

1. Worried I’d run out of wire from the ACME kit, I opted to use spare 18 gauge copper wire to solder the common ground wires between pots. I don’t know if the gauge was too large or the fact the wire was copper, but it took way too long to heat and solder. Even when it was soldered, the connections were weak and unreliable…hence the globs and globs of excess solder

2. the new pickup selector’s works but is currently inaccessible because the screw is too shallow to poke through the top to thread a nut. Hopefully, the old pickup selector is still functional and can be salvaged 

3. Being lazy about placing the new pots at the identical distance on the cardboard prototype as the their final position on the guitar likely resulted in extended time and frustration with threading the pots into their respective holes. I suspect if the time was taken to properly place the pots and measure the wire correctly, the re-threading would have gone much smoother and been easier on the components. 

These are the preliminary drawings for an automata sculpture that was inspired by the kinetic sculpture exhibit at the wonderful Visionary Arts Museum  in Baltimore, Maryland. If you’re not familiar with Automata, here is a good introduction.

The scene is the set of movie. Powered by a single hand-cranked axel, the following motion will take place:

1) a production assistant marking the shot with a slate and stepping out of the shot 

2) the actress fainting in the arms of her co-star

3) the director’s head dropping in disgust of their performance

4) all while the reels of the camera continue to roll. 

Problem: Roommates or co-workers leave dishes in sink for too long and no one remembers who is responsible for the mess
Solution: Dishwasher Cam - This motion activated camera sits near the sink and takes a photo of a person&#8217;s face as they leave dishes in the sink. The camera then rotates down to take photo of the dish itself. The two photos are then automatically emailed to all of the co-workers/roommates or displayed on a screen in a common area to shame people into cleaning up after themselves. It&#8217;s passive-aggressive as hell but hopefully it holds people to account.
I realize that this device is basically a glorified webcam but by sourcing the parts individually and write as much code from scratch as possible, I&#8217;m hoping to learn a lot about the interplay of the parts and the intricacies of the work-flow. 

Problem: Roommates or co-workers leave dishes in sink for too long and no one remembers who is responsible for the mess

Solution: Dishwasher Cam - This motion activated camera sits near the sink and takes a photo of a person’s face as they leave dishes in the sink. The camera then rotates down to take photo of the dish itself. The two photos are then automatically emailed to all of the co-workers/roommates or displayed on a screen in a common area to shame people into cleaning up after themselves. It’s passive-aggressive as hell but hopefully it holds people to account.

I realize that this device is basically a glorified webcam but by sourcing the parts individually and write as much code from scratch as possible, I’m hoping to learn a lot about the interplay of the parts and the intricacies of the work-flow. 

Here are some overly-detailed plans for an “On-Air” light system for our studio and conference rooms. Since the studio time has to be divided between multiple sessions occurring simultaneously in the Blue and Purple conference rooms, the “On-Air” lights should give the session leaders a clear signal when the studio is available for use.

To avoid invasive, expensive and potentially dangerous wiring within the building’s existing electrical framework, I’m hoping to be able to control the light via an arduino-powered switch box that trips a relay between the lights and a standard wall socket.  

Clifford (aka the big red guitar) has been steadily crapping out over the last few years. What was once the occassional pop and hiss has become more or less a permanent, insufferable buzz.

The input jack seemed to be the source of many of its problems. If I was lucky, the cable could be turned until buzzing stopped or at least minimized; though years of this twisting surely contributed to crimped wires and loosening of solder joints. The bridge pickup’s tone pot also caused significant cracking and buzzing if turned above “7” on the dial. In short, it was time for an electronics overall. 

The guitar model is an Ibanez Artstar; a Gibson ES-335 copy. Rather than try to source the replacement parts individually, I found a ES-335 re-wiring kit over at acmeguitarworks.com. Since my Artstar is a 335 copy, I assume this kit would be suitable.

It’s disappointing that Acme Guitar works didn’t have any readily available tutorials for re-wiring the guitar. All that was included was a wiring diagram.

planetz.com is really good resource of step-by-step video instruction for basic connections but his main video series on rewiring his hollow bodied guitar consists of thee humbucker pickups with dedicated volume pots and one tone pot between them…significantly different than one volume/tone pot per humbucker design of a 335 copy. 

There’s also scattered photo and video tutorials online but I’ve yet to find one for an ES-335 copy that is comprehensive and of decent production value. If you’re reading this and happen to know of one, please send it my way. 

This was the first foray into landscaping/woodworking I did a couple of years ago with my girlfriend. Though incredibly proud of how this project turned out, I soon realized that I was more interested in building the wall and the idea of having a garden rather than gardening itself. Hence, the Garden Weeding robot was born.