Show Posts
Pages: 1 ... 38 39 [40] 41 42
586  Forum 2005-2010 (read only) / Frequently-Asked Questions / Re: How to reset micros() to start/zero ? on: December 15, 2010, 01:47:45 pm
I'm moving this to another thread, so we can close this one up.

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1292438829/0

Wk
587  Forum 2005-2010 (read only) / Frequently-Asked Questions / Re: How to reset micros() to start/zero ? on: December 15, 2010, 12:45:08 pm
Ahhh, nevermind.... I found another solution. I took a look at this page:

http://popdevelop.com/2010/04/mastering-timer-interrupts-on-the-arduino/

And create my own MyTimer library.  smiley-grin

It works great, and has no overflow problem. I'm still checking how I can improve it, and even how to have a better resolution, but for now its pretty neat. ;-)

Here's the whole library and also an example below.

MyTimer.h
Code:
/*

      Original code by Sebastian Wallin
      http://popdevelop.com/2010/04/mastering-timer-interrupts-on-the-arduino/

      Adapted and Optimized by WilliamK @ Wusik Dot Com (c) 2010
      http://arduino.wusik.com

      This timer will clock 125000 times in a second.

      You must add to your Arduino code the following:
            
            ISR(TIMER2_OVF_vect) { timer.tick(); } // "timer" as in your "MyTimer timer = MyTimer();" variable //

*/

#ifndef MYTIMER_h
#define MYTIMER_h

#include <inttypes.h>
#include "HardwareSerial.h"

// ------------------------------------------------------------------------------------------- //
class MyTimer
{
public:
      MyTimer();
      
      inline void tick(void)
      {
            TCNT2 = 255;
            timerCounter++;
            if (timerCounter == timerTimeValue) { eventCounter++; timerCounter = 0; }
      }

      void stop(void);
      void start(void);
      void setTime(unsigned long time);
      boolean hasEvent(void);

private:
      unsigned long timerCounter;
      unsigned long timerTimeValue;
      int8_t eventCounter;
      
};

#endif

MyTimer.cpp
Code:
/*

      Original code by Sebastian Wallin
      http://popdevelop.com/2010/04/mastering-timer-interrupts-on-the-arduino/

      Adapted and Optimized by WilliamK @ Wusik Dot Com (c) 2010
      http://arduino.wusik.com

      See MyTimer.h for instructions

*/

#include "WConstants.h"
#include "MyTimer.h"

// ------------------------------------------------------------------------------------------- //
MyTimer::MyTimer()
{
      eventCounter = 0;
      timerCounter = 0;
      timerTimeValue = 125000;
}

// ------------------------------------------------------------------------------------------- //
void MyTimer::start(void)
{
      TIMSK2 &= ~(1<<TOIE2);
      TCCR2A &= ~((1<<WGM21) | (1<<WGM20));
      TCCR2B &= ~(1<<WGM22);
      ASSR &= ~(1<<AS2);
      TIMSK2 &= ~(1<<OCIE2A);
      TCCR2B |= (1<<CS22)  | (1<<CS20);
      TCCR2B &= ~(1<<CS21);
      eventCounter = 0;
      timerCounter = 0;
      TCNT2 = 255;
      TIMSK2 |= (1<<TOIE2);
}

// ------------------------------------------------------------------------------------------- //
void MyTimer::stop(void)
{
      TIMSK2 &= ~(1<<TOIE2);
      eventCounter = 0;
      timerCounter = 0;
}

// ------------------------------------------------------------------------------------------- //
boolean MyTimer::hasEvent(void)
{
      if (eventCounter > 0)
      {
            eventCounter--;
            return true;
      }
      return false;
}

// ------------------------------------------------------------------------------------------- //
void MyTimer::setTime(unsigned long time)
{
      timerTimeValue = time;
}

MyTimerExample.pde
Code:
/*
  
  Original code by Sebastian Wallin
  
  Adapted and Optimized by WilliamK @ Wusik Dot Com
  http://arduino.wusik.com

*/

#include <WProgram.h>
#include <MyTimer.h>

int8_t secondsCounter = 0;
int8_t minutesCounter = 0;
int8_t hoursCounter = 0;
int8_t daysCounter = 0;

MyTimer timer = MyTimer();
ISR(TIMER2_OVF_vect) { timer.tick(); }

void setup()
{
  Serial.begin(115200);
  timer.setTime(125000); // one second //
  timer.start();
}

void loop()
{
  while (timer.hasEvent())
  {
    secondsCounter++;
    if (secondsCounter == 60) { secondsCounter = 0; minutesCounter++; }
    if (minutesCounter == 60) { minutesCounter = 0; hoursCounter++; }
    if (hoursCounter == 24) { hoursCounter = 0; daysCounter++; }
    
    Serial.print("Day: ");
    Serial.print(daysCounter, DEC);
    Serial.print(" Time: ");
    Serial.print(hoursCounter, DEC);
    Serial.print(":");
    Serial.print(minutesCounter, DEC);
    Serial.print(":");
    Serial.println(secondsCounter, DEC);
  }
}
588  Forum 2005-2010 (read only) / Frequently-Asked Questions / Re: How to reset micros() to start/zero ? on: December 15, 2010, 08:05:48 am
Here's the youtube video of my project:



Wk
589  Forum 2005-2010 (read only) / Frequently-Asked Questions / Re: How to reset micros() to start/zero ? on: December 15, 2010, 06:25:18 am
Thanks Korman, but maybe its too earlier for me, as I don't get what you are talking about. What StartTime and EndTime? Keep in mind that this is a PPQ clock. I will try to think more about this later today and see if I understand what you mean.  :-[

Wk
590  Forum 2005-2010 (read only) / Frequently-Asked Questions / Re: How to reset micros() to start/zero ? on: December 15, 2010, 05:57:30 am
Got it, thanks Korman, I'm no longer using floats. ;-)

Now, how do I deal with the overflow problem? What exactly happens? What is the max number micros() will output? So I could just treat it as a big loop, and when micros() is < than the last prevtime, I can just do the math as a looped sample. (its how I think) ;-)

Wk
591  Forum 2005-2010 (read only) / Frequently-Asked Questions / Re: How to reset micros() to start/zero ? on: December 14, 2010, 07:14:56 pm
Also, keep in mind that the other code I posted is just a test, not the actual midi clock I'm using. Of course I compare to another variable. ;-)

MidiClock.h
(removed some other stuff that is not related to this post)
Code:
#define PPQ 96.0f

class MidiClock
{
public:
      MidiClock();

      boolean isTick();
      void midiEcho();
      void nextTick();
      void updateTime();
      void newTime(int _bpm);
      void start();
      void stop();
      void reset();
      void sendCmd(char cmd, char data1, char data2);
      boolean isQuarter();
      boolean isRunning();

      boolean running;
      float bpm;
      unsigned long measurecounter;
      unsigned int beatcounter;
      int ppqcounter;
      boolean didIsQuarter;

private:
      boolean doReset;
      unsigned long prevtime;
      unsigned long currenttime;
      unsigned long ppqtime;
      byte incomingByte;
};

MidiClock.cpp
Code:
/*
 
 www.Wusik.com - Created by WilliamK @ Wusik Dot Com (c) 2010
 
*/

#include "WConstants.h"
#include "MidiClock.h"

// ------------------------------------------------------------------------------------------- //
MidiClock::MidiClock()
{
      MSerial.begin(31250); //start MSerial (defined in the .h file) for MIDI Input/Output at baudrate 31250 //
      #if MCPrintDebug
            Serial.begin(38400); // For Debuging //
      #endif
      bpm = 140;

      doReset = true;
      running = false;
      didIsQuarter = false;
      ppqcounter = 0;
      measurecounter = 0;
      beatcounter = 0;

      updateTime();
}

// ======================================================================================= //
void MidiClock::updateTime()
{
      ppqtime = 60000000.0f / (bpm*PPQ);  // (60 x 1,000,000) / (BPM*PPQ)
      doReset = true;

      #if MCPrintDebug
            Serial.print(bpm);      
            Serial.println(" BPM");
            Serial.print(ppqtime);      
            Serial.println(" ppqtime");
      #endif
}

// ======================================================================================= //
boolean MidiClock::isRunning()
{
      return running;
}

// ======================================================================================= //
void MidiClock::start()
{
      running = true;
      doReset = true;
      reset();
}

// ======================================================================================= //
void MidiClock::reset()
{
      ppqcounter = 0;
      measurecounter = 0;
      beatcounter = 0;
      doReset = true;
}

// ======================================================================================= //
void MidiClock::stop()
{
      running = false;
}

// ======================================================================================= //
void MidiClock::midiEcho()
{
      if (MidiEcho)
      {
            while (MSerial.available() > 0)
            {
                  incomingByte = MSerial.read();  
                  MSerial.print(incomingByte, BYTE);
            }
      }
}

