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

nRF52840 (TWI) using Grove-LCD RGB Backlight V4.0

Hi All,

I am trying to write a driver for the Grove-LCD RGB Back-light V4.0 using nRF52840 DK. However, it doesn't work. I am trying to figure it out why. 

The description of the LCD can be found in this link: https://wiki.seeedstudio.com/Grove-LCD_RGB_Backlight/

It consists of a LCD and a RGB driver. Links are as follows. 

https://files.seeedstudio.com/wiki/Grove_LCD_RGB_Backlight/res/PCA9633.pdf

https://files.seeedstudio.com/wiki/Grove_LCD_RGB_Backlight/res/JHD1313%20FP-RGB-1%201.4.pdf

To get started, I am trying to modifying the existing TWI sensor example given in nRF52840 DK.

It uses ARDUINO_SCL_PIN (Pin 27) as the SCL and ARDUINO_SDA_PIN(Pin 26) as the SDA. 

I have connected above two pins to the SCL and SDA pins of the Grove-LCD. Also, 5 V output and the ground of the DK is connected to the VDD and ground of Grove-LCD receptively.

When I connect to the 5V, all the pixels in the LCD is lit in black color. 

Executing my code does not change or do anything on the LCD. Herewith I have attached the main.c file and the Grove_LCD_RGB library used in Arduino. I am trying to write the driver based on this library. Currently, I have written the initialization part and I expected to see the Blue LED back-light lit. However, I don't see any changes on the LCD.

I have added some debug print messages and they are as follows: All the write events are TX type. Therefore, you see "---1" in the debug messages. 

<info> app:
TWI sensor example started.
<info> app:
LCD_init.
<info> app:
LCD On Backlight
<info> app: RX=0 TX=1 TXRX=2 TXTX=3: --- 1
<info> app:
Function Set
<info> app: RX=0 TX=1 TXRX=2 TXTX=3: --- 1
<info> app:
Turn the display on with
<info> app: RX=0 TX=1 TXRX=2 TXTX=3: --- 1
<info> app:
Initialize to default text direction
<info> app: RX=0 TX=1 TXRX=2 TXTX=3: --- 1
<info> app:
Turn the display on with no cursor or blinking default
<info> app: RX=0 TX=1 TXRX=2 TXTX=3: --- 1
<info> app:
Set REG MODE 1
<info> app:
Write REG MODE 1 data
<info> app:
Write REG MODE 1 data
<info> app: RX=0 TX=1 TXRX=2 TXTX=3: --- 1
<info> app: RX=0 TX=1 TXRX=2 TXTX=3: --- 1
<info> app: RX=0 TX=1 TXRX=2 TXTX=3: --- 1
<info> app:
Set REG MODE 2
<info> app:
Write REG MODE 2 data
<info> app:
Write REG MODE 2 data
<info> app: RX=0 TX=1 TXRX=2 TXTX=3: --- 1
<info> app: RX=0 TX=1 TXRX=2 TXTX=3: --- 1
<info> app:
Set REG MODE 2 again
<info> app:
Write REG MODE 2 data again
<info> app:
Write REG MODE 2 data again
<info> app: RX=0 TX=1 TXRX=2 TXTX=3: --- 1
<info> app: RX=0 TX=1 TXRX=2 TXTX=3: --- 1
<info> app:
Set REG BLUE
<info> app:
Write REG BLUE data
<info> app:
Write REG BLUE data
<info> app: RX=0 TX=1 TXRX=2 TXTX=3: --- 1
<info> app: RX=0 TX=1 TXRX=2 TXTX=3: --- 1

If there are any suggestions, appreciate your support.

Thanks 

 Grove_LCD_RGB_Backlight-master.zip

/**
 * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form, except as embedded into a Nordic
 *    Semiconductor ASA integrated circuit in a product or a software update for
 *    such product, must reproduce the above copyright notice, this list of
 *    conditions and the following disclaimer in the documentation and/or other
 *    materials provided with the distribution.
 *
 * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
 *    contributors may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 *
 * 4. This software, with or without modification, must only be used with a
 *    Nordic Semiconductor ASA integrated circuit.
 *
 * 5. Any software provided in binary form under this license must not be reverse
 *    engineered, decompiled, modified and/or disassembled.
 *
 * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */
/** @file
 * @defgroup tw_sensor_example main.c
 * @{
 * @ingroup nrf_twi_example
 * @brief TWI Sensor Example main file.
 *
 * This file contains the source code for a sample application using TWI.
 *
 */

#include <stdio.h>
#include "boards.h"
#include "app_util_platform.h"
#include "app_error.h"
#include "nrf_drv_twi.h"
#include "nrf_delay.h"


#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"

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

/* Common addresses definition for temperature sensor. */
#define LCD_I2C_ADDR        0x3EU
#define RGB_I2C_ADDR        0x62U

/* LCD flags for function set */
#define LCD_8BITMODE 0x10
#define LCD_4BITMODE 0x00
#define LCD_2LINE 0x08
#define LCD_1LINE 0x00
#define LCD_5x10DOTS 0x04
#define LCD_5x8DOTS 0x00

/* flags for backlight control */
#define LCD_BACKLIGHT 0x08
#define LCD_NOBACKLIGHT 0x00
#define LCD_FUNCTIONSET 0x20

/* flags for display on/off control */
#define LCD_DISPLAYON 0x04
#define LCD_DISPLAYOFF 0x00
#define LCD_CURSORON 0x02
#define LCD_CURSOROFF 0x00
#define LCD_BLINKON 0x01
#define LCD_BLINKOFF 0x00

// commands
#define LCD_CLEARDISPLAY 0x01
#define LCD_RETURNHOME 0x02
#define LCD_ENTRYMODESET 0x04
#define LCD_DISPLAYCONTROL 0x08
#define LCD_CURSORSHIFT 0x10
#define LCD_FUNCTIONSET 0x20
#define LCD_SETCGRAMADDR 0x40
#define LCD_SETDDRAMADDR 0x80

// flags for display entry mode
#define LCD_ENTRYRIGHT 0x00
#define LCD_ENTRYLEFT 0x02
#define LCD_ENTRYSHIFTINCREMENT 0x01
#define LCD_ENTRYSHIFTDECREMENT 0x00

// color define
#define WHITE           0
#define RED             1
#define GREEN           2
#define BLUE            3

#define REG_RED         0x04        // pwm2
#define REG_GREEN       0x03        // pwm1
#define REG_BLUE        0x02        // pwm0

#define REG_MODE1       0x00
#define REG_MODE2       0x01
#define REG_OUTPUT      0x08

//#define LM75B_ADDR          (0x90U >> 1)

//#define LM75B_REG_TEMP      0x00U
//#define LM75B_REG_CONF      0x01U
//#define LM75B_REG_THYST     0x02U
//#define LM75B_REG_TOS       0x03U

/* Mode for LM75B. */
//#define NORMAL_MODE 0U

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

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

/* Buffer for samples read from temperature sensor. */
static uint8_t m_sample;

/**
 * @brief Function for setting active mode on MMA7660 accelerometer.
 */
//void LM75B_set_mode(void)
//{
//    ret_code_t err_code;

//    /* Writing to LM75B_REG_CONF "0" set temperature sensor in NORMAL mode. */
//    uint8_t reg[2] = {LM75B_REG_CONF, NORMAL_MODE};
//    err_code = nrf_drv_twi_tx(&m_twi, LM75B_ADDR, reg, sizeof(reg), false);
//    APP_ERROR_CHECK(err_code);
//    while (m_xfer_done == false);

    /* Writing to pointer byte. */
//    reg[0] = LM75B_REG_TEMP;
//    m_xfer_done = false;
//    err_code = nrf_drv_twi_tx(&m_twi, LM75B_ADDR, reg, 1, false);
//    APP_ERROR_CHECK(err_code);
//    while (m_xfer_done == false);
//}
/**
 * @brief Function for setting LCD.
 */
