This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

OLED SSD1306 with nRF52840 DK Not Working

Hi,

I am trying to interface OLED(SSD1306 driver) module/break-out with nRF52840 D.K, PCA10056 1.0.0 but it's showing some noise/dots/garbage.
Code: nRF5_SDK_15.2.0_9412b96\examples\ble_peripheral\ble_app_uart
Merged: ssd1306 driver & enabled twi_sensor for i2c communication.
Softdevice: nRF5_SDK_15.2.0_9412b96\components\softdevice\s140


#define OLED_SCL NRF_GPIO_PIN_MAP(0,14)
#define OLED_SDA NRF_GPIO_PIN_MAP(0,13)


Code Snippet of twi:

/* TWI instance ID. */
#define TWI_INSTANCE_ID     		1

/* Indicates if operation on TWI has ended. */
static volatile bool m_xfer_done = false;

/* TWI instance. */
static const nrf_drv_twi_t m_twi_master = NRF_DRV_TWI_INSTANCE(TWI_INSTANCE_ID);

void twi_init (uint32_t scl, uint32_t sda)
{
    ret_code_t err_code;

    const nrf_drv_twi_config_t twi_m_config = {
       .scl                = scl,
       .sda                = sda,
       .frequency          = NRF_DRV_TWI_FREQ_100K,
       .interrupt_priority = APP_IRQ_PRIORITY_HIGH,
       .clear_bus_init     = false
    };

    err_code = nrf_drv_twi_init(&m_twi_master, &twi_m_config, NULL, NULL);
    APP_ERROR_CHECK(err_code);

    nrf_drv_twi_enable(&m_twi_master);
}

*
Rest is same as ssd1306_init(sda,scl)

I have tried following:

  1. Same OLED(SSD1306 driver) module/break-out works with nRF51422 D.K, PCA10028 using same ssd1306 drivers but twi_init() is like this which works properly:
    /**
     * @brief TWI master instance
     *
     * Instance of TWI master driver that would be used for communication with simulated
     * eeprom memory.
     */
    static const nrf_drv_twi_t m_twi_master = {
        .p_reg       = NRF_TWI0,
        .irq         = TWI0_IRQ,
        .instance_id = TWI0_INSTANCE_INDEX
    };
    
    
    void twi_evt_handler(nrf_drv_twi_evt_t const * p_event, void * p_context)
    {
    #if 0
        if (p_event->type == NRF_DRV_TWI_ERROR) {
            printf("E\r\n");
        }
    
        if (p_event->type == NRF_DRV_TWI_TX_DONE) {
            printf("T\r\n");
        }
    
        if (p_event->type == NRF_DRV_TWI_RX_DONE) {
            printf("R\r\n");
        }
    #endif
    }
    
    
    ret_code_t twi_master_init(uint32_t scl, uint32_t sda)
    {
        ret_code_t ret;
        const nrf_drv_twi_config_t config = {
            .scl                = scl,
            .sda                = sda,
            .frequency          = TWI0_CONFIG_FREQUENCY,
            .interrupt_priority = TWI0_CONFIG_IRQ_PRIORITY
        };
    
        do {
            ret = nrf_drv_twi_init(&m_twi_master, &config, /*twi_evt_handler*/ NULL,NULL);
            if (NRF_SUCCESS != ret) {
                break;
            }
            nrf_drv_twi_enable(&m_twi_master);
        }
        while (0);
        return ret;
    }
    


  2. Checked other devzone posts with same issues but didn't worked.
  3. Checked slave address of ssd1306.
  4. Checked i2c bus.

Check attached images & OLED module is powered via nRF52840D.K  VDD PIN. Also same was the case with nRF51422 D.K VDD PIN used to power OLED which worked. Please reply for possible solutions to debug this issue.


Regards

Vishal Aditya
Embedded Software Engineer

Parents
  • Have you tested other pins? P0.13 and P0.14 are used for LEDs on the DK. Unless you have disconnected the LEDs using the solder bridges, and made sure you do not initialize the LEDs in your code (for instance through BSP library), you should not use these pins for TWI. 

  • Were you not able to find the TWI address of the display using the TWI_scanner example on those pins either?

  • Hi, i am working on OLED with Vishal. 

    Current situation : OLED working well on the nrf51422 target board and DK PCA10028. 

                                 OLED is not working as expected in the target board (mdbt module housing nrf52840)                                 or with the PCA10056 DK

                                The ssd1306 driver file used is the same in both the cases. 

    After going through the c files, we have narrowed the problem to the TWI function calls. 

    In the working code (nrf51422 SDK 10) the nrf_drv_twi_tx function has a length of type uint32_t but the SDK 15.2 has a length of uint8_t. The max value of length that can be passed to the TWI tx function call is MAXUINT8 (0xFF).

    The OLED driver requires us to send more than 0xFF bytes at once. 

    We think the previous developer has modified the nrf_drv_twi files and made it support a larger value of length. However, I do not want to introduce changes in the library files as this might lead to other bugs. 

    So, I would like to know how to send more than 0xFF bytes in a single TWI command?

    I have tried splitting the data into multiple buffers of size 256 and then calling the TWI TX function repeatedly but this is not working either. (the reason could be that on each function call, the SLAVE ADDRESS will be produced on the bus. This is not part of the OLED command sequence and would lead to unexpected behavior). 

    Please let me know how I can proceed with this. 

    Thanks in advance. 

    Gautham

  • Please let me know how I can proceed with this

    You really need to get an analyser on the bus to see exactly what is happening in both the "working" and the non-working cases.

    Look at the difference(s), and then consider what could cause those differences.

    Otherwise, you are just guessing.

    Also compare the captured traces carefully with the display specifications - it is possible that the "working" case is marginal...

    Cheap analysers are available on the likes of ebay for $10 or less.

  • Hi,

    The legacy TWI master driver in the SDK was limited to 255 bytes, as the driver combined support for TWI and TWIM peripherals. The EasyDMA length of TWIM was limited to 255 bytes in nRF52832. To transmit longer packets, I would recommend switching to the new NRFX drivers. You can use the nrfx_twi.c driver for the legacy TWI periperal (no EasyDMA support), that should work on all nRF52 series ICs, or even better i your case, you can take advantage of the support for 16-bit EasyDMA MAXCNT bit length for TWIM peripheral in nRF52840 and use the nrfx_twim.c driver. These drivers does not have the uint8_t limitation for the length field. Please have a look at this page for details on migration from legacy drivers to nrfx.

    Best regards,
    Jørgen

  • Thanks a lot for your reply.

    I tried using the nrfx_twi driver. On entering debugging mode, I was able to see the the length variable in function call nrfx_twi_tx was 1024 (as expected). But the OLED is still behaving the same way. I will try once again till tomorrow and if I'm unable to do it then I will convert this to a private ticket and post my source code. 

    Initially you mentioned that you found similar behavior on your display as well. Were you able to get it working? 

    Thank you.

    Gautham

  • Ok, let me know if you get it working or not. I only had time to test your code quick, an it gave me the same pattern on the display only inverted.

Reply Children
No Data
Related