question re. pmw outputs

hi

I have been building a MIDI based interface for controlling LED's, I am running this from a 12v car battery as it needs to be mobile. I have 10 1W LED's that I want to control. The problem I am encountering is that the LED's that are plugged into the PMW pins fade in and out when triggered whilst the ones that are not plugged into the PMW pins work great. I am using the following transistors:

which work really well - except for with the PMW outputs. Is this something to do with the pullup resistors?
Everything else works great and there is pretty much zero latency, I have even managed to build them a wireless controller using an ipod touch and the iTouchMidi app but the fade (although pretty) is not what I am looking for.
any help would be greatly appreciated

I don't know too much about electronics and specific components, but this comes to mind:

Could the transistor be too slow for the PWM wave? Because (I think) the speed of the transistor and the speed of the PWM wave interfering may cause the fading.
Sort of like playing two different musical notes at the same time. The combined notes can seem to get louder and softer.
And an ascii diagram 'cause I'm bored:
wave 1
| | | | | | | | | | | | | | | | | | | | |
wave 2
| | | | | | | | | | | | | | | | | | | | | | | | | |
^ louder ^ louder ^louder ^louder

Sorry if this is completely stupid.

Make sure you're using current limiting resistors on those LED's, and if you're using 1W LED's the output of the arduino won't drive them fully, there's only about 40mA available to source from.

The pwm outputs act exactly the same as the other digital pins when using digitalWrite. What does your code look like?

thanks for your replies.
i tried a few different transistors and these where the only ones that worked.
The arduino not being able to fully drive them is ok - as they are bright enough at the moment, but for future reference how would i go about driving them fully?
do you know what rating resistors i would need to use?
the code i am using is outlined below, it is just one that i got from this forum with a few things added.

/* Midi In Basic  0.2 // kuki 8.2007
 *
 * -----------------
 * listen for midi serial data, and light leds for individual notes

 IMPORTANT:
 your arduino might not start if it receives data directly after a reset, because the bootloader thinks you want to uplad a new progam.
 you might need to unplug the midi-hardware until the board is running your program. that is when that statusLed turns on.

#####################################################################################################################################################
SOMETHING ABOUT MIDI MESSAGES
 midi messages start with one status byte followed by 1 _or_ 2 data bytes, depending on the command

 example midi message: 144-36-100
   the status byte "144" tells us what to do. "144" means "note on".
   in this case the second bytes tells us which note to play (36=middle C)
   the third byte is the velocity for that note (that is how powerful the note was struck= 100)
  
 example midi message: 128-36
   this message is a "note off" message (status byte = 128). it is followed by the note (data byte = 36)
   since "note off" messages don't need a velocity value (it's just OFF) there will be no third byte in this case
   NOTE: some midi keyboards will never send a "note off" message, but rather a "note on with zero velocity"
  
 do a web search for midi messages to learn more about aftertouch, poly-pressure, midi time code, midi clock and more interesting things.
#####################################################################################################################################################

HARDWARE NOTE:
The Midi Socket is connected to arduino RX through an opto-isolator to invert the midi signal and seperate the circuits of individual instruments.
connect 8 leds to pin2-pin9 on your arduino.

####################################################################################################################################################


 */

//variables setup

byte incomingByte;
byte note;
byte velocity;


int statusLed = 13;   // select the pin for the LED

int action=2; //0 =note off ; 1=note on ; 2= nada


//setup: declaring iputs and outputs and begin serial
void setup() {
  pinMode(statusLed,OUTPUT);   // declare the LED's pin as output
  pinMode(2,OUTPUT);
  pinMode(3,OUTPUT);
  pinMode(4,OUTPUT);
  pinMode(5,OUTPUT);
  pinMode(6,OUTPUT);
  pinMode(7,OUTPUT);
  pinMode(8,OUTPUT);
  pinMode(9,OUTPUT);
  pinMode(12,OUTPUT);
  pinMode(15,OUTPUT);
  
  //start serial with midi baudrate 31250 or 38400 for debugging
  Serial.begin(31250);        
  digitalWrite(statusLed,HIGH);  
}

