LCD I2C dashed character

Hi all,

I'm using an I2C LCD screen and it's outputting a weird character at the end of the line.

My program is not coded to output any cursor.

Please help ...


Hi

Most likely cause is that you are using println instead of print. The LCD is not capable of displaying the carriage return and newline characters.

Hi,
As we are not soothsayers, how about posting the code?

/*
Update from Code V4 is that this code has the control using the keypad.
The user is able to change between functions by pressing different buttons on the keypad
Use of functions to move the linear actuators.
We only want it on when the sun elevation is greater than 5 and azimuth must be from dawn to dusk.
*/

#include <SolarPosition.h>    //Sun position library to get sun azimuth and elevation angle
#include <DS3232RTC.h>        //For RTC
#include <Wire.h>
#include <Adafruit_Sensor.h>  //For IMU
#include <Adafruit_BNO055.h>  //For IMU
#include <utility/imumaths.h> //For IMU maths
#include <Keypad.h>           //For Keypad
#include <Servo.h>            //For Servo Motor
#include <LiquidCrystal_I2C.h> //For LCD I2C

// Set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 16, 2);

//Set the IMU address
Adafruit_BNO055 myIMU = Adafruit_BNO055(-1, 0x28);

// number of decimal digits to print
uint8_t digits = 3;

//Initialising Keypad
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
char keys[ROWS][COLS] = {
  {'1','U','3','S'},
  {'L','5','R','C'},
  {'7','D','9','T'},
  {'X','Y','Z','E'}
};
byte rowPins[ROWS] = {38,36,34,32}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {30,28,26,24}; //connect to the column pinouts of the keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );


//Initialising Boolean code; these are loops that will run only once in the code
boolean tracking = false;
boolean captureTarget = false;
boolean setTarget = false;
boolean timeToStop = false;
boolean orientationDisplay = false;

//Servo Motor Declaration
Servo myServo;  // create servo object to control a servo
int angle = 0;
boolean homePos = false;
boolean runServo = false;


//Linear actuator variable declaration
int speedLA = 255;
const int ENA_PIN = 5; // the Arduino pin connected to the EN1 pin L298N
const int IN1_PIN = 6; // the Arduino pin connected to the IN1 pin L298N
const int IN2_PIN = 7; // the Arduino pin connected to the IN2 pin L298N

const int ENB_PIN = 10; // the Arduino pin connected to the EN1 pin L298N
const int IN3_PIN = 9; // the Arduino pin connected to the IN3 pin L298N
const int IN4_PIN = 8; // the Arduino pin connected to the IN4 pin L298N

const int LedAzt = 3;
const int LedEle = 4;

volatile float sunEle;
volatile float sunAzt;

float TargetAzimuth;
float TargetElevation;
//these need to be calculated from the sun and target azimuth and elevation angles
float DN_Azimuth;   //destination normal azimuth angle
float DN_Elevation; //destination normal elevation angle

SolarPosition Loughborough(52.76336662631451, -1.2481144519918814);  // Loughborough, UK


bool eleDone = false;
bool aztDone = false;


void setup() {
 
  //Serial.begin(115200);
  //Servo Motor Set Up
   myServo.attach(12);  // attache the servo on pin 9 to the servo object

  //Led Set Up
  pinMode(LedAzt, OUTPUT);
  pinMode(LedEle, OUTPUT);
  SolarPosition::setTimeProvider(RTC.get);      //Using the RTC to get the current time

//********LINEAR ACTUATOR SET UP*********
  pinMode(ENA_PIN, OUTPUT);
  pinMode(IN1_PIN, OUTPUT);
  pinMode(IN2_PIN, OUTPUT);

  pinMode(IN3_PIN, OUTPUT);
  pinMode(IN4_PIN, OUTPUT);
  pinMode(ENB_PIN, OUTPUT);
  
  analogWrite(ENA_PIN, speedLA);
  analogWrite(ENB_PIN, speedLA);
 
//*******IMU SETUP CODE********************************
  //Serial.println("Starting IMU....."); //Serial.println("");

  /* Initialise the sensor */
  if(!myIMU.begin())
  {
    /* There was a problem detecting the BNO055 ... check your connections */
    //Serial.print("Ooops, no IMU detected ... Check your wiring or I2C ADDR!");
    while(1);
  }

  delay(1000);
  myIMU.setExtCrystalUse(true);
  ////Serial.println("Calibration status values: 0=uncalibrated, 3=fully calibrated");
  
    //*******IMU calibration code***************
  uint8_t system, gyro, accel, mag = 0;
  myIMU.getCalibration(&system, &gyro, &accel, &mag);
  //Serial.println("");
  //Serial.print("CALIBRATION: Sys=");
  //Serial.print(system, DEC);
  //Serial.print(" Gyro=");
  //Serial.print(gyro, DEC);
  //Serial.print(" Accel=");
  //Serial.print(accel, DEC);
  //Serial.print(" Mag=");
  //Serial.println(mag, DEC);
  //Serial.print("");



//******LCD Set Up*****************************
  lcd.init();
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Press A to Start");
//**********************************************************

}

