Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trouble polling an ultrasonic sensor's pulse width using .net micro fw

I am following one of many examples of interfacing C# and .net micro framework with a Parallax Ping sensor.

Parallax
http://learn.parallax.com/KickStart/28015

Tutorial 1
https://www.ghielectronics.com/community/codeshare/entry/123

Tutorial 2
http://forums.netduino.com/index.php?/topic/1721-parallax-ping-ultrasonic-sensor/

I have my sensor wired up correctly to my netduino plus' 5v output, a ground, and gpio 0. (I have tried different ports but still end up with the same result.

The problem I am having is that my program detects the high pulse but never detect the low of the pulse. It gets stuck in the second while(true) loop that is in each of those tutorials. Also, my parallax's LED seems to stay on and according to documentation it should pulse with each ping burst, not stay on indefinitely. I messed around using MS.SPOT.CPU.GPIO0 and also SecretLabs Pins.GPIOD0 enums. The secret labs pin yields a blinking LED that never exits the first while(true) loop, while the MS.SPOT port yields a forever LED light that never exits the second while(true) loop. This is my first day programming in MF. Can anyone help me out in pointing out what might be the issue?

Wiring

Video of it in action https://dl.dropboxusercontent.com/u/62170850/20140606_153029.mp4

It looks like I am wired into pins 10 and 13 but I am not. The angle is misleading. I am in fact plugged into Gnd and 11

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.NetduinoPlus;
using Micro_Base_Lib;

namespace Parallax_Ping_Distance_Calculator
{
public class Program
{
    private static OutputPort onboardLed;
    private static InterruptPort onboardButton;
    public static void Main()
    {
        // write your code here
        //Cpu.GlitchFilterTime = new TimeSpan(0, 0, 0, 0, 5); //5 ms glitch filter

        onboardButton = new InterruptPort(Pins.ONBOARD_SW1, true, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeLevelHigh);

        onboardButton.OnInterrupt += new NativeEventHandler(onboardButton_OnInterrupt);

        onboardLed = new OutputPort(Pins.ONBOARD_LED, false); //initial state off


        //go into powersave mode.
        Thread.Sleep(Timeout.Infinite);

    }

    static void onboardButton_OnInterrupt(uint data1, uint data2, DateTime time)
    {
        onboardLed.Write(true);
        onboardButton.ClearInterrupt();
        Ping myPinger = new Ping(SecretLabs.NETMF.Hardware.NetduinoPlus.Pins.GPIO_PIN_D11);
        var dist = myPinger.GetDistance();

        var convertedDistance = myPinger.Convert(dist, DistanceUnits.cm);
        onboardLed.Write(false);
    }

}



    public enum DistanceUnits
    {
        mm,
        cm,
        dm,
        m,
        feet,
        inch,
        yard
    }

    public class Ping
    {
        TristatePort _port;
        DistanceUnits _unit = DistanceUnits.mm;

        double _soundSpeed = 343, _convertion = (10000 / 343) * 2; // default values

        public Ping(Cpu.Pin pin)
        {

            _port = new TristatePort(pin, false, false, ResistorModes.Disabled);
        }

        /// <summary>
        /// Automaticly adjust the convertion factor depending on air temperature.
        /// </summary>
        /// <param name="degC">The temperature in degrees celsius</param>
        public void AdjustSoundSpeed(double degC)
        {
            /* Speed of Sound (at 20 degrees celsius): 343 m/s
             * or
             * _soundSpeed = 331.4 + 0.6 * degC
             * 
             * There are 10,000,000 ticks per second.
             * 10,000,000 / _soundSpeed * 1000 can be simplyfied into:
             * 10,000 / _soundSpeed
             * times it by 2 because of round trip
             * then you get about 58.309 ticks per mm
             * 
             * then multiply if other unit is needed
             * 
             */
            _soundSpeed = 331.4 + 0.6 * degC;
            _convertion = (10000 / _soundSpeed) * 2;
        }

