Two timers in Gadgeteer

Does Gadgeteer can use more than one timer?

Hardware: Cerbuino Bee with Xbee. spider with Xbee.
Software: Gadgeteer 4.2 project.

Below is my code in Cerbuino Bee, I have two timer, Sendtimer and Receivetimer.
The procedure is:
Receivetimer is uesd for receiving the signal from the spider.
When Bee received the signal, the Receivetimer stop. Then, the Sendtimer start to send data back to spider.

But my Sendtimer don’t work anymore.

    public partial class Program
    {
        // This method is run when the mainboard is powered up or reset.   
        SerialPort xbee = new SerialPort("COM1", 115200);

        int count = 0;
        GT.Timer Sendtimer = new GT.Timer(200);
        GT.Timer Receivetimer = new GT.Timer(400);

        void ProgramStarted()
        {
          
            xbee.Open();

            Receivetimer.Tick += new GT.Timer.TickEventHandler(Receivetimer_Tick);
          
            Sendtimer.Tick += new GT.Timer.TickEventHandler(Sendtimer_Tick);
            Receivetimer.Start();
            //Sendtimer.Start();          
            
         
            Debug.Print("Program Started");
        }
           
        void Sendtimer_Tick(GT.Timer timer)
        {              
            Debug.Print("send...");     
            sendata();
           
        }

        void Receivetimer_Tick(GT.Timer timer)
        {

            
            Debug.Print("Receive...");
            int bytetoRead = xbee.ReadByte();
           
            if (bytetoRead > 0)
            {
                Receivetimer.Stop();
                Sendtimer.Start();
            }

            
        }

        private void sendata()
        {
            byte[] buffer = Encoding.UTF8.GetBytes("1");
            xbee.Write(buffer, 0, buffer.Length);
            xbee.Flush();
            
         }
             
    }

I’ve run multiple timers at the same time w/o any problem. So, I’m doubting it has something to do with your timers. The only part of this that I worry about is how you are instantiating xbee & your timers. I would normally do that within ProgramStarted(). Try just having your declarations outside and move your instantiations inside ProgramStarted() and see if anything behaves differently. Otherwise, at first glance it looks like it should work. I worry that something is blowing up in SerialPort that is terminating your thread.

Thanks ian,

I having my declarations outside and move the instantiations inside ProgramStarted()

  SerialPort xbee;
        int count = 0;
        GT.Timer Sendtimer;
        GT.Timer Receivetimer ;

        void ProgramStarted()
        {

           Sendtimer = new GT.Timer(200);
           Receivetimer = new GT.Timer(400);
            xbee = new SerialPort("COM1", 115200);
            //xbee.Open();
            xbee.Open();

And I set a breakpoint in

void Sendtimer_Tick(GT.Timer timer)
        {              
            Debug.Print("send...");     
            sendata();
 
        }

In debuging, can’t go into the Sendtimer_Tick

YES( bytetoRead > 0) is true
I set a breakpoint in Sendtimer.Start(). can stop on it.

Where do you start both timers?

Do I need to start the both timer in the begin in the ProgramStarted()?

In my code I only start the Receivetimer() in ProgramStarted().
After receive the xbee signal, start the Sendtimer.

Next question, why are you using timers?

Because DataReceived event can’t work.
http://www.tinyclr.com/forum/topic?id=10362

@ Tzu Hsuan - create the datareceived event after opening.

xbee.Open();
  xbee.DataReceived += new SerialDataReceivedEventHandler(xbee_DataReceived);

@ Justin

The event only raise once then stop.

Thanks

Can you post the full bee code.

Dear andre, I test your code in a new project, it works well. The timer is ok.
So the problem may the serial port.

And do you want me to send a chars with delimiter to xbee?
I don’t really understand what you mean

@ Justin
Bee code use Timer

public partial class Program
    {
        // This method is run when the mainboard is powered up or reset.   

        SerialPort xbee;
        int count = 0;
        GT.Timer Sendtimer;
        GT.Timer Receivetimer ;

        void ProgramStarted()
        {

           Sendtimer = new GT.Timer(200);
           Receivetimer = new GT.Timer(400);
            xbee = new SerialPort("COM1", 115200);
            xbee.Open();
            Receivetimer.Tick += new GT.Timer.TickEventHandler(Receivetimer_Tick);
            Sendtimer.Tick += new GT.Timer.TickEventHandler(Sendtimer_Tick);
            Receivetimer.Start();
           
            Debug.Print("Program Started");
        }

             
        void Sendtimer_Tick(GT.Timer timer)
        {
            
          
            Debug.Print("send...");            
            sendata();
           
        }

        void Receivetimer_Tick(GT.Timer timer)
        {

            
            Debug.Print("Receive...");
            int bytetoRead = xbee.ReadByte();
            if (bytetoRead > 0)
            {
                Receivetimer.Stop();                           
                Sendtimer.Start();
            }
            
        }

        private void sendata()
        {
            byte[] buffer = Encoding.UTF8.GetBytes("1");
            xbee.Write(buffer, 0, buffer.Length);
            xbee.Flush();
                     
        }


    }


code use DataReceived event

public partial class Program
    {
        // This method is run when the mainboard is powered up or reset.   

        SerialPort xbee;
        int count = 0;   

        void ProgramStarted()
        {

          
           //Receivetimer = new GT.Timer(400);
            xbee = new SerialPort("COM1", 115200);
            xbee.Open();                     
            xbee.DataReceived += new SerialDataReceivedEventHandler(xbee_DataReceived);        
            Debug.Print("Program Started");
        }           
        
        private void sendata()
        {
            byte[] buffer = Encoding.UTF8.GetBytes("1");
            xbee.Write(buffer, 0, buffer.Length);
            xbee.Flush();
            
            
        }

        void xbee_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            Debug.Print("Data Received");

            for (int i = 0; i < 10; i++)
            {
                sendata();
                Thread.Sleep(200);
            }
        }

  
    }

