High Resolution Delay - Netduino Plus 2 (and Netduino Plus 1) - Netduino Forums
   
Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.
Photo

High Resolution Delay


Best Answer j2inet, 09 April 2013 - 02:50 PM

I've just come up with a solution for my needs. I'm using a spin wait. 

 

When my program starts up I time how long it takes to perform 2^20 increments (this way the delay should work across different processor clock waits). Then I just use this information to decide how many cycles to wait. For the timing values that I need it looks like this should work. I've not accounted for the overhead of making the call to the method but I hope that it will be within tolerance for my application. 

 

Source code is below. The default calibration value is from a Netduino Plus 2 with the source code running in debug mode. As long as you call calibrate before using it the default value should not matter. 

    public class SpinWaitTimer    {        double _cyclesPerSecond = 112262.2255516001;        public double CyclesPerSecond        {            get { return _cyclesPerSecond; }            set { _cyclesPerSecond = value; }        }        public SpinWaitTimer()        {        }        public void Calibrate()        {            const int CYCLE_COUNT = 1048576;            int dummyValue = 0;            DateTime startTime = DateTime.Now;            for (int i = 0; i < CYCLE_COUNT; ++i)            {                ++dummyValue;            }            DateTime endTime = DateTime.Now;            TimeSpan timeDifference = endTime.Subtract(startTime);            _cyclesPerSecond = ((double)CYCLE_COUNT / (double)timeDifference.Ticks)*10000000d;        }        public void WaitSeconds(double sec)        {            int cycleCount = (int)((sec * CyclesPerSecond));            int dummyValue = 0;            for (int i = 0; i < cycleCount; ++i)            {                ++dummyValue;            }        }        public void WaitMilliseconds(double microseconds)        {            int cycleCount = (int)(_cyclesPerSecond * CyclesPerSecond / 1000d);            int dummyValue = 0;            for (int i = 0; i < cycleCount; ++i)            {                ++dummyValue;            }        }        public void WaitMicroseconds(double microseconds)        {            int cycleCount = (int)(_cyclesPerSecond * CyclesPerSecond / 1000000d);            int dummyValue = 0;            for (int i = 0; i < cycleCount; ++i)            {                ++dummyValue;            }        }    }
Go to the full post


  • Please log in to reply
6 replies to this topic

#1 j2inet

j2inet

    Member

  • Members
  • PipPip
  • 11 posts

Posted 09 April 2013 - 02:00 PM

I wanted to check and see if this is something that is reasonably possible on a Netduino Plus 2 before I try to work it into a solution. I need to interface to a device that uses serial communication. The device is usually sleeping, but when I need to send it a message I've got to pulse a wake up line for 50 to 100 ?s and then start sending my message 9 to 11 ?s later. As far as I can tell the only delay functionality available on the netduino takes time in ms, not ?s. I thought about doing a busy loop and probing a clock, but from what I can tell I can't get information in the needed resolution to do this with the clock. 

 

Is this something that I could do with the Netduino Plus 2 or should I seek a different solution?



#2 j2inet

j2inet

    Member

  • Members
  • PipPip
  • 11 posts

Posted 09 April 2013 - 02:50 PM   Best Answer

I've just come up with a solution for my needs. I'm using a spin wait. 

 

When my program starts up I time how long it takes to perform 2^20 increments (this way the delay should work across different processor clock waits). Then I just use this information to decide how many cycles to wait. For the timing values that I need it looks like this should work. I've not accounted for the overhead of making the call to the method but I hope that it will be within tolerance for my application. 

 

Source code is below. The default calibration value is from a Netduino Plus 2 with the source code running in debug mode. As long as you call calibrate before using it the default value should not matter. 

    public class SpinWaitTimer    {        double _cyclesPerSecond = 112262.2255516001;        public double CyclesPerSecond        {            get { return _cyclesPerSecond; }            set { _cyclesPerSecond = value; }        }        public SpinWaitTimer()        {        }        public void Calibrate()        {            const int CYCLE_COUNT = 1048576;            int dummyValue = 0;            DateTime startTime = DateTime.Now;            for (int i = 0; i < CYCLE_COUNT; ++i)            {                ++dummyValue;            }            DateTime endTime = DateTime.Now;            TimeSpan timeDifference = endTime.Subtract(startTime);            _cyclesPerSecond = ((double)CYCLE_COUNT / (double)timeDifference.Ticks)*10000000d;        }        public void WaitSeconds(double sec)        {            int cycleCount = (int)((sec * CyclesPerSecond));            int dummyValue = 0;            for (int i = 0; i < cycleCount; ++i)            {                ++dummyValue;            }        }        public void WaitMilliseconds(double microseconds)        {            int cycleCount = (int)(_cyclesPerSecond * CyclesPerSecond / 1000d);            int dummyValue = 0;            for (int i = 0; i < cycleCount; ++i)            {                ++dummyValue;            }        }        public void WaitMicroseconds(double microseconds)        {            int cycleCount = (int)(_cyclesPerSecond * CyclesPerSecond / 1000000d);            int dummyValue = 0;            for (int i = 0; i < cycleCount; ++i)            {                ++dummyValue;            }        }    }


#3 NooM

NooM

    Advanced Member

  • Members
  • PipPipPip
  • 490 posts
  • LocationAustria

Posted 09 April 2013 - 03:40 PM

i dont think that works properly, since netmf has garbagecollector and such, also the thread switching can be an issue.

and its so much code. id use:

 

void SleepUSec(UInt32 Ammount)

{

DateTime startTime = DateTime.Now;

while(startTime.Ticks + (Ammount*10) > DateTime.Now.Ticks)

;

}

 

or something simmiliar should do it.



#4 Nevyn

Nevyn

    Advanced Member

  • Members
  • PipPipPip
  • 1072 posts
  • LocationNorth Yorkshire, UK

Posted 09 April 2013 - 03:44 PM

I'd be interested to see how reliable your solution is as NETMF is multithreading.  The garbage collector can be invoked at any time and you have no control over this.  What happens if an interrupt occurs part way through your loop?  Again this is something you will have no control over.

 

Good luck but my thoughts we going towards adding native code to the firmware to achieve what you want.

 

Regards,

Mark


To be or not to be = 0xFF

 

Blogging about Netduino, .NET, STM8S and STM32 and generally waffling on about life

Follow @nevynuk on Twitter


#5 NooM

NooM

    Advanced Member

  • Members
  • PipPipPip
  • 490 posts
  • LocationAustria

Posted 09 April 2013 - 04:06 PM

just to add: both solutions have that weak point. only native one is "perfect" as nevyn mentioned



#6 CW2

CW2

    Advanced Member

  • Members
  • PipPipPip
  • 1592 posts
  • LocationCzech Republic

Posted 09 April 2013 - 05:07 PM

The common weak point is resolution of the system timer ;)  Gen 2 Netduinos have 1 µs (fSlowClock = 1 MHz), so it works reasonably well, gen 1 boards have fSlowClock = 46875 Hz, so the time resolution is [only] 21.333 µs, which might not be enough.



#7 j2inet

j2inet

    Member

  • Members
  • PipPip
  • 11 posts

Posted 10 April 2013 - 01:26 AM

I'd be interested to see how reliable your solution is as NETMF is multithreading.  The garbage collector can be invoked at any time and you have no control over this.  What happens if an interrupt occurs part way through your loop?  Again this is something you will have no control over.

 

Good luck but my thoughts we going towards adding native code to the firmware to achieve what you want.

 

Thanx. The GC should't be an issue since this is running a single thread and using preallocated buffers and the other hardware would resend the message if an acknowledgement isn't received. I'll be sure to look into putting native code into the firmware for a long term fix. I can't say I am yet familiar with how to do that on Netduino. I had looked to see if there was support for loading native code (like some of the GHI hardware does) but it doesn't look like that will be an option. 

 

Any pointers of where I would look to get started with modifying the firmware? I've found the source code download links on the home page.  What else should I download or read?






0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.