//loop: wait for serial data, and interpret the message
void loop () {
  if (Serial.available() > 0) {
    // read the incoming byte:
    incomingByte = Serial.read();

    // wait for as status-byte, channel 1, note on or off
    if (incomingByte== 144){ // note on message starting starting
      action=1;
    }else if (incomingByte== 128){ // note off message starting
      action=0;
    }else if (incomingByte== 208){ // aftertouch message starting
       //not implemented yet
    }else if (incomingByte== 160){ // polypressure message starting
       //not implemented yet
    }else if ( (action==0)&&(note==0) ){ // if we received a "note off", we wait for which note (databyte)
      note=incomingByte;
      playNote(note, 0);
      note=0;
      velocity=0;
      action=2;
    }else if ( (action==1)&&(note==0) ){ // if we received a "note on", we wait for the note (databyte)
      note=incomingByte;
    }else if ( (action==1)&&(note!=0) ){ // ...and then the velocity
      velocity=incomingByte;
      playNote(note, velocity);
      note=0;
      velocity=0;
      action=0;
    }else{
      //nada
    }
  }
}

void blink(){
  digitalWrite(statusLed, HIGH);
  delay(100);
  digitalWrite(statusLed, LOW);
  delay(100);
}


void playNote(byte note, byte velocity){
  int value=LOW;
  if (velocity >10){
      value=HIGH;
  }else{
   value=LOW;
  }

 //since we don't want to "play" all notes we wait for a note between 36 & 44
 if(note>=36 && note<37){
   byte myPin=6; // to get a pinnumber between 2 and 9
   digitalWrite(myPin, value);
 }

 if(note>=37 && note<38){
   byte myPin=7; // to get a pinnumber between 2 and 9
   digitalWrite(myPin, value);
 }

 if(note>=38 && note<39){
   byte myPin=8; // to get a pinnumber between 2 and 9
   digitalWrite(myPin, value);
 }
 
  if(note>=39 && note<40){
   byte myPin=9; // to get a pinnumber between 2 and 9
   digitalWrite(myPin, value);
 }
 
   if(note>=40 && note<41){
   byte myPin=12; // to get a pinnumber between 2 and 9
   digitalWrite(myPin, value);
 }
 
 if(note>=41 && note<42){
   byte myPin=5; // to get a pinnumber between 2 and 9
   digitalWrite(myPin, value);
 }
 
  if(note>=42 && note<43){
   byte myPin=3; // to get a pinnumber between 2 and 9
   digitalWrite(myPin, value);
 }
 
  if(note>=43 && note<44){
   byte myPin=2; // to get a pinnumber between 2 and 9
   digitalWrite(myPin, value);
 }
 
  if(note>=44 && note<45){
   byte myPin=10; // to get a pinnumber between 2 and 9
   digitalWrite(myPin, value);
 }
 
  if(note>=45 && note<46){
   byte myPin=11; // to get a pinnumber between 2 and 9
   digitalWrite(myPin, value);
 }
 
}

just a quick update - i put in some 1M series resistors and it works perfectly now - no fading or anything. Although the fading was so smooth and much smoother than I have been able to achieve by mapping midi cc values to the dimming. Have managed to sequence the LED's through ableton and control the whole set up wirelessly using an ipod touch and the brilliant OSCulator. Will post some videos of the whole thing in action after the show this weekend. Thanks again for the advice

Hi, I have some questions about this topic... i hope someone will can help me!

I have some problems connecting a Midi Controller (m-audio keystudio 25) to my arduino. I can't get polyphonic midi or fast secuences of midi notes.

But when I connect the arduino to my computer it works perfectly and it can "play" everything i send from cubase or from the midi controller via cubase.

I've been trying to understand it, i think that the controller sends more bytes that 144-xx-yy when i press a note.

One question more of this code:

