Showing posts with label diy stuff. Show all posts
Showing posts with label diy stuff. Show all posts

Sunday, May 10, 2026

MPXV7002 as Breath Sensor

Breath sensor made from an MPXV7002 and a silicon tube. The tube has incisions added near the breathing end to allow air to flow through while still building pressure at the sensor end. Enough pressure is still built up within the tube to allow circular breathing if desired. The sensor sends note on / off and continuous control data.

To improve this I might consider a wider tube that is coupled with the sensor or try more or different-sized puncture holes or a 3D printed mouthpiece. However, it still works really well as-is.

Wiring is simple as the sensor outputs an analog voltage and works fine on 3v3 or 5v power supply. The output voltage is rail to rail across the power supply voltage range, and can represent both positive and negative pressure, meaning that the neutral pressure will output at halfway of the voltage supply.

For a Teensy 3.x or 4.x: 3v3 to the 5V pin on the sensor, ground to ground and output of the sensor to Teensy A0 analog input pin.



Here is some code as an example: 


int air_pin = A0;
int air_pressure;
int air_pressure_prev;
int breath_controller = 1;

int threshold = 75;
int play_flag = 0;

int channel = 1;
int pitch = 60;
int velocity = 127;

void setup() {
Serial.begin(57600);
usbMIDI.read();
}

void loop() {
air_pressure = analogRead(air_pin) >> 3;
if(air_pressure != air_pressure_prev) {
air_pressure_prev = air_pressure;
usbMIDI.sendControlChange(breath_controller, air_pressure, channel);
Serial.println(air_pressure);
delay(10);
}

if(air_pressure > threshold && play_flag == 0) {
usbMIDI.sendNoteOn(pitch, velocity, channel);
Serial.println("note on");
play_flag = 1;
}

if(air_pressure < threshold && play_flag == 1) {
usbMIDI.sendNoteOff(pitch, 0, channel);
Serial.println("note off");
play_flag = 0;
}

}


Thursday, November 30, 2023

Printable Variable Miniskiff

 


I've added a variable miniskiff part studio to the Eurorack case document: https://cad.onshape.com/documents/1637ca71f6ccbf900471de5e/w/ba5b8495e9753650883d1cb0/e/c3f73f4b0fd00e64b5823644?renderMode=0&uiState=656884e93534192f492a1c3b 

This part studio has variables for many aspects of the case including the width in HP. 46 HP is the widest case that will print on a 25 cm 3 volume printer like the Bambu P1P

Wednesday, April 19, 2023

Teensy 4.1 with QMC6310 Magnetometer to USB MIDI

Overview

The QMC6310 magnetometer sensor outputs 16 bit for each axis X, Y and Z. The code uses the Wire library to communicate via the I2C protocol. This example prints the raw axis values to the serial monitor and also sends as a USB MIDI control change message (scaled to 0 - 127). The datasheet for this sensor can be found here


Hardware






The following connections should be made between the Teensy 4.1 and the QMC6310:
  • Teensy 4.1 3V to QMC6310 VCC - orange in the above photo
  • Teensy 4.1 ground to QMC6310 GND - blue in the above photo
  • Teensy 4.1 pin 19 / A5 / SCL / PWM to QMC6310 SCL - green in the above photo
  • Teensy 4.1 pin 18 / A4 / SDA / PWM to QMC6310 SDA - yellow in the above photo


Software

const int address = 0x1c; // 0x1c if part number is QMC6310U or 0x3c if part number is QMC6310N
int16_t axis[3]; // array for axis data X, Y, Z - force 2's compliment for a signed 16 bit integer

#include <Wire.h>

void setup() {

// Begin serial port
Serial.begin(57600);
Serial.println("Begin...");

// Begin Wire library
Wire.begin();

// set up magnetometer
// writeMag(0x29, 0x06); // define sign for XYZ
writeMag(0x0b, 0x00 | 0x01 << 2); // define set / reset on
// field range: 2gauss = 0x11 << 2, 8gauss = 0x10 << 2, 12gauss = 0x01 << 2, 30guass = 0x00 << 2
writeMag(0x0a, 0xcd); // set normal range and ODR to 200 Hz
}

