Show Posts
Pages: 1 ... 37 38 [39] 40 41 42
571  Forum 2005-2010 (read only) / Frequently-Asked Questions / Re: How to reset micros() to start/zero ? on: December 16, 2010, 06:37:19 am
But that's not the case for PPQ clocks. ;-)

120 BPM means 120 Beats, each Beat has 96 pulses.
120 x 96 = 720 events per minute = 12 hz. (if my math is right)

In any event, thanks guys, I learned A LOT from all this talk.

Sorry to bother so much this forum. When I first started working with C++ and Assembly, I also had the same crazy ideas and people made fun of me. It was over 10 years ago, and look where I am now. www.Wusik.com ;-) ;-) ;-)

So I guess I just need a few more years ahead of me in all this Arduino talk.  :-[ :-X

Wk
572  Forum 2005-2010 (read only) / Frequently-Asked Questions / Re: How to reset micros() to start/zero ? on: December 16, 2010, 06:33:33 am
Ahhh, google, I love you.....  ;D

http://www.electronicsblog.net/examples-of-using-arduinoatmega-16-bit-hardware-timer-for-digital-clock/

Ok, new idea, to create the Timer1, which is 16 bits, and have it deal with PPQ. Outside the timer I check which will be the next data to be sent out, and put in a small buffer. When the Timer1 happens, it checks the small buffer and sends midi-out. I just hope it doesn't block the previous PPQ. So I guess I need to time how many midi-notes I can send per PPQ before the next Timer1 call happens. Maybe for now I will leave as one note only, or something like that. Them I start messing around with the buffer size.

Wk
573  Forum 2005-2010 (read only) / Frequently-Asked Questions / Re: How to reset micros() to start/zero ? on: December 16, 2010, 05:57:05 am
Got it, thanks guys, <hug> yesterday I was in a bit of a bad mood.  :-[

I will check the 16 bit timer and see if maybe that would solve my problem. In any event, the MyTimer lib I created also works out. I just need to check if its good enough for a MIDI Clock PPQ at 96 PPQ...

Wk
574  Forum 2005-2010 (read only) / Frequently-Asked Questions / Re: How to reset micros() to start/zero ? on: December 15, 2010, 08:24:08 pm
Guys, I'm learning, and yes, this is not commercial, just trying to learn something new. So, please, don't be so hard on me. ;-)

Still, I have checked the whole code and I still don't understand why it would crash anything just by messing out with one variable that only micros() uses. But hey, what do I know?  :-X

Wk
575  Forum 2005-2010 (read only) / Frequently-Asked Questions / Re: How to reset micros() to start/zero ? on: December 15, 2010, 03:52:45 pm
After taking a look at the source code of wiring/arduino_ide, I found out this:

timer0_overflow_count

That's the one micros() uses.

So I did a quick test:

Code:
#include <WProgram.h>

int8_t secondsCounter = 0;
extern unsigned long timer0_overflow_count;

void setup()
{
  Serial.begin(115200);
  timer0_overflow_count = 0;
}

void loop()
{
    delay(1000);
    secondsCounter++;
    if (secondsCounter > 4)
    {
      timer0_overflow_count = 0;
      secondsCounter = 0;
      Serial.println("!");
    } else Serial.println(micros());

}

And heck, it works. Could it be so simple, or am I going to mess up other stuff up? Just wondering...

Wk
576  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
577  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);
  }
}
578  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
579  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
580  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
581  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);
}

// ======================================================================================= //
// ======================================================================================= //
// ======================================================================================= //
// ======================================================================================= //
582  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
583  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
584  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
585  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
Pages: 1 ... 37 38 [39] 40 41 42