Arduino Nano, BME680, and LCD1602

I rewired some things just to try and take a nice clear picture of all the connections. If there's something you can't see, please let me know.

So I'm sure it's pretty self explanatory, but I'm trying to make an "air quality sensor", and have the readings printed out on the LCD. The code verifies fine, and uploads to the nano, but when I power it on, I just get a wacky assortment of characters.

BME680

Nano Clones

#include <LiquidCrystal.h>
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_BME680.h"


LiquidCrystal lcd(12, 11, 7, 6, 5, 4);

#define SEALEVELPRESSURE_HPA (1013.25)

#define BMP680_I2C_ADDRESS 0x76
Adafruit_BME680 bme; // I2C

void setup() {

  lcd.begin(16, 2);
  //lcd.init();
  //lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("Air Quality");
  delay(3000);

  if (!bme.begin(0x76))
  {
    Serial.println("Could not find BME680!");
    while (1);
  }

  // Set up oversampling and filter initialization
  bme.setTemperatureOversampling(BME680_OS_8X);
  bme.setHumidityOversampling(BME680_OS_2X);
  bme.setPressureOversampling(BME680_OS_4X);
  bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
  bme.setGasHeater(320, 150); // 320*C for 150 ms

}

void loop() {
  if (! bme.performReading())
  {
    Serial.println("Failed to perform reading");
    return;
  }
  lcd.setCursor(0, 0);
  lcd.print("Temperature =");
  lcd.print(bme.temperature);
  lcd.print((char)223);
  lcd.print("C");
  lcd.setCursor(0, 1);
  lcd.print("Pressure = ");
  lcd.print(bme.pressure / 100.0);
  lcd.print("hPa");
  delay(3000);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Humidity = ");
  lcd.print(bme.humidity);
  lcd.print(" %");
  lcd.setCursor(0, 1);
  lcd.print("Gas = ");
  lcd.print(bme.gas_resistance / 1000.0);
  lcd.print(" KOhms");
  delay(3000);
}

Welcome to the forum.

Make a new (small) sketch that prints "Hello" to the display.
A tutorial is here: https://docs.arduino.cc/learn/electronics/lcd-displays
When trying to fix the display, you should try to isolate that problem.

Can you check one more time the 4 data lines ? I think they are okay in the photo, but a wire could be broken or make bad contact.

Can you show a better photo (or a better link) to your BME680 module ? Is that module suitable for a 5V Arduino board ?

I will make a small/simple circuit to verify the LCD functions correctly, and post the results.

I changed out all 4 data lines, no change.

I couldn't find a proper data sheet for that BME680, but the amazon page has great pictures of it and says its "directly compatible with 3.3v and 5v systems."

Just found THIS.

It seems to have a I2C level shifter, so it will work with a Arduino Uno.

I noticed that you don't use the Serial Monitor.
You need another test-sketch for just the BME680, writes its data to the Serial Monitor.

Keep in mind that the display could be broken. If you are sure that all the wires are correct, then try another display.

If it was broken, could it still reach the point that it did? Displaying incorrect text, but displaying text all the same.

The other day when I was messing with this I ran across someone's code specifically to run the BME680 in the serial monitor. I'll grab that and test it out on just the BME680.

It's been a long day, so I'll get to this tomorrow.

Thank you so much for the help! I greatly appreciate you taking time from your day to help me out, I'll do the things you suggested as soon as I get a chance and report back.

Yes, everything is possible.

I suggest you use Bill Perrys library , installable through the IDE library manager and run the diagnostic sketches included in the examples.
It will self-configure and test the LCD and provide the details via the serial monitor.

So to start, I decided to test the BME680.

Here's my simple little circuit.

And I used the I2CDemo code from "Zanshin_BME680" library here:

