|
Post by MikMo on Mar 4, 2023 8:45:56 GMT
For a while i have been toying with the idea of making a "tactile box" with several controls built in. I have a leftover 2x12 AE case that i made custom aluminium front panels for. It will house the project, which will include a DIY ribbon controller, the DIY dual joystick module i made a while back, and some other stuff. Preliminary layout of ribbon controller and joysticks. Joysticks will of course be mounted inside the case, not on top :-) See individual posts about details.
|
|
|
Post by MikMo on Mar 4, 2023 8:50:53 GMT
The ribbon controllerA very long time ago (like 10 years+) i got some free samples of Spectrasymbol touch related products. One of the items was a ca. 20 cm soft pot / ribbon controller. So i decided to use it as a ribbon controller for AE. First i tried to just hook it up as any potentiometer, like a voltage dvider between 5V and ground. This worked, but i got a rather limited range, brecause the soft pot's resistance does not go down to zero when not touched. As i also wanted the ribbon controller to put out a gate and trigger signal whenever it was touched, i chose to go the microcontroller way. There was also som problems with linearity near one end of the soft pot, that was easier to deal with this way. So by now the setup consists of the soft pot, and Aduino Nano microcontroller and a small MCP4725 12 bit DAC. The softpot is read by the Arduino which in turn controls the DAC to put out the CV. This way i can remap the values read from the softpot to the full voltage range of the DAC (and AE). I have also included a "range" toggle switch, so i can scale the CV output to either 0-2V or 0-5V. This is how everything is hooked up: Everything is mostly working by now, i just have a few arduino code changes to make. Arduino code ataced below. The softpot i am using has a very linear response over most of it's length, except the last 15mm or so. So in the Arduino code, i simply exclude values read from the last bit of the ribbon. Since this is not going into a standard AE module format, i am not so concerned about space / size. This could be made smaller by using one of the tiny Arduino Leonardo Beetle boards, like this: www.aliexpress.com/item/1005005163297459.html?spm=a2g0o.productlist.main.63.24052ee3cRATYF&algo_pvid=62385952-a8db-401c-8edc-13f6c2590ebc&algo_exp_id=62385952-a8db-401c-8edc-13f6c2590ebc-31&pdp_ext_f=%7B%22sku_id%22%3A%2212000031932710682%22%7D&pdp_npi=3%40dis%21DKK%2150.75%2145.7%21%21%21%21%21%4021227d8316779200553546097d0705%2112000031932710682%21sea%21DK%21127995896&curPageLogUid=WWTL7npYrtJGThese boards does not have all the Arduino I/O pins broken out, but sufficient pins are available for this and other projects. They also have 500 bytes more SRAM than Arduino Nano. Or even smaller by using discrete components instead of the "ready made" modules i am using. Resources:
Sparkfun article about using softpot's / ribbon controllers with Arduino: learn.sparkfun.com/tutorials/softpot-hookup-guide/allPossible source for softpots (no afiliation) www.sparkfun.com/categories/527Adafruit how to guide for using the MPC4725 DAC with Arduino: learn.adafruit.com/mcp4725-12-bit-dac-tutorialDAC module from Adafruit (no afiliation, just love and gratitude :-)): www.adafruit.com/product/935DAC module i used: ( When i bought them the better Adafruit ones was out of stock, consider supporting Adafruit. They put a lot of time into makng high quality products and libraries for the Arduino eco system, and their products are better quality than the chineese knock offs) www.aliexpress.com/item/1005003301834508.html?spm=a2g0o.productlist.main.1.3ee43d82tydf8L&algo_pvid=ad7059f0-0c07-4084-a000-2a7de0192391&algo_exp_id=ad7059f0-0c07-4084-a000-2a7de0192391-0&pdp_ext_f=%7B%22sku_id%22%3A%2212000025099039286%22%7D&pdp_npi=3%40dis%21USD%211.94%211.84%21%21%21%21%21%40211bd4cd16779169162763533d0745%2112000025099039286%21sea%21DK%21127995896&curPageLogUid=zMxbMRdr7kTWArduino code
/*****************************************************************************************************************************************************'
Ribbon controller for AE synth
Version 1.0
Mikael Mørup 05-03-2023
******************************************************************************************************************************************************/
#include <Wire.h>
#include <Adafruit_MCP4725.h>
Adafruit_MCP4725 dac;
const int ribbonPin = A1;
const int triggerPin = 3;
const int gatePin = 4;
const int rangeSwitchPin = 5; //switch for 0-2V or 0-5V output
const byte stateIdle = 0;
const byte stateTouchBegin = 1;
const byte stateTouched = 2;
const byte triggerDuration = 20; // trigger duration 20 mS
const byte range2V = 0;
const byte range5V = 1;
byte currentState = 0;
byte currentRange = 0;
int ribbonBaseVoltageValue = 0; //the value read from the ribbon when not touched.
int currentRibbonVoltageValue = 0;
long triggerStartTime = 0;
long rangeChangeCheckInterval = 1000; //only check for range switch changes once every second
long lastRangeCheckTime = 0;
// Variables for debouncing the ribbon potentiometer. It will have switchbounce just like a mechanical switch.
int ribbonState;
int lastRibbonState = LOW;
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 20;
int reading = LOW;
void setup()
{
pinMode(triggerPin, OUTPUT);
pinMode(gatePin, OUTPUT);
pinMode(rangeSwitchPin, INPUT_PULLUP);
currentRange = GetRange();
ribbonBaseVoltageValue = analogRead(ribbonPin);
currentState = stateIdle;
dac.begin(0x60);
dac.setVoltage(0, false);
}
void loop()
{
switch (currentState)
{
case stateIdle:
if (millis() > lastRangeCheckTime + rangeChangeCheckInterval)
currentRange = GetRange();
ReadRibbonVoltage();
if (currentRibbonVoltageValue <= ribbonBaseVoltageValue + 3)
reading = LOW;
else
{
reading = HIGH;
if (reading != lastRibbonState)
{
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay)
{
if (reading != ribbonState)
{
ribbonState = reading;
if (ribbonState == HIGH)
{
currentState = stateTouchBegin;
}
}
}
}
lastRibbonState = reading;
break;
case stateTouchBegin:
digitalWrite(triggerPin, HIGH);
triggerStartTime = millis();
digitalWrite(gatePin, HIGH);
currentState = stateTouched;
break;
case stateTouched:
if (triggerStartTime > 0)
CheckTriggerTimeElapsed();
ReadRibbonVoltage();
if (currentRibbonVoltageValue <= ribbonBaseVoltageValue + 3) // If the ribbon is no longer touched
{
digitalWrite(gatePin, LOW);
dac.setVoltage(0, false);
ribbonState = LOW;
reading = LOW;
lastRibbonState = LOW;
currentState = stateIdle;
}
else
SetDacValue(currentRibbonVoltageValue);
break;
}
}
void ReadRibbonVoltage()
{
currentRibbonVoltageValue = analogRead(ribbonPin);
}
void CheckTriggerTimeElapsed()
{
if (millis() >= triggerStartTime + triggerDuration)
{
digitalWrite(triggerPin, LOW);
triggerStartTime = 0;
}
}
byte GetRange()
{
if (digitalRead(rangeSwitchPin) == LOW)
{
lastRangeCheckTime = millis();
return (range2V);
}
else
{
lastRangeCheckTime = millis();
return (range5V);
}
}
void SetDacValue(int value)
{
if (value < 500) // Values below 500 read from the ribbon are rounded up to 500, due to non linearity in the response of the last bit of the ribbon.
value = 500;
int mV = 0;
if (currentRange == range2V)
mV = map (value, 500, 1023, 0, 1640); // map value to 0-2V output
else
mV = map(value, 500, 1023, 0, 4095); // map value to 0-5V output
dac.setVoltage(mV, false);
}
|
|
|
Post by rodney on Apr 14, 2023 12:28:20 GMT
This is exactly what I've been putting off doing for a few years because my 50cm softpot (also Specra Symbol) defaults to its centre position when it is not being touched, where I just want a voltage out for the whole length. adding quantosation and gesture recording are on my list of additions, but I'll try to repoduce what you have done first.
|
|
|
Post by MikMo on Apr 14, 2023 13:31:14 GMT
Adding quantization should be doable. I just don't know if the DAC i used is precise enough for it.
My knowlwdge of scales and music theory in general is - let's just say, limited. But i did find other Arduino based quantizers on the great inter WEB.
|
|
pol
Wiki Editors
Posts: 1,349
Member is Online
|
Post by pol on Apr 19, 2023 17:02:23 GMT
Adding quantization should be doable. I just don't know if the DAC i used is precise enough for it. My knowlwdge of scales and music theory in general is - let's just say, limited. But i did find other Arduino based quantizers on the great inter WEB. There is always just using the Quantizer module.....
|
|
|
Post by rodney on Apr 21, 2023 10:12:57 GMT
Adding quantization should be doable. I just don't know if the DAC i used is precise enough for it. My knowlwdge of scales and music theory in general is - let's just say, limited. But i did find other Arduino based quantizers on the great inter WEB. 12 bits will be enough for 12TET scales, and close-enough for most others, given how unstable our oscillators will be anyhow.
|
|
|
Post by MikMo on Apr 21, 2023 19:32:02 GMT
The lack of a precise ref. voltage for the DAC is probably the biggest problem
Your 5V on the bus may be anything from 4.85 to 5.0 volts.
You would need meassure it and take it into account, but you would need to meassure again after adding more modulesto your system.
Or maybe make a precise 5V ref powered from the 9V on the master module, but that would have to drive the DAC, and then it would get hairy agan :-)
|
|
|
Post by rodney on Apr 23, 2023 2:57:01 GMT
The lack of a precise ref. voltage for the DAC is probably the biggest problem Your 5V on the bus may be anything from 4.85 to 5.0 volts. You would need meassure it and take it into account, but you would need to meassure again after adding more modulesto your system. Or maybe make a precise 5V ref powered from the 9V on the master module, but that would have to drive the DAC, and then it would get hairy agan :-) I wonder how hard it would be to periodically measure and recalibrate automagically? It would be noce not to need that though.
|
|