Camera bug when using ethernet_ENC28.Interface.Open()

This waste my few days to find the problem.
I was use ENC28 module to establish a web server and Camera application.(This application works fine in 4.1 SDK.)
But the camera don’t work well.
camera_CameraConnected event can fire but the takepicture method hanging on, camera_PictureCaptured event never fired.
Finally I use a simple case to test then I find the bug.

If comment the ethernet_ENC28.Interface.Open(), camera works fine.

output:

Program Started
Can start to take a picture
TakePicture Time06/01/2011 01:04:38
picture captured
picture captured Time06/01/2011 01:04:40
The thread ‘’ (0x3) has exited with code 0 (0x0).

If use the ethernet_ENC28.Interface.Open(), the system hanging on

Program Started
Can start to take a picture
TakePicture Time06/01/2011 01:03:44

I am disappointed, up to now, I have two old applications(MF4.1) can’t upgrade to 4.2 smoothly. Waste much time, delay my project progress.
And getting distrusted from my boss, the boss never care about the technique, he always need result.


    public partial class Program
    {
        // This method is run when the mainboard is powered up or reset. 
      
        GT.Picture pic = null;
        bool iscameraready = false;
        void ProgramStarted()
        {
            /*******************************************************************************************
            Modules added in the Program.gadgeteer designer view are used by typing 
            their name followed by a period, e.g.  button.  or  camera.
            
            Many modules generate useful events. Type +=<tab><tab> to add a handler to an event, e.g.:
                button.ButtonPressed +=<tab><tab>
            
            If you want to do something periodically, use a GT.Timer and handle its Tick event, e.g.:
                GT.Timer timer = new GT.Timer(1000); // every second (1000ms)
                timer.Tick +=<tab><tab>
                timer.Start();
            *******************************************************************************************/


            // Use Debug.Print to show messages in Visual Studio's "Output" window during debugging.
            Debug.Print("Program Started");
           
            camera.CameraConnected += new Camera.CameraConnectedEventHandler(camera_CameraConnected);
            camera.PictureCaptured += new Camera.PictureCapturedEventHandler(camera_PictureCaptured);
           // if (!ethernet_ENC28.Interface.IsOpen)
           
           // ethernet_ENC28.Interface.Open();
           
        }

        void camera_PictureCaptured(Camera sender, GT.Picture picture)
        {
            pic = picture;
            Debug.Print("picture captured");
            Debug.Print("picture captured Time" + DateTime.Now.ToString());
        }

        void camera_CameraConnected(Camera sender)
        {
            Debug.Print("Can start to take a picture");
            iscameraready = true;
            camera.TakePicture();
            Debug.Print("TakePicture Time" + DateTime.Now.ToString());
        }
       
    }

Very strange! We will test on our end.

Thanks Gus, hope I am not the only lucky man.

I tried your code, and was able to see your issue. The problem is in the cameraConnected event. It may not fire unless the camera was physically connected. Try the following code to determine if you can take a picture without relying on that event.

while (true)
            {
                Debug.Print("Is camera ready? " + (camera.CameraReady ? "Yes" : "No"));

                if (camera.CameraReady)
                    camera.TakePicture();
                
                Thread.Sleep(1000);
            }

@ Steven, do you mean if the camera is already connected when the application starts?

This is the output.