void loop() {
if (readMag()) { // if there is new data present, print the values of the three axis as a sixteen bit value
Serial.print("X: ");
Serial.print(axis[0]);
usbMIDI.sendControlChange(1, map(axis[0], -32768, 32767, 0, 127), 1);
Serial.print(" Y: ");
Serial.print(axis[1]);
usbMIDI.sendControlChange(2, map(axis[1], -32768, 32767, 0, 127), 1);
Serial.print(" Z: ");
Serial.println(axis[2]);
usbMIDI.sendControlChange(3, map(axis[2], -32768, 32767, 0, 127), 1);
}
}

// this function writes data to the magnetometer
void writeMag(byte reg, byte val) {
Wire.beginTransmission(address);
Wire.write(reg);
Wire.write(val);
Wire.endTransmission();
}

// this function reads X,Y,Z data from the magnetometer
int readMag() {
// set reg 9 to read from
Wire.beginTransmission(address);
Wire.write(0x09);
Wire.endTransmission();

// read from reg 9 for 1 byte - this is the status byte
byte status; // status byte which stores the
Wire.requestFrom(address, 1);
while (Wire.available()) {
status = Wire.read() & 1;
}

if (status == true) {
// set reg 1 to read from
Wire.beginTransmission(address);
Wire.write(0x01);
Wire.endTransmission();
// read from reg 9 for 6 bytes - these are the data bytes X LSB, X HSB, Y LSB, Y HSB, Z LSB, Z HSB
Wire.requestFrom(address, 0x06);
byte index = 0;

// read data into axis array
while (Wire.available()) {
axis[index] = Wire.read() | Wire.read() << 8;
index++;
}
return true; // true if new data is present
}

else {
return false; // false if no new data is present
}
}

Saturday, April 01, 2023

Printing enclosures for breadboards

 




Wednesday, May 05, 2021

Xiao Mx MIDI Device

A simple MIDI device that uses the Adafruit TinyUSB library, a Seeed Studio Xiao, 6 Cherry Mx stabilised switches and 5 9mm Alpha pots. 

Code, schematic, PCB layout, Gerber files can be found here: https://github.com/little-scale/arduino-sketches/tree/master/xiao_mx 









Saturday, April 24, 2021

MIDI USB Host to and from MIDI 5 Pin

Something that I have always wanted and needed is some way of using USB MIDI devices with 5 Pin DIN MIDI devices and vice-versa without going through a computer (or buying a third-party device). 

Teensy 3.6 can act as a USB host for USB MIDI devices, while also being able to send and receive serial data via 5 pin DIN ports. In this case, the Teensy acts as a USB host for a USB MIDI device. Any data that is received from the USB MIDI device is sent out via the 5 pin DIN connector MIDI out port. Any data that is received from the 5 pin DIN connector MIDI in port is sent to the USB MIDI device. 

This will be useful in many instances, for example sending or receiving data from M8 Headless, and then routing to USB devices such as modular USB MIDI to CV converters. 

The hardware is the Serial MIDI input and output found on this page, with the addition of a USB host cable that plugs into the USB host header pins on the Teensy 3.6. 



The code is based on a 6x16 USB MIDI example from the Teensyduino T36_host library. 




View and download here: https://github.com/little-scale/arduino-sketches/blob/master/MIDIUSBHost_to_MIDI5PIN.ino




Monday, March 18, 2019

4022, 4024, 4028 and 4093 Module Panels







Up now on my Github

Friday, March 08, 2019

4022 Eight Stage Counter Module

A 4022-based eight stage counter module for Eurorack.



Download the source files on Github: https://github.com/little-scale/eurorack/tree/master/4000-series

Sunday, January 13, 2019

Secret Handshake: DIY USB MIDI Host Module for Eurorack

The Teensy 3.6 can act as a USB host. This includes support for class-compliant USB MIDI devices, as well as other types of USB devices. 

The strength of this is to be able to use USB MIDI controllers without the need for a laptop or similar device, and can interface with Eurorack. 

I've made a simple Eurorack module that acts as a USB MIDI host, and has two inputs that can be either gate or CV signals, 4 gate outputs and 2 CV outputs. 

