Arduino

Learn to Control Servo Motors Using Sliders Through Arduino and Wekinator

November 28, 2018 by Reginald Watson
Share
banner

Enable an Arduino to control servo motors using sliders through the Wekinator software platform. 

Hardware

Software

1 Wekinator

This guide will detail how to control servo motors using programmed sliders in the Wekinator software platform. 

The sliders are used to send OSC messages to Wekinator. Which will then send the output data to the processing function and forward it on to an Arduino—that will control the servo motors. 

OSC (Open Sound Control), is basically a protocol that allows communication between computers and other multimedia devices. 

It's a simple yet powerful practice that's considered the successor of the MIDI (Musical Instrument Digital Interface) standard. It provides everything needed for real-time control of sound and media processing while remaining flexible and easily implemented.  

First Steps 

  1.  Download and install the JavaScript node.js file on the official website. 
  2. Install the socket.io file that will establish communication between a browser and other programs. Type the command below into the terminal to start the installation process. 

npm install socket.io

Instructions for the Browser 

To receive the OSC messages through a browser, we'll be using the node.js file because it isn't capable of receiving them. The messages will then be forwarded through the WebSocket protocol. 

You can find the code for the node.js file below. Then this code should be placed in a file with a .js extension such as socketio.js and within a folder. 

var http = require('http'),
    socketio = require('socket.io'),
    fs = require('fs'),
    osc = require('osc-min'),
    dgram = require('dgram'),
    remote_osc_ip;
 
var http_server = http.createServer(function(req, res) {
 
  fs.readFile(__dirname + '/socketio.html', function(err, data) {
 
    if(err) {
      res.writeHead(500);
      return res.end('Error loading socket.io.html');
    }
 
    res.writeHead(200);
    res.end(data);
 
  });
 
});
 
var io = socketio(http_server);
 
var udp_server = dgram.createSocket('udp4', function(msg, rinfo) {
 
  var osc_message;
  try {
    osc_message = osc.fromBuffer(msg);
  } catch(err) {
    return console.log('Could not decode OSC message');
  }
 
  if(osc_message.address != '/socketio') {
    return console.log('Invalid OSC address');
  }
 
  remote_osc_ip = rinfo.address;
 
  io.emit('osc', {
    x: parseFloat(osc_message.args[0].value) || 0,
    y: parseFloat(osc_message.args[1].value) || 0
  });
 
});
 
io.on('connection', function(socket) {
 
  socket.on('browser', function(data) {
 
    if(! remote_osc_ip) {
      return;
    }
 
    var osc_msg = osc.toBuffer({
      oscType: 'message',
      address: '/wek/inputs',
      args:[{ 
        type: 'float',
        value: parseFloat(data.x) || 0
      },
      {
        type: 'float',
        value: parseFloat(data.y) || 0
      }]
    });
 
    udp_server.send(osc_msg, 0, osc_msg.length, 6448, remote_osc_ip);
    console.log('Sent OSC message to %s:6448', remote_osc_ip);
 
  });
 
});
 
http_server.listen(8080);
console.log('Starting HTTP server on TCP port 8080');
udp_server.bind(9998);
console.log('Starting UDP server on UDP port 9998');

To run the socketio.js file, type the below command in the CMD directory. 

node socketio.js

Segment of code required to run socketio.js file.

Next, a webpage will need to be created in a web browser. 

The output of the node script should show that the HTTP server is listening on port 8080. 

This webpage will send an OSC message by pressing the button and display the output. The code that will need to be inserted into the webpage below. 

You'll want to save the code in an HTML file and name it 'socketio.html' then place it in the 'socket.io' folder. 

To open the page, you'll need to switch the IP address from http://x.x.x.x:8080. with your system's IP address. 

Webpage displaying sliders that are programmed to control servo motors. 

Processing Sketch

The processing sketch will receive the data from Wekinator and forward it onto the Arduino to control the servo motors. 

It will communicate with the Arduino serial and COM port. 

Note: The baud rate should be the same on both sides. 

Insert the code below to execute the data transfer from Wekinator to the Arduino. 

import vsync.*; // Importing the library that will help us in sending and receiving the values from the Arduino
import processing.serial.*;  // Importing the serial library

