Introduction: PlotClock, WeMos and Blynk Playing Vintage AMI Jukebox

Four technical innovations made this project possible: The 1977 Rowe AMI Jukebox, PlotClock robot arm kit, WeMos/ESP 8266 microcontroller and Blynk App/Cloud service.

NOTE: If you don’t have the Jukebox at hand – don’t stop reading! This project can easily be adopted to control various things controlled by human fingers. One example could be a robot finger playing traditional Xylophone – maybe that instructable comes from you!

My 40 years old Rowe AMI R-81 Jukebox is still working fine playing vintage vinyl singles from 60’s, 70’ and 80’s. Weighting over 160 kg (360 lbs) this player is not quite as portable as modern mp-players, but living at internet era, it is now possible to carry the jukebox and 200 vinyl records in your pocket – virtually of course! And you can even use your own playlists stored in the microcontroller!

Amazing PlotClock robot is originally designed to show current time by drawing time digits on the erasable board. My adaptation for PlotClock is to use it as a robot finger for pressing Jukebox song selection buttons.

The Plotclock ”finger” is driven by 3 servos controlled by WeMos microcontroller. This piece of wonder is (almost) Arduino Uno compatible and has WiFi capabilities, so it is possible to control the jukebox wirelessly from anywhere in the world.

The cream on the cake comes from the incredible easy to use Blynk App and their Blynk Cloud Server giving a nice mobile phone/tablet user interface with full mobility.

Step 1: Hardware

Jukebox

Project jukebox is 1977 Rowe AMI R-81. Any old jukebox with selection buttons will do – noting few limitations by PlotClock: PlotClock’s original arms design can cover an area about 5 x 12 cm so the jukebox button layout (area including all selection buttons) must be about that size. The buttons of older jukeboxes may need more pushing power than PlotClock servos can provide.

AMI R-81 has a memory where it can store all 200 selections. Selections are played based on the order they are stored in the record magazine (carousel type), not on the order they are selected. Multiple selections for one record are played only once.

PlotClock

Plotclock is commercially available DIY kit including mechanical parts, 3 servos, Arduino Uno R3, Arduino Extension board and USB cable. For around 30 USD this is a good buy (eg. Banggood.com). Arduino, extension board and USB cable are not used for this project.

There are several good internet/YouTube tutorials for composing the Plotclock – eg. this: PlotClock instructions

https://static1.squarespace.com/static/52cb189ee4b012ff9269fa8e/t/5526946be4b0ed8e0b3cd296/1428591723698/plotclock_final_instructions.pdf

WeMos

WeMos D1 R2 is ESP8266 based microcontroller. It can be programmed using Arduino IDE and has WiFi capabilities so it is a perfect piece of hardware for this project.

Step 2: Calibration

Calibration is the task for finding accurate angle values for servo angles (between 0 to 180 degrees) to correspond physical positions for selection buttons. Angle values can be found by trigonometry arithemitics or using a CAD software. I got approximate values from my friend who knew how to use of AutoCad.

However, the final calibration had to be made by trial and error. Using the button layout drawn on the piece of paper It is possible to do the ”desktop testing” to find the correct angle values.

Step 3: Assembly

Wiring

Connection from Plotclock servos to Wemos is done with 5 wires: +5, GND, D4, D5 and D6. See details in pictures and code.

Installing on the Jukebox

I didn't want to make any screw holes to the 40 years old jukebox that had so long survived without major damages. Using soft rubber sealant I fixed a piece of aluminium angle list under the jukebox console. Rubber sealant makes tight holding and can be removed without leaving any marks. PlotClock body needed two small aluminium angles to help fitting it on the acrylic plate. The acrylic plate is then fitted to the angle list with two spring loaded clips leaving possibility to make final adjustments vertically and horizontally.

Step 4: Blynk

Blynk is a free app for controlling several types of microcontrollers remotely. With Blynk you can easily build a nice user interface using several types of widgets. There is only one widget needed for this project: the Table widget.

Step 5: Software

Blynk App

There is no coding at the app side. The ”conversation” between the app (Blynk) and the microcontroller (WeMos) is handled by ”Virtual pins” which essentially are channels for sending and receiving information between those two. Virtual pin is for example used to send the row number of selected song from the Blynk app to WeMos, and Wemos handles the rest, ie. sending commands to the Plotclock servos.

WeMos code

/**************************************************************
Table widget at V2
**************************************************************/

#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <Servo.h>

char auth[] = "--YOUR AUTH CODE--";  //Jukebox project
char ssid[] = "--YOUR SSID--";
char pass[] = "--YOUR WIFI PASSWORD--";

int c[50];          //Array for Jukebox record positions (100-299)

Servo myservo1;     //lifting  
Servo myservo2;     //left arm
Servo myservo3;     //right arm

int pos1 = 0;
int pos2 = 0;
int pos3 = 0;
int btn=0;