        private void WriteToLog(string s)
        {
            Debug.Print(DateTime.Now.ToString() + " : " + s);
        }
        /// <summary>
        /// Return the Ping))) sensor's reading in millimeters.
        /// </summary>
        /// <param name="usedefault">Set true to return value in the unit specified by the "Unit" property.
        /// Set false to return value in mm.</param>
        public double GetDistance()
        {
            bool lineState = false;
            long t1, t2;

            // Set it to an output

            if (!_port.Active) 
            _port.Active = true;
            WriteToLog("Port is in output mode");
            WriteToLog(_port.Id + " : " + "Mode: " + (_port.Active == true ? "Output" : "Input"));
            WriteToLog(_port.Id + " : " + "Read: " + _port.Read());

            //10 micro seconds is long enough for the parallax microphone to pick up a a ping.
            //http://www.parallax.com/sites/default/files/downloads/28015-PING-Detect-Distance.pdf - figure 3
            WriteToLog(_port.Id + " : " + "Mode: " + (_port.Active == true ? "Output" : "Input"));
            WriteToLog(_port.Id + " : " + "Read: " + _port.Read());
            _port.Write(true); //turns the port to high 3.3v
            WriteToLog("Signal pulse started");
            WriteToLog(_port.Id + " : " + "Mode: " + (_port.Active == true ? "Output" : "Input"));
            WriteToLog(_port.Id + " : " + "Read: " + _port.Read());
            _port.Write(false); //turns the port to low 0v
            WriteToLog("Signal pulse ended");
            WriteToLog(_port.Id + " : " + "Mode: " + (_port.Active == true ? "Output" : "Input"));
            WriteToLog(_port.Id + " : " + "Read: " + _port.Read());

            // Set port it as an input to pick up sound
            _port.Active = false;
            WriteToLog("Port is in input mode");
            WriteToLog(_port.Id + " : " + "Mode: " + (_port.Active == true ? "Output" : "Input"));
            WriteToLog(_port.Id + " : " + "Read: " + _port.Read());
            //wait for linestate to change to true. indicating the start of the pulse
            WriteToLog("Waiting for line state to turn to true.");
            while (lineState == false)
            {

                lineState = _port.Read();
                WriteToLog(_port.Id + " : " + "Mode: " + (_port.Active == true ? "Output" : "Input"));
                WriteToLog(_port.Id + " : " + "Read: " + _port.Read());
            }

            t1 = System.DateTime.Now.Ticks;
            WriteToLog("Line state reached high at : " + t1.ToString());

            WriteToLog("Waiting for line state to turn to false.");
            //wait for linestate to change to false. indicating the end of the pulse
            while (lineState == true)
            {

                lineState = _port.Read();
                WriteToLog(_port.Id + " : " + "Mode: " + (_port.Active == true ? "Output" : "Input"));
                WriteToLog(_port.Id + " : " + "Read: " + _port.Read());
            }
            t2 = System.DateTime.Now.Ticks;
            WriteToLog("Line state reached low at : " + t1.ToString());
            return Convert(((t2 - t1) / _convertion), _unit);
        }

        /// <summary>
        /// Convert the millimeters into other units.
        /// </summary>
        /// <param name="millimeters">The Ping))) sensor's mm reading.</param>
        /// <param name="outputUnit">The desired output unit.</param>
        public double Convert(double millimeters, DistanceUnits outputUnit)
        {
            double result = millimeters;

            switch (outputUnit)
            {
                case DistanceUnits.cm:
                    result = millimeters * 0.1F;
                    break;
                case DistanceUnits.dm:
                    result = millimeters * 0.01F;
                    break;
                case DistanceUnits.m:
                    result = millimeters * 0.001F;
                    break;
                case DistanceUnits.inch:
                    result = millimeters * 0.0393700787;
                    break;
                case DistanceUnits.feet:
                    result = millimeters * 0.0032808399;
                    break;
                case DistanceUnits.yard:
                    result = millimeters * 0.0010936133;
                    break;
            }

            return result;
        }

        public DistanceUnits Unit
        {
            get { return _unit; }
            set { _unit = value; }
        }
    }

}

06/01/2011 00:00:34 : Port is in output mode
06/01/2011 00:00:34 : 17 : Mode: Output
06/01/2011 00:00:34 : 17 : Read: False
06/01/2011 00:00:34 : 17 : Mode: Output
06/01/2011 00:00:34 : 17 : Read: False
06/01/2011 00:00:34 : Signal pulse started
06/01/2011 00:00:34 : 17 : Mode: Output
06/01/2011 00:00:34 : 17 : Read: True
06/01/2011 00:00:34 : Signal pulse ended
06/01/2011 00:00:34 : 17 : Mode: Output
06/01/2011 00:00:34 : 17 : Read: False
06/01/2011 00:00:34 : Port is in input mode
06/01/2011 00:00:34 : 17 : Mode: Input
06/01/2011 00:00:34 : 17 : Read: False
06/01/2011 00:00:34 : Waiting for line state to turn to true.
06/01/2011 00:00:34 : 17 : Mode: Input
06/01/2011 00:00:34 : 17 : Read: False
06/01/2011 00:00:34 : 17 : Mode: Input
06/01/2011 00:00:34 : 17 : Read: False
06/01/2011 00:00:34 : 17 : Mode: Input
06/01/2011 00:00:34 : 17 : Read: False
06/01/2011 00:00:34 : 17 : Mode: Input
06/01/2011 00:00:34 : 17 : Read: False
06/01/2011 00:00:34 : 17 : Mode: Input
06/01/2011 00:00:34 : 17 : Read: False
06/01/2011 00:00:34 : 17 : Mode: Input
06/01/2011 00:00:34 : 17 : Read: False
06/01/2011 00:00:34 : 17 : Mode: Input
06/01/2011 00:00:34 : 17 : Read: False
06/01/2011 00:00:34 : 17 : Mode: Input
06/01/2011 00:00:34 : 17 : Read: False
06/01/2011 00:00:34 : 17 : Mode: Input
06/01/2011 00:00:34 : 17 : Read: False
06/01/2011 00:00:34 : 17 : Mode: Input
06/01/2011 00:00:34 : 17 : Read: False
06/01/2011 00:00:34 : 17 : Mode: Input
06/01/2011 00:00:34 : 17 : Read: False
06/01/2011 00:00:34 : 17 : Mode: Input
06/01/2011 00:00:34 : 17 : Read: False
06/01/2011 00:00:34 : 17 : Mode: Input
06/01/2011 00:00:34 : 17 : Read: False
06/01/2011 00:00:34 : 17 : Mode: Input
06/01/2011 00:00:34 : 17 : Read: False
06/01/2011 00:00:34 : 17 : Mode: Input
06/01/2011 00:00:34 : 17 : Read: False
06/01/2011 00:00:34 : 17 : Mode: Input
06/01/2011 00:00:34 : 17 : Read: False
06/01/2011 00:00:34 : 17 : Mode: Input
06/01/2011 00:00:34 : 17 : Read: False
06/01/2011 00:00:34 : 17 : Mode: Input
06/01/2011 00:00:34 : 17 : Read: False
06/01/2011 00:00:35 : 17 : Mode: Input

like image 804
Adrian Avatar asked Oct 21 '22 07:10

Adrian


1 Answers

I implemented your code on my NetDuino Plus and after a bit of hacking (I didn't have exactly the same sensor as you did so I had to modify your code slightly) it all seemed to work quite well. So aftersome backtracking of the code I noticed that you were using

Cpu.Pin.GPIO_Pin0

Were as I had by old habit written in

Pins.GPIO_PIN_D0

You see Cpu.Pin refer to the actual mCPU pin were as Pins.GPIO_PIN_D* referes to the pin output on the NetDuino development board.

So change

Cpu.Pin.GPIO_Pin0

To

Pins.GPIO_PIN_D0

And that should solve the problem stated in your question.

like image 108
Karl-Henrik Avatar answered Oct 23 '22 04:10

Karl-Henrik