If you need assistance, please send an email to forum at 4hv dot org. To ensure your email is not marked as spam, please include the phrase "4hv help" in the subject line. You can also find assistance via IRC, at irc.shadowworld.net, room #hvcomm.
Support 4hv.org!
Donate:
4hv.org is hosted on a dedicated server. Unfortunately, this server costs and we rely on the help of site members to keep 4hv.org running. Please consider donating. We will place your name on the thanks list and you'll be helping to keep 4hv.org alive and free for everyone. Members whose names appear in red bold have donated recently. Green bold denotes those who have recently donated to keep the server carbon neutral.
Special Thanks To:
Aaron Holmes
Aaron Wheeler
Adam Horden
Alan Scrimgeour
Andre
Andrew Haynes
Anonymous000
asabase
Austin Weil
barney
Barry
Bert Hickman
Bill Kukowski
Blitzorn
Brandon Paradelas
Bruce Bowling
BubeeMike
Byong Park
Cesiumsponge
Chris F.
Chris Hooper
Corey Worthington
Derek Woodroffe
Dalus
Dan Strother
Daniel Davis
Daniel Uhrenholt
datasheetarchive
Dave Billington
Dave Marshall
David F.
Dennis Rogers
drelectrix
Dr. John Gudenas
Dr. Spark
E.TexasTesla
eastvoltresearch
Eirik Taylor
Erik Dyakov
Erlend^SE
Finn Hammer
Firebug24k
GalliumMan
Gary Peterson
George Slade
GhostNull
Gordon Mcknight
Graham Armitage
Grant
GreySoul
Henry H
IamSmooth
In memory of Leo Powning
Jacob Cash
James Howells
James Pawson
Jeff Greenfield
Jeff Thomas
Jesse Frost
Jim Mitchell
jlr134
Joe Mastroianni
John Forcina
John Oberg
John Willcutt
Jon Newcomb
klugesmith
Leslie Wright
Lutz Hoffman
Mads Barnkob
Martin King
Mats Karlsson
Matt Gibson
Matthew Guidry
mbd
Michael D'Angelo
Mikkel
mileswaldron
mister_rf
Neil Foster
Nick de Smith
Nick Soroka
nicklenorp
Nik
Norman Stanley
Patrick Coleman
Paul Brodie
Paul Jordan
Paul Montgomery
Ped
Peter Krogen
Peter Terren
PhilGood
Richard Feldman
Robert Bush
Royce Bailey
Scott Fusare
Scott Newman
smiffy
Stella
Steven Busic
Steve Conner
Steve Jones
Steve Ward
Sulaiman
Thomas Coyle
Thomas A. Wallace
Thomas W
Timo
Torch
Ulf Jonsson
vasil
Vaxian
vladi mazzilli
wastehl
Weston
William Kim
William N.
William Stehl
Wesley Venis
The aforementioned have contributed financially to the continuing triumph of 4hv.org. They are deserving of my most heartfelt thanks.
Registered Member #3885
Joined: Sun May 15 2011, 12:47AM
Location: Newton, Massachusetts, United States
Posts: 94
Hi all!
I've decided to post some plans for a dead-simple DRSSTC MIDI interrupter based on an Arduino and a handful of fairly basic off-the-shelf components. These plans should make it very easy for anyone to add audio modulation to their solid state coil.
MIDI parsing is done using the Arduino MIDI library, and notes are generated using 16-bit Timer1 in CTC mode - the output compare interrupt generates an output pulse with a duration retrieved from a lookup table to ensure that the output of the coil is roughly the same at every frequency. This lookup table is coil-specific and therefore experimentally determined.
I'm working on adding polyphony by using software counters with 8-bit Timer0 and Timer2 to extend them to 16 bits. Hopefully, this should be out in another few days or so (but no promises).
I've attached the Arduino sketch file, along with a tested Eagle CAD schematic and board layout for a standalone interrupter. The total parts cost is roughly $15, I will be releasing a Digikey bill of materials shortly.
Enjoy!
(If you have any comments about my code, or if you have ideas for features I should incorporate, feel free to suggest them here)
I am planning on selling a few of these boards, etched, drilled, assembled, programmed, and tested, on eBay (target price ~$40, shipped) to see if there is interest. Once these boards have been sold, I may send out a PCB fab order so that I can offer them as kits for even less money. The idea here is to make a basic, inexpensive, and easy to understand DRSSTC interrupter that anyone can add to their coil.
I've also included modified schematic and board files for Bwang's 1Tesla DRSSTC that are compatible with this interrupter. Note that the interrupter is an Eagle 5 file while the modified 1Tesla is an Eagle 6 file.
Here's a video of something very similar to this interrupter playing back music from a computer:
It also does polyphony, although I am unable to release the code for this at the moment:
Registered Member #3885
Joined: Sun May 15 2011, 12:47AM
Location: Newton, Massachusetts, United States
Posts: 94
I've tried again to upload the file - can an admin please delete the previous posts? It seems there's no way for me to try uploading a new file other than to post a reply, and there doesn't seem to be a way for me to delete my own replies if the upload fails...
In case you'd like to take a look at the code without unzipping the file, here it is:
/*
* Monophonic MIDI-Based DRSSTC Interrupter
* Daniel Kramnik, June 29, 2012
* Hardware:
* - Optical transmitter connected to Port D.2 (Arduino Digital Pin 2) through 100 ohm resistor
* - MIDI input connected to RXD (Arduino RX Pin) through 4N25 optocoupler circuit to isolate micro and prevent ground loops
*/
// MIDI class import - Note: this is not a standard Arduino library, it needs to be downloaded and added to your libraries folder
#include <MIDI.h>
// Function prototypes
void setupTimers (void);
void setupInterrupts (void);
void HandleNoteOn (byte, byte, byte);
int findOnTime (int);
// Global constants
#define PW_TABLE_MULTIPLIER 1.5
// Global primitives
volatile int on_time, current_pitch = 0;
void setup() {
// Setup optical transmitter on Port D.2 (Digital Pin 2)
DDRD |= (1 << 2);
PORTD &= ~(1 << 2); // Start the pin LOW (Note: you should *never* use digitalWrite to set this pin, as that function takes several microseconds
setupTimers();
setupInterrupts();
// Initiate MIDI communications, listen to all channels
MIDI.begin(MIDI_CHANNEL_OMNI);
// Setup MIDI callback functions (add more callback functions here to handle other MIDI events)
MIDI.setHandleNoteOn(HandleNoteOn); // Put only the name of the function
}
// Functions for setting up timer and interrupt reigsters
void setupTimers() {
/*
Timer1 is used to time the period of a note, with 0.5uS per tick
When Timer1 reaches the compare value, an interrupt is triggered that generates the output pulse
*/
// Set up 16-bit Timer1 (0.5uS per tick, hardware pins disconnected - interrupt starts disabled)
TCCR1A = 0x00; // CTC mode, hardware pins disconnected
TCCR1B = (1 << CS11) | (1 << WGM12); // CTC mode, set prescaler to divide by 8 for 1 / 2MHz or 0.5uS per tick (clkio = 16MHz)
}
void setupInterrupts() {
sei(); // Enable global interrupts to be safe, nothing else to do here
}
// Main program loop polls for MIDI events
void loop() {
MIDI.read();
}
// MIDI callback functions
void HandleNoteOn(byte channel, byte pitch, byte velocity) {
if (channel == 1) {
if (velocity == 0) { // Note off
if (pitch == current_pitch) {
TIMSK1 &= ~(1 << OCIE1A); // Disable Timer1's overflow interrupt to halt the output
}
}
else { // Note on
TIMSK1 &= ~(1 << OCIE1A); // Disable Timer1's overflow interrupt to halt the output
current_pitch = pitch; // Store the pitch that will be played
int frequency = (int) (220.0 * pow(pow(2.0, 1.0/12.0), pitch - 57) + 0.5); // Decypher the pitch number
int period = 1000000 / frequency; // Perform period and calculation
on_time = findOnTime(frequency); // Get a value from the pulsewidth lookup table
OCR1A = 2 * period; // Set the compare value
TCNT1 = 0; // Reset Timer1
TIMSK1 |= (1 << OCIE1A); // Enable the compare interrupt (start playing the note)
}
}
else {
// Ignore the command if it wasn't on channel 1 - this part may depend on the particular MIDI instrument you use, so modify the code here if you encounter a problem!
}
}
// Pulsewidth lookup table
int findOnTime(int frequency_input) {
int on_time = 17;
if (frequency_input < 1000) {on_time = 17;}
if (frequency_input < 900) {on_time = 18;}
if (frequency_input < 800) {on_time = 20;}
if (frequency_input < 700) {on_time = 20;}
if (frequency_input < 600) {on_time = 23;}
if (frequency_input < 500) {on_time = 27;}
if (frequency_input < 400) {on_time = 30;}
if (frequency_input < 300) {on_time = 35;}
if (frequency_input < 200) {on_time = 40;}
if (frequency_input < 100) {on_time = 45;}
on_time *= PW_TABLE_MULTIPLIER;
return on_time;
}
// Interrupt vectors
// Timer1 Compare Interrupt - signals when it's time to start a bang
ISR (TIMER1_COMPA_vect) {
PORTD |= (1 << 2); // Set the optical transmit pin high
delayMicroseconds(on_time); // Wait
PORTD &= ~(1 << 2); // Set the optical transmit pin low
}
Registered Member #4146
Joined: Tue Oct 18 2011, 02:01AM
Location: Wisconsin, U.S.A
Posts: 56
Nice work. I've also been working on a midi Arduino however i have very little programming knowledge. It can play poly using up to 3 seperate timers with outputs of each tied together but i ran into issues doing it that way. Sadly i went back to not combining the channels and can play alternating notes using more than 1 Tesla coil which will sound great once i build a few more coils. Anyhow i am looking forward to your Poly sketch to see how its all done up. Keep up the good work and its nice to see your willing to share.
edit: You can also use along with midi yoke to stream the midi to the Arduino with usb rather than use extra components if you wanna play midi directly from a pc. Its worked very well for me
Registered Member #1643
Joined: Mon Aug 18 2008, 06:10PM
Location:
Posts: 1039
Nice, I myself for awhile had one going, just tones though, no midi...using a LCD screen and encoders...will look into trying this for fun, hope to see more!
I'd be more interested in the polyphonic though, mono is boring and I already do that off a basic op-amp and FL-Studios :( hehe
Registered Member #4362
Joined: Sat Jan 21 2012, 03:44AM
Location: Texas
Posts: 98
Thanks for the code, it works great. One question, my coil produces very weak sparks while playing keyboard. I would like to increase duration to get a few more cycles and more spark.
Im new to arduino and im not sure where to make a change. on timedelay?
This site is powered by e107, which is released under the GNU GPL License. All work on this site, except where otherwise noted, is licensed under a Creative Commons Attribution-ShareAlike 2.5 License. By submitting any information to this site, you agree that anything submitted will be so licensed. Please read our Disclaimer and Policies page for information on your rights and responsibilities regarding this site.