SerialCamera module, exception in driver

Just tested the serial Camera module with the Raptor… Followed the sample code step-by-step, and could not get it working.

https://www.ghielectronics.com/docs/176/serial-camera-module

All i have connected to the Raptor is the T43 display, the Serial Camera and an power module.

serCam.isNewImageReady is newer TRUE, and I suspect it’s when it tries to convert the downloaded data inside the driver, the exception occurs.

    #### Exception System.Exception - 0x00000000 (5) ####
    #### Message: 
    #### Gadgeteer.Modules.GHIElectronics.SerCam::ReadBytes [IP: 002f] ####
    #### Gadgeteer.Modules.GHIElectronics.SerCam::ReadFrameBuffer [IP: 006b] ####
    #### Gadgeteer.Modules.GHIElectronics.SerCam::UpdateStreaming [IP: 003a] ####
A first chance exception of type 'System.Exception' occurred in GTM.GHIElectronics.SerCam.dll

Do you get the same exception if you remove the display from the project? Does the exception happen right away and repeatedly?

And make sure you are using latest firmware

@ Dat - I’ll double check that the Raptor is on the latest firmware. I’m using the 2014 SDK package.

@ John - It waited a second or so (probably while the internal buffer fills up) then it threw an Exception. I’ll did only have the display and the serial camera connected. I’ll re-try without the T43.

Im experiencing this as well, and considering what to do to avoid that exception. It seems that nothing is wrong with the image, but it is really slow transferring the image data. Setup: Cobra II, with T35 display (which is not used for the image at all.). :wall:

Can you post a minimal program that reliably reproduces it?

@ John - I pretty much copy/pasted the code from the Example “Example 1: Capture & Display”

https://www.ghielectronics.com/docs/176/serial-camera-module

I can redo the code so you get a copy of the solution running/failing…


        private void GetPictureFromCam()
        {
            serCam.SetImageSize(SerCam.Camera_Resolution.SIZE_VGA);
            serCam.SetRatio(255);
            serCam.StartStreaming();
            while (!serCam.isNewImageReady) { Debug.Print("Waiting for cam!"); Thread.Sleep(500); }
            picture = serCam.GetImageData();
            picture_size = serCam.dataImage.Length;
            serCam.StopStreaming();

        }

Good luck!

@ danibjor What socket are you using for the sercam? Can you try with another Raptor and sercam if you have any?

@ njbuch - Selecting a VGA image requires a 1MB+ buffer. In the past, normal MF allocation methods could not be used to allocate a buffer larger than ~700MB. Could the buffer size be an issue?

@ njbuch I was able to get an image from the sercam in about 7 seconds repeatedly. As Mike said, a VGA image is pretty large. If speed is an issue, you can try smaller images.

Hello Community!
Perhaps this would be helpful.
I bought a cerberus, connect it via USB (socket 8), and connect a camera (socket 2).
Then run the following program:
using System.Threading;
using Gadgeteer.Modules.GHIElectronics;
using Microsoft.SPOT;

namespace serCam02
{
public partial class Program
{
// This method is run when the mainboard is powered up or reset.
void ProgramStarted()
{
// Use Debug.Print to show messages in Visual Studio’s “Output” window during debugging.
Debug.Print(“Program Started”);

        for (int i = 0; i < 5; i++)
        {
            Debug.Print("Counts = " + i.ToString());
            GetPictureFromSercam();
        }
    }
    private void GetPictureFromSercam()
    {
        serCam.SetImageSize(SerCam.Camera_Resolution.SIZE_QQVGA);
        serCam.SetRatio(255);
        long start = Microsoft.SPOT.Hardware.Utility.GetMachineTime().Ticks;
        serCam.StartStreaming();
        while (!serCam.isNewImageReady) { Debug.Print("Waiting for cam!"); Thread.Sleep(500); }
        byte[] picture = serCam.GetImageData();
        int picture_size = serCam.dataImage.Length;
        serCam.StopStreaming();
        long end = Microsoft.SPOT.Hardware.Utility.GetMachineTime().Ticks;
        long duration = (end - start) / 10000;
        Debug.Print("duration;  " + duration.ToString() + " ms, " + "  length:  " + 

picture_size.ToString());
}
}
}

The result was one time this:

Using mainboard GHI Electronics FEZCerberus version 1.1
Program Started
WARN: Total initialization time exceeds 10 seconds.
: ProgramStarted is blocking execution, which means events and timers wWaiting for cam!
Waiting for cam!
Waiting for cam!
Der Thread ‘’ (0x4) hat mit Code 0 (0x0) geendet.
duration; 14613 ms, length: 1368
Counts = 1
Waiting for cam!
Der Thread ‘’ (0x5) hat mit Code 0 (0x0) geendet.
duration; 1025 ms, length: 1380
Counts = 2
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.
Waiting for cam!
Waiting for cam!
Waiting for cam!
Waiting for cam!
Der Thread ‘’ (0x6) hat mit Code 0 (0x0) geendet.
duration; 10590 ms, length: 1332
Counts = 3
Waiting for cam!
Waiting for cam!
Waiting for cam!
Waiting for cam!
Der Thread ‘’ (0x7) hat mit Code 0 (0x0) geendet.
duration; 2593 ms, length: 1336
Counts = 4
Waiting for cam!
Waiting for cam!
Waiting for cam!
Waiting for cam!
Der Thread ‘’ (0x8) hat mit Code 0 (0x0) geendet.
duration; 2600 ms, length: 1348
Der Thread ‘’ (0x3) hat mit Code 0 (0x0) geendet.

