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

trying to flash an LED and pluse a piezo in error state


  • Please log in to reply
13 replies to this topic

#1 vader7071

vader7071

    Advanced Member

  • Members
  • PipPipPip
  • 132 posts
  • LocationDothan, AL

Posted 18 May 2014 - 09:34 PM

In another thread, I am working on having two netduino's talk back and forth.

In the event of a comm loss, I want the units to go into an "alarm" state.
 
using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;

namespace alarm
{
    public class Program
    {
        //IO pins
        static InputPort fakeConnection = new InputPort(Pins.GPIO_PIN_D0, false, Port.ResistorMode.PullUp);
        static OutputPort led = new OutputPort(Pins.GPIO_PIN_D6, false);
        static OutputPort piezo = new OutputPort(Pins.GPIO_PIN_D5, false);

        //variables
        static int i = 0;               //counter
        static int critical = 4;        //number of fails to trigger alarm

        public static void Main()
        {
            //If connection is good
            if (fakeConnection.Read() == true)  //true = within range, false = out of range
            {
                i = 0;                          //remotely written overriding count below
            }

            i = i++;                            //Increase counter by 1

            if (i > critical)                   //if connection is broke, counter will go above 1, when counter hits value in critical, set alarm
            {
                piezo.Write(true);              //set alarm piezo
                led.Write(true);                //set alarm led
            }

            Thread.Sleep(200);                  //loop sleep for 200 ms
        }
    }
}
Above is the code I am working on for just the alarm circuit. The notes will fill in the blanks about what each item means (i.e. fake connection is me doing a test with only one board, and faking the connection by using an input to mimic it.)

So far, testing has gone ok. Still tweaking, but one part I am struggling with is making the LED flash and the piezo pulse. Would I need to do this using an interrupt or is there a built in timer I can use to strobe these 2 pins?

#2 ShVerni

ShVerni

    Advanced Member

  • Members
  • PipPipPip
  • 138 posts
  • LocationNew York, New York

Posted 19 May 2014 - 03:15 AM

Hello again Vader!
 
So there are a couple things to note here. First, to make a piezo buzz you'll need to use Pulse Width Modulation, or PWM. A PWM pin can out put a square wave at a desired frequency which is exactly what you want to make a piezo buzz. You can find out a bit more about PWM from here:
 
http://msdn.microsof...y/hh401131.aspx
 
You can find out which pins on the Netduino support PWM from here:
 
http://www.netduino....uino2/specs.htm
 
As for the LED, the only way I can think to blink it using an outputport form the Netduino directly is in a loop. I've modified your code to use PWM and a loop the blinks the LED below:

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

namespace alarm
{
    public class Program
    {
        //IO pins
        static InputPort fakeConnection = new InputPort(Pins.GPIO_PIN_D0, false, Port.ResistorMode.PullUp);
        static OutputPort led = new OutputPort(Pins.GPIO_PIN_D6, false);
        //Create a PWM output using middle C (261.6 Hz) as the frequency and a 50% duty cycle.
        static PWM piezo = new PWM(Cpu.PWMChannel.PWM_0, 261.6, 0.5, false);

        //variables
        static int i = 0;               //counter
        static int critical = 4;        //number of fails to trigger alarm

        public static void Main()
        {
            //Stop the piezo so it's not buzzing when the program starts
            piezo.Stop();
            while (true)
            {
                //If connection is good
                if (fakeConnection.Read() == true)  //true = within range, false = out of range
                {
                    i = 0;                          //remotely written overriding count below
                }

                i = i++;                            //Increase counter by 1

                if (i > critical)                   //if connection is broke, counter will go above 1, when counter hits value in critical, set alarm
                {
                    piezo.Start();                  //set alarm piezo
                    while (i > critical)            //set alarm led
                    {
                        //Toggle the LED by setting it to the opposite of its current state
                        led.Write(!led.Read());
                        //Check to see if we're still in an alarm state
                        if (fakeConnection.Read() == true)
                        {
                            i = 0;
                        }
                        else
                        {
                            Thread.Sleep(200);
                        }
                    }
                    //The alarm has stopped
                    piezo.Stop();
                    led.Write(false);
                }
                Thread.Sleep(200);                  //loop sleep for 200 ms
            }
        }
    }
}

A few things to note about this code:
 
First: Your code didn't have a loop around the whole thing, so I added the while(true) at line 26, as it was the program would exit after one pass through the code.

 

Second: The LED is blinking in the loop starting at line 39. While the LED is blinking, the connection is still being tested to see if communication has been reestablished, and if so to exit the alarm state. You could outsource the LED blinking to its own thread, but that seems like a bit much in this instance. So note, however, that the LED blinking loop will block other code from running, hence why fakeConnection.Read() is also called from inside that loop, otherwise the loop would run forever.

 

I'm sure that's a lot to take it, but hopefully this will help!



#3 vader7071

vader7071

    Advanced Member

  • Members
  • PipPipPip
  • 132 posts
  • LocationDothan, AL

Posted 19 May 2014 - 09:33 PM

Ok, I see some areas where I made a few errors.  Forgot my while loop, that would have been a biggie.  thanks.

 

Now the piezo code, you are creating a PWM 50% duty at a specific tone and the piezo.start and piezo.stop is what turns it off and on.

 

If I wanted to have the tone change while on, instead of coding 261.6 into the PWM, I code that to be an integer and then adjust the value in the integer?  Am I on track?

 

I also see what what is going on when the alarm triggers.  You create a sub loop that runs as long as in alarm flipping the LED status, creating the flash.  To adjust the flash rate, adjust the thread.sleep value inside the error loop, not the overall loop.

 

I also follow how the reset works.

 

I am a HUGE fan of the simplicity.  I have been writing PLC (programmable logic controller) code for years, but that is done in the ladder logic format.  So now I am figuring out how to convert all of my old ladder logic tricks to C# code.



#4 ShVerni

ShVerni

    Advanced Member

  • Members
  • PipPipPip
  • 138 posts
  • LocationNew York, New York

Posted 19 May 2014 - 11:32 PM

I totally agree that elegant code is usually the best code, though I admit the code I shared above could be reworked to use a single loop, which might be considered simpler. Still, having two loops gives the code more options, like the ability to vary the polling times and the LED blink rate independently.

 

In regards to your question about the piezo--if I'm understanding it corectly--you'd still create the PWM object with whatever initial frequency you wanted, you could then change the frequency using the object's property of the same name by adding something like the below wherever you'd want the frequency to change:

 piezo.Frequency = 400; //Put desired frequency here

The frequency actually accepts a double, not an int, so you could use 400.5 or whatever instead for the above example, but if you want to use a variable, make sure it's a double or you'll have to cast it as one. If you wanted to create distinct notes, you'd want to stop the piezo first for bit (depending on how big a pause you want between notes), change the frequency, and then start it again.



#5 vader7071

vader7071

    Advanced Member

  • Members
  • PipPipPip
  • 132 posts
  • LocationDothan, AL

Posted 20 May 2014 - 12:45 AM

Loaded the new code. Made some additions to track testing. Having an issue. The netduino is not reading my input button. Here is the code:
 
using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;

namespace alarm
{
    public class Program
    {
        //IO pins
        static InputPort fakeConnection = new InputPort(Pins.GPIO_PIN_D0, false, Port.ResistorMode.PullUp);
        static OutputPort led = new OutputPort(Pins.GPIO_PIN_D6, false);
        static OutputPort led1 = new OutputPort(Pins.ONBOARD_LED, false); //To flash to make sure code is running
        static OutputPort led2 = new OutputPort(Pins.GPIO_PIN_D1, false); //To show status of "Fake Connection"
        static PWM piezo1 = new PWM(Pins.GPIO_PIN_D5);

        //variables
        static int i = 0;               //counter
        static int critical = 4;        //number of fails to trigger alarm
        static uint tone = 1000000 / 212 ; //212 Hz is middle c


        public static void Main()
        {
            piezo1.SetPulse(0, 0);  //Stop the piezo so it's not buzzing when the program starts
            led.Write(false);       //Turn off alarm LED
            led1.Write(false);      //Turn off code running
            led2.Write(false);      //Turn off Fake Connection follow
            while (true)
            {
                led1.Write(!led1.Read());  //code running flash
                //If connection is good
                if (fakeConnection.Read() == true)  //true = within range, false = out of range
                {
                    led2.Write(fakeConnection.Read());  //LED follows input
                    i = 0;                          //remotely written overriding count below
                }

                i = i++;                            //Increase counter by 1

                if (i > critical)                   //if connection is broke, counter will go above 1, when counter hits value in critical, set alarm
                {
                    piezo1.SetPulse(tone, tone/2);  //set alarm piezo
                    while (i > critical)            //set alarm led
                    {
                        //Toggle the LED by setting it to the opposite of its current state
                        led.Write(!led.Read());
                        //Check to see if we're still in an alarm state
                        if (fakeConnection.Read() == true)
                        {
                            i = 0;
                        }
                        else
                        {
                            Thread.Sleep(200);
                        }
                    }
                    //The alarm has stopped
                    piezo1.SetPulse(0, 0);
                    led.Write(false);
                }
                Thread.Sleep(200);                  //loop sleep for 200 ms
            }
        }
    }
}
Any idea why the code is not seeing the input? The onBoard LED is flashing, so I know the code is running.

Oh also, how did you get the numbers to show in the code section?

#6 ShVerni

ShVerni

    Advanced Member

  • Members
  • PipPipPip
  • 138 posts
  • LocationNew York, New York

Posted 20 May 2014 - 05:10 AM

So a few things I noticed looking through the code.
 
First, this line is redundant:

i = i++;

You can simplify it to:

i++;

Since i++ is the same as i = i + 1.
 
The other is with these lines:

if (fakeConnection.Read() == true)  //true = within range, false = out of range
{
    led2.Write(fakeConnection.Read());  //LED follows input
    i = 0;                          //remotely written overriding count below
}

Since you call led2.Write(fakeConnection.Read()) from within the if (fakeConnection.Read() == true) statement, it should always make the LED True, since otherwise it wouldn't enter the if statement at all. Also, you're calling fakeConnection.Read() twice, which means there's the slight chance it won't be the same each time, so I would only call it once, something like:

while (true)
{
    led1.Write(!led1.Read());  //code running flash
    //Check connection
    bool connected = fakeConnection.Read();
    led2.Write(connected);  //LED follows input
    //If connection is good
    if (connected == true)  //true = within range, false = out of range
    {
        i = 0;                          //remotely written overriding count below
    }

This is also more efficient, since you're only calling the .Read() method once instead of twice, and referencing a boolean variable is probably much faster than reading an input.
 
As for why it's not reading your input, how do you know that? If it's because the LED wasn't turning off, the above changes should fix that. I don't know if you have your piezo or other LEDs hooked up yet. Since you're using a pull-up resistor on the input, it will always be True until you connect it to ground. You could use a simple Debug.Print statement to see what the input sate is, something like:

while (true)
{
    led1.Write(!led1.Read());  //code running flash
    //Check connection
    bool connected = fakeConnection.Read();
    Debug.Print("Connected: " + connected.ToString());
    led2.Write(connected);  //LED follows input
    //If connection is good
    if (connected == true)  //true = within range, false = out of range
    {
        i = 0;                          //remotely written overriding count below
    }

If your input is always reading True or alwaysFalse, then with a little more info on how you're hooking everything up we can try and troubleshoot it.
 
As for the line numbers, when you post code you need to specify a Starting Line Number, I usually use 1 :).

 

Also, I'm not as familiar with the PWM method setPulse since--and I could be wrong here--the legacy SecretLabs.NETMF.Hardware.PWM has been generally replaced with Microsoft.SPOT.Hardware.PWM, but I was pretty sure middle C was 261.6 Hz, at least according to Wikipedia :rolleyes: , but I could very well be wrong about that too.



#7 vader7071

vader7071

    Advanced Member

  • Members
  • PipPipPip
  • 132 posts
  • LocationDothan, AL

Posted 20 May 2014 - 11:22 AM

Ah, I see about the fake.Read.  Right now that is just in there to give visual feedback to the input.  Eventually, it will be removed.

 

As for the "not reading", I made that conclusion from 2 points.  A ) the LED is not changing states, and b ) no matter what I did, it would never go into alarm state.

 

Just to make sure I am thinking correctly, with the line:

static InputPort fakeConnection = new InputPort(Pins.GPIO_PIN_D0, false, Port.ResistorMode.PullUp);

Than means that I am using pin D0 as an input, and it is held to a 5v signal so I connect to a ground to toggle the state.  Or am I thinking backwards?
 

 



#8 knut.tveitane

knut.tveitane

    Member

  • Members
  • PipPip
  • 18 posts

Posted 20 May 2014 - 02:27 PM

 

First, this line is redundant:

  1. i = i++;

Note - it is not just redundant, it is not doing what you (probably) want to achieve. The i++ construct increments the variable i *after* it has been referenced, but *before* the assignment is fullfilled. In other words, i will have the same old value after this statement as it had before.



#9 ShVerni

ShVerni

    Advanced Member

  • Members
  • PipPipPip
  • 138 posts
  • LocationNew York, New York

Posted 20 May 2014 - 03:01 PM

Note - it is not just redundant, it is not doing what you (probably) want to achieve. The i++ construct increments the variable i *after* it has been referenced, but *before* the assignment is fullfilled. In other words, i will have the same old value after this statement as it had before.

This would explain why you never enter the alarm state, Vader, the value of i never changes. I just tested this in a quick console application and, indeed, i doesn't increment. Thanks for the insight, Knut!
 
 

Than means that I am using pin D0 as an input, and it is held to a 5v signal so I connect to a ground to toggle the state.  Or am I thinking backwards?

Your thinking is correct here, although the pin is held to 3.3V, not 5V. Otherwise, as long as the pin is connected to ground, it should read False, and while not connected to ground it should read True.



#10 vader7071

vader7071

    Advanced Member

  • Members
  • PipPipPip
  • 132 posts
  • LocationDothan, AL

Posted 20 May 2014 - 04:45 PM

Note - it is not just redundant, it is not doing what you (probably) want to achieve. The i++ construct increments the variable i *after* it has been referenced, but *before* the assignment is fullfilled. In other words, i will have the same old value after this statement as it had before.

OOOHHHHH...so I just need i++ there and nothing else.

 

Thank you!!!  Now to make that change and test again!



#11 vader7071

vader7071

    Advanced Member

  • Members
  • PipPipPip
  • 132 posts
  • LocationDothan, AL

Posted 20 May 2014 - 06:56 PM

knut.tveitane, thought. Would it be better to use i++ or ++i? I realize what the difference is between the specific lines, but thinking about application.

#12 vader7071

vader7071

    Advanced Member

  • Members
  • PipPipPip
  • 132 posts
  • LocationDothan, AL

Posted 20 May 2014 - 08:06 PM

Success!!!

The alarm test code works!

Here is the latest version:
 
using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;

namespace alarm
{
    public class Program
    {
        //IO pins
        static InputPort fakeConnection = new InputPort(Pins.GPIO_PIN_D0, false, Port.ResistorMode.PullUp);
        static OutputPort led = new OutputPort(Pins.GPIO_PIN_D6, false);
        static OutputPort led1 = new OutputPort(Pins.ONBOARD_LED, false);
        static OutputPort led2 = new OutputPort(Pins.GPIO_PIN_D1, false);
        static PWM piezo1 = new PWM(Pins.GPIO_PIN_D5);

        //variables
        static int i = 0;               //counter
        static int critical = 4;        //number of fails to trigger alarm
        static uint tone1 = 1000000 / 212 ; //212 Hz is middle c
        static uint tone2 = 1000000 / 300; //212 Hz is middle c

        public static void Main()
        {
            //Stop the piezo so it's not buzzing when the program starts
            piezo1.SetPulse(0, 0);
            led.Write(false);
            led1.Write(false);
            led2.Write(false);
            while (true)
            {
                led1.Write(!led1.Read());
                //If connection is good
                if (fakeConnection.Read() == true)                     //true = within range, false = out of range
                {
                    i = 0;                          //remotely written overriding count below
                }

                ++i;                                //Increase counter by 1

                if (i > critical)                   //if connection is broke, counter will go above 1, when counter hits value in critical, set alarm
                {
                    while (i > critical)            //set alarm led
                    {
                        piezo1.SetPulse(tone1, tone1 / 2);  //set alarm piezo
                        led.Write(!led.Read());     //Toggle the LED by setting it to the opposite of its current state
                        Thread.Sleep(100);
                        piezo1.SetPulse(tone2, tone2 / 2);  //set alarm piezo

                        //Check to see if we're still in an alarm state
                        if (fakeConnection.Read() == true)
                        {
                            i = 0;
                        }
                        else
                        {
                            Thread.Sleep(100);
                        }
                    }

                    //The alarm has stopped
                    piezo1.SetPulse(0, 0);
                    led.Write(false);
                }
                Thread.Sleep(200);                  //loop sleep for 200 ms
            }
        }
    }
}
For now I am happy. When I press the button, I go into alarm state, the LED flashes, and the piezo pulses between 2 tones.

I already know what I will want to do next. Next step will be to split the LED flash and the piezo tone into 2 (I am assuming) interrupts so I can control the flash rate and the tone change independently of each other.

But hey, I am STOKED I am this far already.

knut.tveitane, as oyu can see, I went ahead and used the ++i and that seemed to work.

There is going to be another stage in the alarming section, but the big part was getting the total loss to work. Next step is going to be an intermittent setup.

#13 knut.tveitane

knut.tveitane

    Member

  • Members
  • PipPip
  • 18 posts

Posted 21 May 2014 - 07:29 AM

knut.tveitane, thought. Would it be better to use i++ or ++i? I realize what the difference is between the specific lines, but thinking about application.

Used as a statment on its own, the result is the same. The difference in semantics is only significant if used as part of an expression, where you reference the variable: ++i increments the variable before it is referenced, i++ after. (Actually, i = ++i would work in your case - and in this case, the assignment is plain redundant).

 

As a standalone statment, i++ is used more often - but this is only a convention. Following conventions is not a bad habit, though.



#14 vader7071

vader7071

    Advanced Member

  • Members
  • PipPipPip
  • 132 posts
  • LocationDothan, AL

Posted 21 May 2014 - 09:05 PM

Used as a statment on its own, the result is the same. The difference in semantics is only significant if used as part of an expression, where you reference the variable: ++i increments the variable before it is referenced, i++ after. (Actually, i = ++i would work in your case - and in this case, the assignment is plain redundant).

 

As a standalone statment, i++ is used more often - but this is only a convention. Following conventions is not a bad habit, though.

 

Ok.  My thoughts were the count is the critical part, and I want the count to increase and then evaluate.  But since it is a line by itself and not in anything else, it would not matter.






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.