void LCD_init(void)
{
  NRF_LOG_INFO("\r\nLCD_init.");
  ret_code_t err_code;
  
  uint8_t display_function = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
  uint8_t backlight = LCD_NOBACKLIGHT;
  uint8_t function_set = display_function | LCD_FUNCTIONSET;
  uint8_t display_control = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
  uint8_t _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT | LCD_ENTRYMODESET;
  uint8_t reg_mode;
  uint8_t reg_mode_data;

  // Wait for 30 ms ~ 50 ms
  nrf_delay_ms(50);

  // LCD On Backlight
  NRF_LOG_INFO("\r\n LCD On Backlight");
  err_code = nrf_drv_twi_tx(&m_twi, RGB_I2C_ADDR, &backlight, sizeof(backlight), false);
  APP_ERROR_CHECK(err_code);
  while (m_xfer_done == false);

  nrf_delay_ms(100);
  // Function Set
  NRF_LOG_INFO("\r\n Function Set");
  err_code = nrf_drv_twi_tx(&m_twi, LCD_I2C_ADDR, &function_set, sizeof(function_set), false);
  APP_ERROR_CHECK(err_code);
  while (m_xfer_done == false);

  nrf_delay_ms(100);
  // Turn the display on with no cursor or blinking default
  NRF_LOG_INFO("\r\n Turn the display on with");
  err_code = nrf_drv_twi_tx(&m_twi, LCD_I2C_ADDR, &display_control, sizeof(display_control), false);
  APP_ERROR_CHECK(err_code);
  while (m_xfer_done == false);

  nrf_delay_ms(100);
  // Initialize to default text direction (for romance languages)
  NRF_LOG_INFO("\r\n Initialize to default text direction");
  err_code = nrf_drv_twi_tx(&m_twi, LCD_I2C_ADDR, &_displaymode, sizeof(_displaymode), false);
  APP_ERROR_CHECK(err_code);
  while (m_xfer_done == false);
  
  // backlight init
  nrf_delay_ms(100);
  // Turn the display on with no cursor or blinking default
  NRF_LOG_INFO("\r\n Turn the display on with  no cursor or blinking default");
  err_code = nrf_drv_twi_tx(&m_twi, LCD_I2C_ADDR, &display_control, sizeof(display_control), false);
  APP_ERROR_CHECK(err_code);
  while (m_xfer_done == false);

  // Write register mode 1
  reg_mode = REG_MODE1;
  nrf_delay_ms(100);
  // Turn the display on with no cursor or blinking default
  NRF_LOG_INFO("\r\n Set REG MODE 1");
  err_code = nrf_drv_twi_tx(&m_twi, RGB_I2C_ADDR, &reg_mode, sizeof(reg_mode), false);
  APP_ERROR_CHECK(err_code);
  while (m_xfer_done == false);

  // Write regiter mode 1 data
  reg_mode_data = 0;
  NRF_LOG_INFO("\r\n Write REG MODE 1 data");
  err_code = nrf_drv_twi_tx(&m_twi, RGB_I2C_ADDR, &reg_mode_data, sizeof(reg_mode_data), false);
  APP_ERROR_CHECK(err_code);
  while (m_xfer_done == false);

  // Write register mode 2
  reg_mode = REG_MODE2;
  nrf_delay_ms(100);
  // Turn the display on with no cursor or blinking default
  NRF_LOG_INFO("\r\n Set REG MODE 2");
  err_code = nrf_drv_twi_tx(&m_twi, RGB_I2C_ADDR, &reg_mode, sizeof(reg_mode), false);
  APP_ERROR_CHECK(err_code);
  while (m_xfer_done == false);

  // Write regiter mode 2 data
  reg_mode_data = 0xFF;
  NRF_LOG_INFO("\r\n Write REG MODE 2 data");
  err_code = nrf_drv_twi_tx(&m_twi, RGB_I2C_ADDR, &reg_mode_data, sizeof(reg_mode_data), false);
  APP_ERROR_CHECK(err_code);
  while (m_xfer_done == false);

  // Write register mode 2 values
  reg_mode = REG_MODE2;
  nrf_delay_ms(100);
  // Turn the display on with no cursor or blinking default
  NRF_LOG_INFO("\r\n Set REG MODE 2 again");
  err_code = nrf_drv_twi_tx(&m_twi, RGB_I2C_ADDR, &reg_mode, sizeof(reg_mode), false);
  APP_ERROR_CHECK(err_code);
  while (m_xfer_done == false);

  // Write regiter mode 2 data values
  reg_mode_data = 0x20;
  NRF_LOG_INFO("\r\n Write REG MODE 2 data again");
  err_code = nrf_drv_twi_tx(&m_twi, RGB_I2C_ADDR, &reg_mode_data, sizeof(reg_mode_data), false);
  APP_ERROR_CHECK(err_code);
  while (m_xfer_done == false);

  // Set colour Blue
  reg_mode = REG_BLUE;
  nrf_delay_ms(100);
  // Turn the display on with no cursor or blinking default
  NRF_LOG_INFO("\r\n Set REG BLUE");
  err_code = nrf_drv_twi_tx(&m_twi, RGB_I2C_ADDR, &reg_mode, sizeof(reg_mode), false);
  APP_ERROR_CHECK(err_code);
  while (m_xfer_done == false);

  // Write regiter mode 2 data values
  reg_mode_data = 255;
  NRF_LOG_INFO("\r\n Write REG BLUE data");
  err_code = nrf_drv_twi_tx(&m_twi, RGB_I2C_ADDR, &reg_mode_data, sizeof(reg_mode_data), false);
  APP_ERROR_CHECK(err_code);
  while (m_xfer_done == false);

}