Program Started
Is camera ready? No
Is camera ready? No
Is camera ready? Yes
Is camera ready? No
Is camera ready? Yes
Is camera ready? Yes
Is camera ready? Yes
Is camera ready? Yes
Is camera ready? Yes
Is camera ready? Yes
WARN: Total initialization time exceeds 10 seconds.
: ProgramStarted is blocking execution, which means events and timers will not run properly.
: Make sure not to use blocking code such as while(true) - use a GT.Timer instead.
Is camera ready? No
Is camera ready? Yes
Is camera ready? Yes
GC: 19msec 1004532 bytes used, 6335136 bytes available
Type 0F (STRING ): 1380 bytes
Type 11 (CLASS ): 13320 bytes
Type 12 (VALUETYPE ): 1512 bytes
Type 13 (SZARRAY ): 465720 bytes
Type 03 (U1 ): 461160 bytes
Type 04 (CHAR ): 852 bytes
Type 07 (I4 ): 1044 bytes
Type 0F (STRING ): 72 bytes
Type 11 (CLASS ): 2508 bytes
Type 12 (VALUETYPE ): 84 bytes
Type 15 (FREEBLOCK ): 6335136 bytes
Type 16 (CACHEDBLOCK ): 72 bytes
Type 17 (ASSEMBLY ): 35748 bytes
Type 18 (WEAKCLASS ): 96 bytes
Type 19 (REFLECTION ): 168 bytes
Type 1B (DELEGATE_HEAD ): 1008 bytes
Type 1C (DELEGATELIST_HEAD ): 108 bytes
Type 1D (OBJECT_TO_EVENT ): 264 bytes
Type 1E (BINARY_BLOB_HEAD ): 477816 bytes
Type 1F (THREAD ): 1536 bytes
Type 20 (SUBTHREAD ): 192 bytes
Type 21 (STACK_FRAME ): 1260 bytes
Type 22 (TIMER_HEAD ): 72 bytes
Type 23 (LOCK_HEAD ): 60 bytes
Type 24 (LOCK_OWNER_HEAD ): 24 bytes
Type 27 (FINALIZER_HEAD ): 144 bytes
Type 31 (IO_PORT ): 144 bytes
Type 34 (APPDOMAIN_HEAD ): 72 bytes
Type 36 (APPDOMAIN_ASSEMBLY ): 3816 bytes
Is camera ready? Yes
Is camera ready? No
Is camera ready? Yes
Is camera ready? Yes
Is camera ready? Yes
Is camera ready? Yes
Is camera ready? Yes
WARN: Total initialization time exceeds 20 seconds.
: ProgramStarted is blocking execution, which means events and timers will not run properly.
: Make sure not to use blocking code such as while(true) - use a GT.Timer instead.
Is camera ready? No
Is camera ready? Yes
Is camera ready? Yes
GC: 18msec 773772 bytes used, 6565896 bytes available
Type 0F (STRING ): 1380 bytes
Type 11 (CLASS ): 13320 bytes
Type 12 (VALUETYPE ): 1512 bytes
Type 13 (SZARRAY ): 235236 bytes
Type 03 (U1 ): 230676 bytes
Type 04 (CHAR ): 852 bytes
Type 07 (I4 ): 1044 bytes
Type 0F (STRING ): 72 bytes
Type 11 (CLASS ): 2508 bytes
Type 12 (VALUETYPE ): 84 bytes
Type 15 (FREEBLOCK ): 6565896 bytes
Type 17 (ASSEMBLY ): 35748 bytes
Type 18 (WEAKCLASS ): 96 bytes
Type 19 (REFLECTION ): 168 bytes
Type 1B (DELEGATE_HEAD ): 1008 bytes
Type 1C (DELEGATELIST_HEAD ): 108 bytes
Type 1D (OBJECT_TO_EVENT ): 264 bytes
Type 1E (BINARY_BLOB_HEAD ): 477816 bytes
Type 1F (THREAD ): 1536 bytes
Type 20 (SUBTHREAD ): 192 bytes
Type 21 (STACK_FRAME ): 1056 bytes
Type 22 (TIMER_HEAD ): 72 bytes
Type 23 (LOCK_HEAD ): 60 bytes
Type 24 (LOCK_OWNER_HEAD ): 24 bytes
Type 27 (FINALIZER_HEAD ): 144 bytes
Type 31 (IO_PORT ): 144 bytes
Type 34 (APPDOMAIN_HEAD ): 72 bytes
Type 36 (APPDOMAIN_ASSEMBLY ): 3816 bytes
Is camera ready? No
Is camera ready? Yes
Is camera ready? Yes
Is camera ready? No
The program ‘[1] Micro Framework application: Managed’ has exited with code 0 (0x0).

Ok, so you can use that way (polling) instead of the waiting for an event. You just need to do that inside a timer handler, for example, and not PrigramStarted.

…Which just shows it’s taking pictures.

The While(true) construct isn’t something you should do in your programstarted() in Gadgeteer, as you know, which is why it’s whingeing about long start up time. Put the check into a timer and if it’s ready, take a picture and display it (or do whatever you want/need to)