/*! @file I2CDemo.ino

  @section I2CDemo_intro_section Description

  Example program for using I2C to set and read the Bosch BME680 sensor. The sensor measures
  temperature, pressure and humidity and is described at
  https://www.bosch-sensortec.com/bst/products/all_products/BME680. The datasheet is available from
  Bosch at https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BME680_DS001-11.pdf \n\n

  The most recent version of the BME680 library is available at https://github.com/Zanduino/BME680
  and the documentation of the library as well as example programs are described in the project's wiki
  pages located at https://github.com/Zanduino/BME680/wiki. \n\n

  The BME680 is an extremely small physical package that is so tiny as to be impossible to solder at
  home, hence it will be used as part of a third-party breakout board. There are several such boards
  available at this time, for example \n
  | Company  | Link       |
  | -------  | ---------- |
  | Sparkfun | https://www.sparkfun.com/products/14570 |
  | BlueDot  | https://www.bluedot.space/sensor-boards/bme680/ |
  | Adafruit |
  https://learn.adafruit.com/adafruit-BME680-humidity-barometric-pressure-temperature-sensor-breakout
  |
  \n\n

  Bosch supplies sample software that runs on various platforms, including the Arduino family; this
  can be downloaed at https://github.com/BoschSensortec/BSEC-Arduino-library . This software is part
  of the Bosch "BSEC" (Bosch Sensortec Environmental Cluster) framework and somewhat bulky and
  unwieldy for typical Arduino applications, hence the choice to make a more compact and rather less
  abstract library.

  This example program initializes the BME680 to use I2C for communications. The library does not
  using floating point numbers to save on memory space and computation time. The values for
  Temperature, Pressure and Humidity are returned in deci-units, e.g. a Temperature reading of "2731"
  means "27.31" degrees Celsius. The display in the example program uses floating point for
  demonstration purposes only.  Note that the temperature reading is generally higher than the ambient
  temperature due to die and PCB temperature and self-heating of the element.\n\n

  The pressure reading needs to be adjusted for altitude to get the adjusted pressure reading. There
  are numerous sources on the internet for formulae converting from standard sea-level pressure to
  altitude, see the data sheet for the BME180 on page 16 of
  http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf. Rather than put a floating-point
  function in the library which may not be used but which would use space, an example altitude
  computation function has been added to this example program to show how it might be done.

  @section I2CDemolicense License

  This program is free software: you can redistribute it and/or modify it under the terms of the GNU
  General Public License as published by the Free Software Foundation, either version 3 of the
  License, or (at your option) any later version. This program is distributed in the hope that it will
  be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details. You should have
  received a copy of the GNU General Public License along with this program.  If not, see
  <http://www.gnu.org/licenses/>.

  @section I2CDemoauthor Author

  Written by Arnd <Arnd@Zanduino.Com> at https://www.github.com/SV-Zanshin

  @section I2CDemoversions Changelog

  | Version | Date       | Developer  | Comments
  | ------- | ---------- | ---------- | ------------------------------------------------------------ |
  | 1.0.3   | 2020-07-04 | SV-Zanshin | Issue #25 implement clang-formatting                         |
  | 1.0.2   | 2020-05-09 | SV-Zanshin | Issue #8  clean up comments and code                         |
  | 1.0.1   | 2019-01-30 | SV-Zanshin |           Removed old comments                               |
  | 1.0.1   | 2019-01-26 | SV-Zanshin | Issue #3  convert documentation to Doxygen                   |
  | 1.0.0b  | 2018-06-30 | SV-Zanshin |           Cloned from original BME280 program                |
*/
#include "Zanshin_BME680.h"  // Include the BME680 Sensor library
/**************************************************************************************************
** Declare all program constants                                                                 **
**************************************************************************************************/
const uint32_t SERIAL_SPEED {
  115200
};  ///< Set the baud rate for Serial I/O

/**************************************************************************************************
** Declare global variables and instantiate classes                                              **
**************************************************************************************************/
BME680_Class BME680;  ///< Create an instance of the BME680 class
///< Forward function declaration with default value for sea level
float altitude(const int32_t press, const float seaLevel = 1013.25);
float altitude(const int32_t press, const float seaLevel) {
  /*!
    @brief     This converts a pressure measurement into a height in meters
    @details   The corrected sea-level pressure can be passed into the function if it is known,
             otherwise the standard atmospheric pressure of 1013.25hPa is used (see
             https://en.wikipedia.org/wiki/Atmospheric_pressure) for details.
    @param[in] press    Pressure reading from BME680
    @param[in] seaLevel Sea-Level pressure in millibars
    @return    floating point altitude in meters.
  */
  static float Altitude;
  Altitude =
    44330.0 * (1.0 - pow(((float)press / 100.0) / seaLevel, 0.1903));  // Convert into meters
  return (Altitude);
}  // of method altitude()

void setup() {
  /*!
    @brief    Arduino method called once at startup to initialize the system
    @details  This is an Arduino IDE method which is called first upon boot or restart. It is only
            called one time and then control goes to the main "loop()" method, from which
            control never returns
    @return   void
  */
  Serial.begin(SERIAL_SPEED);  // Start serial port at Baud rate
#ifdef __AVR_ATmega32U4__      // If this is a 32U4 processor, then wait 3 seconds to init USB port
  delay(3000);
#endif
  Serial.print(F("Starting I2CDemo example program for BME680\n"));
  Serial.print(F("- Initializing BME680 sensor\n"));
  while (!BME680.begin(I2C_STANDARD_MODE)) {  // Start BME680 using I2C, use first device found
    Serial.print(F("-  Unable to find BME680. Trying again in 5 seconds.\n"));
    delay(5000);
  }  // of loop until device is located
  Serial.print(F("- Setting 16x oversampling for all sensors\n"));
  BME680.setOversampling(TemperatureSensor, Oversample16);  // Use enumerated type values
  BME680.setOversampling(HumiditySensor, Oversample16);     // Use enumerated type values
  BME680.setOversampling(PressureSensor, Oversample16);     // Use enumerated type values
  Serial.print(F("- Setting IIR filter to a value of 4 samples\n"));
  BME680.setIIRFilter(IIR4);  // Use enumerated type values
  Serial.print(F("- Setting gas measurement to 320\xC2\xB0\x43 for 150ms\n"));  // "�C" symbols
  BME680.setGas(320, 150);  // 320�c for 150 milliseconds
}  // of method setup()
void loop() {
  /*!
    @brief    Arduino method for the main program loop
    @details  This is the main program for the Arduino IDE, it is an infinite loop and keeps on
            repeating. The "sprintf()" function is to pretty-print the values, since floating
            point is not supported on the Arduino, split the values into those before and those
            after the decimal point.
    @return   void
  */
  static int32_t  temp, humidity, pressure, gas;  // BME readings
  static char     buf[16];                        // sprintf text buffer
  static float    alt;                            // Temporary variable
  static uint16_t loopCounter = 0;                // Display iterations
  if (loopCounter % 25 == 0) {                    // Show header @25 loops
    Serial.print(F("\nLoop Temp\xC2\xB0\x43 Humid% Press hPa   Alt m Air m"));
    Serial.print(F("\xE2\x84\xA6\n==== ====== ====== ========= ======= ======\n"));  // "�C" symbol
  }                                                     // if-then time to show headers
  BME680.getSensorData(temp, humidity, pressure, gas);  // Get readings
  if (loopCounter++ != 0) {                             // Ignore first reading, might be incorrect
    sprintf(buf, "%4d %3d.%02d", (loopCounter - 1) % 9999,  // Clamp to 9999,
            (int8_t)(temp / 100), (uint8_t)(temp % 100));   // Temp in decidegrees
    Serial.print(buf);
    sprintf(buf, "%3d.%03d", (int8_t)(humidity / 1000),
            (uint16_t)(humidity % 1000));  // Humidity milli-pct
    Serial.print(buf);
    sprintf(buf, "%7d.%02d", (int16_t)(pressure / 100),
            (uint8_t)(pressure % 100));  // Pressure Pascals
    Serial.print(buf);
    alt = altitude(pressure);                                                // temp altitude
    sprintf(buf, "%5d.%02d", (int16_t)(alt), ((uint8_t)(alt * 100) % 100));  // Altitude meters
    Serial.print(buf);
    sprintf(buf, "%4d.%02d\n", (int16_t)(gas / 100), (uint8_t)(gas % 100));  // Resistance milliohms
    Serial.print(buf);
    delay(10000);  // Wait 10s
  }                // of ignore first reading
}  // of method loop()