And the other time that;

Program Started
Counts = 0
Waiting for cam!
Waiting for cam!
Waiting for cam!
Waiting for cam!

Der Thread ‘’ (0x4) hat mit Code 0 (0x0) geendet.
duration; 8609 ms, length: 1372
Counts = 1
Waiting for cam!
Waiting for cam!
Waiting for cam!
Waiting for cam!
Der Thread ‘’ (0x5) hat mit Code 0 (0x0) geendet.
duration; 2606 ms, length: 1384
Counts = 2
Waiting for cam!
Waiting for cam!
Waiting for cam!
Waiting for cam!
Der Thread ‘’ (0x6) hat mit Code 0 (0x0) geendet.
duration; 2599 ms, length: 1344
Counts = 3
WARN: Total initialization time exceeds 20 seconds.
: ProgramStarted is blocking execution, which means events and timers wWaiting for cam!
Waiting for cam!
Waiting for cam!
Der Thread ‘’ (0x7) hat mit Code 0 (0x0) geendet.
duration; 8606 ms, length: 1372
Counts = 4
Waiting for cam!
Waiting for cam!
Waiting for cam!

Waiting for cam!
Der Thread ‘’ (0x8) hat mit Code 0 (0x0) geendet.
duration; 7609 ms, length: 1348
Der Thread ‘’ (0x3) hat mit Code 0 (0x0) geendet.

Can you please explain the results?
Ingeborg

your results are not valid because of this:

for (int i = 0; i < 5; i++)
 {
 Debug.Print("Counts = " + i.ToString());
 GetPictureFromSercam();
 }

You must not put code like this in the ProgramStarted() as it blocks the Gadgeteer framework from completing it’s startup correctly.

You should link that activity to some action. Either a once-off timer, or perhaps a button press, but it needs to be invoked after the ProgramStarted exits and allows the dispatcher to complete.

(note, this may not make the camera work, but it’s not a valid test the way it is)

Here’s a reference on this - it’s not a direct match to your “only partially blocking” execution but the consequence could still be the same…
http://blogs.msdn.com/b/net_gadgeteer/archive/2011/12/19/why-not-while-true.aspx

You must not put code like this in the ProgramStarted() as it blocks the Gadgeteer framework from completing it’s startup correctly.

Plese help with a correct code!

It is very helpful to say what’no going on.
::slight_smile:
Please show us a working example.

@ Ingeborg -

You should create another thread instead of calling in ProgramStarted() funtion.
This function need to be returned as Brett explained.

On cerberus, there is also limitation about memory, if an array is often used, suggest should be global.

Something like these


using System;
using System.Collections;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Presentation;
using Microsoft.SPOT.Presentation.Controls;
using Microsoft.SPOT.Presentation.Media;
using Microsoft.SPOT.Touch;

using Gadgeteer.Networking;
using GT = Gadgeteer;
using GTM = Gadgeteer.Modules;

namespace TestSerCam
{
    public partial class Program
    {
       
        // This method is run when the mainboard is powered up or reset.  
         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.
            new Thread(VideoStreamming).Start();
            Debug.Print("Program Started");
        }
        
        void VideoStreamming()
        {
            serCam.StartStreaming();
           
            while (true)
            {
                Thread.Sleep(100);
                if (serCam.isNewImageReady)
                {
                    serCam.isNewImageReady = false;  
                   
                    data = serCam.dataImage;
                }    
            }
        }
    }
}

Or if you don’t want to create another buffer, you can use the serCam.dataImage directly, but I think you should stop the streaming while you are using it.

void VideoStreamming()
        {
            serCam.StartStreaming();
           
            while (true)
            {
                Thread.Sleep(100);
                if (serCam.isNewImageReady)
                {
                                      serCam.StopStreaming();
                    // use serCam.dataImage directly
                   // Restart Streaming when you are done using the buffer
                }    
            }
        }

PLEASE show us a runnging example (as my above including Debug, etc.
it is not very helpful to show other code examples that are not complete.
I dit not really understand why my example is not working to your opinion!
You have 2 days to explain because I have to work on other projects.
CU Ingeborg

Is this what you wanted?

@ Ingeborg -

using System;
using System.Collections;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Presentation;
using Microsoft.SPOT.Presentation.Controls;
using Microsoft.SPOT.Presentation.Media;
using Microsoft.SPOT.Touch;

using Gadgeteer.Networking;
using GT = Gadgeteer;
using GTM = Gadgeteer.Modules;

namespace TestSerCam
{
    public partial class Program
    {
       
            new Thread(VideoStreamming).Start();
            Debug.Print("Program Started");
        }
       int imageCnt;
        void VideoStreamming()
        {
           serCam.StartStreaming();
           imageCnt = 5;
            while (imageCnt >0)
            {
                Thread.Sleep(50);
                if (serCam.isNewImageReady)
                {
                    serCam.isNewImageReady = false;  
                    Debug.Print("Picture size =  " + serCam.dataImage.Length);
                    imageCnt--;
                }    
            }
        }
    }
}

Telling someone that their attempt to help you was not helpful, and giving them two days to fix your problem, is not going to get you a quick answer.

You do not understand some very basic Gadgeteer concepts, which were explained to you by Brett and Dat. Please try to understand what they are telling you.

This might be a good start https://www.ghielectronics.com/docs/43/first-gadgeteer-project

3 Likes

BTW, a QQVGA image might be too big for the Cerberus memory. It has around 76KB and the Cerberus only has 112KB available.