Walabot FX - Guitar Effect Control

by daveyclk in Circuits > Gadgets

3404 Views, 30 Favorites, 0 Comments

Walabot FX - Guitar Effect Control

IMG_6191.JPG

Control your favourite guitar effect using nothing but awesome guitar poses!

Things You Will Need!

Hardware Components

Walabot - Walabot https://walabot.com/store/us/products/walabot-pro...

Raspberry Pi - Raspberry Pi 3 Model B http://www.mcmelectronics.com/product/83-17300

Sunfounder LCD1602 https://www.amazon.co.uk/SunFounder-LCD1602-Displ...

SunFounder PCA9685 16 Channel 12 Bit PWM Servo Driver for Arduino and Raspberry Pi https://www.amazon.co.uk/d/5ia/SunFounder-PCA9685...

Servo (generic) No link

9V Battery Clip http://octopart.com/233-keystone-20415

4xAA battery holder https://www.adafruit.com/products/830

AA Batteries http://www.amazon.com/dp/B00451SSBI/?tag=octopart...

Jumper wires (generic) https://www.sparkfun.com/products/11026

DPDT Latching Action Foot Switch https://www.rapidonline.com/Catalogue/Product/78-...

Korg SDD3000-PDL https://www.rapidonline.com/Catalogue/Product/78-...


Software OSs, Apps and Online Services

Autodesk Fusion360 - https://www.autodesk.com/products/fusion-360/overv...

Blynk - http://www.blynk.cc/getting-started

Tools etc

3D Printer

Soldering Iron

Abstract

Walabot FX- Guitar Effect Control. Full Demo

What would it be like to control musical expression using nothing but the position of your guitar in 3D space? Well, let's protoype something and find out!

The Basic Idea

I wanted to be able to control 3 effect parameter in real time, I wanted to do this using how I positioned my guitar. So one thing was clear, I was going to need a few things.

  • A sensor that is able to see 3D space
  • Servos to turn the knobs
  • An LCD display
  • An I2C Servo driver
  • A Raspberry Pi
  • To learn Python

Walabot

Watch Walabot Show Off! - Walabot Wed

Want to see through walls? Sense objects in 3D space? Sense if you are breathing from across the room?
Well, you're in luck!

The Walabot is whole new way for sensing the space around you using low power radar.


This was going to be key to this project, i would be able to take the carteasan (X-Y-Z) coodinates of objects in 3D space, and map those to servo positions changing how a guitar effect sounds, in real time, without touching the pedal.

Win.

More information about the Walabot can be found here

Getting Started

IMG_5362.JPG

First things first, you will need a computer to drive the Walabot, for this project i'm using a Raspberry Pi 3 (here in refered to at RPi) due to the built in WiFi and general extra oomph

I bought a 16GB SD card with NOOBS preinstalled to keep things nice and simple, and opted to install Raspian as my Linux OS of choice

(if you are unfamiliar with how to install Raspian, please take a moment to have a little read of this)

OK, once you have got Raspian running on your RPi, there are a few configuration steps to take to get things ready for our project

Setting Up the Raspberry Pi - 1

Firstly make sure you are running the latest Kernel version and check for updates by opening a command shell and typing

sudo apt-get update
sudo apt-get dist-upgrade

