shariltumin / esp32-cam-micropython-2022

MicroPython esp32-cam firmware with camera support compiled with esp-idf-4.4.0. Python script files for live streaming
MIT License
174 stars 33 forks source link

Partial pictures. #7

Closed davefes closed 1 year ago

davefes commented 1 year ago

About 10% of the time I take a picture is it missing bottom part of the image. Also, the file seems to be corrupted, which is causing my server to "hang" waiting for something. camera.framesize(10) and camera.quality(10).

I have found that any delay between camera.init() and doing any of the settings can provoke similar issues.

What is the correct way to init the camera and apply wanted settings?

I also have found that I have to do a POWER_ON reset or I can get camera.init() failed as well.

Would really appreciate some feedback on these issues.

shariltumin commented 1 year ago

Before making any other changes, run camera.init() first.

If camera.init() fails, the board must be hard reset.

POWER ON A push button can be used for this, or in MicroPython, do:

import machine machine.reset()

Image quality and stability are dependent on the following factors: 1) Consistent power supply 2) The OV2640 sensor's quality 3) The connection at the flex 24 connectors 4) The MCU

I'd start by checking the power supply.

Use 5V from the USB-to-Serial to power the ESP32-CAM, i.e. connect 5V from the USB-to-Serial to 5V on the ESP32-CAM board. Make use of a USB hub with an external power supply. PC USB ports may not have sufficient current.

Change to another OV2640 sensor, i.e., the lens.

Run this stress check.

import camera camera.init() while True: img=camera.capture() print(len(img))

You should get reasonably consistent numbers output.

davefes commented 1 year ago

Thank you for your comments.

As per https://github.com/orgs/micropython/discussions/9345 I found that a POWERON_RESET does a better job.

After another late night, specifically changing camera.framesize and camera.quality, I seem to get fewer corrupted pictures using 14 (FRAME_UVGA) and quality 30.

During testing I am powering the ESP32-CAM via a FTDI programmer, but with an added 1000uF cap on the 5V. I am using the flash LED so that could be putting a heavy-load on the AMS1117. I check for supply "dips" using a DSO. In final use it will be powered off a Li-ion cell.

To handle corrupt files I comment-out the print(len(img)) statement and do the following:

#  save image
with open('image.jpeg', 'wb') as outfile:
    outfile.write(img)

f = open('image.jpeg', 'rb')
first2bytes = f.read(2)
f.close()

valid_jpeg = b'\xff\xd8'

if (first2bytes == valid_jpeg):
    print ('success')
    gc.collect()
    import send_file
else:
    print ('not a valid jpeg file')
    utime.sleep(5)
    machine.reset() #  change to a power-on reset implementation

I will consider the other suggestions you have made.

shariltumin commented 1 year ago

Thanks, your POWERON_RESET can be very useful to get machine.PWRON_RESET. machine.reset() gives machine.HARD_RESET only.

davefes commented 1 year ago

The previous test for a valid_jpeg file only appears to sort-out the files that do not have the correct header, which happens occasionally. Files that can be missing some on the bottom of the picture still have the correct header!

Thanks to Google it seems you can check for a proper jpeg file ending ... in "all or most cases".

#  save image
with open('image.jpeg', 'wb') as outfile:
    outfile.write(img)

#  valid jpeg ending
valid_jpeg = b'\xff\xd9'

#  now check for the correct ending
with open('image.jpeg', 'rb') as file:
    try:
        file.seek(-2, 2)
        while file.read(1) != b'\n':
            file.seek(-2, 1)
    except OSError:
        file.seek(0)

    last_line = file.readline()

last_chars = last_line[-2:]
print('Last 2 characters : ', last_chars)

if (last_chars == valid_jpeg):
    print ('success')
    gc.collect()

    import send_file
else:
    print ('not a valid jpeg file')
    utime.sleep(5)
    config.poweron_reset.on()
davefes commented 1 year ago

I suspect even checking for the correct ending that one might still get a "cropped" image. So far, at least, the server seems to handle those "cropped" images properly.

Stress testing now begins.

davefes commented 1 year ago

After many more tests I can see the image that I am saving on flash is correct whilst the image at the server is "cropped" and the server "hangs". Tried adding a '\n' at the end of the .jpeg file but that doesn't fix the problem.