Timer Issues

Hey guys,

I’m having some pretty weird problems crop up when using timers.

Here is an example bit of code:

            //Assign and initiate threads
            Thread AdcHandler = new Thread(AdcThread);
            Thread GpsHandler = new Thread(GpsThreadStart);
            //Thread NavHandler = new Thread(NavThread);
            Thread TxHandler = new Thread(TxThread);


            //Set thread priorities
            AdcHandler.Priority = ThreadPriority.Lowest;
            GpsHandler.Priority = ThreadPriority.Normal;
            TxHandler.Priority = ThreadPriority.BelowNormal;

            //Start threads
            AdcHandler.Start();
            //GpsHandler.Start();
            //TxHandler.Start();

            Timer NavTimer =
                    new Timer(new TimerCallback(NavThread), null, 0, 500);

            Thread.Sleep(Timeout.Infinite);
            //Timeout
        private static void AdcThread()
        {
            while (true)
            {
                //Update battery reading and LEDs, loop every 10s
                adc.AdcUpdate();
                Thread.Sleep(10000);
            }
        }
        public static void NavThread(object o)
        {
            Debug.Print("Nav Thread");
        }

Basically, when all Thread.Start()s are commented out, this code works as expected. “Nav Thread” is debugged about every 500ms.

On the other hand, if I uncomment even a single Thread.Start(), “Nav Thread” will print just once, and never again.

What am I doing wrong?

With all threads commented:

‘Microsoft.SPOT.Debugger.CorDebug.dll’ (Managed): Loaded ‘F:\Visual Studio 2010\Projects\DaveDaveVeh\DaveDaveVeh\bin\Release\le\DaveDaveVeh.exe’, Symbols loaded.
The thread ‘’ (0x2) has exited with code 0 (0x0).
Nav Thread
Nav Thread
Nav Thread
Nav Thread
Nav Thread
Nav Thread
Nav Thread
Nav Thread
Nav Thread
Nav Thread

With just one thread uncommented, as above:

‘Microsoft.SPOT.Debugger.CorDebug.dll’ (Managed): Loaded ‘F:\Visual Studio 2010\Projects\DaveDaveVeh\DaveDaveVeh\bin\Release\le\DaveDaveVeh.exe’, Symbols loaded.
The thread ‘’ (0x2) has exited with code 0 (0x0).
Nav Thread

Just to confirm - the ADC thread, and all the other ones for that matter, work perfectly. There is no blocking involved, nothing problematic at all. Here is the code for the ADC class:

public ADC(){

            battLevel = new AnalogIn((AnalogIn.Pin)FEZ_Pin.AnalogIn.An4);
            //conLevel = new AnalogIn((AnalogIn.Pin)FEZ_Pin.AnalogIn.An5);

            battLevel.SetLinearScale(0, 3300);
            //conLevel.SetLinearScale(0, 1000);

            Cpu.Pin[] battPins = new Cpu.Pin[8]{
                (Cpu.Pin)FEZ_Pin.Digital.Di39,
                (Cpu.Pin)FEZ_Pin.Digital.Di41,
                (Cpu.Pin)FEZ_Pin.Digital.Di43,
                (Cpu.Pin)FEZ_Pin.Digital.Di45,
                (Cpu.Pin)FEZ_Pin.Digital.Di47,
                (Cpu.Pin)FEZ_Pin.Digital.Di49,
                (Cpu.Pin)FEZ_Pin.Digital.Di51,
                (Cpu.Pin)FEZ_Pin.Digital.Di50
            };

            battPort = new ParallelPort(battPins, (Cpu.Pin)FEZ_Pin.Digital.Di48,Cpu.Pin.GPIO_NONE);
        }

        public void AdcUpdate()
        {

                mVolts = Batt2mVolt(battLevel.Read());
                battPort.Write(new byte[1] { RangeBattLeds(mVolts) }, 0, 1);
            
        }

        private int Batt2mVolt(int batt)
        {
            return batt * 369 / 113;
        }

        private byte RangeBattLeds(int mVolt)
        {
            if (mVolt > 7800)
                return 0x7F;
            if (mVolt > 7500)
                return 0x3F;
            if (mVolt > 7200)
                return 0x1F;
            if (mVolt > 6900)
                return 0x0F;
            if (mVolt > 6600)
                return 0x07;
            if (mVolt > 6300)
                return 0x03;
            if (mVolt > 6000)
                return 0x01;
            else
                return 0x00;
        }

I’ve just checked on a Hydra and on a Domino, all is working as expected.

Test code is very basic :

namespace FEZ_Domino_Application2
{
    public class Program
    {
        public static void Main()
        {
            Thread AdcHandler = new Thread(AdcThread);
            AdcHandler.Start();
            Thread TestHandler = new Thread(TestThread);
            TestHandler.Start();
            Timer NavTimer = new Timer(new TimerCallback(NavThread), null, 0, 500);

            Thread.Sleep(Timeout.Infinite);
        }

        public static void NavThread(object o)
        {
            Debug.Print("Nav Thread");
        }

        private static void AdcThread()
        {
            while (true)
            {
                //Update battery reading and LEDs, loop every 10s
                Debug.Print("ADC Thread");
                Thread.Sleep(2000);
            }
        }

        private static void TestThread()
        {
            while (true)
            {
                //Update battery reading and LEDs, loop every 10s
                Debug.Print("Test Thread");
                Thread.Sleep(1000);
            }
        }
    }
}

Result :

'Microsoft.SPOT.Debugger.CorDebug.dll' (Managé) : 'C:\Users\BaF\Documents\Visual Studio 2010\Projects\FEZ Domino Application2\FEZ Domino Application2\bin\Debug\le\FEZ Domino Application.exe' chargé, symboles chargés.
Le thread '<Sans nom>' (0x2) s'est arrêté avec le code 0 (0x0).
ADC Thread
Test Thread
Nav Thread
Nav Thread
Test Thread
Nav Thread
Nav Thread
ADC Thread
Nav Thread
Test Thread
Nav Thread
Nav Thread
Test Thread
Nav Thread
ADC Thread
Nav Thread
Test Thread
Nav Thread
Nav Thread
Test Thread
Nav Thread
ADC Thread
Nav Thread
Test Thread
Nav Thread
Nav Thread
Test Thread
Nav Thread
ADC Thread
Nav Thread
Test Thread
Nav Thread
Le programme '[6] Micro Framework application: Managé' s'est arrêté avec le code 0 (0x0).

Edit: the code is exactly the same for the Hydra.

Xarren

Same for me. A similar code works great on my Panda II.
So something must going wrong in your ADC update function.
Something that seams to block the CPU.

I’ve tried even with a while(true) { } in a thread at highest priority and the timer still ring!

Could you guys do me a favour and run that code together with the ADC update function?

Maybe I’m missing something simple - See if it works for you?

Full code:

using System;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using System.Threading;
using System.IO.Ports;

using GHIElectronics.NETMF.FEZ;
using GHIElectronics.NETMF.Hardware;

namespace DaveDave
{
    public class ADC
    {
        private AnalogIn battLevel, conLevel;
        private ParallelPort battPort, conPort;
        public int mVolts;

        public ADC(){

            battLevel = new AnalogIn((AnalogIn.Pin)FEZ_Pin.AnalogIn.An4);
            //conLevel = new AnalogIn((AnalogIn.Pin)FEZ_Pin.AnalogIn.An5);

            battLevel.SetLinearScale(0, 3300);
            //conLevel.SetLinearScale(0, 1000);

            Cpu.Pin[] battPins = new Cpu.Pin[8]{
                (Cpu.Pin)FEZ_Pin.Digital.Di39,
                (Cpu.Pin)FEZ_Pin.Digital.Di41,
                (Cpu.Pin)FEZ_Pin.Digital.Di43,
                (Cpu.Pin)FEZ_Pin.Digital.Di45,
                (Cpu.Pin)FEZ_Pin.Digital.Di47,
                (Cpu.Pin)FEZ_Pin.Digital.Di49,
                (Cpu.Pin)FEZ_Pin.Digital.Di51,
                (Cpu.Pin)FEZ_Pin.Digital.Di50
            };

            battPort = new ParallelPort(battPins, (Cpu.Pin)FEZ_Pin.Digital.Di48,Cpu.Pin.GPIO_NONE);
        }

        public void AdcUpdate()
        {
            mVolts = Batt2mVolt(battLevel.Read());
            battPort.Write(new byte[1] { RangeBattLeds(mVolts) }, 0, 1); 
        }

        private int Batt2mVolt(int batt)
        {
            return batt * 369 / 113;
        }

