Main Site Documentation

SerCam stepping out of line (double pictures)... wat?


#1

My Serial Camera L1 Module (batch #447) appears to be taking two pictures, when I have only requested one… I can’t really explain it, and I’ve been trying to debug it for ~20 hours.

The issue I have is that serCam.TakePicture() sometimes causes the camera to freeze up; saying: “Cannot take picture at this time” when I request (via WebEventHandlers) pictures faster than it can take them… That’s not really an issue; I would totally love to wait for the camera to be done, but when I get that message “Cannot take picture at this time”; it’s almost surely a sign that the camera will freeze up (and future web requests time out)… Eventually the camera does unfreeze, something like 5 minutes… I added a timeout of 30 seconds to the WebRequest and a dirty timeout (since serCam.thread is private) to the web event handler: i.e. the camera has been busy too long, time to send a response that it’s exceptionally lame.

I’m totally open to the idea that the problem is being caused by me. I have multiple Cobra II boards, and multiple serial camera modules. No combo can surmount this issue; in my mind…

Almost certainly related is another issue… After requesting ~10 or 20 pictures, the board eventually freaks out and completely freezes (must be reset)… I never stick around long enough to see if it will unfreeze (freeze for 10+ minutes). the GC.Debug() shows plenty of memory; which makes me suspect that there isn’t a memory leak when handling the images.
However… The Debugger doesn’t even recognize the board’s real mac address; so I wouldn’t know if I could/should trust the output from Debug.GC() or not.

On a side note; I am very pleased with the quality of the pictures :slight_smile:



//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by the Gadgeteer Designer.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

using Gadgeteer;
using GTM = Gadgeteer.Modules;
using Gadgeteer.Modules.GHIElectronics;

namespace GadgeteerApp1
{
    public partial class Program : Gadgeteer.Program
    {
        // GTM.Module definitions
        public static Gadgeteer.Modules.GHIElectronics.SerCam serCam;

        public static void Main()
        {
            //Important to initialize the Mainboard first
            Mainboard = new GHIElectronics.Gadgeteer.FEZCobra_II();			

            Program program = new Program();
            program.InitializeModules();
            program.ProgramStarted();
            program.Run(); // Starts Dispatcher
        }

        private void InitializeModules()
        {   
            // Initialize GTM.Modules and event handlers here.		
            serCam = new GTM.GHIElectronics.SerCam(5);
            serCam.StartDataCaptured += new SerCam.StartDataCapturedEventHandler(PMCam_StartDataCaptured);
            serCam.OnDataCaptured += new SerCam.DataCapturedEventHandler(PMCam_OnDataCaptured);
            serCam.FinishDataCaptured += new SerCam.FinishDataCapturedEventHandler(PMCam_FinishDataCaptured);
        }
    }
}

Program.cs


using System;
using System.Threading;
using Microsoft.SPOT;

using Gadgeteer.Networking;
using GHINET = GHI.Premium.Net;
using GHI.Premium.Hardware;
using Gadgeteer.Modules.GHIElectronics;


namespace GadgeteerApp1 {
    public partial class Program {

        /**
         * <summary>
         * This is the web server port that is hosted on the localhost (the board running this code) 
         * </summary>
         */
        const int WEB_SERVER_PORT = 80;

        /**
         * <summary>
         *   This is "name" of the wireless network.
         * </summary>
         */
        private static string WIRELESS_SSID = "***";

        /**
         * <summary>
         *   This is "password"/key to join the wireless network.
         * </summary>
         */
        private static string WIRELESS_PASS = "***"; //WPA2 incase it matters for this forum post
        public static GHINET.WiFiRS9110 wifi;
        public static Boolean webServerStarted = false;


        /**
         * <summary>
         *   This is a buffer to hold the image (combine the fragments) 
         *   after Camera.OnDataCaptured is called.
         *   
         *   @ TODO check if this image can be unbuffered (this would be fastest),
         *   or maybe it should be buffered incase the WebResponse fails to go through?
         * </summary>
         */
        public static byte[] bitmapData;


        /**
         * <summary>
         *   This holds the offset for the byte[] datajpg variable.
         *   It's only used by the serial camera.
         * </summary>
         */
        private int serialCameraBufferedImageIndex;

        public void ProgramStarted() {
            Debug.EnableGCMessages(true);
            serCam.SetImageSize(SerCam.Camera_Resolution.SIZE_QVGA);

            // initialize wifi
            wifi = new GHINET.WiFiRS9110(Microsoft.SPOT.Hardware.SPI.SPI_module.SPI2, G120.Pin.P1_10, G120.Pin.P2_11, G120.Pin.P1_9, 4000);

            if (!wifi.IsOpen)
                wifi.Open();

            if (!wifi.NetworkInterface.IsDhcpEnabled)
                wifi.NetworkInterface.EnableDhcp();


            wifi.NetworkAddressChanged += new GHINET.NetworkInterfaceExtension.NetworkAddressChangedEventHandler(wifi_NetworkAddressChanged);
            wifi.WirelessConnectivityChanged += new GHINET.WiFiRS9110.WirelessConnectivityChangedEventHandler(wifi_WirelessConnectivityChanged);

            GHINET.NetworkInterfaceExtension.AssignNetworkingStackTo(wifi);
            GHINET.WiFiNetworkInfo[] scanResult = wifi.Scan();

            // scan for the wifi AP i intend to connect to
            for (int i = 0; i < scanResult.Length; i++)
                if (scanResult[i].SSID == WIRELESS_SSID) {
                    wifi.Join(scanResult[i], WIRELESS_PASS);
                    break; // once found, stop iterating. the rest of the results are useless (unless evil twin attack)
                }

        }

        static byte[] GetBytes(string str) {
            byte[] bytes = new byte[str.Length * sizeof(char)];
            Array.Copy(str.ToCharArray(), bytes, bytes.Length);
            return bytes;
        }

        static void wifi_WirelessConnectivityChanged(object sender, GHINET.WiFiRS9110.WirelessConnectivityEventArgs e) {
        }

        static void wifi_NetworkAddressChanged(object sender, EventArgs e) {
            /* Start the HTTPD server every time the network address changes */
            if (wifi.IsActivated) {
                webServerStarted = true;
                //WebServer.StartLocalServer(wifi.NetworkInterface.IPAddress, WEB_SERVER_PORT);
                startHTTPServer();
            }
                /* Stop the HTTP Server... since we aren't connected */
            else {
                webServerStarted = false;
                WebServer.StopLocalServer();
            }
        }

        static void webEventReceivedPictureHandler(string path, WebServer.HttpMethod method, Responder responder) {
            int sleeping = 0;
            serCam.TakePicture();
            while (serCam.isBusy) {
                sleeping += 200;
                Thread.Sleep(200);
                Debug.Print("Sleeping " + sleeping);
                if (sleeping > 3000) {
                    responder.Respond(GetBytes("The camera took exceptionally long to generate a picture!"), "text/html");
                    return;
                }
            }
            responder.Respond(bitmapData, "image/bmp");
        }

        public static void startHTTPServer() {
            WebEvent webEventtakepicture;
            Debug.Print("------------------------------------------------------");
            Debug.Print("Starting the Web Server listening on " + wifi.NetworkInterface.IPAddress + ":" + WEB_SERVER_PORT.ToString());
            WebServer.StartLocalServer(wifi.NetworkInterface.IPAddress, WEB_SERVER_PORT);
            webServerStarted = true;
            /* this web event does not seem to be working properly... */
            webEventtakepicture = WebServer.SetupWebEvent("picture");
            webEventtakepicture.WebEventReceived += new WebEvent.ReceivedWebEventHandler(webEventReceivedPictureHandler);
            Debug.Print("Handlers have been added to the web server. " +
                "try: http://" + wifi.NetworkInterface.IPAddress + ":" + WEB_SERVER_PORT + "/picture");
            Debug.Print("------------------------------------------------------");
        }

        void PMCam_StartDataCaptured(SerCam sender, int sizeImage) {
            sender.DebugPrintEnabled = true;
            Debug.Print("Starting to take picture");
            Debug.Print("(sender.ToString()): " + (sender.ToString()));
            Debug.Print("Image Size (Bytes): " + sizeImage.ToString());
            serialCameraBufferedImageIndex = 0;
            bitmapData = new byte[sizeImage];
        }

        void PMCam_OnDataCaptured(SerCam sender, byte[] data) {
            sender.DebugPrintEnabled = true;
            if (serialCameraBufferedImageIndex + data.Length > bitmapData.Length)
                throw new Exception("Error");
            Array.Copy(data, 0, bitmapData, serialCameraBufferedImageIndex, data.Length);
            serialCameraBufferedImageIndex += data.Length;
        }


        void PMCam_FinishDataCaptured(SerCam sender) {

        }
    }
}

Debug Output:


Found debugger!

Create TS.

 Loading start at a0e856b0, end a0e9ce0c

   Assembly: mscorlib (4.2.0.0)     Assembly: Microsoft.SPOT.Native (4.2.0.0)     Assembly: Microsoft.SPOT.Hardware (4.2.0.0)  
   Assembly: Microsoft.SPOT.Hardware.PWM (4.2.0.1)     Assembly: Microsoft.SPOT.Security.PKCS11 (4.2.0.0)  
   Assembly: System.Security (4.2.0.0)  Loading Deployment Assemblies.

Attaching deployed file.

   Assembly: Microsoft.SPOT.IO (4.2.0.0)  Attaching deployed file.

   Assembly: GHI.Premium.IO (4.2.9.0)  Attaching deployed file.

   Assembly: Microsoft.SPOT.Graphics (4.2.0.0)  Attaching deployed file.

   Assembly: System.Http (4.2.0.0)  Attaching deployed file.

   Assembly: System (4.2.0.0)  Attaching deployed file.

   Assembly: Microsoft.SPOT.Net.Security (4.2.0.0)  Attaching deployed file.

   Assembly: Gadgeteer.WebServer (2.42.0.0)  Attaching deployed file.

   Assembly: GHI.Premium.System (4.2.9.0)  Attaching deployed file.

   Assembly: Microsoft.SPOT.TinyCore (4.2.0.0)  Attaching deployed file.

   Assembly: Gadgeteer.Serial (2.42.0.0)  Attaching deployed file.

   Assembly: GadgeteerApp1 (1.0.0.0)  Attaching deployed file.

   Assembly: System.Net.Security (4.2.0.0)  Attaching deployed file.

   Assembly: GHI.Premium.Net (4.2.9.0)  Attaching deployed file.

   Assembly: System.IO (4.2.0.0)  Attaching deployed file.

   Assembly: Microsoft.SPOT.Net (4.2.0.0)  Attaching deployed file.

   Assembly: GTM.GHIElectronics.SerCam (1.1.1.0)  Attaching deployed file.

   Assembly: Microsoft.SPOT.Touch (4.2.0.0)  Attaching deployed file.

   Assembly: GHI.Premium.Hardware (4.2.9.0)  Attaching deployed file.

   Assembly: Gadgeteer (2.42.0.0)  Attaching deployed file.

   Assembly: GHIElectronics.Gadgeteer.FEZCobra_II (1.1.1.0)  Attaching deployed file.

   Assembly: Microsoft.SPOT.Hardware.SerialPort (4.2.0.0)  Attaching deployed file.

   Assembly: GHI.Premium.Hardware.G120 (4.2.9.0)  Resolving.

GC: 3msec 527844 bytes used, 6811824 bytes available

Type 0F (STRING              ):     24 bytes

Type 15 (FREEBLOCK           ): 6811824 bytes

Type 17 (ASSEMBLY            ):  35064 bytes

Type 1E (BINARY_BLOB_HEAD    ): 492684 bytes

Type 34 (APPDOMAIN_HEAD      ):     72 bytes

GC: performing heap compaction...

The debugging target runtime is loading the application assemblies and starting execution.
Ready.

'Microsoft.SPOT.Debugger.CorDebug.dll' (Managed): Loaded 'C:\Program Files (x86)\Microsoft .NET Micro Framework\v4.2\Assemblies\le\mscorlib.dll', Symbols loaded.
'Microsoft.SPOT.Debugger.CorDebug.dll' (Managed): Loaded 'C:\Program Files (x86)\Microsoft .NET Micro Framework\v4.2\Assemblies\le\Microsoft.SPOT.Native.dll', Symbols loaded.
'Microsoft.SPOT.Debugger.CorDebug.dll' (Managed): Loaded 'C:\Program Files (x86)\Microsoft .NET Micro Framework\v4.2\Assemblies\le\Microsoft.SPOT.Hardware.dll', Symbols loaded.
'Microsoft.SPOT.Debugger.CorDebug.dll' (Managed): Loaded 'C:\Program Files (x86)\Microsoft .NET Micro Framework\v4.2\Assemblies\le\Microsoft.SPOT.Hardware.PWM.dll', Symbols loaded.
'Microsoft.SPOT.Debugger.CorDebug.dll' (Managed): Loaded 'C:\Program Files (x86)\Microsoft .NET Micro Framework\v4.2\Assemblies\le\Microsoft.SPOT.Security.PKCS11.dll', Symbols loaded.
'Microsoft.SPOT.Debugger.CorDebug.dll' (Managed): Loaded 'C:\Program Files (x86)\Microsoft .NET Micro Framework\v4.2\Assemblies\le\System.Security.dll', Symbols loaded.
'Microsoft.SPOT.Debugger.CorDebug.dll' (Managed): Loaded 'C:\Program Files (x86)\Microsoft .NET Micro Framework\v4.2\Assemblies\le\Microsoft.SPOT.IO.dll', Symbols loaded.
'Microsoft.SPOT.Debugger.CorDebug.dll' (Managed): Loaded 'C:\Program Files (x86)\GHI Electronics\GHI Premium NETMF v4.2 SDK\Assemblies\le\GHI.Premium.System.dll'
'Microsoft.SPOT.Debugger.CorDebug.dll' (Managed): Loaded 'C:\Program Files (x86)\GHI Electronics\GHI Premium NETMF v4.2 SDK\Assemblies\le\GHI.Premium.IO.dll'
'Microsoft.SPOT.Debugger.CorDebug.dll' (Managed): Loaded 'C:\Program Files (x86)\Microsoft .NET Micro Framework\v4.2\Assemblies\le\Microsoft.SPOT.Graphics.dll', Symbols loaded.
'Microsoft.SPOT.Debugger.CorDebug.dll' (Managed): Loaded 'C:\Program Files (x86)\Microsoft .NET Micro Framework\v4.2\Assemblies\le\Microsoft.SPOT.Net.dll', Symbols loaded.
'Microsoft.SPOT.Debugger.CorDebug.dll' (Managed): Loaded 'C:\Program Files (x86)\Microsoft .NET Micro Framework\v4.2\Assemblies\le\System.dll', Symbols loaded.
'Microsoft.SPOT.Debugger.CorDebug.dll' (Managed): Loaded 'C:\Program Files (x86)\Microsoft .NET Micro Framework\v4.2\Assemblies\le\Microsoft.SPOT.Net.Security.dll', Symbols loaded.
'Microsoft.SPOT.Debugger.CorDebug.dll' (Managed): Loaded 'C:\Program Files (x86)\Microsoft .NET Micro Framework\v4.2\Assemblies\le\System.Net.Security.dll', Symbols loaded.
'Microsoft.SPOT.Debugger.CorDebug.dll' (Managed): Loaded 'C:\Program Files (x86)\Microsoft .NET Micro Framework\v4.2\Assemblies\le\System.Http.dll', Symbols loaded.
'Microsoft.SPOT.Debugger.CorDebug.dll' (Managed): Loaded 'C:\Program Files (x86)\Microsoft .NET Micro Framework\v4.2\Assemblies\le\Microsoft.SPOT.TinyCore.dll', Symbols loaded.
'Microsoft.SPOT.Debugger.CorDebug.dll' (Managed): Loaded 'C:\Program Files (x86)\Microsoft .NET Micro Framework\v4.2\Assemblies\le\System.IO.dll', Symbols loaded.
'Microsoft.SPOT.Debugger.CorDebug.dll' (Managed): Loaded 'C:\Program Files (x86)\Microsoft .NET Gadgeteer\Core\Assemblies\.NET Micro Framework 4.2\le\Gadgeteer.dll', Symbols loaded.
'Microsoft.SPOT.Debugger.CorDebug.dll' (Managed): Loaded 'C:\Program Files (x86)\Microsoft .NET Gadgeteer\Core\Assemblies\.NET Micro Framework 4.2\le\Gadgeteer.WebServer.dll', Symbols loaded.
'Microsoft.SPOT.Debugger.CorDebug.dll' (Managed): Loaded 'C:\Program Files (x86)\Microsoft .NET Micro Framework\v4.2\Assemblies\le\Microsoft.SPOT.Hardware.SerialPort.dll', Symbols loaded.
'Microsoft.SPOT.Debugger.CorDebug.dll' (Managed): Loaded 'C:\Program Files (x86)\Microsoft .NET Gadgeteer\Core\Assemblies\.NET Micro Framework 4.2\le\Gadgeteer.Serial.dll', Symbols loaded.
'Microsoft.SPOT.Debugger.CorDebug.dll' (Managed): Loaded 'C:\Program Files (x86)\GHI Electronics\GHI Premium NETMF v4.2 SDK\Assemblies\le\GHI.Premium.Net.dll'
'Microsoft.SPOT.Debugger.CorDebug.dll' (Managed): Loaded 'C:\Program Files (x86)\GHI Electronics\GHI .NET Gadgeteer SDK\Modules\SerCam\NETMF 4.2\le\GTM.GHIElectronics.SerCam.dll', Symbols loaded.
'Microsoft.SPOT.Debugger.CorDebug.dll' (Managed): Loaded 'C:\Program Files (x86)\GHI Electronics\GHI Premium NETMF v4.2 SDK\Assemblies\le\GHI.Premium.Hardware.dll'
'Microsoft.SPOT.Debugger.CorDebug.dll' (Managed): Loaded 'C:\Program Files (x86)\GHI Electronics\GHI .NET Gadgeteer SDK\Mainboards\FEZCobra_II\NETMF 4.2\le\GHIElectronics.Gadgeteer.FEZCobra_II.dll', Symbols loaded.
'Microsoft.SPOT.Debugger.CorDebug.dll' (Managed): Loaded 'C:\Users\ethos-one\AppData\Local\Temporary Projects\GadgeteerApp1\bin\Debug\le\GadgeteerApp1.exe', Symbols loaded.
'Microsoft.SPOT.Debugger.CorDebug.dll' (Managed): Loaded 'C:\Program Files (x86)\Microsoft .NET Micro Framework\v4.2\Assemblies\le\Microsoft.SPOT.Touch.dll', Symbols loaded.
'Microsoft.SPOT.Debugger.CorDebug.dll' (Managed): Loaded 'C:\Program Files (x86)\GHI Electronics\GHI Premium NETMF v4.2 SDK\Assemblies\le\GHI.Premium.Hardware.G120.dll'
The thread '<No Name>' (0x2) has exited with code 0 (0x0).
Using mainboard GHI Electronics FEZCobra II version 1.0
RS9110 firmware version Number is 4.4.5
RS9110 driver version Number is 4.4.5
The thread '<No Name>' (0x3) has exited with code 0 (0x0).
------------------------------------------------------
Starting the Web Server listening on 192.168.1.102:80
Web server started at http://192.168.1.102:80/
Handlers have been added to the web server. try: http://192.168.1.102:80/picture
------------------------------------------------------
The thread '<No Name>' (0x6) has exited with code 0 (0x0).
Sleeping 200
Sleeping 400
Sleeping 600
Starting to take picture
(sender.ToString()): SerCam
Image Size (Bytes): 12608
Sleeping 800
Sleeping 1000
Sleeping 1200
Sleeping 1400
Sleeping 1600
Sleeping 1800
The thread '<No Name>' (0x8) has exited with code 0 (0x0).
Sleeping 2000
The thread '<No Name>' (0x7) has exited with code 0 (0x0).
Sleeping 200
Sleeping 400
Sleeping 600
Starting to take picture
(sender.ToString()): SerCam
Image Size (Bytes): 12696
Sleeping 800
Sleeping 1000
Sleeping 1200
Sleeping 1400
Sleeping 1600
Sleeping 1800
Sleeping 2000
The thread '<No Name>' (0xa) has exited with code 0 (0x0).
Sleeping 2200

Edit: This debug output is from requesting a single picture. I confirm with wireshark that this is the case.

huge buffer of karma for anyone who can return my sanity :slight_smile:


#2

Oh… I noticed that it’s actually the web event handler that’s causing the issue…
I’m not really sure why it’s being invoked twice…


#3

When things do not work as expected, we normally run a simple project to test the one part that s not working.

By the way, can you please set your user name. We like to know who we are talking to :slight_smile:


#4

Hi “-1”

Yes, you’ve said your handler is called twice. THAT is where I’d start to look. don’t bother with the camera yet but put diagnostic logging in there, like “Asked to take a picture at X time by requestor Y”, as well as breakpoints :slight_smile:


#5

I did step through it with a web event that returns a static string (“Test/Hello world!”). This uses all of the same set up as returning a picture otherwise would. It is only called once…

I believe there are some side effects either in the debugger (Visual C# express 2010) or possibly from the camera itself. I will need to get the SerCam_42.cs source, and step through it I suppose…

Also, I did pick User_-1, I think it’s a funny name because of the bitmodel used for two’s compliment VS magnitude only :slight_smile: hehehe… if someone tried to look at all the usernames that match User_*, and try to stuff the number behind mine into a magnitude only model, then they might just learn something :stuck_out_tongue:


#6

@ User_-1 - I don’t know anything about the serial camera module, and I don’t know much about Gadgeteer, so my suggestion may be way off, but…

I noticed that inside the web event handler you have a while loop and do a potentially long Thread.Sleep. Instead you should perhaps start a timer that checks for the camera being not busy.


#7

that is older driver, use this one

http://www.ghielectronics.com/community/forum/topic?id=11811&page=1#msg120110