This is what the serial monitor spit out. Which is pretty accurate compared to what the LCD was showing.

This makes me think the problem is not with the LCD, although I guess it wouldn't be a bad idea to test it as well, just to make sure I don't run into another problem.

I forgot to add, I also used a new nano, to make sure there wasn't an issue with the other one.

I think I figured it out, I won't consider myself "out of the woods" until this whole thing works, lol.

I was having a bit of trouble uploading to my nano's. Both of them. I then came across this:
Baud rate explanation
Which goes on to say how official boards changed to 115200, while clone boards are still 57600.

So I went back, changed the baud rate, which was indeed set at 115200. Uploaded the example code again, and here's the monitor:

Not sure what that funny business is on the beginning of the first line, but everything after that is beautiful.

Now to attempt to display this on a LCD...

I just don't know anymore hahahaaa.

#include "Zanshin_BME680.h"  // Include the BME680 Sensor library
#include <LiquidCrystal.h>

const uint32_t SERIAL_SPEED {
  57600
};  ///< Set the baud rate for Serial I/O

BME680_Class BME680;  ///< Create an instance of the BME680 class
///< Forward function declaration with default value for sea level
float altitude(const int32_t press, const float seaLevel = 1013.25);
float altitude(const int32_t press, const float seaLevel) {

  static float Altitude;
  Altitude =
    44330.0 * (1.0 - pow(((float)press / 100.0) / seaLevel, 0.1903));  // Convert into meters
  return (Altitude);
}  // of method altitude()

const int rs = 12, en = 11, d4 = 4, d5 = 5, d6 = 6, d7 = 7;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);


void setup() {
  lcd.begin(16, 2);
  Serial.begin(SERIAL_SPEED);  // Start serial port at Baud rate
#ifdef __AVR_ATmega32U4__      // If this is a 32U4 processor, then wait 3 seconds to init USB port
  delay(3000);
#endif
  Serial.print(F("Starting I2CDemo example program for BME680\n"));
  Serial.print(F("- Initializing BME680 sensor\n"));
  while (!BME680.begin(I2C_STANDARD_MODE)) {  // Start BME680 using I2C, use first device found
    Serial.print(F("-  Unable to find BME680. Trying again in 5 seconds.\n"));
    delay(5000);
  }  // of loop until device is located
  Serial.print(F("- Setting 16x oversampling for all sensors\n"));
  BME680.setOversampling(TemperatureSensor, Oversample16);  // Use enumerated type values
  BME680.setOversampling(HumiditySensor, Oversample16);     // Use enumerated type values
  BME680.setOversampling(PressureSensor, Oversample16);     // Use enumerated type values
  Serial.print(F("- Setting IIR filter to a value of 4 samples\n"));
  BME680.setIIRFilter(IIR4);  // Use enumerated type values
  Serial.print(F("- Setting gas measurement to 320\xC2\xB0\x43 for 150ms\n"));  // "�C" symbols
  BME680.setGas(320, 150);  // 320�c for 150 milliseconds
}  // of method setup()
void loop() {

  if (Serial.available()) {
    // wait a bit for the entire message to arrive
    delay(100);
    // clear the screen
    lcd.clear();
    // read all the available characters
    while (Serial.available() > 0) {
      // display each character to the LCD
      lcd.write(Serial.read());
    }

    static int32_t  temp, humidity, pressure, gas;  // BME readings
    static char     buf[16];                        // sprintf text buffer
    static float    alt;                            // Temporary variable
    static uint16_t loopCounter = 0;                // Display iterations
    if (loopCounter % 25 == 0) {                    // Show header @25 loops
      Serial.print(F("\nLoop Temp\xC2\xB0\x43 Humid% Press hPa   Alt m Air m"));
      Serial.print(F("\xE2\x84\xA6\n==== ====== ====== ========= ======= ======\n"));  // "�C" symbol
    }                                                     // if-then time to show headers
    BME680.getSensorData(temp, humidity, pressure, gas);  // Get readings
    if (loopCounter++ != 0) {                             // Ignore first reading, might be incorrect
      sprintf(buf, "%4d %3d.%02d", (loopCounter - 1) % 9999,  // Clamp to 9999,
              (int8_t)(temp / 100), (uint8_t)(temp % 100));   // Temp in decidegrees
      Serial.print(buf);
      sprintf(buf, "%3d.%03d", (int8_t)(humidity / 1000),
              (uint16_t)(humidity % 1000));  // Humidity milli-pct
      Serial.print(buf);
      sprintf(buf, "%7d.%02d", (int16_t)(pressure / 100),
              (uint8_t)(pressure % 100));  // Pressure Pascals
      Serial.print(buf);
      alt = altitude(pressure);                                                // temp altitude
      sprintf(buf, "%5d.%02d", (int16_t)(alt), ((uint8_t)(alt * 100) % 100));  // Altitude meters
      Serial.print(buf);
      sprintf(buf, "%4d.%02d\n", (int16_t)(gas / 100), (uint8_t)(gas % 100));  // Resistance milliohms
      Serial.print(buf);
      delay(10000);
    }
  }
}

