espressif / esp32-camera

Apache License 2.0
1.86k stars 633 forks source link

ESP32 OV2640 - Changing Contrast Resets Brightness #401

Closed chalabit closed 2 years ago

chalabit commented 2 years ago

First, Let me apologize if I'm placing this issue in the wrong area.

I'm using an M5Stack Timer Camera, Arduino IDE and the standard camera software. I'm having problems w/ the brightness and contrast controls.

If I set the brightness, the contrast changes. If I set the contrast, the brightness changes.

Is there a known fix for this?

Thanks!

me-no-dev commented 2 years ago

This is a problem with the OV2640 driver. We will try to fix it, but can not give you timeframe currently.

chalabit commented 2 years ago

Thank you.

I've been trying to diagnose what is occurring within the driver and sensor code. For testing, I've been setting and then reading back the various registers on the OV2640 to try to determine what is going wrong.

It seems like the current OV2640 driver is sending the correct values to the sensor for brightness and contrast etc.. However, something is triggering a change to the register values after a write occurs.

Is there another function that is tripped when you change the contrast or brightness?

I may be able to figure it out a solution if you can describe what is occurring.

me-no-dev commented 2 years ago

these tables and these functions control the settings. Tables access the internal SDE registers (you set in one reg the SDE reg address 'BPADDR' and use another reg for SDE FIFO 'BPDATA'). If you decipher the tables, you will see that all 3 tables overwrite som common SDE registers.

We could guess from this that:

Unfortunately we do not have any specs on those registers, so the only option is poking them and checking the result

chalabit commented 2 years ago

Here's the spec from Omnivision.. See section 11.3 page 16 OV2640 Camera Module Software Application Notes.pdf .

chalabit commented 2 years ago

Also. the Omnivision spec w/ more detailed register handling... Camera ov2640_ds1.8.pdf .

me-no-dev commented 2 years ago

Here's the spec from Omnivision.. See section 11.3 page 16 OV2640 Camera Module Software Application Notes.pdf .

This is the same thing as what we have in our code.

me-no-dev commented 2 years ago

Also. the Omnivision spec w/ more detailed register handling... Camera ov2640_ds1.8.pdf .

Also does not describe the SDE registers.

chalabit commented 2 years ago

I will create some code to write/read the registers described above to see what happens and log the results......

me-no-dev commented 2 years ago

thanks!

chalabit commented 2 years ago

I may have an idea to fix the contrast/brightness issue, but need to test it out.

? Would you be able to tell me how to get the source code? I've looked everywhere and I cannot find where the Arduino Camera and OV2640 files are located.. The link you provide above is not for the Arduino. (I'm new to all of this :) )

I'm using the Arduino IDE with an M5Stack TimerCameraX. Ideally, I'd like to download the source code, put it into my test project and try out some ideas. Not sure where to get the source code. I cannot even locate the OV2646.c or OV2640.h files on my computer.... note.. I'm new to all of this so thanks for your patience...

felmue commented 2 years ago

Hi guys

I did an experiment with modified code so when the contrast level is set, only the contrast registers (e.g. SDE regs 7 and 8) are modified but not the brightness registers (e.g. SDE regs 9 and 10). This resulted in an image where the contrast was changed ok but brightness would change a lot as well. I guess that is the reason the current code also modifies the brightness when contrast is set - to compensate for the brightness change.

I then put together the following table (using the brightness values from the original contrast table as start values for brightness 0) for a new brightness value (bv) dependent on the contrast (C) and brightness (B) level:

C \ B |  -2 |  -1 |  0  |  +1 |  +2 |
-------------------------------------
-2    |  32 |  42 |  52 |  62 |  72 |
-1    |  22 |  32 |  42 |  52 |  62 |
 0    |  12 |  22 |  32 |  42 |  52 |
+1    |   2 |  12 |  22 |  32 |  42 |
+2    | (0) |   2 |  12 |  22 |  32 |

The brightness value (bv) can be calculated like this:

bv = 32 + (B * 10) - (C * 10); // Note: bv can get negative

Below are my new set_brightness() and set_contrast() functions:

static int set_brightness(sensor_t *sensor, int level)
{
    int ret=0;
    level += 3;
    if (level <= 0 || level > NUM_BRIGHTNESS_LEVELS) {
        return -1;
    }
    sensor->status.brightness = level-3;

    // Calculate brightness value from brightness and contrast level
    int bv = 0x20 + (sensor->status.brightness * 10) - (sensor->status.contrast * 10);
    if (bv < 0) bv = 0;

    // Write brightness registers (e.g. SDE regs 9 and 10)
    WRITE_REG_OR_RETURN(BANK_DSP, BPADDR, 0x00);
    WRITE_REG_OR_RETURN(BANK_DSP, BPDATA, 0x04);
    WRITE_REG_OR_RETURN(BANK_DSP, BPADDR, 0x09);
    WRITE_REG_OR_RETURN(BANK_DSP, BPDATA, bv);
    WRITE_REG_OR_RETURN(BANK_DSP, BPDATA, 0x06);

    return ret;
}

static int set_contrast(sensor_t *sensor, int level)
{
    int ret=0;
    level += 3;
    if (level <= 0 || level > NUM_CONTRAST_LEVELS) {
        return -1;
    }
    sensor->status.contrast = level-3;

    // Only use contrast values (e.g. SDE regs 7 and 8) from the contrast_regs table
    for (int i=0; i<5; i++) {
        WRITE_REG_OR_RETURN(BANK_DSP, contrast_regs[0][i], contrast_regs[level][i]);
    }
    // then adjust brightness (dependent on current brightness and new contrast level)
    set_brightness(sensor, sensor->status.brightness);

    return ret;
}

Thanks Felix

github-actions[bot] commented 2 years ago

This issue appears to be stale. Please close it if its no longer valid.

Rudd-O commented 7 months ago

This is not completed! Sensor on OV2640 still cannot get contrast and brightness changes as expressed by OP.

grahameHM commented 6 months ago

Agree, still not solved - brightness, contrast, saturation & special effect overwrite each other. Another minor feature I've found is 'constant reboot when calling esp_camera_fb_get first time with small framesize (<4)'.