what is the second timer meant to do? Can you please explain how you expect this to work and you will likely get the best pointers in how to make this work in your scenario.

@ Tzu - You are checking that there is data but you are never actually reading the data. Even worse, you are actually reading one byte of data and then basically just throwing it away. I suspect that you may be overflowing your serial buffer which may be causing things to lock up.

@ Brett

I have two xbees, my application is that Xbee1(Spider) send a packet to xbee2(Bee). When Xbee2 receive the packet then send packets back to Xbee1.
Thank you for your hint, I don’t need two timer. I can do that use only one timer.

Now I still want to know why my second timer don’t work.

@ ian

I change the code to read the buffer but still the same.

 if (bytetoRead > 0)
            {
                Receivetimer.Stop();
                byte[] bytes = new byte[bytetoRead];
                xbee.Read(bytes, 0, bytetoRead);
                string Text = new string(System.Text.Encoding.UTF8.GetChars(bytes));
                Debug.Print("Data Received:" + Text);
             
                Sendtimer.start();
            }

@ andre

I send string with delimiter but why received string is empty?
If I remove the \r\n, Debug.Print can print the string 1.

 byte[] buffer = Encoding.UTF8.GetBytes("1\r\n");          
            xBee.SerialLine.Write(buffer, 0, buffer.Length);
            xBee.SerialLine.Flush();

I still don’t really get it.

You stop a timer then start a different one. But you never reverse that. What do you expect to happen here?

How about you put a global counter and increment that in each timer routine, and debug.print a message and the counter value as you go. Perhaps you can start to understand what is going on here by looking deeper

Dear Brett:
Does your 'reverse" mean restart the timer?
I will put a globe counter in the second timer, after the counter stop, then restart the timer1.
But in my case, I can’t go into the second timer.

I mean, you stop receive timer here, and I can’t see it ever being restarted. Do you expect it to stay stopped for ever?

Dear Brett:
I will start the Receivetimer in Sendtimer but Sendtimer not works.
For example

void Sendtimer_Tick(GT.Timer timer)
        {
            
              for (int i = 0; i < 100; i++)
                {
                    sendata();
                    Thread.Sleep(200);
                }
                Receivetimer.Restart();
           
        }

For your hint, I can do this use only one timer.

  void Receivetimer_Tick(GT.Timer timer)
        {

            
            Debug.Print("Receive...");
            int bytetoRead = xbee.ReadByte();
          
            if (bytetoRead > 0)
            {
                Receivetimer.Stop();
                byte[] bytes = new byte[bytetoRead];
                xbee.Read(bytes, 0, bytetoRead);
                string Text = new string(System.Text.Encoding.UTF8.GetChars(bytes));
                Debug.Print("Data Received:" + Text);
                //
                for (int i = 0; i < 100; i++)
                {
                    sendata();
                    Thread.Sleep(200);
                }
                Receivetimer.Restart();
            }
            
        }

why the Receivetimer can restart but the Sendtimer can’t start? strange

I don’t honestly know what you are expecting to do here - stopping one timer within another thread that will run for at least 20 seconds?

I don’t know how the Gadgeteer implementation of timers has taken this into account - it doesn’t really

I don’t want to rain on your parade here but I am struggling to understand what application logic you’re trying to implement here. Can you explain it at a high level, again you’re more likely to get more focussed assistance if you can explain what you’re attempting to do.