if (Serial.available() > 0) {

  • // read the incoming byte:*
  • incomingByte = Serial.read();*

if it doesn't arribe any byte, what happens? it continues or it stops here?

Thanks for all and sorry for my english :slight_smile:

if it doesn't arribe any byte, what happens? it continues or it stops here?

It continues to execute the next statement.

I can't get polyphonic midi or fast secuences of midi notes.

It sounds like something is blocking in the input routine. You need to post more of your code.

P.S. Post between the square brackets you get when you click on the hash icon in the reply box.

I don't know if i've understood well the PS.

It sounds like something is blocking in the input routine. You need to post more of your code.

Yes, i thought that, but if with cubase the same code can play so many notes at the same time... it's strange...

Here is the code, i've commented for easy undertanding (i hope)

//variables setup

const int NumNotes=22;
const int pols=50;

int statusLed=13;
byte incomingByte;
boolean EstatNotes[NumNotes];
long Intervals[NumNotes];
boolean alguna;
int pinNota[]={52,39,53,34,50,51,30,48,38,49,37,44,  46,31,47,41,45,42,35,43,36,40};
byte velocity=20;
int action=0;
int iteracio=0;
int nota;
byte prova;

void setup() {
  pinMode(statusLed,OUTPUT);   // declare the LED's pin as output
  for (int Pin = 0; Pin < NumNotes; Pin++)  {
     pinMode(pinNota[Pin], OUTPUT);
     EstatNotes[Pin]= false;
     
  }
  Serial.begin(31250); //9600 for USB i 31250 for MIDI i 38400 for debugging 
  digitalWrite(statusLed,LOW);
}

void loop () {
  if (Serial.available() > 0) {
    // read the incoming byte:
    incomingByte = Serial.read();

    if (action==1){ // we've received a NOTE ON, we read the note
      nota=incomingByte;  
      if(nota>=60 && nota<82){ //if it's a note betwen the limits we can play
        nota=nota-60; //put right the index
        action=2; //we have to see the velocity
      }else{ //can't play this note
        action=0; //wait for a NOTE ON message
      }
    }else if (action==2){ //we've received a note on and the note, we read the velocity
      velocity=incomingByte;
      if(velocity>0){ //if it isn't a NOTE OFF message
        PlayNote(nota); //play the note "nota"
      }else{
        intermitent(20); //we will blink the led status to know if the NOTE OFF its a NOTE ON with 0 velocity
      }
      action=0;  

    }else if (incomingByte== 208){ // aftertouch message starting
      //nothing
    }else if (incomingByte== 160){ // polypressure message starting
      action=1;
    }else if (incomingByte== 128){ // aftertouch message starting
      //nothing
    }else if (incomingByte== 144){ // NOTE ON message starting
      action=1;
    }else{ 
      //nothing
    }
  }
  //we have a percussion instrument we have to stop the signal 5millis after the activation.
  StopNotes();
}


void PlayNote(int nota){
  EstatNotes[nota]=true; //record that the note "nota" is activated
  activaNota(nota, HIGH); //activate the note
  Intervals[nota]=millis(); //record in wich time we've activated the note
}

void StopNotes(){ //we have a percussion instrument we have to stop the signal 5millis after the activation.
  for (int k = 0; k < NumNotes; k++)  {
    if(EstatNotes[k]){ //if its playing any note
      if (millis()>=Intervals[k]+pols){ //its time to stop it?
        activaNota(k,LOW); //stop the note
        EstatNotes[k]=false; //record that the note is stopped
      } 
    }
  }
}

void activaNota(int index, byte valor){
  digitalWrite(pinNota[index], valor);
}

void blink(byte valor){
  digitalWrite(statusLed, valor);
}

void intermitent(int temps){
  blink(HIGH);
  delay(temps);
  blink(LOW);
  delay(temps);  
}

Something that sends the midi controller that cubase don't is blocking the input routine...

thanks a lot, Grupmpy_Mike

but if with cubase the same code can play so many notes at the same time

From what I can gather the difference is that in one case the arduino is sending midi data and the results are OK but in the other case the arduino is receiving midi data and that is not working quite right. If that is so then there is no mystery, it is your receiving software that is blocking things.

Now sorry but what I don't like about your code is the use of a lot of else statements. It makes it difficult to see what if the else is referring to. However, I would suggest this is not the way to receive midi data. Receiving multi byte data is difficult because you have to know where you are in the sequence and how many more bytes to expect. So what you need is a state variable to keep track of this, rather like you have used the variable 'action'.

have a look at the code I wrote in my Glockenspiel project:-
http://www.thebox.myzen.co.uk/Hardware/Glockenspiel.html
This looks for note on messages, then when it gets one sets a variable (state variable) so next time it gets a byte it knows where to put it.

Also watch out for the delay function, I see you use this. This blocks any further action / processing until it expires. Try and code round this like you did in the StopNote routine.

first, thanks a lot!!

i've been looking your code (I'm trying to do practically the same but with a metallophone), you can see it here: http://b.static.ak.fbcdn.net/rsrc.php/zAH44/hash/1uvvxs1m.swf?v=134508608256&ev=0

From what I can gather the difference is that in one case the arduino is sending midi data and the results are OK but in the other case the arduino is receiving midi data