void setup()
{ 
  myservo1.attach(2);  //  pin D4, lift
  myservo2.attach(14);  // pin D5, left
  myservo3.attach(12);  // pin D6, right

  myservo1.write(140);
  myservo2.write(90);
  myservo3.write(90);
  
  Serial.begin(115200);
    
  Blynk.begin(auth, ssid, pass);

  // Notify immediately on startup
  //String msg = "Jukebox WeMos connected to: ";
  //Blynk.notify(msg + ssid);

  //clear table at start
  Blynk.virtualWrite(V2, "clr");

  populateTable();
}

BLYNK_WRITE(V2)       //Receive commands from Table widget V2
{
   String cmd = param[0].asStr();  //param[0]="select" or "deselect", param[1]=row
   Serial.print("\nTable: BLYNK_WRITE(V2) cmd: ");
   Serial.print(cmd);
   
   int selection = c[param[1].asInt()];     //Selected row number is in param[1]
   Serial.println("\nSelection: ");
   Serial.println(selection);

   process_selection(selection);
}

void populateTable()
{
       int i = 0; 
       Serial.println("Populating table...") ;

       Blynk.virtualWrite(V2, "add", 0, "Be My Baby - The Supremes", 112);                c[i] = 112;
       Blynk.virtualWrite(V2, "add", 1, "Number One - Jerry Williams", 176);              i++; c[i] = 176;
       Blynk.virtualWrite(V2, "add", 2, "All My Loving - The Beatles", 184);              i++; c[i] = 184;
       Blynk.virtualWrite(V2, "add", 3, "In the Summertime - Mungo Jerry", 236);          i++; c[i] = 236;
       Blynk.virtualWrite(V2, "add", 4, "Black Cloud - Chubby Checker", 155);             i++; c[i] = 155;
       Blynk.virtualWrite(V2, "add", 5, "Mamy Blue - Pop-Tops", 260);                     i++; c[i] = 260;
       Blynk.virtualWrite(V2, "add", 6, "It's Gonna Be Alright - Gerry & Pacemakers", 145);   i++; c[i] = 145;
       Blynk.virtualWrite(V2, "add", 7, "My Way - Tom Jones", 193);                       i++; c[i] = 193;
       Blynk.virtualWrite(V2, "add", 8, "San Bernadino - Christie", 149);                 i++; c[i] = 149;
       Blynk.virtualWrite(V2, "add", 9, "The Twist - Chubby Checker", 169);               i++; c[i] = 169;</p><p>       delay(1000);
  }

void process_selection (int selection)
{
   //parse 3-digit selection (eg. 178) to 3 buttons:
   
   int btn1 = int(selection/100);   //first button
   Serial.println("\nBtn1: ");
   Serial.println(btn1);

   if (btn1 == 1 || btn1 == 2)  //first button must be 1 or 2 - otherwise do the reset
   {
   push_button(btn1);

   selection = selection - (btn1 * 100);
   int btn2 = int(selection/10);   //second button
   Serial.println("\nBtn2: ");
   Serial.println(btn2);
   push_button(btn2);

   selection = selection - (btn2 * 10);
   int btn3 = int(selection);      //third button
   Serial.println("\nBtn3: ");
   Serial.println(btn3);
   push_button(btn3);

   } else
   {
   push_button(11);                //reset button
   }

   //reset servo positions when all done
   delay(2000);
   myservo1.write(140);

   myservo2.write(90);
   myservo3.write(90);}

void push_button(int btn)

 {

    //this is called 3 times for each selection
    //actual button push is done after each button (find 'actual button push')

    switch (btn) {
      
    case 1:
      set_servo_angles (134, 136);     //1
      break;
      
    case 2:  
      set_servo_angles (128,110);     //2
      break;
      
    case 3: 
      set_servo_angles (112,88);  //3
      break;
      
    case 4:
      set_servo_angles (89,68);  //4
       break;
      
    case 5:
      set_servo_angles (62,55);  //5
      break;
      
    case 6:
      set_servo_angles (172,131);  //6
      break;
      
    case 7:
      set_servo_angles (163,106);  //7
      break;
      
    case 8:
      set_servo_angles (140,83);  //8
      break;
      
    case 9:
      set_servo_angles (104,58);  //9
      break;
      
    case 0:
      set_servo_angles (75,36);  //0
      break;
      
    case 11:
      set_servo_angles (36, 30);     //11
      break;
      
    } 

    //end switch

}

void set_servo_angles(int pos2, int pos3)
{
    myservo2.write(pos2);
    myservo3.write(pos3);

    //Servo positions ready - perform the actual button push:
    delay(500);
    myservo1.write(60);    //down 
    delay(500);
    myservo1.write(140);    //up
    delay(500);
}

void loop()
{
  Blynk.run();
}

Step 6: Future Steps

Video widget - live video & audio stream to Blynk App (already tested - working)

Webhook widget - playlist on-demand download from cloud (already tested - working)

Table widget - some small improvements to the widget are welcome (suggestions sent to Blynk developers)

Robotics Contest 2017

Participated in the
Robotics Contest 2017