LCD and Serial printout do not match

The full code is pasted at the bottom of my post (I do not have upload privileges yet).


Hi All,
I'm building a light sensor using the Adafruit TSL2591 HDR sensor, and I am encountering a problem where the the output of a single variable, lux, displays differently in the serial monitor (about 222) and the LCD printout (about 866). As far as I can tell, there is no opportunity for the variable to change between the two print statements:

void loop() {
  lcd.setCursor(4, 1);
  uint16_t lux = read();
  lcd.print(lux);
  Serial.print(F("Lux: ")); Serial.println(lux, 6);
  delay(1000);
}

I am (completely) new to the Arduino IDE, so I might be missing something obvious. My guess was that there is some difference in the variable types that the Serial.print() and LiquidCrystal.print() accept, but that does not appear to be the case in the reference documents (Docs: Serial.print(), LiquidCrystal.print()).

I also found this post that describes a similar problem, which is why I added delay(1000) to the loop, but that did not help.

Does anyone have an idea of why this might be happening?


Full Code:

#include <LiquidCrystal.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_TSL2591.h"

const int rs = 7, en = 8, d4 = 9, d5 = 10, d6 = 11, d7 = 12;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

Adafruit_TSL2591 tsl = Adafruit_TSL2591(2591); 


void configureSensor(void) {
  tsl.setGain(TSL2591_GAIN_MED);
  tsl.setTiming(TSL2591_INTEGRATIONTIME_300MS);
}

uint32_t read(void) {
  uint32_t lum = tsl.getFullLuminosity();
  uint16_t ir = lum >> 16;
  uint16_t full = lum & 0xFFFF;
  uint32_t lux = tsl.calculateLux(full, ir);
  return lux;
}

void setup() {
  lcd.begin(16, 2);
  lcd.print("Lux:");

  configureSensor();
  Serial.begin(9600);
}

void loop() {
  lcd.setCursor(4, 1);
  uint16_t lux = read();
  lcd.print(lux);
  Serial.print(F("Lux: ")); Serial.println(lux, 6);
  delay(1000);
}

Welcome to the forum

It is better to post code than to attach it so don't worry and thank you for using code tags

To post images etc. you need trust level 1, you can get there by:

  • Entering at least 5 topics
  • Reading at least 30 posts
  • Spend a total of 10 minutes reading posts

Users at trust level 1 can...

  • Use all core Discourse functions; all new user restrictions are removed
  • Send PMs
  • Upload images and attachments
Serial.println(lux, 6);

Why the second parameter when lux is an integer ?

3 Likes

Off the cuff observations:

Imagine the first time through the loop, the value of lux is, say, 1234. The code will print 1234 to the LCD.

Now image the second time through the loop, the value of lux is say, 99. The code will print 99 to the LCD... but will only overwrite the first two characters of 1234. So you'll see 9934 on the LCD.

Also, I notice that the read function returns a uint32_t type. Which is then stuffed into a uint16_t type.

1 Like

Good catch! So it prints it in base 6. And 86 base 10 is 222 base 6.

1 Like

:sweat_smile:
A relic of the code I copied from the 'tsl2591' example. And, of course, that was the problem.

For future people looking at this, the Serial.println() accepts a second argument for formatting. When the first argument is an integer, the second argument specifies the base. So I was printing to Serial in base6.

Thank you so much!!!

This does, however, beg the question of why the example code is printing in base6...

Serial.print(F("Lux: ")); Serial.println(tsl.calculateLux(full, ir), 6);

EDIT: the example code uses Adafruit_TSL2591.calculateLux(), which returns a float. Since the first argument in the Serial.println is a float, the number 6 specifies the number of decimal places.


/* TSL2591 Digital Light Sensor */
/* Dynamic Range: 600M:1 */
/* Maximum Lux: 88K */

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_TSL2591.h"

// Example for demonstrating the TSL2591 library - public domain!

// connect SCL to I2C Clock
// connect SDA to I2C Data
// connect Vin to 3.3-5V DC
// connect GROUND to common ground

Adafruit_TSL2591 tsl = Adafruit_TSL2591(2591); // pass in a number for the sensor identifier (for your use later)

/**************************************************************************/
/*
    Displays some basic information on this sensor from the unified
    sensor API sensor_t type (see Adafruit_Sensor for more information)
*/
/**************************************************************************/
void displaySensorDetails(void)
{
  sensor_t sensor;
  tsl.getSensor(&sensor);
  Serial.println(F("------------------------------------"));
  Serial.print  (F("Sensor:       ")); Serial.println(sensor.name);
  Serial.print  (F("Driver Ver:   ")); Serial.println(sensor.version);
  Serial.print  (F("Unique ID:    ")); Serial.println(sensor.sensor_id);
  Serial.print  (F("Max Value:    ")); Serial.print(sensor.max_value); Serial.println(F(" lux"));
  Serial.print  (F("Min Value:    ")); Serial.print(sensor.min_value); Serial.println(F(" lux"));
  Serial.print  (F("Resolution:   ")); Serial.print(sensor.resolution, 4); Serial.println(F(" lux"));  
  Serial.println(F("------------------------------------"));
  Serial.println(F(""));
  delay(500);
}