no, the function of cubase and controller is the same, send to arduino midi messages to play with a metalophone. If cubase send the message (thru a m-audio firewire 410) it works perfectly (you can see it in the video link) but not sending the messages from controller... i don't understand.

I agree that i have to expect (with the action variable) all the bytes that will arribe, but the problem is that the controller seems to send a lot of bytes after the velocity...

i'm sorry for so many comments...

i've been all day testing everything i imagine. Finally, i made this code:

if (Serial.available() > 0) {
    // read the incoming byte:
    incomingByte = Serial.read();
   blink(HIGH);
   delay(200);
   blink(LOW);
   delay(200);
}

connecting to cubase midi out, it didn't do anything until i send a note on and it blink 3 times (3 bytes) and the same with note out

connecting to my controller (a m-audio keyboard), if i didn't do anything it starts to blink a lot. Then, my controller is sending messages when i don't play or move the controllers and buttons. Anyone can tell me if it's normal and if i can fix it?

thanks!

PS. Grumpy, thanks for the code, i use the switch structure it's so much better! I don't understand for what is this condition in the first and second case (getting note and velocity)?

if(incomingByte < 128) {

thanks a lot!

I don't understand for what is this condition in the first and second case (getting note and velocity)?

The note and velocity will be values that are less than 128. If we get something that is greater than this then we have missed something or are not being sent correct data and so need to re synchronise the incoming data stream, to look for a MIDI message again. Normally this will not happen but if it does then the code handles it and re sets the state variable.

thanks a lot one more time and also sorry for my english...

I've solved my problem. It was the keyboard (m-audio keystudio25, I don't recomend it for sending midi messages to arduino!!!!).

First, it sends the byte 254 every few millis (call active sensing, for test the conexions).

Second, this controller (i don't know if it happens with every controller of m-audio), if I play to notes at the same time, it doesn't sends 6 bytes, it sends 5 bytes:

NOTE_ON, NOTE_1, VEL_1, NOTE_2, VEL_2.

And the same with note off, but with vel=0.

Third, if I play a fast note (down and up immediatly) it sends NOTE_ON, NOTE_1, VEL_1, NOTE_1, 0.

I haven't found it anywhere... then if anyone have this problem, i hope it helps. Its my code for read what was my arduino receiving from de midi conexion:

/* THIS CODE READ THE BYTES WE RECIEVE AND SHOW US WITH THE THREE LEDS 13,12,11 FOR UNDERSTANDING THE MIDI MESSAGES*/

int statusLed=13;  //one
int statusLed2=12;  //ten
int statusLed3=11;  //hundred
byte incomingByte;

void setup() {
  pinMode(statusLed,OUTPUT);   // declare the LED's pin as output
  pinMode(statusLed2,OUTPUT);   // declare the LED's pin as output
  pinMode(statusLed3,OUTPUT);   // declare the LED's pin as output

  Serial.begin(31250); //9600 for USB i 31250 for MIDI i 38400 for debugging 
}

void loop () {  
  if (Serial.available() > 0) {
    // read the incoming byte:
    incomingByte = Serial.read();
    comptador(incomingByte);
  }
}

void comptador(int num){
  if (num<0){
    intermitent(30,3);
    intermitent(30,3);
    intermitent(30,3);
    intermitent(30,3);
  }else if (num==0){
    intermitent(30,1);
    intermitent(30,1);
    intermitent(30,1);
    intermitent(30,1);
  }else{ 
    while(num>=100){
      num=num-100;
      intermitent(200,3);
    }
    delay(200);
    while(num>=10){
      num=num-10;
      intermitent(200,2);
    }
    delay(200);
    while(num>=1){
      num=num-1;
      intermitent(200,1);
    }
  }
  delay(300);
  intermitent(20,4); //end of number
  delay(500);  
}

void intermitent(int temps,int led){
  blink(HIGH,led);
  delay(temps);
  blink(LOW,led);
  delay(temps);  
}

void blink(byte valor, int nled){
  switch (nled){
    case 1:
      digitalWrite(statusLed, valor);
      break;
    case 2:
      digitalWrite(statusLed2, valor);
      break;
    case 3:
      digitalWrite(statusLed3, valor);
      break;
    case 4:
      digitalWrite(statusLed, valor);
      digitalWrite(statusLed2, valor);
      digitalWrite(statusLed3, valor);
      break;
  }