[Need help] FEZ Panda II with HC-SR04

Hi guys!

I have FEZ Panda II and HC-SR04.

Before that I had a sensor Parallah Pynh and it had 3 contacts.
And this has 4 contacts, and I can not find a class / library to work with HC-SR04.

Can u help me?

We all can help but you need to have specific questions so we can help :slight_smile:

I want work with HC-SR04, but i don’t understand how write correct code.
How code the Tring and Echo contacts
Maybe exist class looks like for Parallax ping, where you just connect this
library, and use very simple functions to read data from sensor

You will need to start with the beginners guide book and then search codeshare for examples. Once you have a specific question, let us know and the community is always helpful.

@ BUBLIK

Are you seeking help understanding how the HC-SR04 works, or how to implement it using .NET MF?

I just realized that this a distance sensor. We have a new module that uses this sensor. You can just get ours and it will pug and play with any gadgeteer mainboard. Or get our drivers when it is published and roll your own hardware setup. This should be available in few weeks.

@ Mike - How implement it using .NET MF.

OK. I have read the specifications, and I am not 100% sure I understand how the interface works.
Could you please explain how it works.

You need:
send signal (Trig pin)
receive signal (Echo pin)
and then measure the length of the pulse, it will be our distance

I find code for Arduino: http://www.xappsoftware.com/wordpress/2012/03/15/how-to-interface-the-hc-sr04-ultrasonic-ranging-module-to-arduino/

That is actually very close to the Parallax PING)))

The only difference is that trigger and echo pins are separated on HC-SR04 which makes it easier. Check codeshare driver for PING:

http://www.tinyclr.com/codeshare/entry/123

@ Architect - would using edge interrupts improve accuracy?

Depends on how universal he want his driver to be (not all pins on Panda II are interrupt capable). I would definitely use InterruptPort on echo pin in my projects.

Edit. Actually it reminded me that in my other driver I try to use InterruptPort first and if it fails I fall back to InputPort and polling:
http://www.tinyclr.com/codeshare/entry/131

Same approach can be used with HC-SR04 and it would work no matter if pin has interrupts or not.

@ Bublik, if it helps a code snippet that i use to run the HC-SRO4. It’s a bit different in that I measure the duration of the return pulse using the ADC rather than an interrupt or pin capture, but it works fine for my purposes. The drawback is that the time resolution on the measurement is about 100 microseconds which translates to about 1-2 cm. I had some problems trying to use an interrupt or pin capture, but if anyone see’s a better way, I’d be interested in seeing suggestions. I’m looking at Architect’s codeshare.

This snippet just produces the sensor distance measurement in cm in the variable “roundedCM” I used that variable to control some motor logic, but you can do what you want with it. Help you, I hope this does.

* start of UT section
                 * set up the HC-SRO4 trigger pulse with a PWM pin set to 10 us pulse every 50 ms
                */

                    GHIElectronics.NETMF.Hardware.PWM ut_trig = new PWM(PWM.Pin.PWM3);

                    ut_trig.Set(false);
                    ut_trig.SetPulse(50000000, 10000);

                    //Set up ADC
                    int k = 0;  // k is used for counting during ADC and analysis of ADC array data
                    int j = 0;  // counter for measuring length of HC-SRO4 ranging pulse
                    int val = 0; // val is the number of ADC periods the UT signal was high - (could also just use j for val) 

                    // Int64 ticks0 = 0;   // ticks0 marks the start of channel AD0.0 conversion - can be used to verify period
                    // Int64 ticks1 = 0;   //ticks1 marks the end of channel AD0.0 conversion in ~ 100ns/tick 
                    AnalogIn ai = new AnalogIn(AnalogIn.Pin.Ain0);  //instantiate ADC pin 0
                    // setup variables 
                    ai.SetLinearScale(0, 3300);
                    int[] ai_vals = new int[1001];  // ai_vals is the ADC storage array for AD0.0
                    // section 1 - The actual data acquisition 
                    while (true)
                    {
                        // Debug.Print("start ADC Loop      " + DateTime.Now.Ticks.ToString());

                        k = 0; j = 0; val = 0;

                        for (k = 0; k <= 600; k++) // quickly collect data points 
                        {
                            ai_vals[k] = ai.Read();
                        }
                        // Debug.Print("ADC Loop Stopped  " + DateTime.Now.Ticks.ToString());k = 0;
                        for (k = 1; k <= 599; k++) // quickly anaalyze data points 
                        {
                            // count how many points above 3000
                            if (ai_vals[k] > 3000)
                            {
                                j++;
                            }
                            else
                            {
                                // ai_vals data point is below 3000 so check to see if a prior >3000 block was counted - if so get out of loop
                                if (ai_vals[k - 1] > 3000)
                                {
                                    k = 600;
                                }
                            }
                            // Debug.Print(val.ToString()); //  + "   " + val1.ToString());
                        }
                        // Debug.Print("end of print loop                          " + DateTime.Now.Ticks.ToString());
                        // Debug.Print("end of analysis loop                          " + DateTime.Now.Millisecond.ToString());
                        val = j;
                        // calculate a distance from the number of data points above 3000
                        int roundedCM = (int)(val * 0.097 * 34 / 2);
                        Debug.Print("Distance: " + roundedCM.ToString() + "  cm");

                    //Insert code to do somethings with roundedCM info here
}