        private byte RangeBattLeds(int mVolt)
        {
            if (mVolt > 7800)
                return 0x7F;
            if (mVolt > 7500)
                return 0x3F;
            if (mVolt > 7200)
                return 0x1F;
            if (mVolt > 6900)
                return 0x0F;
            if (mVolt > 6600)
                return 0x07;
            if (mVolt > 6300)
                return 0x03;
            if (mVolt > 6000)
                return 0x01;
            else
                return 0x00;
        }

    }
}

Just to point out - when using just threads, everything works very well. There are no problems with any functions stopping each other - What could cause a timer not to run? I’m a bit confused here.

Still working good on Domino :

namespace FEZ_Domino_Application2
{
    public class Program
    {
        public static ADC adc = new ADC();

        public static void Main()
        {
            
            Thread AdcHandler = new Thread(AdcThread);
            AdcHandler.Start();
            Thread TestHandler = new Thread(TestThread);
            TestHandler.Start();
            Timer NavTimer = new Timer(new TimerCallback(NavThread), null, 0, 500);

            Thread.Sleep(Timeout.Infinite);
        }

        public static void NavThread(object o)
        {
            Debug.Print("Nav Thread");
        }

        private static void AdcThread()
        {
            while (true)
            {
                //Update battery reading and LEDs, loop every 10s
                adc.AdcUpdate();
                Debug.Print("ADC Thread, update : "+adc.mVolts.ToString()+" mV");
                Thread.Sleep(2000);
            }
        }

        private static void TestThread()
        {
            while (true)
            {
                //Update battery reading and LEDs, loop every 10s
                Debug.Print("Test Thread");
                Thread.Sleep(1000);
            }
        }
    }
ADC Thread, update : 0 mV
Test Thread
Nav Thread
Nav Thread
Test Thread
Nav Thread
Nav Thread
ADC Thread, update : 0 mV
Nav Thread
Test Thread
Nav Thread
Nav Thread
Test Thread
Nav Thread
ADC Thread, update : 0 mV
Nav Thread
Test Thread
Nav Thread
Nav Thread
Test Thread
Nav Thread
ADC Thread, update : 0 mV
Nav Thread
Test Thread
Nav Thread

I had to change some of the pins in the ADC class, though :wink:

Edit:
you could try to comment the content of your threads and uncomment them one at a time. You may find something ?

Thats really annoying. Takes the mick with it working on yours and not on mine.

And yeah, I’m in the process of trying that now :).

Thanks for helping.

I’m running it on a RLP enabled processor, but even with all the RLP commented out I get the same effect, so that doesn’t seem to be it.

Edit: I’m not getting anywhere with this right now. I give up, and I’m going to sit down and rethink this tomorrow. I’ll keep you updated if I manage to work this out.

Okay, this is really strange.

Running a timer which just debugs “ADC Timer” every second, with the following thread running:

                gpsUart.DiscardInBuffer();

                string[] data;
                byte[] rxBytes = new byte[256];
                char[] chars;
                string[] nmeaStr;
                
                while (gpsUart.BytesToRead != 256)
                    Thread.Sleep(20);

works perfectly, but if I uncomment the following line like this:

gpsUart.DiscardInBuffer();

                string[] data;
                byte[] rxBytes = new byte[256];
                char[] chars;
                string[] nmeaStr;
                
                while (gpsUart.BytesToRead != 256)
                    Thread.Sleep(20);

                gpsUart.Read(rxBytes, 0, 256);

ADC Timer will only print 6 times and then stop.

The Gps thread on the other hand will work just fine.

Anyone with an insight on how Timers work that could enlighten me?

Did you set a Read timeout to your serial port ?

No - I assumed that if it doesn’t read anything it’ll just block there till it can?

And either way - It will have data to read because the previous line ensures there are 256 bits in the buffer. Plus it is reading, as I’m getting data from it all the time.

I’ll try adding a timeout, but I doubt that’ll change anything, its got a constant stream of data. When using multiple threads as before rather than timers (My system is fully functional using threads, I just need a better control over timing) the read bit works perfectly. If there is no data it just stops there and other threads use the time.

Problem solved.

The GC was eating up my timer - the reason it didn’t do it when other threads were disabled was because there wasn’t any garbage.

Made it static and now it all works :).

Nevermind.