Is there known bug concerning PWM.set on 4.1?

I have a buzzer that play melody corresponding to a tone and a period and a duration. The melody is repeated following a pattern corresponding to the period during the duration.

At the end of the duration I clean the timer that allows to change key and the timer that check for duration then I run pwm_buzz.Set(false).

In some cases the buzzer still ring.

Can you show your code?

Yep. Let me reduce its size to have a relevant example.

I think the problem is not in the pwm itself since I have the same behaviour on the relay output.

Hard to say without seeing the code.

I am preparing the code to be showing here. May be tomorrow…

I guess you have a thread stop problem but will effectively easier with the code.

Here’s the code:

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

namespace testcase
{
    public class BUZ
    {
        public ushort channel;
        static PWM buzzer;

        public bool inhibit = false;
        public bool lock_for_key = false;
        Timer timer;
        Timer timer_key;
        private Timer timer_bip;

        const int NOTE_C = 261;
        const int NOTE_D = 294;
        const int NOTE_E = 330;
        const int NOTE_F = 349;
        const int NOTE_G = 392;
        const int NOTE_A = 440;
        const int NOTE_B = 494;
        //============================================================================//

        public BUZ(ushort my_channel, ref Hashtable HTV, ref Hashtable HTT, ref Hashtable HTR, int RateCC)
        {
            channel = my_channel;
            HTV.Add(channel, (float)0);
            HTT.Add(channel, (ushort)5);
            HTR.Add(channel, RateCC);
        }

        public BUZ()
        {
            OutputPort inbz = new OutputPort(EMX.Pin.IO13, false);
            inbz.Write(true); Thread.Sleep(50);
            inbz.Write(false); Thread.Sleep(50);
            inbz.Dispose();
            buzzer = new PWM(PWM.Pin.PWM0);
        }
       
        public void change_tone(object obj)
        {
            objforbuztimer ob1 = (objforbuztimer)obj;
            //ushort indextoread = ob1.cur_index;
            ob1.cur_index = (ushort)((ob1.cur_index + 1) % 8);
            char[] a_st = ob1.config.ToCharArray();
            buzzer.Set(false);
            switch (a_st[ob1.cur_index])
            {
                case '0':
                    {

                        buzzer.Set(false);
                    } break;
                case '1':
                    {
                        buzzer.Set(NOTE_C, 50);
                    } break;
                case '2':
                    {
                        buzzer.Set(NOTE_D, 50);
                    } break;
                case '3':
                    {
                        buzzer.Set(NOTE_E, 50);
                    } break;
                case '4':
                    {
                        buzzer.Set(NOTE_F, 50);
                    } break;
                case '5':
                    {
                        buzzer.Set(NOTE_G, 50);
                    } break;
                case '6':
                    {
                        buzzer.Set(NOTE_A, 50);
                    } break;
                case '7':
                    {
                        buzzer.Set(NOTE_B, 50);
                    } break;
            }
        }


        public void Launch_alarm(ref Alarm cur_al, string config, string sttimer)
        {
            if (inhibit == false)
            {
                objforbuztimer ob1 = new objforbuztimer(ref cur_al, 0, config);
                if (timer_key != null)
                    timer_key.Dispose();
                if (timer != null)
                { timer.Dispose(); }
                buzzer.Set(false);

                if (int.Parse(sttimer) != 9999)
                {
                    timer = new Timer(new TimerCallback(stop_al), ob1, int.Parse(sttimer) * 100, Timeout.Infinite);
                }
                else
                {
                    timer = new Timer(new TimerCallback(stop_al), ob1, Timeout.Infinite, Timeout.Infinite);
                }
                timer_key = new Timer(new TimerCallback(change_tone), ob1, 0, 100);

            }
        }

        public void stop_al(object obj)
        {

            if (timer_key != null)
            {
                timer_key.Dispose();
            }

            if (timer != null)
            {
                timer.Dispose();
            }
            buzzer.Set(false);
        }
        
        public void BUZ_active(bool etat, int tempo)  //only for key bip
        {
            if (etat)
            {
                lock_for_key = true;
                buzzer.Set(true);
                timer_bip = new Timer(new TimerCallback(BUZ_end_timer), this, tempo, Timeout.Infinite);
            }
            else
            {
                if (lock_for_key == false)
                    buzzer.Set(false);
            }
        }
       
        private static void BUZ_end_timer(object source)  //only for key bip
        {

            BUZ loc_buz = (BUZ)source;
            loc_buz.lock_for_key = false;
            loc_buz.BUZ_active(false, 0);
            loc_buz.timer_bip.Dispose();
        }



        public class objforbuztimer
        {
            public Alarm cur_al;
            public ushort cur_index;
            public string config;

            public objforbuztimer(ref Alarm my_cur_al, ushort mycurindex, string my_config)
            {
                cur_al = my_cur_al;
                cur_index = mycurindex;
                config = my_config;
            }
        }
    }
}

yep, in some cases even if the code enter in stop_al the buzzer still rings

Do you use a pull up or pulldown resistor in front of you buzzer ?

When you say ring, do you mean a constant frequency or the melody continue ?

I am using a pulldown resistor (as described by the following schematic).

When I say that the buzzer rings, I mean it stays sometimes on the last tone (constant frequency), the melody does not go on. The buzzer rings until a key bip or a new alarm is executed…

The same happens also for the external buzzer that is not using PWM, that is why this does not seem to be a fault in the pwm class but rather a fault in my code.

I think that I need to write a smaple code to reproduce the problem (which is difficult due to the fact that sometime it works well sometimes not)

@ andre.m - Pull the pin from ~2.2v to 0

@ leforban

I tried to compile you code to test, but need the Alarm class, and a use case…

Kenavo

I’ve used the Panda II in a couple projects to drive RGB LEDs using all 6 PWMs through 4N35 optocouplers and I’ve never had a problem like this… I don’t even use pulldown resistors. I use the SetPulse method though rather than Set. You might try that when it’s time to silence the buzzer. buzzer.SetPulse(10000, 0);

Or maybe just try the other form of Set like buzzer.Set(1000, 0); rather than Set(false);

It wouldn’t necessarily get to the root of the problem, but if it corrects it for you then it wouldn’t really hurt anything by doing it that way.

Here’s the Alarm Class:



using Microsoft.SPOT;
using System;
using USBH_SDC;

namespace USU
{
    public class Alarm
    {
    
        public ushort channel;
        public ushort channel_1 = 0;
        public ushort channel_2 = 0;
        public uint melody1 = 0;
        public uint melody2 = 0;
        public Alarm(ushort c, ushort my_channel_1, ushort my_channel_2, uint mel1, uint mel2)
        {
            channel = c;
            channel_1 = my_channel_1;
            channel_2 = my_channel_2;
            melody1 = mel1;
            melody2 = mel2;
        }
    }
    public class Alarms
    {
        public Alarm[] Ar_Alarm;
        public ushort size;

        public void add(ref Hashtable HTV, ref Hashtable HTT, ref Hashtable HTR, bool my_userchangeable, int my_RateCC, ushort channel, ushort channel1, ushort channel2, uint mel1, uint mel2)
        {
            size++;
            Alarm[] tmp_Ar_Alarm;
            if(Ar_Alarm==null)
                 tmp_Ar_Alarm= new Alarm[1];
            else
            {
                tmp_Ar_Alarm = new Alarm[Ar_Alarm.Length + 1];
                Array.Copy(Ar_Alarm, tmp_Ar_Alarm, Ar_Alarm.Length);    
            }
            
            Alarm al = new Alarm(channel,channel1,channel2,mel1,mel2);
            tmp_Ar_Alarm[tmp_Ar_Alarm.Length-1] = al;
            Ar_Alarm= new Alarm[tmp_Ar_Alarm.Length];
            Array.Copy(tmp_Ar_Alarm,Ar_Alarm,tmp_Ar_Alarm.Length);
            HTV.Add(channel, Util.NaN);
            HTT.Add(channel,(ushort)5);
            HTR.Add(channel,my_RateCC);

            
        }
        public void run(ref Hashtable HTV, ref Hashtable HTT, ushort channel, BUZ buz, BUZEX buzex, string timer)
        {
            Alarm cur_al;
            for (int i = 0; i < size; i++)
            {
                if (Ar_Alarm[i].channel == channel) //l'alarme est trouvé dans le tableau
                {
                    cur_al = Ar_Alarm[i];
                    if (cur_al.channel_1 == buz.channel)
                    {
                        buz.Launch_alarm(ref cur_al, cur_al.melody1.ToString(), timer);
                    }
                    if (cur_al.channel_2 == buzex.channel)
                    {
                        buzex.Launch_alarm(ref cur_al, cur_al.melody2.ToString(), timer);
                    }
                    break;
                }
            }
        }
    }

}

I am still trying to debug this. After trying to understand what couold be the cause of a permanent buzzer ring, It seems that problems appears when the alarm is launched and when during the alarm time, GC cleans the memory. The thing that is weird is that it goes well to the stop_al method a perform the PWM.set(10000,0) but this seems to have no effect.