// ======================================================================================= //
boolean MidiClock::isTick()
{      
      currenttime = micros();

      if (doReset)
      {
            prevtime = currenttime+ppqtime;
            doReset = false;
            didIsQuarter = false;
            ppqcounter = 0;
            measurecounter = 0;
            beatcounter = 0;
      }

      if (running)
      {
            
            //if (otherProcessesTime > 0 && (currenttime+otherProcessesTime) >= prevtime)
            /*if ((currenttime+4000) >= prevtime)
            {
                  while (currenttime < prevtime) { currenttime = micros(); }
            }*/

            if (currenttime >= prevtime)
            {
                  //if (currenttime >= (prevtime+90)) missedPPQ++;

                  prevtime += ppqtime;
                  return true;
            }
      }
      return false;
}

// ======================================================================================= //
boolean MidiClock::isQuarter()
{
      if (!didIsQuarter)
      {
            didIsQuarter = true;
            return true;
      }

      return false;
}

// ======================================================================================= //
void MidiClock::newTime(int _bpm)
{
      bpm = _bpm;
      updateTime();
}

// ======================================================================================= //
void MidiClock::nextTick()
{
      if (ppqcounter == 0 || ppqcounter == ((PPQ/4)*1) || ppqcounter == ((PPQ/4)*2) || ppqcounter == ((PPQ/4)*3))
      {
            didIsQuarter = false;
            beatcounter++;
            if (beatcounter == 16) beatcounter = 0;
      }

    // Next Tick //
      ppqcounter++;
      if (ppqcounter == PPQ)
    {
            ppqcounter = 0;
            measurecounter++;
            Serial.print("Measure: ");
            Serial.println(measurecounter, DEC);
      }

      /*#if MCPrintDebug
            if (missedPPQ > 10)
            {
                  missedPPQ = 0;
                  Serial.println("BADCLK!");
            }
      #endif*/
}

// ======================================================================================= //
void MidiClock::sendCmd(char cmd, char data1, char data2)
{
  MSerial.print(cmd, BYTE);
  MSerial.print(data1, BYTE);
  MSerial.print(data2, BYTE);
}

// ======================================================================================= //
// ======================================================================================= //
// ======================================================================================= //
// ======================================================================================= //
592  Forum 2005-2010 (read only) / Frequently-Asked Questions / Re: How to reset micros() to start/zero ? on: December 14, 2010, 04:34:35 pm
Ok, I removed the float and indeed, it still works and doesn't drift. (from the small test I did) Now I will make a bigger test.

Code:
BPM: 95.00
PPQ: 96.00
Micros PPQ: 6578
All BPM Done!
Processed Time MS: 59991

BPM: 120.00
PPQ: 96.00
Micros PPQ: 5208
All BPM Done!
Processed Time MS: 59996

BPM: 145.00
PPQ: 96.00
Micros PPQ: 4310
All BPM Done!
Processed Time MS: 59995

BPM: 170.00
PPQ: 96.00
Micros PPQ: 3676
All BPM Done!
Processed Time MS: 59994
593  Forum 2005-2010 (read only) / Frequently-Asked Questions / Re: How to reset micros() to start/zero ? on: December 14, 2010, 04:27:05 pm
Hummm, unless I'm totally off here, that doesn't seem to work for a midi clock, but I will check tomorrow, with a fresh mind. ;-)

In any event, the way I setup the midi clock, it does output correctly, but who knows.

I must use floats, as the PPQ time is not an integer, its a fractional number, so I can't just round down, otherwise the clock will drift a bit after a few minutes, and that's not good. But I will test anyway, with unsigned long, just in case, maybe it takes a bit longer to drift, and it could be that it doesn't drift that much anyway, but I need to check first...

Wk
594  Forum 2005-2010 (read only) / Frequently-Asked Questions / Re: How to reset micros() to start/zero ? on: December 14, 2010, 03:52:15 pm
Thanks guys.

Check this following thread:

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1292022093

There you can take a look of the code.

Code:
 currentmicroTime = (float)micros();
  if (currentmicroTime >= ppqmicroTime)

I guess what I could do is also check

Code:
 if (currentmicroTime < ppqmicroTime)

Which would tell me it has gone back to zero?

A bit lost, but I'm sure I will figure this out eventually. ;-)

Thanks again, Wk
595  Forum 2005-2010 (read only) / Frequently-Asked Questions / How to reset micros() to start/zero ? on: December 14, 2010, 03:22:04 pm
Guys, I'm using micros() for my midi clock, but I need to reset it every time Play is pressed, so we don't end up having problems with the overflow after 70 minutes...

