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