raduprv / esp32-cam_ov2640-timelapse

A timelapse program for esp32 cam with ov2640 sensor. The exposure is done manually based on the light level, and the image quality is far better than the default settings.
Apache License 2.0
37 stars 5 forks source link

program logic a little confusing #3

Open jensdk3 opened 3 years ago

jensdk3 commented 3 years ago

Hi Raduprv, Thanks for this excellent program and all your effort!

I'm a little confused on the structure of your program logic.

1) You first distinguish between night and day mode based on a threshold of 140. Day mode values then get a fine grained exposure adjustments. (line 178-288) 2) You then take a picture (line 292) 3) Then, based on the original light value, you then do fine grained exposure adjustments for night mode values. (line 297-483)

Questions

raduprv commented 3 years ago

Yes, it looks pretty ugly, but everything is necessary. Getting the frame at line 292 is necessary because it takes one frame for the values to set in properly, and to get the next frame faster. You can of course experiment with that code and see what happens if you comment that out. I put the camera on stand by because otherwise it will consume power doing nothing until the ESP32 goes to sleep. I originally made this program to run on battery, so every little power saving matters. As for resetting the sensor if it's not sent to sleep, I don't know. The program works fine without it, most of the time. But I THINK it works a bit better with it. If you don't put it to sleep it might make no difference, so feel free to experiment.

raduprv commented 3 years ago

Oh, and the thing is, in night mode, the camera will return you the frame very late if you don't get the first frame first. In day mode, that's not an issue.

jensdk3 commented 3 years ago

Ok, makes sense. But @raduprv, imagine a use case where you will take many images at same lighting conditions with ample power. It would then make perfect sense to combine step 1+3 and choose the optimal exposure settings only once and start shooting, right?

raduprv commented 3 years ago

Yes, if you have constant ample light and plenty of power, you can find the best exposure for your light, and then do a while() loop where you take pictures, save them, and do a delay.

jensdk3 commented 3 years ago

@raduprv , inspired by your comments I made a dedicated function to control exposure. It post it here because it might be useful to others. It works well and images gets progressively darker as I ramp up the light value. This is as expected since my ambient lighting conditions are constant. However, if light=>day_switch_value the jpg's always gets garbled - I tried many different values from 140-200. Can you figure out what could be the reason?

void setexposure(int light){
  sensor_t * s = esp_camera_sensor_get();
  s->set_reg(s,0xff,0xff,0x01);//banksel    
  int day_switch_value=140;
  Serial.print("Setting light: ");
  Serial.println(light);

    if(light<day_switch_value)
    {
      Serial.print("in night mode... ");   
      //here we are in night mode
      if(light<45)s->set_reg(s,0x11,0xff,1);//frame rate (1 means longer exposure)
      s->set_reg(s,0x13,0xff,0);//manual everything
      s->set_reg(s,0x0c,0x6,0x8);//manual banding

      s->set_reg(s,0x45,0x3f,0x3f);//really long exposure (but it doesn't really work)
    }
    else
    {
      //here we are in daylight mode
      Serial.println("in day mode... ");   

      s->set_reg(s,0x2d,0xff,0x0);//extra lines
      s->set_reg(s,0x2e,0xff,0x0);//extra lines

      s->set_reg(s,0x47,0xff,0x0);//Frame Length Adjustment MSBs

    if(light<150)
    {
      Serial.println("light 140<=light<150");   
      s->set_reg(s,0x46,0xff,0xd0);//Frame Length Adjustment LSBs
      s->set_reg(s,0x2a,0xff,0xff);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0xff);//line adjust
      s->set_reg(s,0x45,0xff,0xff);//exposure (doesn't seem to work)
    }
    else if(light<160)
    {
      Serial.println("light 150<=light<160");   
      s->set_reg(s,0x46,0xff,0xc0);//Frame Length Adjustment LSBs
      s->set_reg(s,0x2a,0xff,0xb0);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0xff);//line adjust
      s->set_reg(s,0x45,0xff,0x10);//exposure (doesn't seem to work)
    }    
    else if(light<170)
    {
      Serial.println("light 160<=light<170");   
      s->set_reg(s,0x46,0xff,0xb0);//Frame Length Adjustment LSBs
      s->set_reg(s,0x2a,0xff,0x80);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0xff);//line adjust
      s->set_reg(s,0x45,0xff,0x10);//exposure (doesn't seem to work)
    }    
    else if(light<180)
    {
      Serial.println("light 170<=light<180");   
      s->set_reg(s,0x46,0xff,0xa8);//Frame Length Adjustment LSBs
      s->set_reg(s,0x2a,0xff,0x80);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0xff);//line adjust
      s->set_reg(s,0x45,0xff,0x10);//exposure (doesn't seem to work)
    } 
    else if(light<190)
    {
      Serial.println("light 180<=light<190");   
      s->set_reg(s,0x46,0xff,0xa6);//Frame Length Adjustment LSBs
      s->set_reg(s,0x2a,0xff,0x80);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0xff);//line adjust
      s->set_reg(s,0x45,0xff,0x90);//exposure (doesn't seem to work)
    } 
    else if(light<200)
    {
      Serial.println("light 190<=light<200");   
      s->set_reg(s,0x46,0xff,0xa4);//Frame Length Adjustment LSBs
      s->set_reg(s,0x2a,0xff,0x80);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0xff);//line adjust
      s->set_reg(s,0x45,0xff,0x10);//exposure (doesn't seem to work)
    } 
    else if(light<210)
    {
      Serial.println("light 200<=light<210");   
      s->set_reg(s,0x46,0xff,0x98);//Frame Length Adjustment LSBs
      s->set_reg(s,0x2a,0xff,0x60);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0xff);//line adjust
      s->set_reg(s,0x45,0xff,0x10);//exposure (doesn't seem to work)
    } 
    else if(light<220)
    {
      Serial.println("light 210<=light<220");   
      s->set_reg(s,0x46,0xff,0x80);//Frame Length Adjustment LSBs
      s->set_reg(s,0x2a,0xff,0x20);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0xff);//line adjust
      s->set_reg(s,0x45,0xff,0x10);//exposure (doesn't seem to work)
    } 
    else if(light<230)
    {
      Serial.println("light 220<=light<230");   
      s->set_reg(s,0x46,0xff,0x70);//Frame Length Adjustment LSBs
      s->set_reg(s,0x2a,0xff,0x20);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0xff);//line adjust
      s->set_reg(s,0x45,0xff,0x10);//exposure (doesn't seem to work)
    } 
    else if(light<240)
    {
      Serial.println("light 230<=light<240");   
      s->set_reg(s,0x46,0xff,0x60);//Frame Length Adjustment LSBs
      s->set_reg(s,0x2a,0xff,0x20);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0x80);//line adjust
      s->set_reg(s,0x45,0xff,0x10);//exposure (doesn't seem to work)
    } 
    else if(light<253)
    {
      Serial.println("light 240<=light<253");   
      s->set_reg(s,0x46,0xff,0x10);//Frame Length Adjustment LSBs
      s->set_reg(s,0x2a,0xff,0x0);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0x40);//line adjust
      s->set_reg(s,0x45,0xff,0x10);//exposure (doesn't seem to work)
    }
    else
    {
      Serial.println("light >=253");   
      s->set_reg(s,0x46,0xff,0x0);//Frame Length Adjustment LSBs
      s->set_reg(s,0x2a,0xff,0x0);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0x0);//line adjust
      s->set_reg(s,0x45,0xff,0x0);//exposure (doesn't seem to work)
      s->set_reg(s,0x10,0xff,0x0);//exposure (doesn't seem to work)
    }

    s->set_reg(s,0x0f,0xff,0x4b);//no idea
    s->set_reg(s,0x03,0xff,0xcf);//no idea
    s->set_reg(s,0x3d,0xff,0x34);//changes the exposure somehow, has to do with frame rate

    s->set_reg(s,0x11,0xff,0x0);//frame rate
    s->set_reg(s,0x43,0xff,0x11);//11 is the default value     
    }

    /*
   Serial.println("Getting first frame at");
   Serial.println(millis());    
    //fb = esp_camera_fb_get();
    //skip_frame();
   Serial.println("Got first frame at");
   Serial.println(millis());    
   */

    if(light==0)
    {
      Serial.println("light=0");
      s->set_reg(s,0x47,0xff,0x40);//Frame Length Adjustment MSBs
      s->set_reg(s,0x2a,0xf0,0xf0);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0xff);//line adjust
    }
    else if(light==1)
    {
      Serial.println("light=1");
      s->set_reg(s,0x47,0xff,0x40);//Frame Length Adjustment MSBs
      s->set_reg(s,0x2a,0xf0,0xd0);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0xff);//line adjust
    }
    else if(light==2)
    {
      Serial.println("light=2");
      s->set_reg(s,0x47,0xff,0x40);//Frame Length Adjustment MSBs
      s->set_reg(s,0x2a,0xf0,0xb0);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0xff);//line adjust  
    }
    else if(light==3)
    {
      Serial.println("light=3");
      s->set_reg(s,0x47,0xff,0x40);//Frame Length Adjustment MSBs
      s->set_reg(s,0x2a,0xf0,0x70);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0xff);//line adjust      
    }    
    else if(light==4)
    {
      Serial.println("light=4");
      s->set_reg(s,0x47,0xff,0x40);//Frame Length Adjustment MSBs
      s->set_reg(s,0x2a,0xf0,0x40);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0xff);//line adjust
    }
    else if(light==5)
    {
      Serial.println("light=5");
      s->set_reg(s,0x47,0xff,0x20);//Frame Length Adjustment MSBs
      s->set_reg(s,0x2a,0xf0,0x80);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0xff);//line adjust        
    }
    else if(light==6)
    {
      Serial.println("light=6");
      s->set_reg(s,0x47,0xff,0x20);//Frame Length Adjustment MSBs
      s->set_reg(s,0x2a,0xf0,0x40);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0xff);//line adjust        
    }         
    else if(light==7)
    {
      Serial.println("light=7");
      s->set_reg(s,0x47,0xff,0x20);//Frame Length Adjustment MSBs
      s->set_reg(s,0x2a,0xf0,0x30);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0xff);//line adjust        
    }
    else if(light==8)
    {
      Serial.println("light=8");
      s->set_reg(s,0x47,0xff,0x20);//Frame Length Adjustment MSBs
      s->set_reg(s,0x2a,0xf0,0x20);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0xff);//line adjust        
    }     
    else if(light==9)
    {
      Serial.println("light=9");
      s->set_reg(s,0x47,0xff,0x20);//Frame Length Adjustment MSBs
      s->set_reg(s,0x2a,0xf0,0x10);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0xff);//line adjust        
    }    
    else if(light==10)
    {
      Serial.println("light=10");
      s->set_reg(s,0x47,0xff,0x10);//Frame Length Adjustment MSBs
      s->set_reg(s,0x2a,0xf0,0x70);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0xff);//line adjust        
    }
    else if(light<=12)
    {
      Serial.println("light 11 or 12");
      s->set_reg(s,0x47,0xff,0x10);//Frame Length Adjustment MSBs
      s->set_reg(s,0x2a,0xf0,0x60);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0xff);//line adjust        
    }
    else if(light<=14)
    {
      Serial.println("light 13 or 14");
      s->set_reg(s,0x47,0xff,0x10);//Frame Length Adjustment MSBs
      s->set_reg(s,0x2a,0xf0,0x40);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0xff);//line adjust        
    }          
    else if(light<=18)
    {
      Serial.println("14<light<=18");
      s->set_reg(s,0x47,0xff,0x08);//Frame Length Adjustment MSBs
      s->set_reg(s,0x2a,0xf0,0xb0);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0xff);//line adjust        
    }
    else if(light<=20)
    {
      Serial.println("18<light<=20");
      s->set_reg(s,0x47,0xff,0x08);//Frame Length Adjustment MSBs
      s->set_reg(s,0x2a,0xf0,0x80);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0xff);//line adjust        
    }      
    else if(light<=23)
    {
      Serial.println("20<light<=23");
      s->set_reg(s,0x47,0xff,0x08);//Frame Length Adjustment MSBs
      s->set_reg(s,0x2a,0xf0,0x60);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0xff);//line adjust        
    }           
    else if(light<=27)
    {
      Serial.println("23<light<=27");
      s->set_reg(s,0x47,0xff,0x04);//Frame Length Adjustment MSBs
      s->set_reg(s,0x2a,0xf0,0xd0);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0xff);//line adjust        
    }
    else if(light<=31)
    {
       Serial.println("27<light<=31");
      s->set_reg(s,0x47,0xff,0x04);//Frame Length Adjustment MSBs
      s->set_reg(s,0x2a,0xf0,0x80);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0xff);//line adjust        
    }     
    else if(light<=35)
    {
      Serial.println("31<light<=35");
      s->set_reg(s,0x47,0xff,0x04);//Frame Length Adjustment MSBs
      s->set_reg(s,0x2a,0xf0,0x60);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0xff);//line adjust        
    }    
    else if(light<=40)
    {
      Serial.println("35<light<=40");
      s->set_reg(s,0x47,0xff,0x02);//Frame Length Adjustment MSBs
      s->set_reg(s,0x2a,0xf0,0x70);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0xff);//line adjust        
    }
    else if(light<45)
    {
      Serial.println("40<light<45");
      s->set_reg(s,0x47,0xff,0x02);//Frame Length Adjustment MSBs
      s->set_reg(s,0x2a,0xf0,0x40);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0xff);//line adjust        
    }
    //after this the frame rate is higher, so we need to compensate
    else if(light<50)
    {
      Serial.println("45<=light<50");
      s->set_reg(s,0x47,0xff,0x04);//Frame Length Adjustment MSBs
      s->set_reg(s,0x2a,0xf0,0xa0);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0xff);//line adjust        
    }    
    else if(light<55)
    {
      Serial.println("50<=light<55");
      s->set_reg(s,0x47,0xff,0x04);//Frame Length Adjustment MSBs
      s->set_reg(s,0x2a,0xf0,0x70);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0xff);//line adjust        
    }
    else if(light<65)
    {
      Serial.println("55<=light<65");
      s->set_reg(s,0x47,0xff,0x04);//Frame Length Adjustment MSBs
      s->set_reg(s,0x2a,0xf0,0x30);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0xff);//line adjust        
    }
    else if(light<75)
    {
      Serial.println("65<=light<75");
      s->set_reg(s,0x47,0xff,0x02);//Frame Length Adjustment MSBs
      s->set_reg(s,0x2a,0xf0,0x80);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0xff);//line adjust        
    }                 
    else if(light<90)
    {
      Serial.println("75<=light<90");
      s->set_reg(s,0x47,0xff,0x02);//Frame Length Adjustment MSBs
      s->set_reg(s,0x2a,0xf0,0x50);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0xbf);//line adjust        
    }
    else if(light<100)
    {
      Serial.println("90<=light<100");
      s->set_reg(s,0x47,0xff,0x02);//Frame Length Adjustment MSBs
      s->set_reg(s,0x2a,0xf0,0x20);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0x8f);//line adjust        
    } 
    else if(light<110)
    {
      Serial.println("100<=light<110");
      s->set_reg(s,0x47,0xff,0x02);//Frame Length Adjustment MSBs
      s->set_reg(s,0x2a,0xf0,0x10);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0x7f);//line adjust        
    }      
    else if(light<120)
    {
      Serial.println("110<=light<120");
      s->set_reg(s,0x47,0xff,0x01);//Frame Length Adjustment MSBs
      s->set_reg(s,0x2a,0xf0,0x10);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0x5f);//line adjust        
    }     
    else if(light<130)
    {
      Serial.println("120<=light<130");
      s->set_reg(s,0x47,0xff,0x00);//Frame Length Adjustment MSBs
      s->set_reg(s,0x2a,0xf0,0x0);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0x2f);//line adjust        
    }
    else if(light<140)
    {
      Serial.println("130<=light<140");
      s->set_reg(s,0x47,0xff,0x00);//Frame Length Adjustment MSBs
      s->set_reg(s,0x2a,0xf0,0x0);//line adjust MSB
      s->set_reg(s,0x2b,0xff,0x0);//line adjust        
    }

    if(light<day_switch_value)s->set_reg(s,0x43,0xff,0x40);//magic value to give us the frame faster (bit 6 must be 1)
  }
raduprv commented 3 years ago

I don't remember all the details, but the thing is, some operations and registers must be set before others. Also, try uncommenting getting the frame buffer, you will have trouble without it. Can you post a garbled photo?

jensdk3 commented 3 years ago

I uncommented/enabled getting the framebuffer but no change. Here is a garbled image with light=200.

200

raduprv commented 3 years ago

I don't know what's wrong. I haven't played with this sensor in a few months. Make sure that all my code is in the right order, and you didn't forget to set some register (or set the wrong one).