The output:

Program Started
Is camera ready? No
Can start to take a picture
TakePicture Time06/01/2011 00:18:51
Is camera ready? No
Is camera ready? No
picture captured
picture captured Time06/01/2011 00:18:52
Is camera ready? Yes
picture captured
picture captured Time06/01/2011 00:18:54
Is camera ready? Yes
picture captured
picture captured Time06/01/2011 00:18:55
Is camera ready? Yes
picture captured
picture captured Time06/01/2011 00:18:56
Is camera ready? Yes
picture captured
picture captured Time06/01/2011 00:18:57
Is camera ready? Yes
Is camera ready? No
picture captured
picture captured Time06/01/2011 00:18:58
The thread ‘’ (0x3) has exited with code 0 (0x0).
Is camera ready? Yes
picture captured
picture captured Time06/01/2011 00:19:00
Is camera ready? Yes
Is camera ready? No
picture captured
picture captured Time06/01/2011 00:19:01
Is camera ready? Yes

public partial class Program
    {
        GT.Picture pic = null;
        bool iscameraready = false;
        void ProgramStarted()
        {
            /*******************************************************************************************
            Modules added in the Program.gadgeteer designer view are used by typing 
            their name followed by a period, e.g.  button.  or  camera.
 
            Many modules generate useful events. Type +=<tab><tab> to add a handler to an event, e.g.:
                button.ButtonPressed +=<tab><tab>
 
            If you want to do something periodically, use a GT.Timer and handle its Tick event, e.g.:
                GT.Timer timer = new GT.Timer(1000); // every second (1000ms)
                timer.Tick +=<tab><tab>
                timer.Start();
            *******************************************************************************************/
              GT.Timer timer = new GT.Timer(1000); // every second (1000ms)
              timer.Tick += new GT.Timer.TickEventHandler(timer_Tick);
                timer.Start();

            // Use Debug.Print to show messages in Visual Studio's "Output" window during debugging.
            Debug.Print("Program Started");

            camera.CameraConnected += new Camera.CameraConnectedEventHandler(camera_CameraConnected);
            camera.PictureCaptured += new Camera.PictureCapturedEventHandler(camera_PictureCaptured);
             if (!ethernet_ENC28.Interface.IsOpen)

            ethernet_ENC28.Interface.Open();                                                               
       }

        void timer_Tick(GT.Timer timer)
        {
            Debug.Print("Is camera ready? " + (camera.CameraReady ? "Yes" : "No"));

            if (camera.CameraReady)
                camera.TakePicture();
        }

        void camera_PictureCaptured(Camera sender, GT.Picture picture)
        {
            pic = picture;
            Debug.Print("picture captured");
            Debug.Print("picture captured Time" + DateTime.Now.ToString());
        }

        void camera_CameraConnected(Camera sender)
        {
            Debug.Print("Can start to take a picture");
            iscameraready = true;
            camera.TakePicture();
            Debug.Print("TakePicture Time" + DateTime.Now.ToString());
        }
    }

Why the camera ready is unstable?

Looks pretty stable to me. Sine you are polling at equal time intervals it is not guaranteed that camera will be ready on each poll. Plus time to take a picture and be ready can be and is different each time.

If the networks up, camera not work.

Debug.Output

Program Started
Address Changed
Subnet mask:xxx.xxx.0.0
IP address: xxx.xxx.x.xx
Can start to take a picture
TakePicture Time06/01/2011 00:22:30
Is camera ready? No
Is camera ready? No
Is camera ready? No
Is camera ready? No
The thread ‘’ (0x3) has exited with code 0 (0x0).
Is camera ready? No
Is camera ready? No
Is camera ready? No
The program ‘[8] Micro Framework application: Managed’ has exited with code 0 (0x0).

