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 light measurement


  • Please log in to reply
62 replies to this topic

#41 CW2

CW2

    Advanced Member

  • Members
  • PipPipPip
  • 1592 posts
  • LocationCzech Republic

Posted 19 September 2011 - 04:34 PM

I believe so, yes. There should be a download somewhere on Microsoft's site. The only thing I don't know is how it's licensed (free, for use with CE

Well, I am not very optimistic about the licensing, but I'll give it a try, there is 180-day trial available for download. I remember evaluating the pre-release version available on Microsoft Connect, but I forgot what was the result :-(

[I hope those 'brave souls' you mentioned above aren't Microsoft employees, working in the ARM compiler team Posted Image]

#42 monewwq1

monewwq1

    Advanced Member

  • Members
  • PipPipPip
  • 104 posts

Posted 19 September 2011 - 05:48 PM

Chris, et. al, Here is the simple version of my code: [

#43 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 19 September 2011 - 06:01 PM

Hmm, how many pulses is the device sending? I suppose it's possible that it's queueing up such a large number of events that the event queue is filling all available memory. In which case the debugger might not be able to get enough memory to keep a connection to Visual Studio. If that's the case, reading the pin in a loop using managed code would most likely also be too slow. We'd need to look into creating a .PulseCount() type of function which waited and counted the # of pulses during a certain period. We'd have to figure out the logistics on that though (start on first edge vs. start immediately, etc.)...to make sure it worked with a variety of applications. Chris

#44 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 19 September 2011 - 06:03 PM

P.S. A quick way to help determine if the Netduino's memory is getting filled with events is printing out the avaiable memory using Debug.Print(Debug.GC(true)); in your loop (not the event -- Debug.Print will slow down your event).

#45 monewwq1

monewwq1

    Advanced Member

  • Members
  • PipPipPip
  • 104 posts

Posted 19 September 2011 - 06:23 PM

P.S. A quick way to help determine if the Netduino's memory is getting filled with events is printing out the avaiable memory using Debug.Print(Debug.GC(true)); in your loop (not the event -- Debug.Print will slow down your event).



Here's the Debug.GC(true) output, and I ran this from the main loop, not the event:

27888
27000
27912
31056
32796
32796
32796
32796
32796
32796
32796
32796
32796
32796
32796
32796
32796
32796
32532
20472

After the 20472, I lose connection with the IDE. I am using a Netduino Plus by the way. If I turn off networking, would that help? I see that with networking turned off, I should have 60k of RAM. If so, how do I turn off networking? If that won't help, what else can I do?

#46 CW2

CW2

    Advanced Member

  • Members
  • PipPipPip
  • 1592 posts
  • LocationCzech Republic

Posted 19 September 2011 - 06:40 PM

IMHO you'd need to disable the interrupt (from within the handler) to ensure the interrupt queue does not overflow, then signal completion via event checked in the main loop. Something along the following (not verified, just an idea):

...
private static long _pulseCount;
private static long ticksStart;
private static long ticksEnd;

private static InterruptPort port;
private static AutoResetEvent done = new AutoResetEvent(false);


private static void Main()
{
  port =  new InterruptPort(..., false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeHigh);
  port.OnInterrupt += _dataOutInterruptPort_OnInterrupt;
  port.DisableInterrupt(); // Automatically enabled by the above call


  while(true)
  {
 	_pulseCount = -1;

 	port.EnableInterrupt();
 	done.WaitOne();

 	var durationMicroseconds = (ticksEnd - ticksStart)/10; // 100-ns units, but 21.4 µs granularity
 	Debug.Print(durationMicroseconds .ToString() + " " + _pulseCount.ToString());
  }
}


static void _dataOutInterruptPort_OnInterrupt(uint port, uint state, DateTime time)
{
  // TODO: Probably needs lock here (or InterlockedIncrement)
  if(++_pulseCount == 0);
  {
    // At this time, there are already interrupts waiting in the queue.
    _dataOutInterruptPort.DisableInterrupt();

    ticksStart = time.Ticks;
    done.Set();
  }
  else
  {
    // The value is overwritten, till the last interrupt
    ticksEnd = time.Ticks;
  }
}


#47 monewwq1

monewwq1

    Advanced Member

  • Members
  • PipPipPip
  • 104 posts

Posted 19 September 2011 - 07:11 PM

The c

#48 CW2

CW2

    Advanced Member

  • Members
  • PipPipPip
  • 1592 posts
  • LocationCzech Republic

Posted 19 September 2011 - 07:50 PM

I will try CW2's suggestions.

I have actually tried it and it is able to measure 10 kHz - unfortunately, I don't have neither signal generator nor Netduino firmware with the newest PWM implementation, so I cannot try higher frequencies.

using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;

namespace FrequencyCounterTest
{
  public class Program
  {
    private static InterruptPort port;

    private static int pulseCount;
    private static long ticksStart;
    private static long ticksEnd;

    private static AutoResetEvent done = new AutoResetEvent(false);

    private static void Main()
    {
      port =  new InterruptPort(Pins.GPIO_PIN_D2, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeLow);
      port.OnInterrupt += port_OnInterrupt;
      port.DisableInterrupt(); // Automatically enabled by the above call

      while(true)
      {
        pulseCount = -1;

        port.EnableInterrupt();
        done.WaitOne();

        // Wait for the last interrupt handler (we don't know exactly when that happens)
        Thread.Sleep(1000);

        // Tick is 100-ns unit, but the clock has 21.4 µs granularity
        var durationSeconds = (ticksEnd - ticksStart)/(float)TimeSpan.TicksPerSecond;
        //Debug.Print(durationSeconds.ToString() + " " + pulseCount.ToString());
        Debug.Print("F = " + (pulseCount/durationSeconds).ToString("F1") + " Hz");
      }
    }

    static void port_OnInterrupt(uint data1, uint data2, DateTime time)
    {
      // TODO: Probably needs lock here (or InterlockedIncrement)
      if(++pulseCount == 0)
      {
        // At this time, there are already interrupts waiting in the queue.
        ticksStart = time.Ticks;
        port.DisableInterrupt();
        done.Set();
      }
      ticksEnd = time.Ticks;
    }
  }
}


#49 monewwq1

monewwq1

    Advanced Member

  • Members
  • PipPipPip
  • 104 posts

Posted 20 September 2011 - 12:46 AM

I have actually tried it and it is able to measure 10 kHz - unfortunately, I don't have neither signal generator nor Netduino firmware with the newest PWM implementation, so I cannot try higher frequencies.


CW2, here are some of the numbers I am getting with your code:

F = 1802.8 Hz
F = 2467.3 Hz
F = 2930.0 Hz
F = 4076.6 Hz
F = 3125.0 Hz
F = 3232.6 Hz
F = 3125.0 Hz
F = 3348.4 Hz
F = 3349.0 Hz
F = 2467.3 Hz
F = 3347.8 Hz
F = 2930.0 Hz
F = 3125.0 Hz
F = 4688.2 Hz
F = 2467.3 Hz
F = 4075.8 Hz
F = 5208.3 Hz
F = 7401.9 Hz
F = 8635.6 Hz
F = 7812.5 Hz
F = 16581.6 Hz
F = 17081.8 Hz
F = 17347.7 Hz
F = 17987.1 Hz
F = 17790.1 Hz
F = 17701.4 Hz
F = 16971.8 Hz
F = 14610.1 Hz
F = 14322.9 Hz
F = 14802.9 Hz
F = 15828.6 Hz 

I shined a bright light near the sensor and that is how the frequency jumped over 10k. However, if I shine the light directly on the sensor, the whole thing locks up again.

I have added the Interlocked increment statement and that does not help:

// TODO: Probably needs lock here (or InterlockedIncrement)
            if (Interlocked.Increment(ref pulseCount) == 0)


#50 Stefan W.

Stefan W.

    Advanced Member

  • Members
  • PipPipPip
  • 153 posts

Posted 20 September 2011 - 05:35 AM

Not wanting to spoil something, but be careful. It's not "so close to working" - you are still more than an order of magnitude away from your target (500khz). The trick from CW2 is an interesting one, but as you've seen there are limitations - it builds on disabling the interrupt handler before the queue fills up, which it can't if the frequency is very high (as you've seen) and which gets also harder should the GC decide to kick in before the handler start and the removal of the handler. Also, a limitation of that approach is that you only sample for a short time, so you're susceptible to "noisy light" (if the sensor is fast enough for that, didn't check that).
  • CW2 likes this
I believe that no discovery of fact, however trivial, can be wholly useless to the race, and that no trumpeting of falsehood, however virtuous in intent, can be anything but vicious.
-- H.L. Mencken, "What I Believe"

#51 CW2

CW2

    Advanced Member

  • Members
  • PipPipPip
  • 1592 posts
  • LocationCzech Republic

Posted 20 September 2011 - 07:28 AM

I have added the Interlocked increment statement and that does not help:

No, it does not really help in the way you need, it actually makes it a little bit worse, because the execution of the interrupt handler now takes longer. The original intention for the lock was to ensure the main loop reads correct value of pulseCount (*) when handlers are still executing, but this was avoided by adding Thread.Sleep() there.

(*) In the original code pulseCount was long, and CLR guarantees that reads and writes of variables of value types that are the size (or smaller) of the processor's natural pointer size are atomic, so accessing 64-bit long on 32-bit microcontroller is not atomic. I then changed pulseCount to int.

This is so close to working. How can I prevent it from locking up and get full 1000Hz resolution?

It should work at 1000 Hz (in all likelihood you'd need to replace '0' in the interrupt condition with a positive number, e.g. 10, and check durationSeconds to avoid division by zero), but you probably mean 1000 kHz - I am sorry, but I don't think this can be achieved in managed code.

Stefan W. is completely right; the actual limit is significantly lower than 500 kHz: at 100 kHz the interrupt occurs every 10 µs, which is too fast for managed code to keep up - I don't have exact numbers right now, but execution of managed code statements takes roughly tens of µs (it is not possible to measure code execution precise enough, due to the resolution of the system clock, but I could do that with my custom firmware that has improved clock resolution 2.7 µs).

The 'sample for short period' is also spot-on, but there is not really much we can do about that, I am not sure if increasing the interrupt queue length would help, because of GC - maybe pre-allocating memory blocks can work, but it does not seem to be a trivial change... Implementing 'true' frequency counter will be much easier.

#52 Mario Vernari

Mario Vernari

    Advanced Member

  • Members
  • PipPipPip
  • 1768 posts
  • LocationVenezia, Italia

Posted 20 September 2011 - 07:56 AM

Sorry, but...in which way we may detect the highest interrupt rate allowable? If too many int's are queuing, the result is a hang, or simply losing counts? At home I own a frequency generator, thus I may make some experiment... Feel free to suggest to right way.
Biggest fault of Netduino? It runs by electricity.

#53 monewwq1

monewwq1

    Advanced Member

  • Members
  • PipPipPip
  • 104 posts

Posted 20 September 2011 - 12:14 PM

It should work at 1000 Hz (in all likelihood you'd need to replace '0' in the interrupt condition with a positive number, e.g. 10, and check durationSeconds to avoid division by zero), but you probably mean 1000 kHz - I am sorry, but I don't think this can be achieved in managed code.


Yes, sorry about that. I meant 1000kHz (1MHz).

Stefan W. is completely right; the actual limit is significantly lower than 500 kHz: at 100 kHz the interrupt occurs every 10 µs, which is too fast for managed code to keep up - I don't have exact numbers right now, but execution of managed code statements takes roughly tens of µs (it is not possible to measure code execution precise enough, due to the resolution of the system clock, but I could do that with my custom firmware that has improved clock resolution 2.7 µs).


I am building your custom firmware this morning, but will it work with Netduino Plus? And if I run your custom firmware with this project, do I have a chance of achieving 1000kHz?

#54 Stefan W.

Stefan W.

    Advanced Member

  • Members
  • PipPipPip
  • 153 posts

Posted 20 September 2011 - 01:11 PM

No, the custom firmware just increases clock resolution, it does not make code run magically faster. Seriously, you are wasting your time. I don't get why you think this is a reasonable goal ... you will not be able to count pulses coming in at 1mhz in managed code. Why are you so fixated on directly interfacing this sensor with the netduino? As was already suggested in the beginning: Use another sensor, e.g. with a phototransistor or photoresistor (it does not get much cheaper or easier than this) or use another MCU to do the counting for you.
  • CW2 likes this
I believe that no discovery of fact, however trivial, can be wholly useless to the race, and that no trumpeting of falsehood, however virtuous in intent, can be anything but vicious.
-- H.L. Mencken, "What I Believe"

#55 monewwq1

monewwq1

    Advanced Member

  • Members
  • PipPipPip
  • 104 posts

Posted 20 September 2011 - 01:29 PM

No, the custom firmware just increases clock resolution, it does not make code run magically faster. Seriously, you are wasting your time.
I don't get why you think this is a reasonable goal ... you will not be able to count pulses coming in at 1mhz in managed code. Why are you so fixated on directly interfacing this sensor with the netduino?
As was already suggested in the beginning: Use another sensor, e.g. with a phototransistor or photoresistor (it does not get much cheaper or easier than this) or use another MCU to do the counting for you.


Adding more hardware to this project is a kludge since the chip on-board the Netduino can count these pulses, and I'm not going shopping for more components when I have what I need right here. I just need to know how to be able to count the pulses up to 1MHz. I want to get this sensor to work with an ARM7 48MHz chip, and Netduino has one. I do not care if this project cannot run in managed code.

Is it possible to get this sensor working with native code on Netduino, or not? Can I build my own custom Netduino firmware using the porting kit and make this sensor work?

#56 Mario Vernari

Mario Vernari

    Advanced Member

  • Members
  • PipPipPip
  • 1768 posts
  • LocationVenezia, Italia

Posted 20 September 2011 - 01:49 PM

Adding more hardware to this project is a kludge since the chip on-board the Netduino can count these pulses, and I'm not going shopping for more components when I have what I need right here. I just need to know how to be able to count the pulses up to 1MHz. I want to get this sensor to work with an ARM7 48MHz chip, and Netduino has one. I do not care if this project cannot run in managed code.

Is it possible to get this sensor working with native code on Netduino, or not? Can I build my own custom Netduino firmware using the porting kit and make this sensor work?

I own a truck: it has 500HP. I wonder why it can't reach 300Km/h...But I'm sure: it's 500HP powered! Much more than a Ferrari!...
I definitively want it will able to reach 300Km/h, even it's a truck...
What can I do?
Biggest fault of Netduino? It runs by electricity.

#57 monewwq1

monewwq1

    Advanced Member

  • Members
  • PipPipPip
  • 104 posts

Posted 20 September 2011 - 01:51 PM

I own a truck: it has 500HP. I wonder why it can't reach 300Km/h...But I'm sure: it's 500HP powered! Much more than a Ferrari!...
I definitively want it will able to reach 300Km/h, even it's a truck...
What can I do?



#58 CW2

CW2

    Advanced Member

  • Members
  • PipPipPip
  • 1592 posts
  • LocationCzech Republic

Posted 20 September 2011 - 01:58 PM

Is it possible to get this sensor working with native code on Netduino, or not? Can I build my own custom Netduino firmware using the porting kit and make this sensor work?

The answer is yes, to both questions.

#59 Stefan W.

Stefan W.

    Advanced Member

  • Members
  • PipPipPip
  • 153 posts

Posted 20 September 2011 - 02:13 PM

Adding more hardware to this project is a kludge since the chip on-board the Netduino can count these pulses, and I'm not going shopping for more components when I have what I need right here.


"Using a lot of time to build a custom firmware is a kludge since there is cheap hardware available that can measure the light intensity easily with the netduino, and I'm not wasting my valuable time building a custom firmware when there are easy alternatives available."

I just need to know how to be able to count the pulses up to 1MHz.


And we told you the easiest way to do that.

Is it possible to get this sensor working with native code on Netduino, or not? Can I build my own custom Netduino firmware using the porting kit and make this sensor work?


Yes, and if you use 15 minutes of your time (including the time that you take posting here) to do that in order not to go shopping for the components, you are working for less than minimum wage.

If I am not going to get any further positive support on this forum, I guess I will have to look elsewhere.

You are getting positive support, you just don't recognize it.
I believe that no discovery of fact, however trivial, can be wholly useless to the race, and that no trumpeting of falsehood, however virtuous in intent, can be anything but vicious.
-- H.L. Mencken, "What I Believe"

#60 Mario Vernari

Mario Vernari

    Advanced Member

  • Members
  • PipPipPip
  • 1768 posts
  • LocationVenezia, Italia

Posted 20 September 2011 - 02:15 PM

NickDuino, I don't want to hurt you, not anyone else. I apologize if I done. I may also understand your viewpoint, but I'm much closer to the Stefan consideration. That's probably because I find much more cumbersome setting up a C/C++ porting kit, learning how to write a driver, and rewrite the firmware. IMHO, this solution is much like "shooting at a mosquito using a bazooka". Netduino uses a very powerful MCU, but it is overloaded by tons of code. If you browse this forum, you'll find many of my posts about the unbelievable occupation of 512K of flash (I may accept the RAM usage). Running managed code seems requiring MEGATONS of resources. For example, Java Micro (pretty equivalent) requires MB of free rooms. So, probably you'll be able to write some C/C++/asm driver and interface it with C#, but I feel is the longest path to reach the shop at corner. I only would have to drive you to the simplest way, nothing else! It's not you: I've seen it's very common in the forum. I really wonder why it makes so scandalous connecting two MCUs together, when it's a very common practice...why not? An AVR is less than 5 bucks, and you may create easily any C++ program, without any effort. Thousands times simpler than touching the Netduino firmware, I guess... Sorry again, I'll leave this thread. Cheers
Biggest fault of Netduino? It runs by electricity.




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.