/**
 * @brief Function for handling data from temperature sensor.
 *
 * @param[in] temp          Temperature in Celsius degrees read from sensor.
 */
__STATIC_INLINE void data_handler(uint8_t temp)
{
    NRF_LOG_INFO("RX=0 TX=1 TXRX=2 TXTX=3: --- %d ", temp);
}

/**
 * @brief TWI events handler.
 */
void twi_handler(nrf_drv_twi_evt_t const * p_event, void * p_context)
{
    switch (p_event->type)
    {
        case NRF_DRV_TWI_EVT_DONE:
            if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_RX)
            {
                m_sample = 0;
                data_handler(m_sample);
            }
            if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_TX)
            {
                m_sample = 1;
                data_handler(m_sample);
            }
            if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_TXRX)
            {
                m_sample = 2;
                data_handler(m_sample);
            }
            if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_TXTX)
            {
                m_sample = 3;
                data_handler(m_sample);
            }
            m_xfer_done = true;
            break;
        default:
            break;
    }
}

/**
 * @brief UART initialization.
 */
void twi_init (void)
{
    ret_code_t err_code;

    const nrf_drv_twi_config_t twi_lcd_config = {
       .scl                = ARDUINO_SCL_PIN,
       .sda                = ARDUINO_SDA_PIN,
       .frequency          = NRF_DRV_TWI_FREQ_250K,
       .interrupt_priority = APP_IRQ_PRIORITY_HIGH,
       .clear_bus_init     = false
    };

    err_code = nrf_drv_twi_init(&m_twi, &twi_lcd_config, twi_handler, NULL);
    APP_ERROR_CHECK(err_code);

    nrf_drv_twi_enable(&m_twi);
}

/**
 * @brief Function for reading data from temperature sensor.
 */
//static void read_sensor_data()
//{
//    m_xfer_done = false;
//
//    /* Read 1 byte from the specified address - skip 3 bits dedicated for fractional part of temperature. */
//    ret_code_t err_code = nrf_drv_twi_rx(&m_twi, LM75B_ADDR, &m_sample, sizeof(m_sample));
//    APP_ERROR_CHECK(err_code);
//}
static void end_lcd_write()
{
    m_xfer_done = false;

    /* Read 1 byte from the specified address - skip 3 bits dedicated for fractional part of temperature. */
    //ret_code_t err_code = nrf_drv_twi_rx(&m_twi, LM75B_ADDR, &m_sample, sizeof(m_sample));
    //APP_ERROR_CHECK(err_code);
}

/**
 * @brief Function for main application entry.
 */
int main(void)
{
    APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
    NRF_LOG_DEFAULT_BACKENDS_INIT();

    NRF_LOG_INFO("\r\nTWI sensor example started.");
    NRF_LOG_FLUSH();
    twi_init();
    LCD_init();
//    LM75B_set_mode();

    while (true)
    {
        nrf_delay_ms(500);

        do
        {
            __WFE();
        }while (m_xfer_done == false);

//        read_sensor_data();
          end_lcd_write();
        NRF_LOG_FLUSH();
    }
}

/** @} */

Parents Reply Children
Related