I know the circuit is kinda hard to see, it's the same wiring as the original.
BME680 is wired I2C (SCL to A5 and SDA to A4)
The LCD is wired RS/D12, RW/Gnd, E/D11, D4-7/D4-7, added a pot.

Nothing prints to the LCD, and the serial monitor stops here.

That sketch waits for something. I seems to wait for an entired message to arrive, I have no idea what that is doing there.
If you find a library or a sketch or a tutorial or something, can you give a link to it ?

Adafruit has the best tutorials: https://learn.adafruit.com/adafruit-bme680-humidity-temperature-barometic-pressure-voc-gas

If you set the sketch to Serial.begin(9600); then you must set the Serial Monitor to 9600 baud as well (in the lower-right-corner). That is not automatically detected.
I suggest to set both to 115200.

I have it set to 57600. Soooo... I'm gonna let you in on a little secret, and you may have picked up on this already but...

I don't know how to code.

You'd be surprised how often I can chop up various bits of coding and, with a bit of knowledge about syntax and knowing how to find the functions of different libraries, get it to work.

Most of the time it's not too bad troubleshooting, but this one is really throwing me for a loop.

This was 2 examples chopped up and Frankenstein'd together.

First we have the "I2CDemo" from the Zanshin_BME680 library:

/*! @file I2CDemo.ino

  @section I2CDemo_intro_section Description

  Example program for using I2C to set and read the Bosch BME680 sensor. The sensor measures
  temperature, pressure and humidity and is described at
  https://www.bosch-sensortec.com/bst/products/all_products/BME680. The datasheet is available from
  Bosch at https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BME680_DS001-11.pdf \n\n

  The most recent version of the BME680 library is available at https://github.com/Zanduino/BME680
  and the documentation of the library as well as example programs are described in the project's wiki
  pages located at https://github.com/Zanduino/BME680/wiki. \n\n

  The BME680 is an extremely small physical package that is so tiny as to be impossible to solder at
  home, hence it will be used as part of a third-party breakout board. There are several such boards
  available at this time, for example \n
  | Company  | Link       |
  | -------  | ---------- |
  | Sparkfun | https://www.sparkfun.com/products/14570 |
  | BlueDot  | https://www.bluedot.space/sensor-boards/bme680/ |
  | Adafruit |
  https://learn.adafruit.com/adafruit-BME680-humidity-barometric-pressure-temperature-sensor-breakout
  |
  \n\n

  Bosch supplies sample software that runs on various platforms, including the Arduino family; this
  can be downloaed at https://github.com/BoschSensortec/BSEC-Arduino-library . This software is part
  of the Bosch "BSEC" (Bosch Sensortec Environmental Cluster) framework and somewhat bulky and
  unwieldy for typical Arduino applications, hence the choice to make a more compact and rather less
  abstract library.

  This example program initializes the BME680 to use I2C for communications. The library does not
  using floating point numbers to save on memory space and computation time. The values for
  Temperature, Pressure and Humidity are returned in deci-units, e.g. a Temperature reading of "2731"
  means "27.31" degrees Celsius. The display in the example program uses floating point for
  demonstration purposes only.  Note that the temperature reading is generally higher than the ambient
  temperature due to die and PCB temperature and self-heating of the element.\n\n

  The pressure reading needs to be adjusted for altitude to get the adjusted pressure reading. There
  are numerous sources on the internet for formulae converting from standard sea-level pressure to
  altitude, see the data sheet for the BME180 on page 16 of
  http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf. Rather than put a floating-point
  function in the library which may not be used but which would use space, an example altitude
  computation function has been added to this example program to show how it might be done.

  @section I2CDemolicense License

  This program is free software: you can redistribute it and/or modify it under the terms of the GNU
  General Public License as published by the Free Software Foundation, either version 3 of the
  License, or (at your option) any later version. This program is distributed in the hope that it will
  be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details. You should have
  received a copy of the GNU General Public License along with this program.  If not, see
  <http://www.gnu.org/licenses/>.

  @section I2CDemoauthor Author

  Written by Arnd <Arnd@Zanduino.Com> at https://www.github.com/SV-Zanshin

  @section I2CDemoversions Changelog

  | Version | Date       | Developer  | Comments
  | ------- | ---------- | ---------- | ------------------------------------------------------------ |
  | 1.0.3   | 2020-07-04 | SV-Zanshin | Issue #25 implement clang-formatting                         |
  | 1.0.2   | 2020-05-09 | SV-Zanshin | Issue #8  clean up comments and code                         |
  | 1.0.1   | 2019-01-30 | SV-Zanshin |           Removed old comments                               |
  | 1.0.1   | 2019-01-26 | SV-Zanshin | Issue #3  convert documentation to Doxygen                   |
  | 1.0.0b  | 2018-06-30 | SV-Zanshin |           Cloned from original BME280 program                |
*/
#include "Zanshin_BME680.h"  // Include the BME680 Sensor library
/**************************************************************************************************
** Declare all program constants                                                                 **
**************************************************************************************************/
const uint32_t SERIAL_SPEED {
  115200
};  ///< Set the baud rate for Serial I/O

/**************************************************************************************************
** Declare global variables and instantiate classes                                              **
**************************************************************************************************/
BME680_Class BME680;  ///< Create an instance of the BME680 class
///< Forward function declaration with default value for sea level
float altitude(const int32_t press, const float seaLevel = 1013.25);
float altitude(const int32_t press, const float seaLevel) {
  /*!
    @brief     This converts a pressure measurement into a height in meters
    @details   The corrected sea-level pressure can be passed into the function if it is known,
             otherwise the standard atmospheric pressure of 1013.25hPa is used (see
             https://en.wikipedia.org/wiki/Atmospheric_pressure) for details.
    @param[in] press    Pressure reading from BME680
    @param[in] seaLevel Sea-Level pressure in millibars
    @return    floating point altitude in meters.
  */
  static float Altitude;
  Altitude =
    44330.0 * (1.0 - pow(((float)press / 100.0) / seaLevel, 0.1903));  // Convert into meters
  return (Altitude);
}  // of method altitude()

void setup() {
  /*!
    @brief    Arduino method called once at startup to initialize the system
    @details  This is an Arduino IDE method which is called first upon boot or restart. It is only
            called one time and then control goes to the main "loop()" method, from which
            control never returns
    @return   void
  */
  Serial.begin(SERIAL_SPEED);  // Start serial port at Baud rate
#ifdef __AVR_ATmega32U4__      // If this is a 32U4 processor, then wait 3 seconds to init USB port
  delay(3000);
#endif
  Serial.print(F("Starting I2CDemo example program for BME680\n"));
  Serial.print(F("- Initializing BME680 sensor\n"));
  while (!BME680.begin(I2C_STANDARD_MODE)) {  // Start BME680 using I2C, use first device found
    Serial.print(F("-  Unable to find BME680. Trying again in 5 seconds.\n"));
    delay(5000);
  }  // of loop until device is located
  Serial.print(F("- Setting 16x oversampling for all sensors\n"));
  BME680.setOversampling(TemperatureSensor, Oversample16);  // Use enumerated type values
  BME680.setOversampling(HumiditySensor, Oversample16);     // Use enumerated type values
  BME680.setOversampling(PressureSensor, Oversample16);     // Use enumerated type values
  Serial.print(F("- Setting IIR filter to a value of 4 samples\n"));
  BME680.setIIRFilter(IIR4);  // Use enumerated type values
  Serial.print(F("- Setting gas measurement to 320\xC2\xB0\x43 for 150ms\n"));  // "�C" symbols
  BME680.setGas(320, 150);  // 320�c for 150 milliseconds
}  // of method setup()
void loop() {
  /*!
    @brief    Arduino method for the main program loop
    @details  This is the main program for the Arduino IDE, it is an infinite loop and keeps on
            repeating. The "sprintf()" function is to pretty-print the values, since floating
            point is not supported on the Arduino, split the values into those before and those
            after the decimal point.
    @return   void
  */
  static int32_t  temp, humidity, pressure, gas;  // BME readings
  static char     buf[16];                        // sprintf text buffer
  static float    alt;                            // Temporary variable
  static uint16_t loopCounter = 0;                // Display iterations
  if (loopCounter % 25 == 0) {                    // Show header @25 loops
    Serial.print(F("\nLoop Temp\xC2\xB0\x43 Humid% Press hPa   Alt m Air m"));
    Serial.print(F("\xE2\x84\xA6\n==== ====== ====== ========= ======= ======\n"));  // "�C" symbol
  }                                                     // if-then time to show headers
  BME680.getSensorData(temp, humidity, pressure, gas);  // Get readings
  if (loopCounter++ != 0) {                             // Ignore first reading, might be incorrect
    sprintf(buf, "%4d %3d.%02d", (loopCounter - 1) % 9999,  // Clamp to 9999,
            (int8_t)(temp / 100), (uint8_t)(temp % 100));   // Temp in decidegrees
    Serial.print(buf);
    sprintf(buf, "%3d.%03d", (int8_t)(humidity / 1000),
            (uint16_t)(humidity % 1000));  // Humidity milli-pct
    Serial.print(buf);
    sprintf(buf, "%7d.%02d", (int16_t)(pressure / 100),
            (uint8_t)(pressure % 100));  // Pressure Pascals
    Serial.print(buf);
    alt = altitude(pressure);                                                // temp altitude
    sprintf(buf, "%5d.%02d", (int16_t)(alt), ((uint8_t)(alt * 100) % 100));  // Altitude meters
    Serial.print(buf);
    sprintf(buf, "%4d.%02d\n", (int16_t)(gas / 100), (uint8_t)(gas % 100));  // Resistance milliohms
    Serial.print(buf);
    delay(10000);  // Wait 10s
  }                // of ignore first reading
}  // of method loop()

And then we have "SerialDisplay" from the Adafruit LiquidCrystal library.

/*
  LiquidCrystal Library - Serial Input

  Demonstrates the use a 16x2 LCD display.  The LiquidCrystal
  library works with all LCD displays that are compatible with the
  Hitachi HD44780 driver. There are many of them out there, and you
  can usually tell them by the 16-pin interface.

  This sketch displays text sent over the serial port
  (e.g. from the Serial Monitor) on an attached LCD.

  The circuit:
   LCD RS pin to digital pin 12
   LCD Enable pin to digital pin 11
   LCD D4 pin to digital pin 5
   LCD D5 pin to digital pin 4
   LCD D6 pin to digital pin 3
   LCD D7 pin to digital pin 2
   10K resistor:
   ends to +5V and ground
   wiper to LCD VO pin (pin 3)

  Library originally added 18 Apr 2008
  by David A. Mellis
  library modified 5 Jul 2009
  by Limor Fried (http://www.ladyada.net)
  example added 9 Jul 2009
  by Tom Igoe
  modified 25 July 2009
  by David A. Mellis

  http://www.arduino.cc/en/Tutorial/LiquidCrystal
*/

// include the library code:
#include "Wire.h"
#include "Adafruit_LiquidCrystal.h"

// initialize the library with the numbers of the interface pins
Adafruit_LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {
  // set up the LCD's number of rows and columns:
  lcd.begin(16, 2);
  // initialize the serial communications:
  Serial.begin(9600);
}

void loop()
{
  // when characters arrive over the serial port...
  if (Serial.available()) {
    // wait a bit for the entire message to arrive
    delay(100);
    // clear the screen
    lcd.clear();
    // read all the available characters
    while (Serial.available() > 0) {
      // display each character to the LCD
      lcd.write(Serial.read());
    }
  }
}

Seems you ignored my previous advice regarding @bperrys library, my final suggestion is to concentrate on getting (at least) the "hello world" sketch successfully on the LCD. Good Luck :raised_hand_with_fingers_splayed:

I didn't ignore it, I just haven't made it that far yet. I have a lot on my plate at work, and this is where I work on these things. I have installed Bill Perry's library, just haven't used it yet.

Please don't mistake my "slothyness" for disregard or that I'm taking your advice for granted.

I really do appreciate you guys helping me out.

My next step is to do some extensive testing with the LCD, and I plan on doing more than the "Hello world" test. To 1. make sure it functions as it should and 2. I'll guaranteed learn something.

As always, once I get to it (probably tomorrow), I will report all my results.

Also, just curious, am I doing okay on how I'm posting? I made a point to read the forum posts on how to post code and pictures and everything. I'm trying to do my best to give all the required/necessary information, just want to make sure I'm doing everything I should/can.

Thanks again guys!

Okay, so I've completed my first LCD test using Bill Perry's library. First off, being such a noob at this, that was quite overwhelming at first. But I did some reading, read the documentation that came with the library, and I finally realized which one of the MANY examples I needed to try. A lot of them are for I2C, and I don't have one of those breakout boards you need to do that, and a few of them were for very specific LCDs. Either way... Here's my results.

// vi:ts=4
// ----------------------------------------------------------------------------
// Serial2LCD - simple demonstration printing characters from serial port
// Created by Bill Perry 2020-06-28
// bperrybap@opensource.billsworld.billandterrie.com
//
// This example code is unlicensed and is released into the public domain
// ----------------------------------------------------------------------------
//
// This sketch is for LCDs that are directly controlled with Arduino pins.
//
// Sketch demonstrates hd44780 how to read a message of characters from
// serial port and display it on the LCD.
// It takes advantage of the hd44780 library automatic line
// wrapping capability.
// See the LineWrap sketch for details about line wrapping.
//
// Configure LCD_COLS, LCD_ROWS and BAUDRATE if desired/needed
// Expected behavior of the sketch:
// - characters received from serial port are displayed on LCD
// - CR and LF are ignored/dropped
//
// If initialization of the LCD fails and the arduino supports a built in LED,
// the sketch will simply blink the built in LED with the initalization error
// code.
//
// Some 16x1 displays are actually a 8x2 display that have both lines on
// a single line on the display.
// If you have one of these displays, simply set the geometry to 8x2 instead
// of 16x1.