2 Likes

@ idafez -

Thanks!
But I have some problems…

in this lines:
GHIElectronics.NETMF.Hardware.PWM ut_trig = new PWM((PWM.Pin)FEZ_Pin.PWM.Di3);
AnalogIn ai = new AnalogIn (FEZ_Pin.AnalogIn.An0);

This is full code
using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using GHIElectronics.NETMF.FEZ;

namespace sonar
{
public class Program
{
public static void Main()
{

        GHIElectronics.NETMF.Hardware.PWM ut_trig = new PWM((PWM.Pin)FEZ_Pin.PWM.Di3);

        ut_trig.Set(false);
        ut_trig.SetPulse(50000000, 10000);

        //Set up ADC
        int k = 0;  // k is used for counting during ADC and analysis of ADC array data
        int j = 0;  // counter for measuring length of HC-SRO4 ranging pulse
        int val = 0; // val is the number of ADC periods the UT signal was high - (could also just use j for val) 

        // Int64 ticks0 = 0;   // ticks0 marks the start of channel AD0.0 conversion - can be used to verify period
        // Int64 ticks1 = 0;   //ticks1 marks the end of channel AD0.0 conversion in ~ 100ns/tick 
        AnalogIn ai = new AnalogIn (FEZ_Pin.AnalogIn.An0);  //instantiate ADC pin 0
        // setup variables 
        ai.SetLinearScale(0, 3300);
        int[] ai_vals = new int[1001];  // ai_vals is the ADC storage array for AD0.0
        // section 1 - The actual data acquisition 
        while (true)
        {
            // Debug.Print("start ADC Loop      " + DateTime.Now.Ticks.ToString());

            k = 0; j = 0; val = 0;

            for (k = 0; k <= 600; k++) // quickly collect data points 
            {
                ai_vals[k] = ai.Read();
            }
            // Debug.Print("ADC Loop Stopped  " + DateTime.Now.Ticks.ToString());k = 0;
            for (k = 1; k <= 599; k++) // quickly anaalyze data points 
            {
                // count how many points above 3000
                if (ai_vals[k] > 3000)
                {
                    j++;
                }
                else
                {
                    // ai_vals data point is below 3000 so check to see if a prior >3000 block was counted - if so get out of loop
                    if (ai_vals[k - 1] > 3000)
                    {
                        k = 600;
                    }
                }
                // Debug.Print(val.ToString()); //  + "   " + val1.ToString());
            }
            // Debug.Print("end of print loop                          " + DateTime.Now.Ticks.ToString());
            // Debug.Print("end of analysis loop                          " + DateTime.Now.Millisecond.ToString());
            val = j;
            // calculate a distance from the number of data points above 3000
            int roundedCM = (int)(val * 0.097 * 34 / 2);
            Debug.Print("Distance: " + roundedCM.ToString() + "  cm");

            //Insert code to do somethings with roundedCM info here
        }
    }

}

}

