PWM (delay) problems

Hello,
I’m building a BPM based LFO using the PWM output.
I have 8 BPM presaved (70, 80, 90, 100, 110, 120, 130, 140(pot controlled)) and use 6 Subdivision (1/2, 1/4. 1/8. 1/16, 1/32 and 1/64(pot controlled)).

I worked really good when i used only one wave form, but when i add a second wave form (controlled through a pot) the BPM is not correct any more. It is slowed down.

Here is the code i have now, feel free to give some pointers on making this code nicer. But my big issue is explained above. How do I solve this. I want to add a couple of waveforms but it’s not working properly when adding them.

#include <LCD4Bit.h>

/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  • BPM LFO - an Arduino-based Beat based LFO LFO
  • RonaldB, 20-08-2008
*/
LCD4Bit lcd = LCD4Bit(2); 

const int pinPwmout = 3;
const int pinBPM = 0;
const int pinSUB = 1;
const int pinWAVE = 2;
const int modeSquare = 100;
const int modeRandom = 200;
const int RAND_LOW_THRESHOLD = 30;
const int RAND_HIGH_THRESHOLD = 255;
int BPMmode = 0;
int SUBmode = 1;
int WAVEmode = 2;
int tempo;
int value;

void setup ()
{
pinMode(pinPwmout, OUTPUT);
lcd.init();
StartupMessage();
}

void StartupMessage()
{
lcd.clear();
lcd.cursorTo (1, 2);
lcd.printIn ("RoBo DIGITAL");
delay(1000);
lcd.cursorTo (2, 2);
lcd.printIn ("BPM LFO v1.0");
delay(1000);
lcd.clear();
} 

void CheckWaveform()
{
int v2 = analogRead (pinWAVE);
if(v2 >= 0 && v2 <= 500)
{
WAVEmode = modeSquare;
}
else if (v2 > 500)
{
WAVEmode = modeRandom;
}
UpdateDisplayWAVE();
{
UpdateDisplayWAVE();
}
}

void CheckBPM()
{
int v = analogRead (pinBPM);
if(v >= 0 && v <= 125) 
{
BPMmode = 857; //60000/70
}
else if (v > 125 && v <= 250)
{
BPMmode = 750; //60000/80
} 
else if (v > 250 && v <= 375)
{
BPMmode = 667; //60000/90
} 
else if (v > 375 && v <= 500)
{
BPMmode = 600; //60000/100
} 
else if (v > 500 && v <= 625)
{
BPMmode = 545; //60000/110
} 
else if (v > 625 && v <= 750)
{
BPMmode = 500; //60000/120
} 
else if (v > 750 && v <= 825)
{
BPMmode = 462; //60000/130
} 
else if (v > 825)
{
BPMmode = 429; //60000/140
} 
UpdateDisplayBPM();
{
UpdateDisplayBPM();
}

{
int v1 = analogRead (pinSUB);
if(v1 >= 0 && v1 <= 150)
{
SUBmode = 1; // 1/2
}
else if (v1 > 150 && v1 <= 300)
{
SUBmode = 2; // 1/4
}
// else if (v1 > 300 && v1 <= 400)
// {
// SUBmode = (8/3); // 1/8*
// }
else if (v1 > 300 && v1 <= 450)
{
SUBmode = 4; // 1/8
}
else if (v1 > 450 && v1 <= 600)
{
SUBmode = 8; // 1/16
}
else if (v1 > 600 && v1 <= 750)
{
SUBmode = 16; // 1/32
}
else if (v1 > 750)
{
SUBmode = 32; // 1/64
}

UpdateDisplaySUB();
{
UpdateDisplaySUB();
}
}
} 

void loop()
{
int counter = 0;
bool controlsChanged = false;
tempo = BPMmode/SUBmode;
CheckWaveform();
{
if(WAVEmode == modeSquare)
{
analogWrite (pinPwmout, 255);
delay(tempo);
analogWrite (pinPwmout, 0);
delay(tempo);
CheckBPM();
}
else if (WAVEmode == modeRandom)
{
// random mode, get a random number between thresholds
int randNumber = random(RAND_LOW_THRESHOLD, RAND_HIGH_THRESHOLD);
analogWrite (pinPwmout, randNumber);
delay(tempo);
analogWrite (pinPwmout, 255 - randNumber);
delay(tempo);
CheckBPM();
}
}
}

void UpdateDisplayBPM()
{
lcd.cursorTo(1, 0);
if (BPMmode == 857)
{
lcd.printIn ("BPM:70 ");
}
else if (BPMmode == 750)
{
lcd.printIn ("BPM:80 ");
}
else if (BPMmode == 667)
{
lcd.printIn ("BPM:90 ");
}
else if (BPMmode == 600)
{
lcd.printIn ("BPM:100");
}
else if (BPMmode == 545)
{
lcd.printIn ("BPM:110");
}
else if (BPMmode == 500)
{
lcd.printIn ("BPM:120");
}
else if (BPMmode == 462)
{
lcd.printIn ("BPM:130");
}
else if (BPMmode == 429)
{
lcd.printIn ("BPM:140");
}
}
void UpdateDisplaySUB()
{
lcd.cursorTo(1, 8);
if (SUBmode == 1)
{
lcd.printIn ("SB:1/2 ");
}
else if (SUBmode == 2)
{
lcd.printIn ("SB:1/4 ");
}
// else if (SUBmode == (8/3))
// {
// lcd.printIn ("SUB:1/8*");
// }
else if (SUBmode == 4)
{
lcd.printIn ("SB:1/8 ");
}
else if (SUBmode == 8)
{
lcd.printIn ("SB:1/16");
}
else if (SUBmode == 16)
{
lcd.printIn ("SB:1/32");
}
else if (SUBmode == 32)
{
lcd.printIn ("SB:1/64");
}
}

void UpdateDisplayWAVE()
{
lcd.cursorTo(2, 0);
if (WAVEmode == modeSquare)
{
lcd.printIn ("Wave:Square ");
}
else if (WAVEmode == modeRandom)
{
lcd.printIn ("Wave:Random ");
}
}

Is there anyone how can give me a clue how to solve this? :-/

Problem solved :smiley:

So, to help others. What was the solution?

Well i thought i solved it but that was not the thing:

But i found out what went wrong, the delay calculating in the code isn’t working like it should.
As an example i calculate delay(BPMmode/SUBmode) now for an example i take 667 as BPMmode and / that through SUBmode 4 i get 166.75ms delay. Now i think why the PWM isn’t blinking at this rate is because the delay in ms can’t handle the .75ms. Is that correct?

Maybe someone with some more experiance with the delay code can jump in here.
I have tried the delayMicroseconds code but this was’nt working also. But maybe i got that wrong.
from what i have got 667ms is 667000microseconds? right?

I’m not sure about the delay issues (I would have said to int() the value just to be safe, and if is delayMicroseconds, be aware that delayMicroseconds(0) causes unexpectedly long delay, so that I always make the delay be at least 2 or 3 uS long no matter what), but as for the legibility of the code, have you tried using switch case instead of those else-if statements?

http://www.arduino.cc/en/Reference/SwitchCase

I’m a bit confused about the syntax at the end of several of your functions where you do this


void blabla
{
read pin value

else-if-else-if

functioncall //this functioncall is formatted like it’s in the else-if, but if I read the {} right, it isn’t

{
functioncall //this second functionall is the same as the first, why the different syntax?
}
}


Am I missing something, or are you invoking the same function twice in a row, but with slightly different formatting? It almost looks like the first call is meant to be in the else-if statements, but isn’t? Is there a trick I’m not aware of which requires invoking a function inside curly braces like you do the second time? The arduino reference for curly braces makes no mention of it…

Oh, and I understand it is not recommended to use delayMicroseconds() for more than a millisecond. For one thing, system timer does not update during that delay, and other things are suspended (i think). To delay for 6.7ms, for example, you’d want to chain a delay() and a delayMicroseconds(), would be my understanding.

What i do with the else if statements is this:

I want the LFO to have a corresponding ms time (synced to a BPM and a subdivision) callculation for this is 60000/BPM*SUB=MS

Now as an example i want the LFO to sync with a BPM of 100 and in quarter notes (it’s a musical project).
the callculation is then 60000/100*1=600ms of DELAY.

The reason i have the else if statements for BPM and SUB is generaly because this was the only way to do this, at least i thought so.

But now i’m thinking of the idea to do the following. I want a pot to control a range of ms from 10ms to 3000ms. How do I set this up? I will look for sollutions.

I hope i made it clear for you :slight_smile: