GrovePi+ Causing Camera to Error Out?[SOLVED]


#1

So my setup is a Raspberry Pi 3 with a GrovePi+ board attached and the newest raspberry pi camera module. Connected to the GrovePi+ I have 3 temperature/humidity sensors, 1 magnetic reed switch, and a relay all attached to digital ports. The camera connected via the ribbon cable and the Raspberry Pi camera port. I have a script that runs every 15 minutes to take readings from the temperature/humidity and reed switch. The relay is activated manually through a script when it is needed. I have a script running continuously using the camera to detect motion by taking an initial picture and then continuously looping through another picture and comparing the images to detect changes and therefor motion, which then causes a video to start recording. After a different amount of time the script runs, it errors out with this message.

mmal: mmal_vc_component_enable: failed to enable component: ENOSPC
mmal: camera component couldn’t be enabled
mmal: main: Failed to create camera component
mmal: Failed to run camera app. Please check for firmware updates.

Everything is up to date and I am able to pictures or video manually whenever I want with no issues, it’s just when the script runs that I get this error. After some research it seems this error is do to a few possible things. Up to date firmware which mine is up to date. Accessing the camera from more than one process, which I do not believe to be caused by my script, I have the same script running on a Pi Zero with no GrovePi and do not experience this error. Another cause I have seen is the GPU Memory not being set high enough, I had it at 128 in /boot/config.txt and saw a post to bump it up to 144 and it fixed their issue, but that has not solved mine.

My question is, has there been any reported issues, I haven’t been able to find in the forum, related to the GrovePi’s I2C communication interfering with the camera port?

My camera script is below, maybe I missed something within it that causes the problem, possibly the camera process not closing out so when it comes back around it thinks the camera is being accessed by 2 different process.

import StringIO
import subprocess
import os
import time
from datetime import datetime
from PIL import Image

Motion detection settings:

Threshold - how much a pixel has to change by to be marked as “changed”

Sensitivity - how many changed pixels before capturing an image, needs to be higher if noisy view

ForceCapture - whether to force an image to be captured every forceCaptureTime seconds, values True or False

filepath - location of folder to save photos

filenamePrefix - string that prefixes the file name for easier identification of files.

diskSpaceToReserve - Delete oldest images to avoid filling disk. How much byte to keep free on disk.

cameraSettings - “” = no extra settings; “-hf” = Set horizontal flip of image; “-vf” = Set vertical flip; “-hf -vf” = both horizontal and vertical flip

threshold = 10
sensitivity = 30
forceCapture = False
forceCaptureTime = 60 * 60 # Once an hour
filepath = "/home/pi/Hub6/Camera"
filenamePrefix = "Hub6"
diskSpaceToReserve = 40 * 1024 * 1024 # Keep 40 mb free on disk
cameraSettings = “”

settings of the photos to save

saveWidth = 1296
saveHeight = 972
saveQuality = 15 # Set jpeg quality (0 to 100)

Test-Image settings

testWidth = 100
testHeight = 75

this is the default setting, if the whole image should be scanned for changed pixel

testAreaCount = 1
testBorders = [ [[1,testWidth],[1,testHeight]] ] # [ [[start pixel on left side,end pixel on right side],[start pixel on top side,stop pixel on bottom side]] ]

testBorders are NOT zero-based, the first pixel is 1 and the last pixel is testWith or testHeight

with “testBorders”, you can define areas, where the script should scan for changed pixel

for example, if your picture looks like this:

…XXXX

“.” is a street or a house, “X” are trees which move arround like crazy when the wind is blowing

because of the wind in the trees, there will be taken photos all the time. to prevent this, your setting might look like this:

testAreaCount = 2

testBorders = [ [[1,50],[1,75]], [[51,100],[26,75]] ] # area y=1 to 25 not scanned in x=51 to 100

even more complex example

testAreaCount = 4

testBorders = [ [[1,39],[1,75]], [[40,67],[43,75]], [[68,85],[48,75]], [[86,100],[41,75]] ]

in debug mode, a file debug.bmp is written to disk with marked changed pixel an with marked border of scan-area

debug mode should only be turned on while testing the parameters above

debugMode = False # False or True

Capture a small test image (for motion detection)

def captureTestImage(settings, width, height):
command = “raspistill %s -w %s -h %s -t 200 -e bmp -n -o -” % (settings, width, height)
imageData = StringIO.StringIO()
imageData.write(subprocess.check_output(command, shell=True))
imageData.seek(0)
im = Image.open(imageData)
buffer = im.load()
imageData.close()
return im, buffer

Save a full size image to disk

def saveImage(settings, width, height, quality, diskSpaceToReserve):
keepDiskSpaceFree(diskSpaceToReserve)
timestr = time.strftime("%m-%d-%Y_%H:%M:%S")
filename = filepath + “/” + filenamePrefix

print “Captured %s” % filename + timestr

os.system("raspivid -o /home/pi/Hub6/Camera/Hub6_"+timestr+".h264 -vf -t 60000 -n")
os.system("sudo chmod 777 /home/pi/Hub6/Camera/Hub6_"+timestr+".h264")
os.system("avconv -r 30 -i /home/pi/Hub6/Camera/Hub6_"+timestr+".h264 -vcodec copy /home/pi/Hub6/Camera/Hub6_"+timestr+".mp4")
os.system("sudo rm /home/pi/Hub6/Camera/Hub6_"+timestr+".h264")

Keep free space above given level

def keepDiskSpaceFree(bytesToReserve):
if (getFreeSpace() < bytesToReserve):
for filename in sorted(os.listdir(filepath + “/”)):
if filename.startswith(filenamePrefix) and filename.endswith(".jpg"):
os.remove(filepath + “/” + filename)
# print “Deleted %s/%s to avoid filling disk” % (filepath,filename)
if (getFreeSpace() > bytesToReserve):
return

Get available disk space

def getFreeSpace():
st = os.statvfs(filepath + “/”)
du = st.f_bavail * st.f_frsize
return du

Get first image

image1, buffer1 = captureTestImage(cameraSettings, testWidth, testHeight)

Reset last capture time

lastCapture = time.time()

while (True):

# Get comparison image
image2, buffer2 = captureTestImage(cameraSettings, testWidth, testHeight)

# Count changed pixels
changedPixels = 0
takePicture = False

if (debugMode): # in debug mode, save a bitmap-file with marked changed pixels and with visible testarea-borders
    debugimage = Image.new("RGB",(testWidth, testHeight))
    debugim = debugimage.load()

for z in xrange(0, testAreaCount): # = xrange(0,1) with default-values = z will only have the value of 0 = only one scan-area = whole picture
    for x in xrange(testBorders[z][0][0]-1, testBorders[z][0][1]): # = xrange(0,100) with default-values
        for y in xrange(testBorders[z][1][0]-1, testBorders[z][1][1]):   # = xrange(0,75) with default-values; testBorders are NOT zero-based, buffer1[x,y] are zero-based (0,0 is top left of image, testWidth-1,testHeight-1 is botton right)
            if (debugMode):
                debugim[x,y] = buffer2[x,y]
                if ((x == testBorders[z][0][0]-1) or (x == testBorders[z][0][1]-1) or (y == testBorders[z][1][0]-1) or (y == testBorders[z][1][1]-1)):
                    # print "Border %s %s" % (x,y)
                    debugim[x,y] = (0, 0, 255) # in debug mode, mark all border pixel to blue
            # Just check green channel as it's the highest quality channel
            pixdiff = abs(buffer1[x,y][1] - buffer2[x,y][1])
            if pixdiff > threshold:
                changedPixels += 1
                if (debugMode):
                    debugim[x,y] = (0, 255, 0) # in debug mode, mark all changed pixel to green
            # Save an image if pixels changed
            if (changedPixels > sensitivity):
                takePicture = True # will shoot the photo later
            if ((debugMode == False) and (changedPixels > sensitivity)):
                break  # break the y loop
        if ((debugMode == False) and (changedPixels > sensitivity)):
            break  # break the x loop
    if ((debugMode == False) and (changedPixels > sensitivity)):
        break  # break the z loop

if (debugMode):
    debugimage.save(filepath + "/debug.bmp") # save debug image as bmp
   # print "debug.bmp saved, %s changed pixel" % changedPixels
# else:
#     print "%s changed pixel" % changedPixels

# Check force capture

if forceCapture:

#    if time.time() - lastCapture > forceCaptureTime:
 #       takePicture = True

if takePicture:
    lastCapture = time.time()
    saveImage(cameraSettings, saveWidth, saveHeight, saveQuality, diskSpaceToReserve)

# Swap comparison buffers

image1 = image2

buffer1 = buffer2


#2

@nickmiller1591,
I just searched for this error too and it looks like it is related to just the camera. Since you have two Pi setups and this is coming on the Pi3, can you remove the GrovePi and try running the script a couple of times and see if the problem goes away or if it still comes. Also, does the error come all the time or does it come randomly.