And, i have code, but it contain eerors in this lines:


private static InterruptPort EchoPin = new InterruptPort((Cpu.Pin)FEZ_Pin.Digital.Di10);
private static OutputPort TriggerPin = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.Di12);

Can u help to fix them, i don’nt understand why error(

using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using GHIElectronics.NETMF.FEZ;

namespace sonar
{
    public class Program
    {
        private static int ticks;

        private static InterruptPort EchoPin = new InterruptPort((Cpu.Pin)FEZ_Pin.Digital.Di10);
        private static OutputPort TriggerPin = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.Di12);

        public static void Main()
        {
            EchoPin.OnInterrupt += new NativeEventHandler(port_OnInterrupt);
            EchoPin.DisableInterrupt();
            while (true)
            {
                Distance();
                //Debug.Print("distance = " + myDistance + " mm.");
                Thread.Sleep(1000);
            }
        }

        public static void Distance()
        {
            EchoPin.EnableInterrupt();
            TriggerPin.Write(false);
            Thread.Sleep(2);
            TriggerPin.Write(true);
            Thread.Sleep(10);
            TriggerPin.Write(false);
            Thread.Sleep(2);
        }

        private static void port_OnInterrupt(uint port, uint state, DateTime time)
        {
            if (state == 0) // falling edge, end of pulse
            {
                int pulseWidth = (int)time.Ticks - ticks;
                // valid for 20°C
                //int pulseWidthMilliSeconds = pulseWidth * 10 / 582;
                //valid for 24°C
                int pulseWidthMilliSeconds = (pulseWidth * 10 / (int)578.29);
                Debug.Print("Distance = " + pulseWidthMilliSeconds.ToString() + " millimètres.");
            }
            else
            {
                ticks = (int)time.Ticks;
            }
            EchoPin.ClearInterrupt();
        }

    }
}

What kind of errors?

@ BUBLIK - I can help with a few things but I’m not sure which of your last two posts you’d like to focus on - one uses the ADC for timing and the other an interrupt.

What is the error message you receive and what does the intellisense message in Visual Studio tell you if you are hovering over an underlined error? My first guess would be to check that you have added all the references, as I don’t see “using GHIElectronics.NETMF.Harddware;” and you will need that for either version of your code.

I’m also a bit puzzled about how you are setting up the trigger pulse in your last post. It looks like you are sending a a 10 ms pulse bracketed by two 2ms delays. I believe the recommended trigger signal is 10 microsenod pulse no faster than every 50 ms. That is what I used in the code I provided you earlier using PWM. Specifically,

GHIElectronics.NETMF.Hardware.PWM ut_trig = new PWM((PWM.Pin)FEZ_Pin.PWM.Di3);
ut_trig.Set(false);
ut_trig.SetPulse(50000000, 10000);

Let me know if this helps.

This error for last code:

Error 2 “Microsoft.SPOT.Hardware.OutputPort” does not contain a constructor that takes no arguments “1” C :confused: Users/Yuriy/Desktop/111/sonar/sonar/sonar/Program.cs 14 48 sonar

and thir error for other code:

Error 5 Could not find the name of a type or namespace “AnalogIn” (missing a using directive or an assembly reference?) C: \ Users \ Yuriy \ Desktop \ 111 \ sonar2 \ sonar2 \ sonar2 \ Program.cs 26 31 sonar

You have to look at the documentation about the classes you are using. It has information about class constructors and parameters used in each constructor (if more than one).

For example there are two constructors for OutputPort:

These errors can be easily avoided by reading the documentation first. Otherwise this is going to be a very long thread. :wink:

@ Architect -
Thanks!
I understand, but when I compile have a new error:

An unhandled exception of type “System.ArgumentException” occurred Microsoft.SPOT.Hardware.dll

@ this line:

private static InterruptPort EchoPin = new InterruptPort((Cpu.Pin)FEZ_Pin.Digital.Di10, true, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeBoth);