Introduction: Walabot FX - Guitar Effect Control
Control your favourite guitar effect using nothing but awesome guitar poses!
Step 1: 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
Step 2: Abstract
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!
Step 3: 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
Step 4: Walabot
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.
Step 5: Getting Started
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
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
Step 6: 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.
Step 7: 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
Step 8: 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
Step 9: 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
Step 10: 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
Step 11: For the Walabot
From a command shell
Sudo pip install “/usr/share/walabot/python/WalabotAPI-1.0.21.zip”
Step 12: 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.
Step 13: For the LCD
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
Step 14: Blynk
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.
Step 15: Configuring the Blynk App
Step 16: You Can Use This QR Code With the Blynk App to Clone My Project to Save You Time
OK Now that the app is all set up, we can configure Python and the RPi to talk to it over the internets. Magic
Step 17: 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
Step 18: 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
Step 19: The Hardware
First Breadboard prototype
Step 20: Enclosure Design
The enclosure was designed and rendered in the awesome Fusion360
Step 21: Guts Shots
Step 22: Final Assembly Shots
Step 23: To Fix the Walabot to the Stand
Use the self adhesive metal disk that comes with the walabot to fix it in place
Step 24: Hardware STL Files for 3D Printing
Attachments
Step 25: Schematics for Wiring the Thing Up
Attachments
Step 26: 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/pisudo 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
Attachments
Step 27: 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
Step 28: Conclusion
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.