Motorizing Sliders
The missing piece of Vinophonics is the integration of motorized sliders.
We need to read the position of 16 sliders (potentiometers), and actuate the motors for each to position them, according to the vineyard sensor data. Once we can do this, we can map sensor information to each of these sliders, allowing the vineyard data (via the blockchain) to modify the sound for which the slider is patched.
For example, we could associate (in software) the relative positions for slider #3 to represent the temperature range of -3ºC - 38ªC, where the minimal temperature value represents the bottom end of the slide, and a hot summer afternoon, the top. But to do this, we need to be able the read the 16 slider positions, and move them up and down by actuating their motors.
To break down the complexity of this problem, we can tackle each of the following questions:
Can we read a slider position with an arduino?
Here are some instructions with examples for reading a linear potentiometer.
https://www.instructables.com/id/Wiring-Linear-Sliding-Potentiometer-With-Arduino/
The sliders (linear potentiometers) used in Vinophonics are not the same used for testing here, but are very similar.
Ostensibly, the only differences between the two sliders are:
The test sliders are 100mm long, while the Vinophonics sliders are 60mm
The connectors are different on the two sliders (but with the same pin names and functions...hopefully)
These are the actual sliders built into Vinophonics:
https://www.mouser.es/datasheet/2/54/sm-778343.pdf
And these are the sliders used for testing:
https://www.sparkfun.com/products/10976#comment-53d36766ce395ff8478b4568
These motorized sliders have 9 pins:
Positive terminal on the motor
Ground terminal on the motor
1 Ground terminal for potentiometer 1
1' Ground terminal for potentiometer 2
2 Voltage read for potentiometer 1
2' Voltage read for potentiometer 2
3 5V input for potentiometer 1
3' 5V input for potentiometer 1
T touch-sense
The slider has, therefore, two potentiometers. One is used for reading the slider position by an arduino, whereas the other potentiometer is used to adjust the voltages in Vinophonics, modulating sounds, etc. These are 10KΩ wiper resistors. Testing with an ohm meter between points 2 and 1, or 2' and 1', should report between 0-10KΩ. When 5V is applied to 3 (or 3') pin 2 (or 2') can be connected to an analog pin, like A(0) on the arduino and read. According to the slider position (0-1023), the analog pin can be configured to read 0-5V.
The idea is something similar to this, as described here.
https://www.14core.com/wiring-multiple-sliding-potentiometer-on-microcontroller/
We first test two sliders, using this small bit of code:
const int sP1 = A0, sP2 = A1;
int RawVal1 = 0, RawVal2 = 0, onDelay = 1000;
float vVal1= 0, vVal2 = 0;
float res1 = 0, res2 = 0;
void setup() {
Serial.begin(9600);
pinMode(sP1, INPUT);
pinMode(sP2, INPUT);
Serial.println("14CORE | Sliding Potensiometer Test Code");
Serial.println("========================================");
}
void loop() {
RawVal1 = analogRead(sP1);
RawVal2 = analogRead(sP2);
vVal1 = (RawVal1 * 5.0) / 1024.0;
vVal2 = (RawVal2 * 5.0) / 1024.0;
res1 = 5000.0 * (RawVal1/2024.0);
res2 = 5000.0 * (RawVal2/2024.0);
Serial.println("Raw Value 1 = ");
Serial.println(RawVal1);
Serial.println("\t Voltage 1 = ");
Serial.println(vVal1);
Serial.println("\t Resistance 1 = ");
Serial.println(res1);
Serial.println("Raw Value 2 = ");
Serial.println(RawVal2);
Serial.println("\t Voltage 2 = ");
Serial.println(vVal2);
Serial.println("\t Resistance 2 = ");
Serial.println(res2);
delay(onDelay);
}
So, since this works, we should be able to read all 16 slider positions, using the same logic with 16 analog pins available on an Arduino MEGA.
https://store.arduino.cc/mega-2560-r3
2. Touch Sensitivity
The pin labeled T on the slider is useful for touch sensitivity. By using the CapacitiveSensor.h library on the arduino, it is possible to create a condition whereas when a human touches the sliders, further movement actions are suspended. For this to work, it may be necessary to replace the plastic slider keycaps with metal ones.
#include <CapacitiveSensor.h>
/*
* CapitiveSense Library Demo Sketch
* Paul Badger 2008
* Uses a high value resistor e.g. 10M between send pin and receive pin
* Resistor effects sensitivity, experiment with values, 50K - 50M. Larger resistor values yield larger sensor values.
* Receive pin is the sensor pin - try different amounts of foil/metal on this pin
*/
CapacitiveSensor cs_4_2 = CapacitiveSensor(4,2); // 10M resistor between pins 4 & 2, pin 2 is sensor pin, add a wire and or foil if desired
CapacitiveSensor cs_4_6 = CapacitiveSensor(4,6); // 10M resistor between pins 4 & 6, pin 6 is sensor pin, add a wire and or foil
CapacitiveSensor cs_4_8 = CapacitiveSensor(4,8); // 10M resistor between pins 4 & 8, pin 8 is sensor pin, add a wire and or foil
void setup()
{
cs_4_2.set_CS_AutocaL_Millis(0xFFFFFFFF); // turn off autocalibrate on channel 1 - just as an example
Serial.begin(9600);
}
void loop()
{
long start = millis();
long total1 = cs_4_2.capacitiveSensor(30);
long total2 = cs_4_6.capacitiveSensor(30);
long total3 = cs_4_8.capacitiveSensor(30);
Serial.print(millis() - start); // check on performance in milliseconds
Serial.print("\t"); // tab character for debug windown spacing
Serial.print(total1); // print sensor output 1
Serial.print("\t");
Serial.print(total2); // print sensor output 2
Serial.print("\t");
Serial.println(total3); // print sensor output 3
delay(10); // arbitrary delay to limit data to serial port
3. Can we move a slider position from the arduino by actuating the motor?
Connecting sufficient voltage to the slider motor will move the slider. The polarity determines which way the motor turns, and thus, the direction the slider moves.
Here is a good video that explains how this works:
https://www.youtube.com/watch?v=fEuUHqmlPD4
Here are some more helpful examples:
https://blog.codyhazelwood.me/motorized-faders-and-the-arduino/
https://www.youtube.com/watch?v=r12wG7ebvnY
To get the slider motor to change directions, and position the slider where would like, we need an h-bridge to change the polarity. For our test example, we build and h-bridge using a L293D IC. Apparently, the L293DNE works exactly the same way, and the SN754410 will also work. Each of these chips can drive 2 motors. So, Vinophonics would require 8 L293D IC's for the 16 slider motors.
Here is a good tutorial explaining what an h-bridge looks like, and how we build one:
http://www.learningaboutelectronics.com/Articles/Arduino-microcontroller-H-bridge-circuit.php
The L293/SN754410 is capable of controlling 2 motors.
It is a 4-channel H-bridge, meaning it can connect 4 terminal wires from motors. Since each motor has 2 terminals, it can control 2 motors (2x2=4).
Pin 1 is the enable pin for terminals 1 and 2. It enables motor to turn on when it is connected to a power. And disables the motor from functioning when connected to ground.
Pin 2 is the motor logic pin for terminal 1. This is the voltage level which one of the motor terminals receive. The logic level will determine what action the motor will take. This is one of the two logic levels that determines the function of the motor connected.
Pin 3 is the pin where we connect one of the terminals of the motor to.
Pin 4 and Pin 5 both get grounded.
Pin 6 is where we connect the other motor terminal to. This completes the 2-terminal connections necessary for a motor to be hooked up to the H-bridge IC.
Pin 7 is the motor logic pin for terminal 2. This is the second voltage signal we feed to the motor to determine the action the motor will take.
Pin 8 is the pin which receives the voltage needed to power on the motor. It is the motor power pin. This is the pin where we place the positive voltage of the power supply that will operate the DC motor. So if the motor is a 9V motor, then you will need to feed 9V into this pin. If the motor is a 12V motor, then you will need to feed 12V into this pin.
Pin 9 is the enable pin for terminals 3 and 4. It enables the motor to turn on when connected to power and disables the motor when connected to ground.
Pin 10 is the motor logic pin for terminal 3. This is one of the logic voltage signals that determines the action that the second motor will take.
Pin 11 is the pin where we connect one of the terminals of the second motor to.
Pin 12 and Pin 13 both get grounded.
Pin 14 is the pin where we connect the other terminal of the second motor to.
Pin 15 is the motor logic pin for terminal 4. It is the second voltage signal that we feed into the second motor to determine the action the motor will take.
Pin 16 is the pin which receives the voltage needed for power for the IC. It is the IC power pin. The IC needs just about 5V in order to operate. Therefore, we feed 5V into this pin.
Each slider requires two digital pins (one for each of the logic pins). The enable pin (pin 1) could be connected directly to 5V, thus saving a pin on the arduino, however if the enable pin is connected to a PWM pin, the speed of the slider can effectively be controlled.
Enable | Logic Pin 1 | Logic Pin 2 | Result |
High | Low | High | Forward |
High | High | Low | Reverse |
High | Low | Low | Stop |
High | High | High | Stop |
Low | Doesn't matter | Doesn't matter | Off |
The Arduino MEGA has 54 digital pins and 16 analog pins, but only 14 or 15 of the digital pins support PWM.
In other words, 16 motors requires 32 digital logic pins, and 16 enable pins.
So, to test the slider movement, there are different software examples available.
Like this one:
Here is a sample of this code used for a first test of the h-bridge:
//Arduino Pin Assignments
const int motorDown = 3; //H-Bridge control to make the motor go down
const int motorUp = 5; //H-Bridge control to make the motor go up
//Inputs
const int wiper = 0; //Position of fader relative to GND (Analog 0)
const int pot = 3; //Potentiometer to set position of fader (Analog 3)
//Variables
double faderMax = 0; //Value read by fader's maximum position (0-1023)
double faderMin = 0; //Value read by fader's minimum position (0-1023)
void setup() {
pinMode (motorUp, OUTPUT);
pinMode (motorDown, OUTPUT);
calibrateFader();
}
void loop() {
int state = analogRead(pot); //Read the state of the potentiometer
if (state < analogRead(wiper) - 10 && state > faderMin) {
digitalWrite(motorDown, HIGH);
while (state < analogRead(wiper) - 10) {}; //Loops until motor is done moving
digitalWrite(motorDown, LOW);
}
else if (state > analogRead(wiper) + 10 && state < faderMax) {
digitalWrite(motorUp, HIGH);
while (state > analogRead(wiper) + 10) {}; //Loops until motor is done moving
digitalWrite(motorUp, LOW);
}
}
//Calibrates the min and max position of the fader
void calibrateFader() {
//Send fader to the top and read max position
digitalWrite(motorUp, HIGH);
delay(250);
digitalWrite(motorUp, LOW);
faderMax = analogRead(wiper);
//Send fader to the bottom and read max position
digitalWrite(motorDown, HIGH);
delay(250);
digitalWrite(motorDown, LOW);
faderMin = analogRead(wiper);
}
or following the examples in this video:
If you change the void loop function to Lumpy, SpringA, or SpringB, this is an easy test, but specifically with SlideToValue(x) we can move the slider carriage to a specific position. Also, we can switch to non-PWM pins, and although we lose the ability to control the motor carriage speed, the slider moves just as well.
https://www.youtube.com/watch?v=r12wG7ebvnY
The Arduino could easily drive two sliders:
1 Analog position to read the slider position.
2 digital pins for each slider (4 digital pins)
2 digital pins (shared pins on the arduino) for the touch lines
Here is a crude example of how two sliders can be controlled by one Arduino UNO:
5. And how about with 16 sliders?
Well, we should be able to drive 16 sliders with one Arduino Mega. This is the $24,000 question!
All 16 analog pins for reading the slider positions.
32 digital pins for motor control (although only 15 of these could be PWM...PWM is not really a requirement)
2 digital pins for touch lines (we should be able to share the touch line controls…if you touch one slider, you touch them all)
8 H-bridges (2 motors each)
We could also use a PWM multiplexor. (I have one)
But we still need to get data from the RasperryPi (from the blockchain read script) to the program moving the sliders. So, we might also consider running the Arduino in slave mode from the RPI using PyFirmata. Not only will this give us the option of running one piece of python code, rather than two pieces of software, and thus be more simple, it would also give us the option of using one of the free RPI PWM pins, should we choose to setup the 16 motor control pins with PWM.
To review, the RPI is running the following functions:
Full ethereum node, running geth
Reading the 3 position "blockchain" switch on the vinophonics panel, and writing the panel LED
Streaming audio-out from Vinophonics to the internet using an IceCast client
Streaming a low-refresh webcam of the vinophonics patch configuration
Connecting Vinophonics to the local wifi network
Thus, with PyFirmata, we would add a 6th function:
Reading the slider positions and moving the slider to correspond to the blockchain sensor readings
How can I optimize the layout (cabling)?
I guess once the total cabling layout is done on a breadboard(s) this could be simplified into a circuitboard?
7. How can I optimize the data transfer between RPI and Arduino?
The RPi and ArduinoMega are connected by a USB cable, we should be able to eliminate this and cable directly.