// Below libraries will connect and send, receive the values from wekinator
import oscP5.*;  
import netP5.*;

// Creating the instances
OscP5 oscP5;
NetAddress dest;
ValueSender sender;

// These variables will be synchronized with the Arduino and they should be same on the Arduino side.
public int output;
public int output1;
public int input = 2;

void setup() 
{
  // Starting the serial communication, the baud rate and the com port should be same as on the Arduino side.
  Serial serial = new Serial(this, "COM8", 9600);
  sender = new ValueSender(this, serial);
  
  // Synchronizing the variables as on the Arduino side. The order should be same.
  sender.observe("output");
  sender.observe("output1");
  
  // Starting the communication with wekinator. listen on port 12000, return messages on port 6448
  oscP5 = new OscP5(this, 12000); 
  dest = new NetAddress("127.0.0.1", 9998);
  sendOsc();
}


// Receive OSC messages from Wekinator
void oscEvent(OscMessage theOscMessage) {
  if (theOscMessage.checkAddrPattern("/wek/outputs") == true) {
    // Receiving the output from wekinator
    float value = theOscMessage.get(0).floatValue();  // First output
    float value1 = theOscMessage.get(1).floatValue();  // Second output
    
    // Converting the output to int type
      output = int(value);    
      output1 = int(value1);  
      println(output);
      println(output1);
  }
}

// Function to send OSC messages to browser
void sendOsc() {
  OscMessage msg = new OscMessage("/socketio");  // tell the address
  msg.add((float)input); // add the message
  msg.add((float)input); // add the message
  oscP5.send(msg, dest); //send the OSC message
}

void draw() 
{
  //  Nothing to be drawn for this example
}

Arduino Sketch

The Arduino sketch should receive the output data from processing and control the servos. 

The code required is provided below, however, before uploading the sketch, make that the processing function isn't running. Otherwise, it will come back with an error if it senses that the port is busy. 

#include <VSync.h>    // Including the library that will help us in receiving and sending the values from processing
#include <Servo.h>    // Including the servo library
ValueReceiver<2> receiver;  /*Creating the receiver that will receive up to 2 values. 
Put the number of values to synchronize in the brackets */

/* The below two variables will be synchronized in the processing 
and they should be same on both sides. */
int output;
int output1;

// Creating the instances
Servo myservo;
Servo myservo1;

void setup()
{
  /* Starting the serial communication because we are communicating with the 
  Arduino through serial. The baud rate should be same as on the processing side. */
  Serial.begin(9600);
  
  // Initializing the servo pins
  myservo.attach(8);
  myservo1.attach(9);
  
  // Synchronizing the variables with the processing. The variables must be int type.
  receiver.observe(output);
  receiver.observe(output1);
}

void loop()
{
 // Receiving the output from the processing.
  receiver.sync();
  
  // Check for the info we're looking for from Processing
  if (output < 180) {
    myservo.write(output);
  }

  if (output1 <180)
  {
    myservo1.write(output1);
  }
}

Wekinator Instructions

Wekinator will receive the data from the web browser at port 6448 and after analyzing it, send to processing at port 12000. 

Now, launch Wekinator and adjust the settings to the values below. Lastly, assign the output type to custom and select configure. 

The Create new project window in Wekinator platform.

Then, change the minimum and maximum values, assign the output type to the integer, and select done. 

The Customize Output Types window in Wekinator.

A new window will appear like the one below. 

The New Project window in Wekinator platform.

How to Run the Program

Input the socketio.js file through the cmd program for it to create a server that will help send data to the Wekinator. 

In your browser, enter your PC's IP address, followed by port 8080 and it will prompt the webpage to open. 

Now upload the code for the Arduino in the Arduino IDE, then change the baud rate and COM port in processing and upload the code. 

You can input some executions into Wekinator by moving the sliders on the webpage. 

After setting up the samples, click on the train button to run them. Wekinator will then send the data to processing and the servos can be controlled by adjusting the slider settings. 

Don't forget to check out our project video guide below as well!

Author

Avatar
Reginald Watson

I love challenging myself by creating new projects using different microcontrollers to see what I can come up with.