void SetTargetProgram(){
  
  char key = keypad.getKey();
   if(setTarget == false){
    //Serial.println("Set Target Program");
    setTarget = true;
   }
   
    if(key == 'L'){
      // extend the azimuth actuator
      ExtendAzimuth(); 
      aztDone = false;
      //Serial.println("Extending Azimuth"); 
      
    }
    if (key == 'R'){
      // retract the azimuth actuator
     RetractAzimuth(); 
     aztDone = false;
     //Serial.println("Retracting Azimuth");  
      
    }
    if (key == 'X'){
      // stop the azimuth actuator
      StopAzimuth();
      //Serial.println("Stopped Azimuth");
      aztDone = true;
  
    }
    if(key == 'D'){
      // extend the ELEVATION actuator
      ExtendElevation();
      eleDone = false;
      //Serial.println("Extending Elevation");
      
    }
    if (key == 'U'){
      // retract the ELEVATION actuator
      RetractElevation(); 
      eleDone = false;  
      //Serial.println("Retracting Elevation");
      
    }
    if (key == 'Y'){
      // stop the ELEVATION actuator
      StopElevation();
      //Serial.println("Stopped Elevation"); 
      eleDone = true;
      
    }
} 

void CaptureTarget(){
  float Nazt, Nele;
  //Serial.println("");
  //Serial.println("Capture Target!");
  
  imu::Vector<3> destinationNormal = myIMU.getVector(Adafruit_BNO055::VECTOR_EULER);
  //Calculating the destination normal
  Nazt = destinationNormal.x();         //In this iteration, the mirror normal is pointing towards the bisector when the capture target button is pressed
  Nele = 90-destinationNormal.z();   //Therefore, we need to calculate the target position from the destination normal.
  //Serial.print("Current Azt: ");
  //Serial.print(Nazt); 
  //Serial.print("\t\tCurrent Ele: ");
  //Serial.println(Nele);
  
  SolarPosition(Loughborough.getSolarPosition(), digits);   //this gets the surrent sun position in real time
  TargetAzimuth =(2*Nazt) -  sunAzt;
  TargetElevation =(2*Nele) - sunEle;

  //Serial.print("Target Azt : ");
  //Serial.print(TargetAzimuth);
  //Serial.print("\t\tTarget Ele: ");
  //Serial.println(TargetElevation);
}
 
void SolarPosition(SolarPosition_t pos, int numDigits){
  
  //*******Calculating the SUN azimuth and elevation angle********
  sunEle = pos.elevation;  //Sun Elevation Angle in Degrees
  sunAzt = pos.azimuth;     //Sun Azimuth Angle in Degrees
  //Serial.print("Sun Azimuth: ");
  //Serial.print(sunAzt, numDigits);
  //Serial.print(" deg");
  //Serial.print("\tSun Elevation: ");
  //Serial.print(sunEle, numDigits);
  //Serial.println(" deg   ");

}

void DestinationNormal(){
 //********CODE to calculate the Destination Azimuth and Elevation******************
  DN_Azimuth = (sunAzt + TargetAzimuth ) / 2 ;          //Midpoint azimuth
  DN_Elevation =(sunEle + TargetElevation) / 2 ;        //Midpoint Elevation
}
void moveServo(){
    if(homePos == false){
    for (angle = 0; angle <= 180; angle += 1) { // goes from 0 degrees to 180 degrees
      // in steps of 1 degree
      myServo.write(angle);              // tell servo to go to angleition in variable 'angle'
      delay(20);                       // waits 15ms for the servo to reach the angleition
    }
    for (angle = 180; angle >= 0; angle -= 1) { // goes from 180 degrees to 0 degrees
      myServo.write(angle);              // tell servo to go to angleition in variable 'angle'
      delay(20);                       // waits 15ms for the servo to reach the angleition
    }
  homePos = true;
  } 
  myServo.write(94);
}

