Grove LCD - Grove LCD: Device not ready.

Hi,

I am running the standard Grove LCD code, as below but am getting an error, "Grove LCD: Device not ready.'

the code is

/*
 * Copyright (c) 2012-2014 Wind River Systems, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr.h>
#include <device.h>
//#include <display/cfb.h>
#include <stdio.h>
#include <drivers/display.h>
#include <nrf-pinctrl.h>
#include <drivers/i2c.h>
#include <sys/printk.h>

#include <zephyr/drivers/sensor.h>
#include <zephyr/sys/printk.h>
#include <zephyr/sys/util.h>

#include <drivers/misc/grove_lcd/grove_lcd.h>
#include <string.h>

/**
 * @file Display a counter through I2C and Grove LCD.
 */

/* sleep time in msec */
#define SLEEPTIME  100

uint8_t clamp_rgb(int val)
{
	if (val > 255) {
		return 255;
	} else if (val < 0) {
		return 0;
	} else {
		return val;
	}
}

void main(void)
{
	const struct device *glcd = DEVICE_DT_GET(DT_NODELABEL(glcd));
	char str[20];
	int rgb[] = { 0x0, 0x0, 0x0 };
	uint8_t rgb_chg[3];
	const uint8_t rgb_step = 16U;
	uint8_t set_config;
	int i, j, m;
	int cnt;


	if (!device_is_ready(glcd)) {
		printk("Grove LCD: Device not ready.\n");
		return;
	}

	/* Now configure the LCD the way we want it */

	set_config = GLCD_FS_ROWS_2
		     | GLCD_FS_DOT_SIZE_LITTLE
		     | GLCD_FS_8BIT_MODE;

	glcd_function_set(glcd, set_config);

	set_config = GLCD_DS_DISPLAY_ON | GLCD_DS_CURSOR_ON | GLCD_DS_BLINK_ON;

	glcd_display_state_set(glcd, set_config);

	/* Setup variables /*/
	for (i = 0; i < sizeof(str); i++) {
		str[i] = '\0';
	}

	/* Starting counting */
	cnt = 0;

	while (1) {
		glcd_cursor_pos_set(glcd, 0, 0);

		/* RGB values are from 0 - 511.
		 * First half means incrementally brighter.
		 * Second half is opposite (i.e. goes darker).
		 */

		/* Update the RGB values for backlight */
		m = (rgb[2] > 255) ? (512 - rgb[2]) : (rgb[2]);
		rgb_chg[2] = clamp_rgb(m);

		m = (rgb[1] > 255) ? (512 - rgb[1]) : (rgb[1]);
		rgb_chg[1] = clamp_rgb(m);

		m = (rgb[0] > 255) ? (512 - rgb[0]) : (rgb[0]);
		rgb_chg[0] = clamp_rgb(m);

		glcd_color_set(glcd, rgb_chg[0], rgb_chg[1], rgb_chg[2]);

		/* Display the counter
		 *
		 * well... sprintf() might be easier,
		 * but this is more fun.
		 */
		m = cnt;
		i = 1000000000;
		j = 0;
		while (i > 0) {
			str[j] = '0' + (m / i);

			m = m % i;
			i = i / 10;
			j++;
		}
		cnt++;

		glcd_print(glcd, str, j);

		/* Rotate RGB values */
		rgb[2] += rgb_step;
		if (rgb[2] > 511) {
			rgb[2] = 0;
			rgb[1] += rgb_step;
		}
		if (rgb[1] > 511) {
			rgb[1] = 0;
			rgb[0] += rgb_step;
		}
		if (rgb[0] > 511) {
			rgb[0] = 0;
		}

		/* wait a while */
		k_msleep(SLEEPTIME);
	}
}

my overlay file is

/ {
        chosen {
		zephyr,display = &glcd;
        };
};

&pinctrl {
	uart0_default_alt: uart0_default_alt {
		group0 {
			psels = <NRF_PSEL(UART_TX, 0, 24)>, <NRF_PSEL(UART_RX, 0, 22)>;
		};
	};

	uart0_sleep_alt: uart0_sleep_alt {
		group1 {
			psels = <NRF_PSEL(UART_TX, 0, 24)>, <NRF_PSEL(UART_RX, 0, 22)>;
			low-power-enable;
		};
	};

	i2c0_default_alt: i2c0_default_alt {
       		group2 {
          		psels = <NRF_PSEL(TWIM_SDA, 0, 17)>,
                  		<NRF_PSEL(TWIM_SCL, 0, 20)>;
       			};
    		};
};