/**************************************************************************/
/*
    Configures the gain and integration time for the TSL2591
*/
/**************************************************************************/
void configureSensor(void)
{
  // You can change the gain on the fly, to adapt to brighter/dimmer light situations
  //tsl.setGain(TSL2591_GAIN_LOW);    // 1x gain (bright light)
  tsl.setGain(TSL2591_GAIN_MED);      // 25x gain
  //tsl.setGain(TSL2591_GAIN_HIGH);   // 428x gain
  
  // Changing the integration time gives you a longer time over which to sense light
  // longer timelines are slower, but are good in very low light situtations!
  //tsl.setTiming(TSL2591_INTEGRATIONTIME_100MS);  // shortest integration time (bright light)
  // tsl.setTiming(TSL2591_INTEGRATIONTIME_200MS);
  tsl.setTiming(TSL2591_INTEGRATIONTIME_300MS);
  // tsl.setTiming(TSL2591_INTEGRATIONTIME_400MS);
  // tsl.setTiming(TSL2591_INTEGRATIONTIME_500MS);
  // tsl.setTiming(TSL2591_INTEGRATIONTIME_600MS);  // longest integration time (dim light)

  /* Display the gain and integration time for reference sake */  
  Serial.println(F("------------------------------------"));
  Serial.print  (F("Gain:         "));
  tsl2591Gain_t gain = tsl.getGain();
  switch(gain)
  {
    case TSL2591_GAIN_LOW:
      Serial.println(F("1x (Low)"));
      break;
    case TSL2591_GAIN_MED:
      Serial.println(F("25x (Medium)"));
      break;
    case TSL2591_GAIN_HIGH:
      Serial.println(F("428x (High)"));
      break;
    case TSL2591_GAIN_MAX:
      Serial.println(F("9876x (Max)"));
      break;
  }
  Serial.print  (F("Timing:       "));
  Serial.print((tsl.getTiming() + 1) * 100, DEC); 
  Serial.println(F(" ms"));
  Serial.println(F("------------------------------------"));
  Serial.println(F(""));
}


/**************************************************************************/
/*
    Program entry point for the Arduino sketch
*/
/**************************************************************************/
void setup(void) 
{
  Serial.begin(9600);
  
  Serial.println(F("Starting Adafruit TSL2591 Test!"));
  
  if (tsl.begin()) 
  {
    Serial.println(F("Found a TSL2591 sensor"));
  } 
  else 
  {
    Serial.println(F("No sensor found ... check your wiring?"));
    while (1);
  }
    
  /* Display some basic information on this sensor */
  displaySensorDetails();
  
  /* Configure the sensor */
  configureSensor();

  // Now we're ready to get readings ... move on to loop()!
}

/**************************************************************************/
/*
    Shows how to perform a basic read on visible, full spectrum or
    infrared light (returns raw 16-bit ADC values)
*/
/**************************************************************************/
void simpleRead(void)
{
  // Simple data read example. Just read the infrared, fullspecrtrum diode 
  // or 'visible' (difference between the two) channels.
  // This can take 100-600 milliseconds! Uncomment whichever of the following you want to read
  uint16_t x = tsl.getLuminosity(TSL2591_VISIBLE);
  //uint16_t x = tsl.getLuminosity(TSL2591_FULLSPECTRUM);
  //uint16_t x = tsl.getLuminosity(TSL2591_INFRARED);

  Serial.print(F("[ ")); Serial.print(millis()); Serial.print(F(" ms ] "));
  Serial.print(F("Luminosity: "));
  Serial.println(x, DEC);
}

/**************************************************************************/
/*
    Show how to read IR and Full Spectrum at once and convert to lux
*/
/**************************************************************************/
void advancedRead(void)
{
  // More advanced data read example. Read 32 bits with top 16 bits IR, bottom 16 bits full spectrum
  // That way you can do whatever math and comparisons you want!
  uint32_t lum = tsl.getFullLuminosity();
  uint16_t ir, full;
  ir = lum >> 16;
  full = lum & 0xFFFF;
  Serial.print(F("[ ")); Serial.print(millis()); Serial.print(F(" ms ] "));
  Serial.print(F("IR: ")); Serial.print(ir);  Serial.print(F("  "));
  Serial.print(F("Full: ")); Serial.print(full); Serial.print(F("  "));
  Serial.print(F("Visible: ")); Serial.print(full - ir); Serial.print(F("  "));
  Serial.print(F("Lux: ")); Serial.println(tsl.calculateLux(full, ir), 6);
}

/**************************************************************************/
/*
    Performs a read using the Adafruit Unified Sensor API.
*/
/**************************************************************************/
void unifiedSensorAPIRead(void)
{
  /* Get a new sensor event */ 
  sensors_event_t event;
  tsl.getEvent(&event);
 
  /* Display the results (light is measured in lux) */
  Serial.print(F("[ ")); Serial.print(event.timestamp); Serial.print(F(" ms ] "));
  if ((event.light == 0) |
      (event.light > 4294966000.0) | 
      (event.light <-4294966000.0))
  {
    /* If event.light = 0 lux the sensor is probably saturated */
    /* and no reliable data could be generated! */
    /* if event.light is +/- 4294967040 there was a float over/underflow */
    Serial.println(F("Invalid data (adjust gain or timing)"));
  }
  else
  {
    Serial.print(event.light); Serial.println(F(" lux"));
  }
}


/**************************************************************************/
/*
    Arduino loop function, called once 'setup' is complete (your own code
    should go here)
*/
/**************************************************************************/
void loop(void) 
{ 
  //simpleRead(); 
  advancedRead();
  // unifiedSensorAPIRead();
  
  delay(500);
}

I'll bet calculateLux returns a float.

Edit: yep. From Adafruit_TSL2591.h:

float calculateLux(uint16_t ch0, uint16_t ch1);
1 Like

Is it printing in base 6 or is it printing a float with 6 decimal places ?

You've got it. In the example the 6 is representing the number of decimal places and in my code it was representing base6. I edited my response above to reflect this.

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