Show Posts
Pages: [1] 2
1  Using Arduino / LEDs and Multiplexing / Re: Help with Colorduino on: June 02, 2013, 03:02:02 am
I had the same problem. I was trying to upload to Colorduino through an FTDI cable but was getting "stk500_recv() programmer is not responding" errors. It resolved when I also connected the DTR pin of my FTDI cable to the Colorduino DTR pin, in addition to the four pins described in Lincomatic's "Lampduino" Instructable.
2  Using Arduino / Audio / Re: Velocity Sensitivity with non-MIDI Keyboard on: March 23, 2013, 12:38:28 am
The 122 switches give velocity information by comparing the timing between the two buttons for each key, which are spaced at slightly different depths. I'm surprised it works with any reliability, but apparently it does well enough and is a pretty common design for simple keyboards:
http://www.openmusiclabs.com/learning/digital/input-matrix-scanning/keyboard/

I would think this would be possible with one arduino. You'd need to figure out an efficient loop that would monitor and track the press timing for each switch, calculate velocities using timing differences, and send key ON and OFF MIDI signals when appropriate. One reasonable first step might be to try to create MIDI output from one pair of switches on one key, as that would sidestep all the complications related to multiplexing.
3  Community / Exhibition / Gallery / Re: Smooth animation with an 8x8 RGB LED matrix on: March 04, 2013, 07:22:53 pm
This looks great!

Once my 8x8 matrix arrives, I'd like to try to adapt it as an interactive nightlight, where new particles would be triggered if a PIR motion detector is triggered while ambient light is low. I was thinking I might be able to accomplish this by updating your "Flame.ino" example (https://github.com/giladaya/arduino-particle-sys/blob/master/examples/Flame/Flame.ino). In that example, some of the parameters for the particle system are established in Setup:
Code:
source.x = 112;  
source.y = 1;  
Emitter_Fountain::minLife = 20;  
Emitter_Fountain::maxLife = 80;  
Particle_Std::ay = 1;

I was thinking that I could add some lines to Loop that would adjust these continuously. For instance:
Code:
if (triggerPin == HIGH && ambientLight <= lightThreshold) {      //assuming these are all defined elsewhere...
   Particle_Std::ay = 1;
}
else { Particle_Std::ay = 0; }

I expect this would leave the particles at the bottom of the display most of the time, but then they'd shoot up when the PIR is triggered in the dark.
Any ideas or suggestions for a more elegant implementation, or smarter usage of the library? Thanks! I'm looking forward to experimenting with this.
4  Community / Exhibition / Gallery / Re: "Sound Radar" midi controller on: February 26, 2013, 02:24:07 pm
Very cool!
From a usage point of view, it might be more interactive if you could figure out a way to rotate the sensors (perhaps mount with a slip ring: https://www.adafruit.com/products/1195) underneath so that the disc and magnets on top were stationary, allowing the user to tweak the beat pattern without stopping. To complete the look, you could use a string of green EL wire alongside the sensors, sweeping underneath like a radar display. Mechanically, that'd be harder to pull off, and it might lose some of the tactile spinniness you've got there, but it could be a fruitful variation.
5  Using Arduino / Audio / Re: Library for playing MIDI files from the Arduino on: January 06, 2013, 04:35:34 pm
Thanks for your work on this -- I can see a lot of applications and think it will be helpful for a lot of people.

I have a related newbie question: For those of us without an SD-enabled Ethernet shield, what adjustments should be made? I have an adafruit waveshield and will be getting an SD breakout shield, but I'm not sure what modifications in SD reading pins to make. For instance, your MIDIFile_Play sample uses "#define SD_SELECT 4"; it might be helpful to explain what an "SD chip select pin" is and what other common values might be for other arduino versions or shields with SD readers.

Also, I imagine it would be possible to store very small MIDI files in the arduino's memory itself. That would open up some options for people who want to play back simple music or other actions (lights, servos, etc.) with an open, easy-to-modify standard like MIDI, but without needing to include an SD card in their setup. Would that be hard to do? What would be the best way to approach that?

Thanks again. Looking forward to learning enough to use this.
6  Topics / Home Automation and Networked Objects / Re: How to dispense laundry soap on: October 03, 2012, 01:18:53 pm
Another method would be to have your machine mechanically press the pump (with a cam or a solenoid) on a standard liquid soap dispenser, like this one:
http://www.foodservicewarehouse.com/thunder-group/plsd377/p366978.aspx
Could vary quantity by number of pumps, timing, etc.
7  Using Arduino / LEDs and Multiplexing / Re: RGB Sketch that shouldn't work but does? Does anyone know why? on: September 05, 2012, 05:39:19 pm
I suspect you're using a common anode RGB LED, whereas the example might be using a common cathode RGB LED.
http://flashgamer.com/arduino/comments/rgb-led-common-cathode-or-common-anode
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1287565569
8  Using Arduino / Audio / Re: Make LEDs blink in rythm with music on: August 10, 2012, 05:15:24 pm
I'd move the LED pin declaration up before the tone loop, and then toggle the LEDs to go on before each tone and off before each rest. I haven't tested this but I think it'd work.

Code:
int led = 13;
pinMode(led, OUTPUT)

for (int thisNote = 0; thisNote < 64; thisNote++) {
    int noteDuration = 900/noteDurations[thisNote];
    digitalWrite(led, HIGH);
    tone(8, melody[thisNote],noteDuration);
    digitalWrite(led, LOW);
    int pauseBetweenNotes = noteDuration * 1;
    delay(pauseBetweenNotes);
    noTone(8);
  }

9  Using Arduino / Audio / Advantages of DAC over PWM for synthesizer tone generation? on: July 24, 2012, 03:22:27 pm
Adafruit offers a new 12-bit DAC breakout that operates over I2C:
http://www.adafruit.com/products/935

I imagine this might be an easier way to output synthesized sound than using PWM output filtered in hardware, no? What are the advantages/disadvantages?

It looks like the I2C interface can operate 100kbps on the standard (arduino-capable) mode -- what does that mean in terms of output frequency range?

Thanks for any help!
10  Using Arduino / Audio / Re: play speed control with MP3 module on: April 30, 2012, 05:04:59 pm
If you don't mind converting the MP3s to WAV format first, you could accomplish this effect with the adafruit wave shield.

http://www.adafruit.com/blog/2008/05/21/wave-shield-bending-the-playback-sample-rate/
11  Using Arduino / Audio / MIDI playback/sequencer with finely controlled beat timing? on: January 11, 2012, 05:57:07 pm
I've come across a variety of projects which produce MIDI output based on a strict timing grid (e.g. Mike's Glockenspiel, MidiDuino, Cahors, etc.). Could anyone direct me towards some code which allows a finer timing grid, like MIDI ticks? Based on the sophisticated work I've seen using the internal timers to make synthesizers, it seems like sending MIDI signals on a precise schedule shouldn't be too hard, but I'm having trouble bridging that knowledge gap.
Thanks!
12  Using Arduino / Audio / Re: Clarification on MIDI Bank select for the VS1053 music chip on: January 03, 2012, 05:12:54 pm
Two banks, as described in the Sparkfun example code:
http://dlnmh9ip6v2uc.cloudfront.net/datasheets/Dev/Arduino/Shields/MusicIntrument_Example.pde
 talkMIDI(0xB0, 0, 0x00); //Default bank GM1
 talkMIDI(0xB0, 0, 0x78); //Bank select drums

The sparkfun example also mentions a third bank that seems to be the same as the GM1 one:
 talkMIDI(0xB0, 0, 0x79); //Bank select Melodic
13  Using Arduino / Audio / Re: Read and Play MIDI file in arduino on: January 03, 2012, 01:14:21 am
[Continuation of my prior post]
That seems to work well enough, but one thing I'd really like to improve is the "feel" of the beat and the ability to plug in more complicated sequences. As currently set up, each beat is locked in a static "grid" and I can't easily add additional subdivisions (such as 32nd notes or triplets), or play notes longer than a 16th. Also, the timing might be a bit off since calculations happen between each delay. I can't tell.

So, for my next step I'd like to play a MIDI file, or perhaps a sanitized, simplified version thereof, using a timer instead of delays. I've seen examples of how to accomplish a single task using a timer, but I get confused when trying to apply to a long list of events. In pseudo-code, I'd like to:

0. Load 2D array with a sequence of { int tick, int note, int velocity } lines, with a noteOn and noteOff for each note
1. Loop through the array as a timer counts ticks for each measure.
2. With each array item, check if the tick has passed. If so, trigger the noteOn. If not, wait a bit (1ms?) and check that point in the array again. (I think that triggering within about 10ms of the desired time will be good enough for me.)
3. If the timer count hits 384 (384 = 4 beats x 4 subdivisions x 24 ticks; I think that's a tenth as many as the MIDI file I was working from), reset it to zero and go back to step 1.

Is that a sensible way to set it up? How could I optimize it better to allow more cycles for reading and interpreting input?

I've given a first shot at coding this, but I'm getting errors relating to pointers (which I'm trying to learn about) in the loop() section where I look up the note in the array (2nd field) based on the tick in the array (1st field). Should I be setting this up differently, or would it be a simple syntax tweak to fix this?

Code:
#include <NewSoftSerial.h>
NewSoftSerial mySerial(2, 3); //Soft TX on 3, we don't use RX in this code

byte note = 0; //The MIDI note value to be played
byte resetMIDI = 4; //Tied to VS1053 Reset line
byte ledPin = 13; //MIDI traffic indicator
int instrument = 0;
int scale_major[] = {0, 2, 4, 5, 7, 9, 11};        //one octave of major scale
int scale_minpent[] = {0, 2, 3, 5, 6, 7, 10};     //minor pentatonic scale
int scale_consonant[] = {0, 2, 4, 7, 9, 12, 14}; //major pentatonic scale plus octave and 9th (to be same array length as others)


int drum_motown[100][3] = //Tick (out of 384 per bar), note, velocity
{                         //This is an attempt to adapt data from an actual MIDI file, with
  { 0,54,94 },            //matching 0-velocity lines in place of noteOff messages
  { 0,48,97 },
  { 8,54,0 },
  { 48,54,75 },
  { 51,48,0 },
  { 54,54,0 },
  { 96,50,106 },
  { 96,54,96 },
  { 103,54,0 },
  { 127,50,0 },
  { 144,54,73 },
  { 153,54,0 },
  { 171,50,92 },
  { 177,50,0 },
  { 192,54,82 },
  { 201,54,0 },
  { 219,48,85 },
  { 240,54,84 },
  { 240,48,0 },
  { 246,54,0 },
  { 267,48,86 },
  { 273,48,0 },
  { 288,54,101 },
  { 288,50,103 },
  { 296,54,0 },
  { 318,50,0 },
  { 336,54,77 },
  { 344,54,0 },
  { 363,50,70 },
  { 368,50,0 }
};
int drumSpot = 0;
int drumSpotTime = 0;

long curTime = 0;
int timeclock96 = 0;  //96 ticks per beat, based on 4 subdivs per beat and 24 ticks per subdiv (not 240 like the source midi file)




void setup() {
  Serial.begin(57600);

  //Setup soft serial for MIDI control
  mySerial.begin(31250);

  //Reset the VS1053
  pinMode(resetMIDI, OUTPUT);
  digitalWrite(resetMIDI, LOW);
  delay(100);
  digitalWrite(resetMIDI, HIGH);
  delay(100);
 
  talkMIDI(0xB0, 0x07, 30); //0xB0 is channel message for channel 1 (0), set channel volume to 30
  talkMIDI(0xB0, 0, 0x00); //Bank select GM1
 
  talkMIDI(0xB9, 0x07, 50); //0xB0 is channel message for channel 10 (9), set channel volume to 50
  talkMIDI(0xB9, 0, 0x78); //Bank select drums
 
  curTime = millis();
}




void loop() {
  timeclock96 = (millis() - curTime)/96;
  Serial.println(timeclock96);
  for (int j = drumSpot; j<100; j++) {
    drumSpotTime = (int)drum_motown[drumSpot,0];
    if (drumSpotTime < timeclock96) {
      noteOn(0, (byte)10, drum_motown[drumSpot,1], drum_motown[drumSpot,2]);   //ERROR HERE: invalid conversion from int* to byte
    }
  if (timeclock96 >= 96) {
    curTime = millis();
  }
 
//  playNoodling(0, random(48,59), scale_consonant, 180, 0);

}


void playNoodling(byte channel, int key, int scale[], float tempo, int instrument) {
  Serial.print(" Instrument: ");
  Serial.println(instrument, DEC);
  talkMIDI(0xC0, instrument, 0); //Set instrument number. 0xC0 is a 1 data byte command
  talkMIDI(0xCA, 30, 0); //Set instrument number. 0xC0 is a 1 data byte command
 
  for (int i = 0; i < 16; i++) {
    int note = key + scale[random(0, 6)];
    noteOn(1, channel, note, 80);
    noteOn(0, 10, drum_pattern1[i], 50);
   
    //1 minute      60 seconds    1000 ms               
    //---------  x  ---------  x  --------
    //120 Beats     1 minute      1 second
    delay(60000/tempo);
    noteOff(1, channel, note, 0);
    noteOff(0, 10, drum_pattern1[i], 0);
  }
}



void allOff(byte channel) {
  talkMIDI ( (0xB0 | channel), 123, 0);
}

//Send a MIDI note-on message.  Like pressing a piano key
//channel ranges from 0-15
void noteOn(boolean instr, byte channel, byte note, byte attack_velocity) {
  talkMIDI( (0x90 | channel), note, attack_velocity);
}

//Send a MIDI note-off message.  Like releasing a piano key
void noteOff(boolean instr, byte channel, byte note, byte release_velocity) {
  talkMIDI( (0x80 | channel), note, release_velocity);
}

//Plays a MIDI note. Doesn't check to see that cmd is greater than 127, or that data values are less than 127
void talkMIDI(byte cmd, byte data1, byte data2) {
  digitalWrite(ledPin, HIGH);
//  Serial.write(cmd);
//  Serial.write(data1);
  mySerial.print(cmd, BYTE);
  mySerial.print(data1, BYTE);

  //Some commands only have one data byte. All cmds less than 0xBn have 2 data bytes
  //(sort of: http://253.ccarh.org/handout/midiprotocol/)
  if( (cmd & 0xF0) <= 0xB0)
//     Serial.write(data2);
   mySerial.print(data2, BYTE);

  digitalWrite(ledPin, LOW);
}



Many thanks in advance to anyone who can provide a suggestion as to how to improve this code! My apologies that it's so scrappy!
14  Using Arduino / Audio / Re: Read and Play MIDI file in arduino on: January 03, 2012, 01:13:28 am
Neat project! I'm trying to accomplish something similar. Specifically, I'd like the Arduino to output midi signals to my SparkFun Music Instrument Shield http://www.sparkfun.com/products/10587. Ideally, I'd like to combine some "canned" midi signals (including a variety of different drum loops) with some "live" signals generated from sensors. I had some success using the NewSoftSerial library to feed MIDI data to the shield.

Here's a sketch I did (based on one of the Sparkfun example sketches) which plays a simple beat. It reads the notes from characters in an array ("b" is kick, "t" is hi-hat, "k" is snare, space is a rest). It reads the delays attached to each note from another array, which in this case I've set up to allow swing on the 16ths.
Code:

#include <NewSoftSerial.h>
NewSoftSerial mySerial(2, 3); //Soft TX on 3, we don't use RX in this code

byte note = 0; //The MIDI note value to be played
byte resetMIDI = 4; //Tied to VS1053 Reset line
byte ledPin = 13; //MIDI traffic inidicator
int instrument = 0;


int length;
char beat1[] = { "bbttktttbktbkttt"};  //Beat pattern #1
char beat2[] = { "bttbb   b  bb   "};    //Beat pattern #2
bool tempoUp = 1;
float swing = 0.33;                           //0 is no swing; 0.33 should approximate typical "triplet" swing (2/3 + 1/3)
float beats[] = { 1+swing, 1-swing, 1+swing, 1-swing, 1+swing, 1-swing, 1+swing, 1-swing,
  1+swing, 1-swing, 1+swing, 1-swing, 1+swing, 1-swing, 1+swing, 1-swing }; 

float tempo = 60;

void playNote(char note, float duration) {
  char names[] = { 'b', 't', 'k' };
  int tones[] = { 35, 42, 38 };

  for (int i = 0; i < 3; i++) {
    if (names[i] == note) {
      Serial.print(note);
      noteOn(0,tones[i],100);
      // 16th note in ms         1 beat             1 min               60000 ms   
      //  = 15000/tempo        ------------      x -------          x  ----------
      //                               4 16ths notes     beats (bpm)     min         
      delay(duration*15000/tempo);  //duration adjustment allows for swing
      noteOff(0,tones[i],0);
    }
  }
}

void playLoop(char beat[]) {
  Serial.print("Swing:");
  Serial.print(float(swing));
  Serial.print(" ");
 
  Serial.print("Tempo:");
  Serial.print(int(tempo));
  Serial.print(" ");
  for (int i = 0; i < 16; i++) {
    if (beat[i] == ' ') {
      Serial.print("-");
      delay(beats[i]*15000/tempo);  //See above; each 16th's length in ms is 15000/tempo
    } else {
      playNote(beat[i], beats[i]);
    }
    delay(0);
    if (tempoUp) { tempo *= 1.005; }  //accelerando...
    else { tempo /= 1.005; }          //or decelerando
    if (tempo > 150) { tempoUp = 0; } //slow down after 150 bpm
    if (tempo < 50) { tempoUp = 1; }  //speed up after 50 bpm
  }
  Serial.println("");
}


void setup() {
  Serial.begin(57600);
  //Setup soft serial for MIDI control
  mySerial.begin(31250);

  //Reset the VS1053
  pinMode(resetMIDI, OUTPUT);
  digitalWrite(resetMIDI, LOW);
  delay(100);
  digitalWrite(resetMIDI, HIGH);
  delay(100);
}

void loop() {
  talkMIDI(0xB0, 0x07, 50);      //0xB0 is channel message, set channel volume to near max (127)
  talkMIDI(0xB0, 0, 0x78);       //Bank select drums
  talkMIDI(0xC0, instrument, 0); //Select instrument; doesn't matter which for drums
 
  playLoop(beat1);
  playLoop(beat2);
 
  for (int i = 0; i < 16; i++) {  //Set swing for each pair in beats[]
    if (i%2 == 0) { beats[i] = 1+swing; }
    else { beats[i] = 1-swing; }
  }
}


void noteOn(byte channel, byte note, byte attack_velocity) {
  talkMIDI( (0x90 | channel), note, attack_velocity);
}

void noteOff(byte channel, byte note, byte release_velocity) {
  talkMIDI( (0x80 | channel), note, release_velocity);
}

//Plays a MIDI note. Doesn't check to see that cmd is greater than 127, or that data values are less than 127
void talkMIDI(byte cmd, byte data1, byte data2) {
  digitalWrite(ledPin, HIGH);
//  Serial.write(cmd);
//  Serial.write(data1);
  mySerial.print(cmd, BYTE);
  mySerial.print(data1, BYTE);
  if( (cmd & 0xF0) <= 0xB0 || (cmd & 0xF0) == 0xE0)
//     Serial.write(data2);
  mySerial.print(data2, BYTE);
  digitalWrite(ledPin, LOW);
}



To be continued in next post....
15  Forum 2005-2010 (read only) / Interfacing / Re: Ethernet shield - webClient example on: February 20, 2010, 02:37:42 am
I came across Georg Kaindl's recent Arduino Ethernet libraries and gave a shot at using his EthernetDHCP library to get my WebClient sketch to work.

I get this output:
Code:
Discovering servers....................
Requesting lease.
Obtained lease!
My IP address is 192.168.2.3
Gateway IP address is 192.168.2.1
DNS IP address is 192.168.2.1
hostName is Arduino

connecting...
Trying client.connect() #1.....    connection failed
Trying client.connect() #2.....    connected
Trying client.connect() #3.....    connection failed
Trying client.connect() #4.....    connection failed
Trying client.connect() #5.....    connection failed
Trying client.connect() #6.....    connection failed
Trying client.connect() #7.....    connection failed
Trying client.connect() #8.....    connection failed
Trying client.connect() #9.....    connection failed
Trying client.connect() #10.....    connection failed

...when I run this code:
Code:
//  Copyright (C) 2010 Georg Kaindl
//  http://gkaindl.com
//
//  This file is part of Arduino EthernetDHCP.
//
//  EthernetDHCP is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as
//  published by the Free Software Foundation, either version 3 of
//  the License, or (at your option) any later version.
//
//  EthernetDHCP is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with EthernetDHCP. If not, see
//  <http://www.gnu.org/licenses/>.
//

//  Illustrates how to use EthernetDHCP in polling (non-blocking)
//  mode.

#include <Ethernet.h>
#include <EthernetDHCP.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte server[] = { 66, 102, 7, 147 }; // Google

const char* ip_to_str(const uint8_t*);

Client client(server, 80);



void setup()
{
  Serial.begin(9600);
  
  // Initiate a DHCP session. The argument is the MAC (hardware) address that
  // you want your Ethernet shield to use. The second argument enables polling
  // mode, which means that this call will not block like in the
  // SynchronousDHCP example, but will return immediately.
  // Within your loop(), you can then poll the DHCP library for its status,
  // finding out its state, so that you can tell when a lease has been
  // obtained. You can even find out when the library is in the process of
  // renewing your lease.
  EthernetDHCP.begin(mac, 1);
}

void loop()
{
  static DhcpState prevState = DhcpStateNone;
  static unsigned long prevTime = 0;
  
  // poll() queries the DHCP library for its current state (all possible values
  // are shown in the switch statement below). This way, you can find out if a
  // lease has been obtained or is in the process of being renewed, without
  // blocking your sketch. Therefore, you could display an error message or
  // something if a lease cannot be obtained within reasonable time.
  // Also, poll() will actually run the DHCP module, just like maintain(), so
  // you should call either of these two methods at least once within your
  // loop() section, or you risk losing your DHCP lease when it expires!
  DhcpState state = EthernetDHCP.poll();

  if (prevState != state) {
    Serial.println();

    switch (state) {
      case DhcpStateDiscovering:
        Serial.print("Discovering servers.");
        break;
      case DhcpStateRequesting:
        Serial.print("Requesting lease.");
        break;
      case DhcpStateRenewing:
        Serial.print("Renewing lease.");
        break;
      case DhcpStateLeased: {
        Serial.println("Obtained lease!");

        // Since we're here, it means that we now have a DHCP lease, so we
        // print out some information.
        const byte* ipAddr = EthernetDHCP.ipAddress();
        const byte* gatewayAddr = EthernetDHCP.gatewayIpAddress();
        const byte* dnsAddr = EthernetDHCP.dnsIpAddress();

        Serial.print("My IP address is ");
        Serial.println(ip_to_str(ipAddr));

        Serial.print("Gateway IP address is ");
        Serial.println(ip_to_str(gatewayAddr));

        Serial.print("DNS IP address is ");
        Serial.println(ip_to_str(dnsAddr));

        //Serial.println();
        
        delay(2000);
        
        Serial.print("hostName is ");
        Serial.println(EthernetDHCP.hostName());
        Serial.println();
        
        Serial.println("connecting...");
  
        for (int i = 0; i < 10; i++){
          Serial.print("Trying client.connect() #");  //added line
          Serial.print(i+1);
          Serial.print(".....  ");
          delay(3000);
          if (client.connect()) {
            Serial.println("  connected");
            client.println("GET /search?q=arduino HTTP/1.0");
            client.println();
          } else {
            Serial.println("  connection failed");
          }
        }
        
        break;
      }
    }
  } else if (state != DhcpStateLeased && millis() - prevTime > 300) {
     prevTime = millis();
     Serial.print('.');
  }

  prevState = state;
}

// Just a utility function to nicely format an IP address.
const char* ip_to_str(const uint8_t* ipAddr)
{
  static char buf[16];
  sprintf(buf, "%d.%d.%d.%d\0", ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3]);
  return buf;
}

Any guesses from the tubes as to why no output from the GET command? Any guesses as to why the second client.connect() outputs "connected" but not the others?

Many many thanks!
Pages: [1] 2