// ----------------------------------------------------------------------------
// pinout:
//  1 - LCD gnd
//  2 - VCC (5v)
//  3 - not connected
//  4 - RS Register Select (rs)
//  5 - Read/Write
//  6 - Enable (en)
//  7 - Data 0 (db0) ----
//  8 - Data 1 (db1)     |-------- Not used in 4 bit mode
//  9 - Data 2 (db2)     |
// 10 - Data 3 (db3) ----
// 11 - Data 4 (db4)
// 12 - Data 5 (db5)
// 13 - Data 6 (db6)
// 14 - Data 7 (db7)
// ----------------------------------------------------------------------------

#include <hd44780.h>
#include <hd44780ioClass/hd44780_pinIO.h> // Arduino pin i/o class header

// declare Arduino pins used for LCD functions
// and the lcd object

// Note: this can be with or without backlight control:

// without backlight control:
// note that ESP8266 based arduinos must use the Dn defines rather than
// raw pin numbers.
#if defined (ARDUINO_ARCH_ESP8266)
const int rs = D8, en = D9, db4 = D4, db5 = D5, db6 = D6, db7 = D7; // esp8266 Lolin/Wemos D1 R1 (uno form factor)
#elif defined(ARDUINO_ARCH_ESP32)
// note: GPIO12 needs a pulldown resistor
const int rs = 12, en = 13, db4 = 17, db5 = 16, db6 = 27, db7 = 14; // esp32 espduino32 D1 R32 (uno form factor)
#else
const int rs = 8, en = 9, db4 = 4, db5 = 5, db6 = 6, db7 = 7; // for all other devices
#endif
hd44780_pinIO lcd(rs, en, db4, db5, db6, db7);

//with backlight control:
//	backlight control requires two additional parameters
//	- an additional pin to control the backlight
//	- backlight active level which tells the library the level
//		needed to turn on the backlight.
//		note: If the backlight control pin supports PWM, dimming can be done
//			using setBacklight(dimvalue);
//
//	WARNING: some lcd keypads have a broken backlight circuit
//		If you have a lcd keypad, it is recommended that you first run the
//		LCDKeypadCheck sketch to verify that the backlight circuitry
//		is ok before enabling backlight control.
//		However, the hd44780_PinIO class will autodetect the issue and
//		work around it in s/w. If the backlight circuitry is broken,
//		dimming will not be possible even if the backlight pin supports PWM.
//
#if defined (ARDUINO_ARCH_ESP8266)
// esp8266 Lolin/Wemos D1 R1 (uno form factor)
//const int rs=D8, en=D9, db4=D4, db5=D5, db6=D6, db7=D7, bl=D10, blLevel=HIGH;
#elif defined(ARDUINO_ARCH_ESP32)
// esp32 espduino32 D1 R32 (uno form factor)
// note: GPIO12 needs a pulldown resistor
//       Dimming will not work on esp32 as it does not have analogWrite()
//const int rs=12, en=13, db4=17, db5=16, db6=27, db7=14, bl=5, blLevel=HIGH;
#else
//const int rs=8, en=9, db4=4, db5=5, db6=6, db7=7, bl=10, blLevel=HIGH;
#endif
//hd44780_pinIO lcd(rs, en, db4, db5, db6, db7, bl, blLevel);


// LCD geometry
const int LCD_COLS = 16;
const int LCD_ROWS = 2;

const int BAUDRATE = 9600;

void setup()
{
  int status;

  // initalize Serial port
  Serial.begin(BAUDRATE);

  // initialize LCD with number of columns and rows:
  // hd44780 returns a status from begin() that can be used
  // to determine if initalization failed.
  // the actual status codes are defined in <hd44780.h>
  status = lcd.begin(LCD_COLS, LCD_ROWS);
  if (status) // non zero status means it was unsuccesful
  {
    // begin() failed

    Serial.print("LCD initalization failed: ");
    Serial.println(status);

    // blink error code using the onboard LED if possible
    hd44780::fatalError(status); // does not return
  }

  // turn on automatic line wrapping
  // which automatically wraps lines to the next lower line and wraps back
  // to the top when at the bottom line
  // NOTE:
  // noLineWrap() can be used to disable automatic line wrapping.
  // _write() can be called instead of write() to send data bytes
  // to the display bypassing any special character or line wrap processing.
  lcd.lineWrap();

  lcd.print("Serial2LCD");
  if (LCD_ROWS > 1)
  {
    lcd.setCursor(0, 1);
    lcd.print("Baud:");
    lcd.print(BAUDRATE);
  }
}

void loop()
{

  // check to see if characters available
  // indicating a message is coming in
  if (Serial.available())
  {
    // wait some time for rest of message to arrive
    delay(100);

    // Clear the display before showing the new message
    lcd.clear();

    // print the message on the LCD
    while (Serial.available() > 0)
    {
      char c;
      c = Serial.read();
      if (c != '\r' && c != '\n') // drop CR and LF characters
        lcd.write(c);
    }
  }
}

As I said, I don't own one of those breakout board/backpacks for I2C wiring, BUT I do have a 74HC595 Shift Register that I could use for SPI, as seen HERE.

It seems that would open up my options a lot more with Bill Perry's library examples.

1 Like

Ughh... I am so lost. I can get the LCD1602 to work. I can get the BME680 to work.

For the life of me I can NOT get the LCD1602 to print the output of the BME680. I can get it to print out nicely in the serial monitor, but I just can't get it to the LCD.

Bill Perry's library is pretty extensive, but is way over my head because I just don't really know what I'm doing. A lot of the examples are pre setup code, which again, with my extremely limited knowledge, is completely lost on me.

Sometimes it's really hard to mash 2 existing codes together hahahaha.

Post your attempt.

This was my latest attempt at messing with the code I felt was the closest to working.

#include "Zanshin_BME680.h"  // Include the BME680 Sensor library
#include <LiquidCrystal.h>

const uint32_t SERIAL_SPEED {
  57600
};  ///< Set the baud rate for Serial I/O

BME680_Class BME680;  ///< Create an instance of the BME680 class
///< Forward function declaration with default value for sea level
float altitude(const int32_t press, const float seaLevel = 1013.25);
float altitude(const int32_t press, const float seaLevel) {

  static float Altitude;
  Altitude =
    44330.0 * (1.0 - pow(((float)press / 100.0) / seaLevel, 0.1903));  // Convert into meters
  return (Altitude);
}  // of method altitude()

const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);


void setup() {
  lcd.begin(16, 2);
  Serial.begin(SERIAL_SPEED);  // Start serial port at Baud rate
#ifdef __AVR_ATmega32U4__      // If this is a 32U4 processor, then wait 3 seconds to init USB port
  delay(3000);
#endif
  Serial.print(F("Starting I2CDemo example program for BME680\n"));
  Serial.print(F("- Initializing BME680 sensor\n"));
  while (!BME680.begin(I2C_STANDARD_MODE)) {  // Start BME680 using I2C, use first device found
    Serial.print(F("-  Unable to find BME680. Trying again in 5 seconds.\n"));
    delay(5000);
  }  // of loop until device is located
  Serial.print(F("- Setting 16x oversampling for all sensors\n"));
  BME680.setOversampling(TemperatureSensor, Oversample16);  // Use enumerated type values
  BME680.setOversampling(HumiditySensor, Oversample16);     // Use enumerated type values
  BME680.setOversampling(PressureSensor, Oversample16);     // Use enumerated type values
  Serial.print(F("- Setting IIR filter to a value of 4 samples\n"));
  BME680.setIIRFilter(IIR4);  // Use enumerated type values
  Serial.print(F("- Setting gas measurement to 320\xC2\xB0\x43 for 150ms\n"));  // "�C" symbols
  BME680.setGas(320, 150);  // 320�c for 150 milliseconds
}  // of method setup()
void loop() {

  static int32_t  temp, humidity, pressure, gas;  // BME readings
  static char     buf[16];                        // sprintf text buffer
  static float    alt;                            // Temporary variable
  static uint16_t loopCounter = 0;                // Display iterations
  if (loopCounter % 25 == 0) {                    // Show header @25 loops
    Serial.print(F("\nLoop Temp\xC2\xB0\x43 Humid% Press hPa   Alt m Air m"));
    Serial.print(F("\xE2\x84\xA6\n==== ====== ====== ========= ======= ======\n"));  // "�C" symbol
  }                                                     // if-then time to show headers
  BME680.getSensorData(temp, humidity, pressure, gas);  // Get readings
  if (loopCounter++ != 0) {                             // Ignore first reading, might be incorrect
    sprintf(buf, "%4d %3d.%02d", (loopCounter - 1) % 9999,  // Clamp to 9999,
            (int8_t)(temp / 100), (uint8_t)(temp % 100));   // Temp in decidegrees
    Serial.print(buf);
    sprintf(buf, "%3d.%03d", (int8_t)(humidity / 1000),
            (uint16_t)(humidity % 1000));  // Humidity milli-pct
    Serial.print(buf);
    sprintf(buf, "%7d.%02d", (int16_t)(pressure / 100),
            (uint8_t)(pressure % 100));  // Pressure Pascals
    Serial.print(buf);
    alt = altitude(pressure);                                                // temp altitude
    sprintf(buf, "%5d.%02d", (int16_t)(alt), ((uint8_t)(alt * 100) % 100));  // Altitude meters
    Serial.print(buf);
    sprintf(buf, "%4d.%02d\n", (int16_t)(gas / 100), (uint8_t)(gas % 100));  // Resistance milliohms
    Serial.print(buf);
    delay(5000);
  }
  if (Serial.available())
  {
    // wait some time for rest of message to arrive
    delay(100);

    // Clear the display before showing the new message
    lcd.clear();

    // print the message on the LCD
    while (Serial.available() > 0)
    {
      char c;
      c = Serial.read();
      if (c != '\r' && c != '\n') // drop CR and LF characters
        lcd.write(c);

    }
  }
}

Everything works except the LCD won't display what I want it to.

I would start by simply trying to print hello on the lcd with the BME680 in play.

The trick here is to start with one of your working programs and make tiny changes that add the other library, then test. Create the needed object, test. Try to use it, test. etc. etc. On the way, you'll hopefully get valuable clues when it fails.