Any way I could just reset micros() timer to zero ?

Thanks, Wk
596  Forum 2005-2010 (read only) / Frequently-Asked Questions / Re: Midi Clock (PPQ) Wrong Math? on: December 11, 2010, 08:09:40 am
Nermind, my math for counting the PPQ and Beats was a bit wrong. <ultra shame face>

Here's the correct code for a very simple MIDI Clock with variable BPM and PPQ.

Code:
// Wusik.com (c) WilliamK 2010
// Serial 115200 //

boolean Started = false;
boolean badClock = false;
unsigned long startTime;
unsigned long currentTime;
unsigned long processedtime;
float BPM = 95.0f;
float PPQ = 96.0f;
float ppqtime;
float currentmicroTime;
float ppqmicroTime;
int beats = 0;
int ppqcounter = 0;

void setup()
{
  Serial.begin(115200);
}

void loop()
{
  if (!Started)
  {
      Started = true;
      ppqtime = 60000000.0f / (BPM*PPQ);  // (60 x 1,000,000) / (BPM*PPQ)
      Serial.print("BPM: ");
      Serial.println(BPM);
      Serial.print("PPQ: ");
      Serial.println(PPQ);
      Serial.print("Micros PPQ: ");    
      Serial.println(ppqtime);
      beats = 0;
      ppqcounter = 0;
      startTime = millis();
      ppqmicroTime = (float)micros() + ppqtime;
  }  

  currentmicroTime = (float)micros();
  if (currentmicroTime >= ppqmicroTime)
  {
    currentTime = millis();    
    ppqmicroTime += ppqtime;
    ppqcounter++;
    if (ppqcounter == PPQ)
    {
      ppqcounter = 0;
      beats++;
      if (beats == BPM)
      {
        processedtime = currentTime - startTime;
        Serial.println("All BPM Done!");
        Serial.print("Processed Time MS: ");        
        Serial.println(processedtime);
        BPM += 25;
        Started = false;        
      }
    }
  }
}

Here's the output from the Serial, which is 99.9% correct in terms of timing.  8-)

Code:
BPM: 95.00
PPQ: 96.00
Micros PPQ: 6578.95
All BPM Done!
Processed Time MS: 60002

BPM: 120.00
PPQ: 96.00
Micros PPQ: 5208.33
All BPM Done!
Processed Time MS: 59996

BPM: 145.00
PPQ: 96.00
Micros PPQ: 4310.34
All BPM Done!
Processed Time MS: 59938

Best Regards, WilliamK
597  Forum 2005-2010 (read only) / Frequently-Asked Questions / Midi Clock (PPQ) Wrong Math? on: December 10, 2010, 06:01:33 pm
Guys, trying to figure out why my midi clock is running a bit slower. Can someone check if my math is correct?  :-[

Code:
int bpm = 140;
#define PPQ 96
unsigned long ppqtime = 60000000 / (bpm*PPQ);

In C++ I would actually do like this:

Code:
float ppqtime = 60000000.0f / (float(bpm)*float(PPQ));

So I'm not sure if my Arduino code is correct or not...

Thanks, Wk
598  Forum 2005-2010 (read only) / Frequently-Asked Questions / Midi Clock (PPQ) and micros() ? Reliable? on: December 07, 2010, 05:13:05 pm
Guys, I'm trying to get a good midi clock with 16 to 96 PPQ, but somehow, it doesn't seem that the micros() is returning perfect timing information. Any comments on this?

Here's an example.

Code:
ppqtime = 60000000 / (bpm*PPQ);  // (60 x 1,000,000) / (BPM*PPQ) - done at SETUP or Time BPM Changed

// In the LOOP //

if (micros() >= prevtime)
{
     prevtime += ppqtime;
     // send notes now //
}


Best Regards, WilliamK
599  Forum 2005-2010 (read only) / Frequently-Asked Questions / Re: How to connect 74HC165 ? on: December 02, 2010, 06:39:08 pm
BTW: Vss is Ground on the picture, not sure if Vss is a common nomenclature?

Wk
600  Forum 2005-2010 (read only) / Frequently-Asked Questions / Re: How to connect 74HC165 ? on: December 02, 2010, 06:38:20 pm
Yup, that one did the trick.



It was easy to setup, and it did even use less pins compared to the tutorial on the arduino site. ;-)

I also managed to get everything working with less code. Its very easy to understand indeed. Thanks again.

Wk
Pages: 1 ... 38 39 [40] 41 42