Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs

Turning camera off in nrf52-ble-image-transfer-demo for nRF52840 Dongle

Hello everyone, I'd like to implement the nrf52-ble-image-transfer-demo for nRF52840 Dongle. The normal code already plays well. However, since I am aiming for a low-power application, I need to somehow put the camera in sleep mode while it is not used. Since I've found no such code or method, I simply turn it off completely using MOSFET. This worked well for the big nRF52840. I simply introduced a camera_init_new() function to initialize the camera before every Take Picture command. The only problem here I have is that I need to put in a delay after the camera init, I think this is due to the fact that the camera needs some time to initialize. 

However, this does not work for the Donlge. The whole thing simply crashes as soon as I send the take picture command. Funny though that after it crashes it performs some kind of reset, meaning that I get automatically disconnected and can connect again.

Anyone an idea where the problem might be?

Parents
  • Hi,

    Did you build the application for the pca10059, or did you run the pca10056 build on the dongle? Did you make any other modifications to the example to get it running on the Dongle? Do you use the same GPIOs (if not, which GPIOs do you use?), did you disable UART, etc?

    The reset behavior is typically due to an error/assert in the application, where the default behavior is to do a soft reset in the error handler. 

    Do you have debug capabilities on your dongle? I.e., do you use a debugger to program the dongle, or do you use the bootloader solution that comes with the dongle to program it over the USB port?

    Best regards,
    Jørgen

  • The code (for nRF 52840, not dongle) would be: first, at the beginning of the main and before the initialization, I clear the pin for the gate of my p-channel MOSFET:

    nrf_gpio_cfg_output(32 + 8);
    nrf_gpio_pin_clear(32 + 8);

    so that the camera is powered. Then, after the initialization and before the advertising_start function, i set the pin again so that the camera is shut down and does not drain current anymore:

    nrf_gpio_pin_set(32 + 8);

    advertising_start();

    In the for-loop, when the take picture command comes in, I clear the gate pin again so that the camera is powered again, call the camera_init_new() function to initialize the camera again, and proceed with the code. 

    switch(new_command)
    {

    case APP_CMD_SINGLE_CAPTURE:
    nrf_gpio_pin_clear(32 + 8);
    nrf_delay_ms(4);
    camera_init_new();
    nrf_delay_ms(500);
    if(arducam_mini_2mp_bytesAvailable() == 0)
    {

    NRF_LOG_INFO("Starting capture...");
    arducam_mini_2mp_startSingleCapture();
    image_size = arducam_mini_2mp_bytesAvailable();
    NRF_LOG_INFO("Capture complete: size %i bytes", (int)(image_size));
    ble_its_img_info_t image_info;
    image_info.file_size_bytes = image_size;

    ble_its_img_info_send(&m_its, &image_info);

    }

    At the end of the image transfer loop, I check if the arducam_mini_2mp_bytesAvailable() == 0 to set the gate pin again to shut the camera down.

    I use the altered camera_init_new() function instead of the camera_init() function because the code did not work with using the normal camera_init() function. I do not know completely yet, but I assume this is due to the camera_init() function also initializing the necessary Pins of the nRF, which can't be initialized more than once. So these were the changes I made in the camera_init() function: instead of calling the arducam_mini_2mp_open(&m_camera_init) function, i introduced the arducam_mini_2mp_open_new(&m_camera_init) function, where I left everything the same except for removing the arducam_spiRegisterCallback(spiCallback); function:

    void arducam_mini_2mp_open_new(arducam_mini_2mp_init_t *config)
    {
    // put your setup code here, to run once:
    uint8_t vid, pid;
    uint8_t temp;
    arducam_new_init(OV2640, config->pinScl, config->pinSda, config->pinCsn, config->pinMosi, config->pinMiso, config->pinSck);

    //nrfSystem.registerError(LS_DEBUG, "ARDUCAM", 0, "Camera Start");

    //arducam_spiRegisterCallback(spiCallback);

    //Check if the ArduCAM SPI bus is OK
    arducam_write_reg(ARDUCHIP_TEST1, 0x55);
    temp = arducam_read_reg(ARDUCHIP_TEST1);
    //Serial.println(temp);
    if (temp != 0x55)
    {
    //nrfSystem.registerError(LS_ERROR, "ARDUCAM", 0, "SPI interface non responsive");
    while(1);
    }
    //Check if the camera module type is OV2640
    arducam_wrSensorReg8_8(0xff, 0x01);
    arducam_rdSensorReg8_8(OV2640_CHIPID_HIGH, &vid);
    arducam_rdSensorReg8_8(OV2640_CHIPID_LOW, &pid);
    if ((vid != 0x26) || (pid != 0x42))
    {
    //nrfSystem.registerError(LS_ERROR, "ARDUCAM", 0, "TWI interface non responsive");
    }
    else
    {
    //nrfSystem.registerError(LS_DEBUG, "ARDUCAM", 0, "OV2640 module detected");
    }

    arducam_set_format(JPEG);
    arducam_InitCAM();
    //arducam_OV2640_set_JPEG_size(OV2640_160x120);
    nrf_delay_ms(10);
    arducam_clear_fifo_flag();
    }

    Also, after calling the camera_init_new() function I need to go into a delay for ca 500 ms. I do not know why, since the necessary delays needed for the camera to initialize are already put in the camera_init() and camera_init_new() function, but that was something I determined by trying. 

    So, this code does work on the nRF52840, however, it does not on the Dongle (of course after adjusting the pin numbers). 

Reply
  • The code (for nRF 52840, not dongle) would be: first, at the beginning of the main and before the initialization, I clear the pin for the gate of my p-channel MOSFET:

    nrf_gpio_cfg_output(32 + 8);
    nrf_gpio_pin_clear(32 + 8);

    so that the camera is powered. Then, after the initialization and before the advertising_start function, i set the pin again so that the camera is shut down and does not drain current anymore:

    nrf_gpio_pin_set(32 + 8);

    advertising_start();

    In the for-loop, when the take picture command comes in, I clear the gate pin again so that the camera is powered again, call the camera_init_new() function to initialize the camera again, and proceed with the code. 

    switch(new_command)
    {

    case APP_CMD_SINGLE_CAPTURE:
    nrf_gpio_pin_clear(32 + 8);
    nrf_delay_ms(4);
    camera_init_new();
    nrf_delay_ms(500);
    if(arducam_mini_2mp_bytesAvailable() == 0)
    {

    NRF_LOG_INFO("Starting capture...");
    arducam_mini_2mp_startSingleCapture();
    image_size = arducam_mini_2mp_bytesAvailable();
    NRF_LOG_INFO("Capture complete: size %i bytes", (int)(image_size));
    ble_its_img_info_t image_info;
    image_info.file_size_bytes = image_size;

    ble_its_img_info_send(&m_its, &image_info);

    }

    At the end of the image transfer loop, I check if the arducam_mini_2mp_bytesAvailable() == 0 to set the gate pin again to shut the camera down.

    I use the altered camera_init_new() function instead of the camera_init() function because the code did not work with using the normal camera_init() function. I do not know completely yet, but I assume this is due to the camera_init() function also initializing the necessary Pins of the nRF, which can't be initialized more than once. So these were the changes I made in the camera_init() function: instead of calling the arducam_mini_2mp_open(&m_camera_init) function, i introduced the arducam_mini_2mp_open_new(&m_camera_init) function, where I left everything the same except for removing the arducam_spiRegisterCallback(spiCallback); function:

    void arducam_mini_2mp_open_new(arducam_mini_2mp_init_t *config)
    {
    // put your setup code here, to run once:
    uint8_t vid, pid;
    uint8_t temp;
    arducam_new_init(OV2640, config->pinScl, config->pinSda, config->pinCsn, config->pinMosi, config->pinMiso, config->pinSck);

    //nrfSystem.registerError(LS_DEBUG, "ARDUCAM", 0, "Camera Start");

    //arducam_spiRegisterCallback(spiCallback);

    //Check if the ArduCAM SPI bus is OK
    arducam_write_reg(ARDUCHIP_TEST1, 0x55);
    temp = arducam_read_reg(ARDUCHIP_TEST1);
    //Serial.println(temp);
    if (temp != 0x55)
    {
    //nrfSystem.registerError(LS_ERROR, "ARDUCAM", 0, "SPI interface non responsive");
    while(1);
    }
    //Check if the camera module type is OV2640
    arducam_wrSensorReg8_8(0xff, 0x01);
    arducam_rdSensorReg8_8(OV2640_CHIPID_HIGH, &vid);
    arducam_rdSensorReg8_8(OV2640_CHIPID_LOW, &pid);
    if ((vid != 0x26) || (pid != 0x42))
    {
    //nrfSystem.registerError(LS_ERROR, "ARDUCAM", 0, "TWI interface non responsive");
    }
    else
    {
    //nrfSystem.registerError(LS_DEBUG, "ARDUCAM", 0, "OV2640 module detected");
    }

    arducam_set_format(JPEG);
    arducam_InitCAM();
    //arducam_OV2640_set_JPEG_size(OV2640_160x120);
    nrf_delay_ms(10);
    arducam_clear_fifo_flag();
    }

    Also, after calling the camera_init_new() function I need to go into a delay for ca 500 ms. I do not know why, since the necessary delays needed for the camera to initialize are already put in the camera_init() and camera_init_new() function, but that was something I determined by trying. 

    So, this code does work on the nRF52840, however, it does not on the Dongle (of course after adjusting the pin numbers). 

Children
No Data
Related