void HeliostatTracking(){
   //Serial.println("Heliostat Tracking Program");
   SolarPosition(Loughborough.getSolarPosition(), digits);       //Get the Sun Azimuth and Elevation angles and return the destination normal angles
   DestinationNormal();
   
  //******CODE to find the CURRENT Azimuth and Elevation angles of the mirror********
  float CN_Azimuth, CN_Elevation;     //euler degrees of current normal 
  imu::Vector<3> CurrentNormal = myIMU.getVector(Adafruit_BNO055::VECTOR_EULER);
  
  
  //Serial.print("Current Azt: ");
  //Serial.print(CN_Azimuth = CurrentNormal.x());     //Current Normal Azimuth angle, x euler angle in degress
  //Serial.print("\t\tEle: ");
  //Serial.println(CN_Elevation = 90 - CurrentNormal.z());     //Current Normal Elevation angle, z euler angle in degress; We are changing the elevation angle plane to be the plane of the mirror
  //Serial.print("Destination: ");
  //Serial.print(DN_Azimuth); 
  //Serial.print("\t\tEle ");
  //Serial.println(DN_Elevation);
   
  //*******Now we need to move the linear actuators accordingly***************************
  
  if (sunEle >4 && sunAzt > 110 && sunAzt < 250){ //perform the following code only when the sun position is high enough in the sky
     
    //Serial.println("");
    char keyTrack = keypad.getKey(); 
    if(keyTrack == 'E'){
          timeToStop = true;
        }
        
      //the reason the angles are rounded is because it is very difficult for the Destination normal value (till 2 decimal places) to be equal to the Current Normal Value
      //this gives us an error +/- 1 degree.
      if(round(DN_Azimuth) > round(CN_Azimuth)){    //if the Destination Azimuth is greater than Current Azimuth retract the azimuth linear actuator
         //retract Azimuth linear actuator
         RetractAzimuth();
         digitalWrite(LedAzt, HIGH);     //LED is lit up to indicate that the destination azimuth is greater than the current azimuth    
      }
      else if (round(DN_Azimuth) < round(CN_Azimuth)){
          //extend Azimuth linear actuator
          ExtendAzimuth();
          analogWrite(LedAzt, 50);         //LED brightness reduces to indicate that the destination azimuth is less than the current azimuth
               
      }
      else{
        //stop azimuth linear actuator and pause program for 2 seconds for example. Experimentally determine later if you want to increase the time. THis causes the sun to move enough for the next reading.
        StopAzimuth();
        digitalWrite(LedAzt, LOW);            //LED is turned off indicate that the destination azimuth is equal to the current azimuth and hence the mirror has reached the correct orientation
        delay(200);
      }
    
      //Now, we need to move the elevation linear actuator accordingly
      if(round(DN_Elevation) > round(CN_Elevation)){    //if the Destination Elevation is greater than Current Elevation retract the elevation linear actuator
          //retract elevation linear actuator
          RetractElevation();          
          digitalWrite(LedEle, HIGH);          //LED is lit up to indicate that the destination elevation is greater than the current elevation
      }
      else if (round(DN_Elevation) < round(CN_Elevation)){
        //extend elevation linear actuator
        ExtendElevation();
        analogWrite(LedEle, 50);      //LED brightness reduces to indicate that the destination elevation is less than the current elevation
      }
      else{
        //stop elevation linear actuator and pause program for 2 milliseconds for example. Experimentally determine later if you want to increase the time. THis causes the sun to move enough for the next reading.
        StopElevation();
        digitalWrite(LedEle, LOW);      //LED is turned off indicating that the destination elevation is equal to the current elevation and hence the mirror has reached the correct elevation angle
        delay(200);
      }
      
      if(round(DN_Azimuth) == round(CN_Azimuth) && round(DN_Elevation) == round(CN_Elevation)){
       
        //Serial.print("Error Azimuth = "); //Serial.print(abs(DN_Azimuth-CN_Azimuth));
        //Serial.print("\t\tError Elevation = "); //Serial.println(abs(DN_Elevation-CN_Elevation));
        //Serial.println("");        
        
        if(keyTrack == 'E'){
          timeToStop = true;
        }
        delay(30000);
      }    
   }
  delay(100);
}

void ExtendAzimuth(){
  digitalWrite(IN1_PIN, HIGH);
  digitalWrite(IN2_PIN, LOW);
}

void RetractAzimuth(){
  digitalWrite(IN1_PIN, LOW);
  digitalWrite(IN2_PIN, HIGH);
}

void StopAzimuth(){
  digitalWrite(IN1_PIN, LOW);
  digitalWrite(IN2_PIN, LOW);
}

void ExtendElevation(){
  digitalWrite(IN3_PIN, HIGH);
  digitalWrite(IN4_PIN, LOW);
}

void RetractElevation(){
  digitalWrite(IN3_PIN, LOW);
  digitalWrite(IN4_PIN, HIGH);
}

void StopElevation(){
  digitalWrite(IN3_PIN, LOW);
  digitalWrite(IN4_PIN, LOW);
}

void loop() {
  
  if(orientationDisplay == false){
    //float Mirror_Azt, Mirror_Ele;     //euler degrees of current normal 
    int updateScreen;
    imu::Vector<3> mirrorOrientation = myIMU.getVector(Adafruit_BNO055::VECTOR_EULER);
    if(updateScreen = millis() + 1000){
  //The display message is on the second row (COLUMN X ROW)
    lcd.setCursor(0,1);
    lcd.print("A:");
    lcd.setCursor(2,1);
    lcd.print(round(mirrorOrientation.x()));     //Display Azimuth angle to 2 decimal places
    lcd.setCursor(8,1);
    lcd.print("E: ");
    lcd.setCursor(10,1);
    lcd.println(round(90 - mirrorOrientation.z())); //Display elevation angle to 2 decimal places
    updateScreen = millis();
    }
  }

  
  //****Code to callibrate the IMU by rotating the servo motor 180 degrees*****
  //This code will run only once on start up to callibrate the IMU
  if(runServo == false){
    moveServo();
    runServo = true;
  }

  //****Code for the Keypad Control: User Interface****************
  char keyPress = keypad.getKey(); 
  
  while(keyPress == 'S'){ //Go to Set Target Program    
   if(setTarget == false){
    //Serial.println("Set Target Program");
    setTarget = true;
      
   lcd.clear();
   lcd.setCursor(0,0);
   lcd.print("Set Target");
   
   }
   SetTargetProgram();
   if ((aztDone==true) && (eleDone==true)){
     captureTarget = false; 
     keyPress = '1'; 
     timeToStop = false;    
   }
  }
   
  eleDone = false;
  aztDone = false; 
  timeToStop = false; 
  orientationDisplay = false;
  
  if(keyPress == 'C' && captureTarget == false){  //Go to Capture Target Program
   lcd.clear();
   lcd.setCursor(0,0);
   lcd.print("Target Captured");
   
   CaptureTarget();
   orientationDisplay = true;
   lcd.setCursor(0,1);
   lcd.print(TargetAzimuth,1);
   lcd.setCursor(8,1);
   lcd.print(TargetElevation,1);
  
      
      captureTarget = true;
      setTarget = false;
      timeToStop = false; 
  }
  if(keyPress == 'T'){
       lcd.clear();
       lcd.setCursor(0,0);
       lcd.print("Tracking Mode");
  }
  while(keyPress == 'T'){    //Start Heliostat tracking program    
      if(tracking == true){
       lcd.clear();
       lcd.setCursor(0,0);
       lcd.print("Tracking Mode");
      //Serial.println("Start Tracking Button Pressed");
      tracking = false;
      orientationDisplay = false;
       
      }
           
    HeliostatTracking();
      if(timeToStop == true){
        keyPress = '1';
        StopAzimuth();
        StopElevation();
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("System Paused");
        //Serial.println("System Paused");
      }
  }
    
  if(keyPress == 'Z'){
    //Serial.println("Callibrating System...");
    homePos = false;
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Callibrating...");
    moveServo();   
  }
  
 delay(50);
}

No I'm using lcd.print()

lcd.println(round(90 - mirrorOrientation.z()));

That just saved my life. THANK YOU

Hi
You are using 15 lcd.print.

Hi,

what microcontroller are you using in this project? Arduino mega?

Point was, he was actually using lcd.println() what automatically generates this consequence.

is this relevant in any manner? :thinking:

Hi @Paul_B

This question has nothing to do with the lcd.print question.
I asked because I'm compiling the code he used and I intend to load it on the microcontroller.

Thanks

Likely a Mega, going by the pin numbers for the keypad. I'm not aware of any other boards that have pin numbers in the 30's.

OK then but the actual problem is already solved. :grin:

I also saw the pin numbers and thought about mega, but would like confirmation from the OP.

Hi @sroy10
when compiling your code it reported an error.
"'RTC' was not declared in this scope"

I didn't find the creation of the RTC instance.

Ex: DS3232RTC RTC;

Noticed the same when I tried to compile.

Also likely a mistake:

    if (updateScreen = millis() + 1000) {

Hi,
right.

@david_2018
Yeah... have you heard of Arduino Due? :rofl::rofl::wink:

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