Trying to learn more about coding

Greetings,

So my objective was to make or find a working code appropriate for my basic needs to achieve simple stuff like displaying temperature and pressure on the I2C LCD screen and displaying as well altitude on an Android App that I made and it worked quite well with the help of this community forum users as well as some YouTube channels, still, I have some ambiguity with some specific lines in the code.

The first one is what are the 2,1,0,4,5,6,7,3 and ,POSITIVE); do?

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); 

2nd, Literally what is everything about it especially what the F between println and "Arduino does?

Serial.println(F("Arduino + BMP280"));

3rd, pretty sure these ones are about calculating pressure and temperature but still don't know we didn't do one as well for the altitude or simply because it doesn't require this kind of line, also what sprintf and "%d.%02u% do specifically .

sprintf(text, "%u.%02u hPa ", (int)(pressure/100), (int)((uint32_t)pressure % 100));

sprintf(text, "%d.%02u%cC  ", (int)temperature, (int)(temperature * 100)%100, 223);

here is the full code :


#include <Wire.h>             
#include <Adafruit_Sensor.h>  
#include <Adafruit_BMP280.h>  
#include <LiquidCrystal_I2C.h>   

#define BMP280_I2C_ADDRESS  0x76

Adafruit_BMP280 bmp280;

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); 

void setup() {
  Serial.begin(9600);

  lcd.begin(16, 2);
  
  Serial.println(F("Arduino + BMP280"));
  
  if (!bmp280.begin(BMP280_I2C_ADDRESS))
  {  
    Serial.println("Could not find a valid BMP280 sensor, check wiring!");
    while (1);
  }

  lcd.setCursor(0, 0);
  lcd.print("Temp:");
  lcd.setCursor(0, 1);
  lcd.print("Pres:");
}

char text[14]; 

void loop()
{
  
  float temperature = bmp280.readTemperature();  
  float pressure    = bmp280.readPressure();     
  float altitude_   = bmp280.readAltitude(1013.25); 


  sprintf(text, "%d.%02u%cC  ", (int)temperature, (int)(temperature * 100)%100, 223);
  lcd.setCursor(5, 0);
  lcd.print(text);

  sprintf(text, "%u.%02u hPa ", (int)(pressure/100), (int)((uint32_t)pressure % 100));
  lcd.setCursor(5, 1);
  lcd.print(text);


  Serial.print("Temperature = ");
  Serial.print(temperature);
  Serial.println(" °C");

  Serial.print("Pressure    = ");
  Serial.print(pressure/100);
  Serial.println(" hPa");

  Serial.print("Approx Altitude = ");
  Serial.print(altitude_);
  Serial.println(" m");
    
  Serial.println();  
  delay(2000);      
  
}

The 0x27 is the I2C address of the LCD, the numbers are the pins of the I2C expander that connect to the RS, EN, D4, D5, D6, D7 pins of the LCD. And Positive is for the backlight polarity. That is called the pin mapping and must match the way that the LCD is wired to the I2C expander.

The F macro.

The sprintf() function.
The format specifiers.

see LiquidCrystal()

see Progmem and F()

i often see code littered with statements clearing the screen, specifying line and columns and strings to prints. the # of these lines make the code hard to read

i prefer to have a single sub-function to display one ore more lines on a display. it's arguments are the strings for each lines, possibly including NULL to not display anything on that line. And I use sprintf() to format the strings

there are a couple advantages to using a single sub-functions. any display issues are fixed by changing lines in one funcitons. those same strings can also be printed to the serial monitor. And of course, can similarly be modified for a different display and interface: OLED, bigger display, ...

snprintf is a safer method to use as it protects against buffer overflow
see C static code analysis

if (snprintf(text, sizeof(text), "%u.%02u hPa ", (int)(pressure/100), (int)((uint32_t)pressure % 100)) > sizeof(text)) {
     // Error buffer too small but no crash here
     Serial.println(F("Increase text size"));
}
1 Like

Why does a I2C-connected LCD still need RS, EN, D4..D7,pins declared ?
The I2C-Bus is used to reduce the number of IO-pins to 2 IO-pins SCL/SDA
or is this some kind of IO-expander that offers some more general purpose IO-pins?
If yes it would be confusing to name these general purpose IO-pins with the pin-names of a non-I2C-LCD.
best regards Stefan

Because different manufacturers use different pin mappings, so the library has to know which I2C expander pins connect to which pins of the LCD. The library has to translate the I2C commands to the right bytes to put out to the I2C expander chip. There are several pin mapping schemes so one has to know the particular mapping to be able to tell the library. Or use the hd44780 library for I2C LCDs. That library is able to figure out the I2C address of the display and the pin mapping, automatically.

Yes, the I2C expander on the LCD backpack receives through I2C and outputs to the LCD. So only SDA and SCL go to the I2C expander, then the I2C expander pins output to the LCD.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.