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, ®_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, ®_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, ®_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, ®_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, ®_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, ®_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, ®_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, ®_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();
}
}
/** @} */