(sudo is added to ensure you've got administrative privilages eg. stuff will work)

This may take a while to complete, so go and have a nice cup of tea.

Setting Up the Raspberry Pi - 2

You need to install the Walabot SDK for RPi. From your RPi web browser go to
https://www.walabot.com/gettingstarted and download the Raspberry Pi Installer Package.

From a command shell:

cd downloads
sudo dpkg -I walabotSDK_RasbPi.deb

Setting Up the Raspberry Pi - 3

We need to start configuring the RPi to use the i2c bus.
From a command shell:

sudo apt-get install python-smbus
sudo apt-get install i2c-tools

once this is done, you have to add the following to the modules file

From a command shell:

sudo nano /etc/modules

add these 2 strings on seperate lines:

i2c-dev 
i2c-bcm2708

Setting Up the Raspberry Pi - 4

The Walabot draws a fair bit of current, and we'll also use GPIO's to control stuff so we need to set these up

From a command shell:

sudo nano /boot/config.txt

add the following lines at the end of the file:

safe_mode_gpio=4
max_usb_current=1

The RPi is an excellent tool for makers, but it is limited in the current it can send to the Walabot. Hence why we're adding a 1Amp max current rather than the more standard 500mA

Python

Why Python? well, as it's super easy to code, fast to get running and there's loads of good python examples available! i'd never used it before and was soon up and running in no time.
Now the RPi is configured for what we want, the next step is to configure Python to have access to the Walabot API, LCD Servo interfaces

For the Walabot

From a command shell

Sudo pip install “/usr/share/walabot/python/WalabotAPI-1.0.21.zip”

For the Servo Interface

From a command shell

sudo apt-get install git build-essential python-dev
cd ~
git clone  https://github.com/adafruit/Adafruit_Python_PCA96...
cd Adafruit_Python_PCA9685
sudo python setup.py install

Why do we need to used a servo driver? Well, for an RPi a couple of reasons.


1. The current drawn by a servo can be very high, and that number gets larger the more servos you have (of course). If you're driving the servo directky from an RPi you run the risk of blowing it's power supply

2. Timings of the PWM (Pulse Width Modulation) that control the servos position are very important. As the RPi doesn't use a realtime OS (there may be interrupts and such) the timings a not accurate and can make the servos twitch nervously. A dedicated driver allows accurate control, but also allows for up to 16 servos to be added, so this is great for expansion.

For the LCD

Guitar_Effect_Enclosure_2017-Feb-27_07-04-02PM-000_NamedView.png

open your RPi web browser


https://www.sunfounder.com/learn/category/sensor-k...

download

https://github.com/daveyclk/SunFounder_SensorKit_...

From a command shell:

sudo mkdir /usr/share/sunfounder

Using the graphical explorer, copy the python folder out of the zip file into you new sunfounder folder

The LCD is used to prompt the user as to what exactly is going on. Showing the process of configuration through to the x, y and z values being mapped onto each servo

Blynk

IMG_5341.PNG
IMG_5343.PNG
IMG_5342.PNG

Blynk is a brilliant IoT service that allows you to create a custom app to control your stuff. It seemed like the perfect solution to give me remote control of the walabot to really dial in the settings...


One problem. Blynk is not currently supported on the Python platform, bugger. But fear not! i was able to find a nice little work around that allows remote control and remote parameter input! it is a little hacky

first step is to download the Blynk app from your favourite app store

Second, sign up for an account

Once that is done, open the app and start a new project, choosing Raspberry Pi 3 as the hardware.

The app will allocate you an access token (you will need this to put in your code)

Once you have done that. you will need to set up the app as shown in the images. This is how it will interface with the walabot.

Configuring the Blynk App

IMG_5344.PNG
IMG_5345.PNG
IMG_5346.PNG
IMG_5347.PNG
IMG_5348.PNG
IMG_5349.PNG
IMG_5352.PNG
IMG_5350.PNG
IMG_5351.PNG
IMG_5353.PNG
IMG_5354.PNG
IMG_5355.PNG

You Can Use This QR Code With the Blynk App to Clone My Project to Save You Time

img_5415_d8X1FKBuQO.jpg

OK Now that the app is all set up, we can configure Python and the RPi to talk to it over the internets. Magic

Running Blynk With the Raspberry Pi and Using the Blynk HTTPS for Python

Firstly, you need to install the Blynk HTTPS wrapper for Python


From a command shell:

sudo git clone  http://github.com/daveyclk/blynkapi.git
sudo pip install blynkapi

Secondly, you need to install the Blynk Service on the RPi

From a command shell:

git clone  http://github.com/daveyclk/blynkapi.git
cd blynk-library/linux
make clean all target=raspberry

to run the blynk service

sudo ./blynk --token=YourAuthToken

To ensure the Blynk Service runs on start up you need to modify the /etc/rc.local

by doing

sudo nano /etc/rc.local

add this at the end

./blynk-library/linux/blynk --token=my token &

(i have included a cope of my /etc/rc.local file in the code section for reference)

To test it's working simply type

sudo /etc/rc.local start

The Blynk Service should now be running

Autorunning the Script

Now that this is all set up and configured, and we have the python code ready. we can set things to auto run so we can ditch the keyboard and monitors


There are a few things to do

Create a new script file to run out Python Program

sudo nano guitareffect.sh

add these lines

#!/bin/sh
python /home/pi/GuitarEffectCLI.py

make sure to save it

Next we need to give the script permission to run by typing

Sudo chmod +x /home/pi/guitareffect.sh

And finally, we need to add this script to the /etc/rc.local file that we tinkered with earlier.

Sudo nano /etc/rc.local

Add

/home/pi/guitareffect.sh & 

be sure to include the "&" this allows the Python Script to run in the background

Right! That's all the configuration and software sorted, next it's time to wire up the hardware

The Hardware

Walabot guitar effects control proto1

First Breadboard prototype

Enclosure Design

Guitar_Effect_Enclosure_2017-Feb-27_07-03-52PM-000_CustomizedView3609695402.png
Guitar_Effect_Enclosure_2017-Feb-27_07-05-32PM-000_CustomizedView8453318724.png
Guitar_Effect_Enclosure_2017-Feb-27_07-06-46PM-000_CustomizedView23458523877.png
Guitar_Effect_Enclosure_2017-Feb-27_07-07-38PM-000_CustomizedView19743522460.png
Guitar_Effect_Enclosure_2017-Feb-27_07-09-30PM-000_CustomizedView15253226487.png

The enclosure was designed and rendered in the awesome Fusion360

Guts Shots

IMG_5363.JPG
IMG_5364.JPG
IMG_5365.JPG

Final Assembly Shots

IMG_6195.JPG
IMG_6205.JPG
IMG_5371.JPG
IMG_5376msml.jpg
IMG_6188.JPG
IMG_5376.JPG
IMG_5375.JPG
IMG_6219.JPG
IMG_6198.JPG

To Fix the Walabot to the Stand

IMG_6197.JPG

Use the self adhesive metal disk that comes with the walabot to fix it in place

Hardware STL Files for 3D Printing

Schematics for Wiring the Thing Up

Code

Use the attached Python script for your project

from __future__ import print_function
from sys import platform from os import system from blynkapi import Blynk import WalabotAPI import time import RPi.GPIO as GPIO

#set up GPIO using Board Numbering GPIO.setmode(GPIO.BOARD) GPIO.setup(18, GPIO.IN, pull_up_down = GPIO.PUD_UP)

#blynk auth token auth_token = "your_auth_token_here"

# Import the PCA9685 module for servo control. import Adafruit_PCA9685

#import LCD module from location from imp import load_source LCD1602 = load_source('LCD1602', '/usr/share/sunfounder/Python/LCD1602.py')

# Initialise the PCA9685 using the default address (0x40). pwm = Adafruit_PCA9685.PCA9685()

# blynk objects defaults = Blynk(auth_token, pin = "V9") start_button = Blynk(auth_token, pin = "V3") Rmax = Blynk(auth_token, pin = "V0") Rmin = Blynk(auth_token, pin = "V1") Rres = Blynk(auth_token, pin = "V2")

ThetaMax = Blynk(auth_token, pin = "V4") ThetaRes = Blynk(auth_token, pin = "V5")

PhiMax = Blynk(auth_token, pin = "V6") PhiRes = Blynk(auth_token, pin = "V7")

Threshold = Blynk(auth_token, pin = "V8")

ServoMin = Blynk(auth_token, pin = "V10") ServoMax = Blynk(auth_token, pin = "V11")

def LCDsetup(): LCD1602.init(0x27, 1) # init(slave address, background light)

def numMap(x, in_min, in_max, out_min, out_max): """ used for mapping the walabot readings to servo position """ return int((x- in_min) * (out_max - out_min) / (in_max - in_min) + out_min)

# use this for rounding up the raw data to the assigned value def myRound(x, base=2): return int(base * round(float(x)/base))

#extracts the number form the returned blynk string def numberExtract(val): val = str(val) return int(filter(str.isdigit, val))

# Set frequency to 60hz, good for servos. pwm.set_pwm_freq(60)

# Configure min and max servo pulse lengths defaults SERVO_MIN = 175 # Min pulse length out of 4096 SERVO_MAX = 575 # Max pulse length out of 4096

# walabot default values R_MAX = 60 R_MIN = 20 R_RES = 5

THETA_MAX = 20 THETA_RES = 5

PHI_MAX = 20 PHI_RES = 5

THRESHOLD = 1

# variables for blynk switching on = "[u'1']"

class Walabot:

def __init__(self): self.wlbt = WalabotAPI self.wlbt.Init() self.wlbt.SetSettingsFolder() self.isConnected = False self.isTargets = False

def blynkConfig(self): load_defaults = defaults.get_val() if str(load_defaults) == on: SERVO_MAX = ServoMax.get_val() SERVO_MAX = numberExtract(SERVO_MAX) print("Servo Max =", SERVO_MAX)

SERVO_MIN = ServoMin.get_val() SERVO_MIN = numberExtract(SERVO_MIN) print("Servo MIN =", SERVO_MIN) R_MAX = Rmax.get_val() R_MAX = numberExtract(R_MAX) print("R max =", R_MAX)

R_MIN = Rmin.get_val() R_MIN = numberExtract(R_MIN) print("R Min =", R_MIN)

R_RES = Rres.get_val() R_RES = numberExtract(R_RES) print("R Res =", R_RES)

THETA_MAX = ThetaMax.get_val() THETA_MAX = numberExtract(THETA_MAX) print("Theta Max =", THETA_MAX) THETA_RES = ThetaRes.get_val() THETA_RES = numberExtract(THETA_RES) print("Theta Res =", THETA_RES)

PHI_MAX = PhiMax.get_val() PHI_MAX = numberExtract(PHI_MAX) print("Phi Max =", PHI_MAX) PHI_RES = PhiRes.get_val() PHI_RES = numberExtract(PHI_RES) print("Phi Res =", PHI_RES)

THRESHOLD = Threshold.get_val() THRESHOLD = numberExtract(THRESHOLD) print("Threshold =", THRESHOLD)

else: # if nothing from blynk app, load defaults SERVO_MIN = 175 # Min pulse length out of 4096 SERVO_MAX = 575 # Max pulse length out of 4096

# walabot default values R_MAX = 60 R_MIN = 20 R_RES = 5

THETA_MAX = 20 THETA_RES = 5

PHI_MAX = 20 PHI_RES = 5

THRESHOLD = 1 def connect(self): try: self.wlbt.ConnectAny() self.isConnected = True self.wlbt.SetProfile(self.wlbt.PROF_SENSOR) #self.wlbt.SetDynamicImageFilter(self.wlbt.FILTER_TYPE_MTI) self.wlbt.SetDynamicImageFilter(self.wlbt.FILTER_TYPE_NONE) #self.wlbt.SetDynamicImageFilter(self.wlbt.FILTER_TYPE_DERIVATIVE) self.wlbt.SetArenaTheta(-THETA_MAX, THETA_MAX, THETA_RES) self.wlbt.SetArenaPhi(-PHI_MAX, PHI_MAX, PHI_RES) self.wlbt.SetArenaR(R_MIN, R_MAX, R_RES) self.wlbt.SetThreshold(THRESHOLD) except self.wlbt.WalabotError as err: if err.code != 19: # 'WALABOT_INSTRUMENT_NOT_FOUND' raise err

def start(self): self.wlbt.Start()

def calibrate(self): self.wlbt.StartCalibration()

def get_targets(self): self.wlbt.Trigger() return self.wlbt.GetSensorTargets()

def stop(self): self.wlbt.Stop()

def disconnect(self): self.wlbt.Disconnect()

def main(): flag = True check = "" LCDsetup() while flag: LCD1602.write(0, 0, 'Guitar ') LCD1602.write(0, 1, 'Effect Control') time.sleep(2) LCD1602.write(0, 0, 'Press Start to ') LCD1602.write(0, 1, 'begin ') time.sleep(2) if (str(check) == on): flag = False else: check = start_button.get_val() #check for blynk start button press if (GPIO.input(18) == 0): #check footswitch flag = False

LCD1602.write(0, 0, "OK! let's Do it ") LCD1602.write(0, 1, ' ') wlbt = Walabot() wlbt.blynkConfig() wlbt.connect() LCD1602.clear() if not wlbt.isConnected: LCD1602.write(0, 0, 'Not Connected ') else: LCD1602.write(0, 0, 'Connected ') time.sleep(2) wlbt.start() wlbt.calibrate() LCD1602.write(0, 0, 'Calibrating.....') time.sleep(3) LCD1602.write(0, 0, 'Starting Walabot')

appcheck = start_button.app_status() flag = True # reset flag for main prog

while flag: # used to put effect in standby (effectively) if (appcheck == True): if (str(check) != on): if (GPIO.input(18) != 0): #check footswitch flag = False else: check = start_button.get_val() #check for start button press appcheck = start_button.app_status()

else: if (GPIO.input(18) != 0): #check footswitch flag = False

xval = 0 yval = 0 zval = 0 average = 2 delayTime = 0

targets = wlbt.get_targets()

if len(targets) > 0: for j in range(average):

targets = wlbt.get_targets() if len(targets) > 0: print(len(targets)) targets = targets[0]

print(str(targets.xPosCm)) xval += int(targets.xPosCm) yval += int(targets.yPosCm) zval += int(targets.zPosCm) time.sleep(delayTime) else: print("no targets") xval = xval/average

xval = numMap(xval, -60, 60, SERVO_MIN, SERVO_MAX) xval = myRound(xval) if xval < SERVO_MIN: # protect the servo xval = SERVO_MIN if xval > SERVO_MAX: xval = SERVO_MAX LCD1602.write(0, 0, 'x=' + str(xval) + ' ') pwm.set_pwm(0, 0, xval)

yval = yval/average

yval = numMap(yval, -60, 60, SERVO_MIN, SERVO_MAX) yval = myRound(yval) if yval < SERVO_MIN: # protect the servo yval = SERVO_MIN if yval > SERVO_MAX: yval = SERVO_MAX LCD1602.write(0, 1, 'y=' + str(yval)) pwm.set_pwm(1, 0, yval)

zval = zval/average

zval = numMap(zval, R_MIN, R_MAX, SERVO_MIN, SERVO_MAX) zval = myRound(zval) if zval < SERVO_MIN: # protect the servo zval = SERVO_MIN if zval > SERVO_MAX: zval = SERVO_MAX LCD1602.write(8, 1, 'z=' + str(zval)) pwm.set_pwm(2, 0, zval)

else: print("no targets") LCD1602.write(0, 0, "Shutting Down ") LCD1602.write(0, 1, 'The Walabot ') time.sleep(3) wlbt.stop() wlbt.disconnect()

if __name__ == '__main__': while True: main()

for the guitareffect.sh

#!/bin/sh
cd /home/pi

sudo python GuitarEffectCLI.py


A copy of the RC local file for reference

#!/bin/sh -e
# # rc.local # # This script is executed at the end of each multiuser runlevel. # Make sure that the script will "exit 0" on success or any other # value on error. # # In order to enable or disable this script just change the execution # bits. # # By default this script does nothing.

# Print the IP address _IP=$(hostname -I) || true if [ "$_IP" ]; then printf "My IP address is %s\n" "$_IP" fi

./blynk-library/linux/blynk --token="you token goes here" & sleep 10 sudo /home/pi/guitareffect.sh & exit 0


Downloads

Github Repositories to Use

Use this for the Sunfounder LCD

https://github.com/daveyclk/SunFounder_SensorKit_f...

Use this for the servo driver

https://github.com/daveyclk/Adafruit_Python_PCA968...

Use this for the Blynk Python HTTPS Wrapper

https://github.com/daveyclk/blynkapi


Conclusion

Walabot FX- Guitar Effect Control. Full Demo
IMG_6183.JPG
IMG_6177.JPG
IMG_6207.JPG
IMG_6215.JPG
IMG_6196.JPG

Well this has been a steep learning curve, but has been so worth it.


My take aways are

  • I had to learn Python..turns out it's ace
  • Interfaced the Python on the Raspberry Pi with the Blynk IoT service. This is not officially supported so there is some limits to it's functions. Still works great though!
  • It turns out the Walabot is great for musical expression. I used it on a Korg SDD3000, but you can use any effect you like

Have a go yourself. This isn't limited to guitar effects, i can be used with any instrument with any effect.