public partial class Program
    {
        GT.Picture pic = null;
        bool iscameraready = false;
        GT.Timer timer = new GT.Timer(3000); // every second (1000ms)
        void ProgramStarted()
        {
            /*******************************************************************************************
            Modules added in the Program.gadgeteer designer view are used by typing 
            their name followed by a period, e.g.  button.  or  camera.
 
            Many modules generate useful events. Type +=<tab><tab> to add a handler to an event, e.g.:
                button.ButtonPressed +=<tab><tab>
 
            If you want to do something periodically, use a GT.Timer and handle its Tick event, e.g.:
                GT.Timer timer = new GT.Timer(1000); // every second (1000ms)
                timer.Tick +=<tab><tab>
                timer.Start();
            *******************************************************************************************/
              
              timer.Tick += new GT.Timer.TickEventHandler(timer_Tick);
               

            // Use Debug.Print to show messages in Visual Studio's "Output" window during debugging.
            Debug.Print("Program Started");
           
            ethernet_ENC28.Interface.NetworkAddressChanged += new NetworkInterfaceExtension.NetworkAddressChangedEventHandler(Interface_NetworkAddressChanged);
            //camera.CameraConnected += new Camera.CameraConnectedEventHandler(camera_CameraConnected);
            camera.PictureCaptured += new Camera.PictureCapturedEventHandler(camera_PictureCaptured);
             if (!ethernet_ENC28.Interface.IsOpen)

            ethernet_ENC28.Interface.Open();

             if (ethernet_ENC28.Interface.IsCableConnected)
             {
                 ethernet_ENC28.Interface.NetworkInterface.EnableStaticIP("xxx.xxx.xx.xx", "xxx.xxx.x.x", "xxx.xxx.x.xx");
                 ethernet_ENC28.Interface.NetworkInterface.EnableStaticDns(new string[] { "xxx.xxx.x.x" });
                 //ethernet_ENC28.Interface.NetworkInterface.EnableDhcp();
                 //ethernet_ENC28.Interface.NetworkInterface.EnableDynamicDns();


                 NetworkInterfaceExtension.AssignNetworkingStackTo(ethernet_ENC28.Interface);

             }
             else
             {
                 Debug.Print("Calble not connected");

             }                                   
       }
        void Interface_NetworkAddressChanged(object sender, EventArgs e)
        {
            Debug.Print("Address Changed");
            Debug.Print("Subnet mask:" + ethernet_ENC28.Interface.NetworkInterface.SubnetMask);
            Debug.Print("IP address: " + ethernet_ENC28.Interface.NetworkInterface.IPAddress);

            timer.Start();
        }
        void timer_Tick(GT.Timer timer)
        {
            Debug.Print("Is camera ready? " + (camera.CameraReady ? "Yes" : "No"));

            if (camera.CameraReady)
                camera.TakePicture();
        }

        void camera_PictureCaptured(Camera sender, GT.Picture picture)
        {
            pic = picture;
            Debug.Print("picture captured");
            Debug.Print("picture captured Time" + DateTime.Now.ToString());
        }

        void camera_CameraConnected(Camera sender)
        {
            Debug.Print("Can start to take a picture");
            iscameraready = true;
            camera.TakePicture();
            Debug.Print("TakePicture Time" + DateTime.Now.ToString());
        }
    }

Something is not right. Your output shows that code inside CameraConnected has been executed, but your code shows that you don’t subscribe to that event.

Sorry, the previous output show the CameraConnected excuted.

when comment the event the output is below

Program Started
Address Changed
Subnet mask:xxx.xxx.x.xx
IP address: xxx.xxx.x.xx
Is camera ready? Yes
Is camera ready? No
Is camera ready? No
The thread ‘’ (0x3) has exited with code 0 (0x0).
Is camera ready? No
Is camera ready? No
Is camera ready? No
Is camera ready? No
Is camera ready? No

Very strange. It took the picture but never fired the event that it was taken. It looks like a bug. Maybe GHI can reproduce.

… or the first time the camera ready check executed it wasn’t actually ready?

Can you debug step into the TakePicture() and see whether that works or not?

There can be a fundamental error ( I hope I am wrong), but there were some other threads recently that mentioned a working code stops working after adding one more module. I wonder if there is a bug in the event management code.

TakePicture() can be executed in first time but picture captured event not.
@ Architect, yes the same problem also occurred on SD card module.

Hi,GHI, any answer for this problem?

thanks

I just ran your code from reply #11, and the camera is successfully taking a picture about every 3 seconds. Have you made any other changes to the code?

EDIT: I forgot to add that the network is up while this code is running and I am able to ping the device while the program is running.