All of the relevant files can be found here: https://github.com/little-scale/eurorack/tree/master/USB_MIDI_Host

This includes an example for Launchpad Mini, PS4 controller, NanoKontrol 2. 





Different USB MIDI devices have different Arduino sketches written for them as firmware. Each USB device has different controls, functions and mappings, and so the flexibility of having a USB Host module is weighed against needing to program each device.

I will be adding and updating this project in the coming weeks. My plan is to make a new PCB with buffered outputs, voltage scaling, and busses for IO expansion.

Here are demonstrations for NanoKontrol 2, PS4 controller and Launchpad Mini.




Monday, December 31, 2018

Chromatic Drum Gate Sync



This Teensy-based project has 12 gate outputs that are set using note messages over USB MIDI.

Each note in the scale (C, C#, D, D# etc) corresponds to a gate output labelled G1 - G12, and will set high from a note on message and low from a note off message.

If a USB MIDI clock sync is sent, Gate 12 will output a short trigger upon sequencer START or CONTINUE. Gate 11 will output a sync signal at a rate of 12PPQN. Gate 10 will output a sync signal at a rate of 16th notes. Gate 9 will output a sync signal at a rate of 8th notes.






Download the code (.ino), schematic (.sch) and board (.brd) files here:
https://github.com/little-scale/eurorack/tree/master/chromatic_drum_gate_sync

Saturday, September 01, 2018

AD633 as Eurorack Ring Modulation / Amplitude Modulation / Bipolar VCA

Here is an AD633 ring modulation / amplitude modulation / bipolar VCA circuit. U4 is the X input, U5 is the Y input, the ratio between R1 and R2 sets the level of the offset of the Y input, and VR2 crossfades between the Y input and the DC offset, thereby setting the strength of the modulation and allowing some of the X input carrier into the output signal.

In the demo below, two STO modules are used to provide a signal to the X and Y inputs. The signals are swept through different frequencies and waveform shapes.


Sunday, June 17, 2018

Exo Sequencer for Eurorack



The Exo Sequencer (as in... exotic, external, exoplanet, exothermic...) is a sixteen step sequencer with control voltage and trigger outputs. The control voltage range is relatively small (around 3V), and is not quantised. 




The width of the module is 18HP. 

The step order is selected in a number of ways: 
• Sending a gate or trigger to the INC input will increment the sequence
• Sending a gate or trigger to the DEC input will decrement the sequence
• Sending a combination of four LOW or HIGH signals to the four inputs A0, A1, A2 and A3 will select the step as a binary address e.g. 0000 will select step 1, 0010 will select step 3, 0111 will select step 8, 1111 will select step 16 and so on
• Sending a control voltage to the STEP input will directly select the step number, where 0V is step 1 and roughly 3.3V is step 16. This control voltage can be scaled using the STEP potentiometer
These methods for selecting the step order are not mutually exclusive, and can be used in conjunction with one another. 

The length of the sequence (used for calculating when using the INC, DEC or STEP inputs) is selected via the LENGTH potentiometer and can be modulated via a control voltage input. 

The offset of the sequence (determining the starting step) is selected via the OFFSET potentiometer and can be modulated via a control voltage input. 

Circuit board layouts, schematics, code, panel files for laser cutting and a bill of materials can be found here: https://github.com/little-scale/eurorack/tree/master/exo_sequencer 

This module is also on Modular Grid
A demonstration video is coming soon. This module can be seen and heard in some of the videos in this post






Sunday, June 03, 2018

Monophonic USB MIDI to CV Converter with 8 Octave Range

This is a USB-powered monophonic USB MIDI to CV converter with a roughly 8 octave range, from roughly -3.3V to 5V for pitch CV, 0V to 4.096V for velocity CV and a 3.3V gate for note on / note off events. The DAC is 12 bits, meaning that the range of 8.32V at a rate of 1V per octave is distributed across 4096 steps, yielding a pitch resolution of approximately 2.43 cents per data step.

The Teensy LC separates an incoming MIDI note message into values for pitch CV, velocity CV and a note gate. The pitch and velocity values are sent to an MCP4822 dual 12-bit DAC.

The first channel of the MCP4822 is amplified by two using the first op-amp of a TL072, and then offset by negative 3.3V by using the second op-amp of a TL072 resulting in a pitch CV range of approximately -3.3V to 5V. The velocity CV and note gate are fed directly to the Eurorack setup via a 1k resistors.

A Digilent Powerbrick uses 5V from the VIN on the Teensy LC and transforms this into  ±12V power supply, used to power the TL072.

This type of setup and can be refined and scaled to higher bit depth resolutions by using various DACs, different voltage ranges by changing the ratio between R2 and R1 (for scale) and feeding a different voltage into R8 (for offset).

#include <SPI.h>

int cs_pin = 0;
int gate_pin = 14;
int amp_gain = 0; // gain for amplifier - 0 = 2x, 1 = 1x
int previous_pitch;
float pitch_change_value;
float pitch_value;
float maximum_voltage = 8.32; // voltage output after op amps
float maximum_pitch_value = maximum_voltage * 12.0; 
float number_of_steps = 4096; // DAC resolution

void setup() {
  pinMode(cs_pin, OUTPUT);
  pinMode(gate_pin, OUTPUT);
  digitalWriteFast(cs_pin, HIGH);

  SPI.begin();
  usbMIDI.setHandleNoteOn(OnNoteOn);
  usbMIDI.setHandleNoteOff(OnNoteOff);
  usbMIDI.setHandlePitchChange(OnPitchChange);

}

void loop() {
  usbMIDI.read();
}

void OnNoteOn (byte channel, byte pitch, byte velocity) {
  if (channel == 1) {
    if (velocity > 0) {

      previous_pitch = pitch;
      pitch_value = map(previous_pitch + pitch_change_value, 0.0, maximum_pitch_value, 0.0, number_of_steps);
      writeDAC(cs_pin, 0, pitch_value);
      writeDAC(cs_pin, 1, velocity << 5);
      digitalWriteFast(gate_pin, HIGH);
    }

    else {
      digitalWriteFast(gate_pin, LOW);
    }
  }
}

void OnNoteOff (byte channel, byte pitch, byte velocity) {
  if (channel == 1) {
    digitalWriteFast(gate_pin, LOW);
  }
}

void OnPitchChange (byte channel, int pitch_change) {
  if (channel == 1) {
    pitch_change_value = map((float) pitch_change, 0.0, 16383.0, -12.0, 12.0);
    pitch_value = map(previous_pitch + pitch_change_value, 0.0, maximum_pitch_value, 0.0, number_of_steps);
    writeDAC(cs_pin, 0, pitch_value);
  }
}

void writeDAC (int cs, int dac, int val) {
  digitalWrite(cs, LOW);
  dac = dac & 1;
  val = val & 4095;
  SPI.transfer(dac << 7 | amp_gain << 5 | 1 << 4 | val >> 8);
  SPI.transfer(val & 255);
  digitalWrite(cs, HIGH);
}






Sunday, May 27, 2018

Pitch CV to Frequency Conversion with Offset Opamp and ADC

As a follow on from the previous post, another (related) way of converting a pitch CV signal to a frequency value is to offset any negative voltages, and then divide the pitch CV signal and then measure the voltage. In this case, a Teensy LC is used.

This method makes a few assumptions:
• That pitch CV signals may be unipolar, with negative voltages and positive voltages
• A user can set the offset via a pot, thereby having a variable range in terms of negative and positive voltages
• The pitch CV signal will be 1 volt per octave
• The pitch CV signal will be roughly a 10v range

12V and -12V power supply rails are required. In this case, the Digilent PowerBrick supplies both from USB 5V. A Eurorack power supply could also deliver 12V and -12V.

The pitch CV signal is summed with an offset voltage. The offset voltage is derived by dividing +12v to -12v with a 10k potentiometer. The sum of both signals is fed into an inverting opamp with unity gain, whose output is fed into a second inverting opamp. The resulting signal is a phase-correct unipolar pitch CV signal (assuming the 10k potentiometer is set correctly) in the range of perhaps 0V to 10V.

This signal is then divided by 3 by using a resistor voltage divider, where 20k is on the input side and 10k goes to ground - this will then equate to 1/3V per octave. The output of this voltage divider is then fed through some clamping diodes (such as 1n4148), to limit the range to 0V - 3.3V. The voltage is then read as a 12-bit analog to digital value.

The value range of the ADC conversion is 0 - 4095, and this represents a voltage range of 0V - 3.3V, which in turn represents a pitch range of 0 to 9.9 octaves (at 1/3V per octave) with a resolution of about 2.9 cents.

The ADC conversion value is mapped to MIDI pitch, giving a range of 120 - 132 semitones. This MIDI note value is then converted to frequency using my Arduino mtof library, which can be downloaded here.

The frequency value could be used to control another synthesiser or oscillator, or used for analysis and further conversion.

In this particular example, the resulting frequency value is sent via two MIDI pitch messages - one for the integer portion and one for the floating portion - and then reconstructed as a frequency value for a sine wave in a Max patch. A comparison can then be made to the analog output of a VCO to see how accurate the pitch conversion is. Note that a scaler value of 1.03 corrects for tuning issues - this value may change depending on setup.

#include <mtof.h>
#include <math.h>

float data; 
float pitch; 
float pitch_offset = 0; 
float freq;

float max_voltage_of_adc = 3.3; 
float voltage_division_ratio = 0.3333333333333;  
float notes_per_octave = 12;
float volts_per_octave = 1; 
float scaler = 1.03;

float mapping_upper_limit = (max_voltage_of_adc / voltage_division_ratio) * notes_per_octave * volts_per_octave * scaler;

void setup() {
  analogReadResolution(12); // 12-bit ADC resolution
}

void loop() {
  data = analogRead(0); // read pitch CV as data value using ADC
  pitch = pitch_offset + map(data, 0.0, 4095.0, 0.0, mapping_upper_limit); // convert pitch CV data value to a MIDI note number
  freq = mtof.toFrequency(pitch); // convert MIDI note number to frequency

  /*  To test out the frequency values that are being generated from pitch cv conversion, the frequency value is sent over MIDI pitch bend. 
   *  Pitch bend channel 1 is used for the integer component, and pitch bend channel 2 is used for the float component
   *  The pitch bend messages are re-constituted in a Max patch for testing. 
   *  The pitch bend messages are not intended for use with a 'normal' MIDI synth
   *  This is because they used as a way of conveying the data and not as a regular pitch bend message. 
  */
  
  usbMIDI.sendPitchBend(freq, 1); // split up integer part of the frequency and send as a pitch bend value
  usbMIDI.sendPitchBend(fmod(freq, 1.0) * 10000.0, 2);
  
  delay(1); 
}







Saturday, April 07, 2018

Quad Probability Gate for Eurorack



A module that has one gate input, one cv input and four gate outputs. The cv input sets the likelihood (from 0% / 0v to 100% / 5v) that the input gate is mirrored at each of the four output gates. The probability for each output gate is calculated individually.








Download source code, schematics, panel and pcb here: https://github.com/little-scale/eurorack/tree/master/quad_probability_gate

Monday, January 22, 2018

DIY CV Controlled Sequencer


Overview
A sequencer with eight steps, one CV input, one CV output and one Trig output. The CV value determines which step is sent to the CV output.

A scaling pot adjusts the number of steps represented by the CV signal. Every time the CV signal input changes sufficiently to select a different step, the new step is selected and sent to the CV output, and a trigger is generated and sent the Trig output.

The number of steps can be increased, and the code and schematic can also be used with Arduino etc.




Demo Video





Code


Download here: http://milkcrate.com.au/_other/downloads/arduino/CV_Controlled_Sequencer/CV_Controlled_Sequencer.ino





Schematic

Thursday, November 09, 2017

Four Channel CC to CV - Code, Schematic, Board and Case






This simple project takes a CV signal, scales and converts it to USB MIDI data, useful for visualising LFOs and long envelopes. Negative voltages are clipped.

Download the schematic, board, code and case design here: http://milkcrate.com.au/_other/downloads/projects/CV_to_MIDI/