I think you were mentioning about this post and might have already tried this but can you try the following:

  • Make sure the camera ribbon cable is tightly connected
  • Maybe increase the GPU Memory to 256MB from raspi-config and see if that helps
  • Run the firmware update on the Pi sudo rpi-update and see if that helps

I also had a few questions about the program above. There are a few places in the script which you have posted above which have a timeout parameter in the camera commands:

command = “raspistill %s -w %s -h %s -t 200 -e bmp -n -o -” % (settings, width, height)
imageData.write(subprocess.check_output(command, shell=True))

and

os.system(“raspivid -o /home/pi/Hub6/Camera/Hub6_”+timestr+".h264 -vf -t 60000 -n")
so does the program actually halt for 200ms in the first case and 60 seconds in the second case because the camera commands would still be running in the background or does it just move on to the next steps and do you think that might be a source of the problems.

One last thing, can you check the power supply that you are using and make sure that it is a 5V 2A power supply because we have seen a lot of weird problems like this due to a power supply which is not good enough.


#3

Thanks for the reply karan. I’ll make sure the ribbon cable is connected properly and change the GPU memory first. Firmware should be up to date as I updated about a week ago before putting the Pi into action. As far as what happens in those parts of the script I will have to do some more research because I was wondering the same thing. I’ve read this error can occur when the camera is accessed multiple times simultaneously or accessed after a previous process may be done but didn’t close out completely. The weird part about that is, the error seems to be totally random as far as timing, I’m trying to add a few print statements in while it runs to catch how long it goes before the error occurs to see if there is a pattern there. The power supply may also be an issue, which I didn’t consider before. The power supply itself is the correct 5v, 2A, but its connected through an older power strip which may issues itself and in turn affecting the Pi PSU. I’ll update my findings soon.


#4

An update on my findings:

The ribbon cable is seated properly, I even tried a new ribbon cable as well. I set the GPU_Mem in /boot/config.txt to 256 and the pi has the latest update. I am still experiencing the script to error out after some time. I tried tracking exactly how it takes for the script to error out and there seems to be no pattern. It first ran for about an hour before the error, then it went for almost 8 hours before the error, and then most recently ran for about 1 hour 20 minutes before the error occured. Here is what the full error message states, and it happens at this point in the script everytime:

This base of this script was written by other people and I found it posted out on the Raspberry Pi forums so the bulk of it is a bit beyond my programming knowledge.

I tested finding out what happens with the raspistill and raspivid parts of the script and the script does stop and wait for the “-t 200” or “-t 600000” time interval to complete before moving on to different parts of the script.

I’m not sure if seeing this whole error message helps, but I’m starting to think it may be a power issue, I’m going to next test that out by powering from a known good power source and not using the power strip I have been using.


#5

Do keep us posted on this too. Another things that you can try is to just run either raspistill or raspivid at a time and see if they crash if you run the code for a whole day. I have a bit of suspicion on how they are being run too.


#6

So after trying to remove the power strip and powering from a known good power source I was still having problems. I decided to try and use a different Pi and different camera module/ribbon cable thinking it may have been a hardware issue. I also decided to maybe just try modifying the regular Raspbian Jessie Image to work with the grovepi thinking maybe there was some unnecessary background process running with Raspbian for Robots. New problem I am experiencing so far is that the 3 temp/humidity sensors I am using are all reporting the same exact temperature and humidity at every reading. One sits right next to an AC Unit, the other is within an enclosure housing network equipment and the third is outside of the enclosure monitoring the outside environment…so it really makes no sens for all 3 to have the same exact values. Any thoughts? Should I go back to the Raspbian for Robots image? The weird thing is the values change, but all change the same, and I clearly define using different ports, D2, D4, and D7.


#7

Are you sure you’re not polling the same sensor port three different times?


#8

Thanks for the reply John. I’m sure I’m not pulling data from the same port, I have it clearly defined in my script and that was one of the first things I checked. So I decided anyway to go back to my Raspbian for Robots image to take away that variable of a different OS. Started everything up yesterday afternoon and so far the camera script is still running which is much longer than it every did before so I’m beginning to think it was a hardware issue either within the old Pi itself, the camera port on that Pi, or possibly the camera I was using. I’ll continue to monitor and update my findings soon.


#9

Ok, please let us know!


#10

After switching out the Pi and the camera module, everything has been running solid for over a week now. Seems like it turned out to just be a hardware issue. Thanks for all of your help John and Karan.


#11

This topic was automatically closed after 24 hours. New replies are no longer allowed.