&uart0 {
	pinctrl-0 = <&uart0_default_alt>;
	pinctrl-1 = <&uart0_sleep_alt>;	
	pinctrl-names = "default", "sleep";
	compatible = "nordic,nrf-uart";
	current-speed = <115200>;
	status = "okay";
};

&i2c0 {
	status = "okay";
	compatible = "nordic,nrf-twim";	
	pinctrl-0 = <&i2c0_default>;
	pinctrl-1 = <&i2c0_sleep>;
	pinctrl-names = "default", "sleep";
    	clock-frequency = <I2C_BITRATE_STANDARD>;  
//	clock-frequency = <I2C_BITRATE_FAST>;  
	zephyr,concat-buf-size = <520>;

	glcd: glcd@3e {
		compatible = "seeed,grove-lcd-rgb";
		label = "GLCD";
		reg = <0x3e>;
	};

};


&i2c0 {
/delete-property/sda-gpios;
/delete-property/scl-gpios;
};

and my proj file

# General config
CONFIG_BOARD_HAS_NRF5_BOOTLOADER=n
CONFIG_ASSERT=y
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_GPIO=y
CONFIG_SERIAL=y
CONFIG_UART_INTERRUPT_DRIVEN=y
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NEWLIB_LIBC=y
CONFIG_CONSOLE_SUBSYS=y
CONFIG_CONSOLE_GETCHAR=y
CONFIG_STDOUT_CONSOLE=y
CONFIG_CONSOLE=y

CONFIG_CPLUSPLUS=y
CONFIG_LOG=y
CONFIG_SHELL=y
CONFIG_REBOOT=y
CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y
CONFIG_UART_CONSOLE=y

CONFIG_GPIO=y
CONFIG_STDOUT_CONSOLE=y
CONFIG_PRINTK=y

CONFIG_PINCTRL=y
CONFIG_PM_DEVICE=y

CONFIG_I2C=y
CONFIG_I2C_NRFX=y
CONFIG_SENSOR=y

CONFIG_BOOT_BANNER=n

#Display
CONFIG_DISPLAY=y
CONFIG_CHARACTER_FRAMEBUFFER=y
CONFIG_SHELL=y
CONFIG_CHARACTER_FRAMEBUFFER_SHELL=y
CONFIG_HEAP_MEM_POOL_SIZE=16384
CONFIG_GROVE_LCD_RGB=y

I think I'm missing something obvious but can't see it :-(

Rod

Parents
  • Hi Rod

    To debug, add the following to your prj.conf:

    CONFIG_LOG=y
    CONFIG_GROVE_LCD_RGB_LOG_LEVEL_DBG=y
    
    

    Then you can add some custom debugging log to glcd_initialize(), which will be called automatically on startup.

    I guess this function does not finish somehow, and therefore your code reports that it is not ready yet.

    Regards,
    Sigurd Hellesvik

  • Hi Sigurd,

    I have enabled debug and added a couple of debug statements shown below.

    static int glcd_initialize(const struct device *dev)
    {
    	const struct glcd_config *config = dev->config;
    	uint8_t cmd;
    
    	LOG_DBG("initialize called");
    
    	LOG_DBG("Check if Device is Ready");
    
    	if (!device_is_ready(config->bus.bus)) {
    	LOG_DBG("Check if Device is Ready Failed");
    		return -ENODEV;
    	}
    

    This is what I see

    uart:~$ Grove LCD: Device not ready.
    
    [00:00:00.311,798] <dbg> grove_lcd: glcd_initialize: initialize called
    [00:00:00.311,798] <dbg> grove_lcd: glcd_initialize: Check if Device is Ready
    [00:00:00.311,828] <dbg> grove_lcd: glcd_initialize: Check if Device is Ready Failed
    uart:~$ 
    

    Rod

Reply
  • Hi Sigurd,

    I have enabled debug and added a couple of debug statements shown below.

    static int glcd_initialize(const struct device *dev)
    {
    	const struct glcd_config *config = dev->config;
    	uint8_t cmd;
    
    	LOG_DBG("initialize called");
    
    	LOG_DBG("Check if Device is Ready");
    
    	if (!device_is_ready(config->bus.bus)) {
    	LOG_DBG("Check if Device is Ready Failed");
    		return -ENODEV;
    	}
    

    This is what I see

    uart:~$ Grove LCD: Device not ready.
    
    [00:00:00.311,798] <dbg> grove_lcd: glcd_initialize: initialize called
    [00:00:00.311,798] <dbg> grove_lcd: glcd_initialize: Check if Device is Ready
    [00:00:00.311,828] <dbg> grove_lcd: glcd_initialize: Check if Device is Ready Failed
    uart:~$ 
    

    Rod

Children
  • Hi Rod,

    Try to move

    add_subdirectory(misc)

    to below

    add_subdirectory_ifdef(CONFIG_I2C i2c)

    in zephyr/drivers/CMakeLists.txt.

    Does this fix your issue?

    In which case, the problem might look like a bug.

    Regards,
    Sigurd Hellesvik

  • Hi

    Disregard my previous comment.
    It seems that you can fix the order of I2C initialization by changing CONFIG_I2C_INIT_PRIORITY.

    Regards,
    Sigurd Hellesvik

  • Hi Sigurd,

    I added the following line to my config file

    CONFIG_I2C_INIT_PRIORITY = 30

    I tried 60 but this didn't make any difference . Any suggestions for which value I should use?

    This moves it a bit further..

    [00:00:00.309,020] <dbg> grove_lcd: glcd_initialize: initialize called
    [00:00:00.309,051] <dbg> grove_lcd: glcd_initialize: Check if Device is Ready
    [00:00:00.309,051] <dbg> grove_lcd: glcd_initialize: Device is Ready
    [00:00:00.309,082] <dbg> grove_lcd: glcd_initialize: delay 50 ms while the VDD powers on
    [00:00:00.359,375] <err> i2c_nrfx_twim: Error 0x0BAE0001 occurred for message 0
    [00:00:00.359,436] <dbg> grove_lcd: glcd_function_set: set function options, delay 5 ms
    [00:00:00.364,715] <err> i2c_nrfx_twim: Error 0x0BAE0001 occurred for message 0
    [00:00:00.364,746] <dbg> grove_lcd: glcd_display_state_set: set display_state options, delay 5 ms
    [00:00:00.370,025] <err> i2c_nrfx_twim: Error 0x0BAE0001 occurred for message 0
    [00:00:00.370,056] <dbg> grove_lcd: glcd_clear: clear, delay 20 ms
    [00:00:00.390,380] <err> i2c_nrfx_twim: Error 0x0BAE0001 occurred for message 0
    [00:00:00.390,411] <dbg> grove_lcd: glcd_input_state_set: set the input_set, no delay
    [00:00:00.390,441] <inf> grove_lcd: configuring the RGB background
    [00:00:00.390,655] <err> i2c_nrfx_twim: Error 0x0BAE0001 occurred for message 0
    [00:00:00.390,869] <err> i2c_nrfx_twim: Error 0x0BAE0001 occurred for message 0
    [00:00:00.391,082] <err> i2c_nrfx_twim: Error 0x0BAE0001 occurred for message 0
    [00:00:00.391,113] <dbg> grove_lcd: glcd_initialize: background set to white
    [00:00:00.391,296] <err> i2c_nrfx_twim: Error 0x0BAE0001 occurred for message 0
    [00:00:00.391,510] <err> i2c_nrfx_twim: Error 0x0BAE0001 occurred for message 0
    [00:00:00.391,723] <err> i2c_nrfx_twim: Error 0x0BAE0001 occurred for message 0
    [00:00:00.391,937] <err> i2c_nrfx_twim: Error 0x0BAE0001 occurred for message 0
    [00:00:00.391,967] <dbg> grove_lcd: glcd_function_set: set function options, delay 5 ms
    [00:00:00.397,308] <err> i2c_nrfx_twim: Error 0x0BAE0001 occurred for message 0
    [00:00:00.397,338] <dbg> grove_lcd: glcd_display_state_set: set display_state options, delay 5 ms
    [00:00:00.402,648] <err> i2c_nrfx_twim: Error 0x0BAE0001 occurred for message 0
    [00:00:00.402,893] <err> i2c_nrfx_twim: Error 0x0BAE0001 occurred for message 0
    

    Rod

  • The grove init function uses CONFIG_KERNEL_INIT_PRIORITY_DEVICE, so as long as I2C has higher priority than this, I guess it should be fine.

    To debug your I2C errors, I suggest that you use an oscilloscope or logic analyzer to have a look at the I2C lines and see if the communication makes sense.

    Also see nrfx_errors.h for error codes.

    Regards,
    Sigurd Hellesvik

  • I am pretty sure I have had this working previously on this board with an older version of the SDK which makes me this its  a software config error. I will check

    Rod

Related