I'm using the LCD dispaly with the soil moisture sensor and it seems using the following returns an odd set of characters on the first line.
LCD.print("Soil Moisture"); //Print Message on First Row
Although using the following, works perfectly
LCD.print("Water level"); //Print Message on First Row
Also worth noting, its printing correctly to SerialMonitor
Being new to learning Arduino, it feels like a bug to me but I can't be sure.
The whole code is as follows:
// This sketch will use the soil moisture sensor and display the result on the LCD
#include <LiquidCrystal.h>
// include the LCD library
LiquidCrystal LCD(10, 9, 7, 6, 5, 4);
// Set pins as 10,9,7,6,5,4. It might be different for your LCD, check the producer catalog
int potPin = A0; //input pin
int soil = 0;
int percent = 0;
void setup() {
Serial.begin(9600);
LCD.begin(16,2); //Tell Arduino to start your 16 column 2 row LCD
LCD.setCursor(0,0); //Set LCD cursor to upper left corner, column 0, row 0
LCD.print("Soil Moisture"); //Print Message on First Row
delay(1000);
}
void loop() {
// map the values
int soil = analogRead(potPin) ;
soil = constrain(soil, 600, 1023);
soil = map(soil, 600, 1023, 0, 100);
LCD.setCursor(0,1);
//display final numbers
LCD.print(soil);
//print the percent symbol at the end
LCD.print("%");
//wait 0.1 seconds
delay(75);
//wipe the extra characters
LCD.print(" ");
Serial.print("Water level:");
Serial.print(soil);
Serial.println("%");
delay(1000);
}
Related
I'm using Tinkercad, and since it's my first time programming an LCD I just copied the procedure to connect the pins and make it work.
The thing is that it just lights up without displaying anything, I tried both wiring and unwiring the R/W pin but that doesn't work either, nothing will be displayed.
What did I miss? The other functions of the code works normally.
Image of the circuit:
This is the code:
#include <LiquidCrystal.h>
const int pin = 0; // analog pin
float celsius = 0, farhenheit =0; // temperature variables
float millivolts; //Millivolts from the sensor
int sensor;
const int G_LED = 13;
const int Y_LED = 12;
LiquidCrystal lcd(10, 9, 5, 4, 3, 2); // Building the LCD
void setup() {
lcd.begin(16,2);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("C="); // "C=", "F=" and "mV" should be printed
lcd.setCursor(0, 1); // on the LCD in a column
lcd.print("F=");
lcd.setCursor(0, 2);
lcd.print("mV=");
pinMode(G_LED, OUTPUT);
pinMode(Y_LED, OUTPUT);
Serial.begin(9600);
}
void loop() {
sensor = analogRead(pin); // Reading the value from the LM35 sensor using the A0 ingress
millivolts = (sensor / 1023.0) * 5000; // Converting the value in a number that indicates the millivolts
celsius = ((sensor * 0.00488) - 0.5) / 0.01; // Celsius value (10 mV for each degree, 0°=500mV)
farhenheit = celsius * 1.8 + 32; // Fahrenheit value
lcd.setCursor(4, 2); // Set the cursor at the right of "mV="
lcd.print(millivolts); // Print the mV value
lcd.setCursor(4, 0); // Same here for °C and °F
lcd.print(celsius);
lcd.setCursor(4, 1);
Serial.print(farhenheit);
if (millivolts < 700) { // Green LED is on when the temperature is under or equal to 20°
// if (celsius < 20) { // Alternative
analogWrite(G_LED, 255);
analogWrite(Y_LED, 0); }
else {
analogWrite(G_LED, 0);
analogWrite(Y_LED, 255); // Yellow LED is on when the temperature is above of 20°C
}
delay(1000);
}
Fix - I could not find the error, but I suspect it was due to the strange layout of the connections. You also tried to set the cursor to line 3, but the LCD you were using did not have 3 lines, it was a 16x2 LCD.
What I Did - So what I did was I re-did the entire project, I linked up a new LCD, this time with a digital contrast so that it could be dynamically changed. I also made sure to include the sensor you used in your last project. Over-all the project is an Arduino controlling an LCD and outputting the temperature in Fahrenheit and millivolts.
Here is the project link (Tinkercad).
Code:
#include <LiquidCrystal.h>
// Adds the liquid crystal lib
int contrast = 40; // Set the contrast of the LCD
LiquidCrystal lcd (12, 11, 5, 4, 3, 2); // Instantiate the LCD
float fahrenheit;
float millivolts;
void setup ()
{
analogWrite(6, contrast); // Wrjte the contrast to the LCD
lcd.begin(16, 2); // Init the LCD
}
void loop ()
{
int sensor = analogRead(0);
millivolts = (sensor/1023.0)*5000;
fahrenheit = (((sensor*0.00488)-0.5)/0.01)*1.8+32;
lcd.setCursor(0, 0);
lcd.print("Temp(F):");
lcd.setCursor(11, 0);
lcd.print(fahrenheit);
lcd.setCursor(0, 1);
lcd.print("Volts(mV):");
lcd.setCursor(12, 1);
lcd.print(millivolts);
}
Diagram
I am trying to have Arduino output on both LED screen using the LiquidCrystal library, and on Serial Monitor (later to a txt file or something like that).
In my code, I commented out Serial.begin(9600) and then the screen outputs correctly, but as soon as I include it, the serial monitor outputs fine but the screen flips out and outputs gibberish.
I'm fairly new and I know there's something basic I don't know like 9600 should be augmented because so much power is needed maybe?
#include <LiquidCrystal.h>
#include <DHT.h>
#include <math.h>
/*
* Cannot do both screens and log in the console.
* Currently Serial 9600 is commented out, to allow to print on the screen
* Need Fixing
*/
#include "DHT.h"
#define DHTPIN 8 // what digital pin we're connected to
#define DHTTYPE DHT11 // DHT 11
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor
DHT dht(DHTPIN, DHTTYPE);
LiquidCrystal lcd(1, 2, 4, 5, 6, 7);
void setup() {
//Serial.begin(9600);
Serial.println("Temperature Recorder");
dht.begin();
// Now LiquidCrystal led monitor stuff
lcd.begin(16,2);
lcd.setCursor(2,0);
lcd.print("** Wanet **");
delay(1500);
lcd.setCursor(1,1);
lcd.print("Motherfuckers.");
delay(3000);
lcd.clear();
}
void loop() {
// Wait a few seconds between measurements.
delay(1000);
// Reading temperature or humidity takes about 250 milliseconds!
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
float h = dht.readHumidity();
// Read temperature as Celsius (the default)
float t = dht.readTemperature();
// Read temperature as Fahrenheit (isFahrenheit = true)
float f = dht.readTemperature(true);
// Check if any reads failed and exit early (to try again).
if (isnan(h) || isnan(t) || isnan(f)) {
Serial.println("Failed to read from DHT sensor!");
return;
}
// Compute heat index in Fahrenheit (the default)
float hif = dht.computeHeatIndex(f, h);
// Compute heat index in Celsius (isFahreheit = false)
float hic = dht.computeHeatIndex(t, h, false);
Serial.print("Humidity: ");
Serial.print(h);
Serial.print(" %\t");
Serial.print("Temperature: ");
Serial.print(t);
Serial.print(" *C ");
Serial.print(f);
Serial.print(" *F\t");
Serial.print(" | Heat index: ");
Serial.print(hic);
Serial.print(" *C ");
Serial.print(hif);
Serial.println(" *F");
Serial.println("------------------------------------");
// led screen printing
lcd.setCursor(0,0);
lcd.print("Temp: Humidity:");
lcd.setCursor(0,1);
lcd.print(t);
lcd.print(" ");
lcd.print(round(f));
lcd.print("%");
delay(5000);
lcd.clear();
lcd.setCursor(2,0);
lcd.print("The world");
lcd.setCursor(4,1);
lcd.print("OURS");
delay(6000);
}
Cheers
On the docs of Arduino's Serial
Serial
It communicates on digital pins 0 (RX) and 1 (TX) as well as with the computer via USB. Thus, if you use these functions, you cannot also use pins 0 and 1 for digital input or output.
You have two options or you don't use those 2 pins
like this
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);
or if you must have those pin you might consider to use a library like softwareSerial which emulates the serial communication a pair of pin of your choice. but the serial monitor via USB won't work anyway.
Ah right so if you are using LiquidCrystal lcd(6, 5, 4, 3, 2, 1);
You cannot use serial.println(""); too because they conflict on D1 / TX->
so would it then be possible to use both lcd.print(""); and serial.println(""); if we shift to pins
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);
or am I misunderstanding?
Use other Arduino pins for the lcd display. D1 is shared with serial communication.
I want to make the led strips gradually lights up as the flex sensor bends. But I want the led strips start to light up when the flex sensor is 45 degree.
And I want the led strips to be off before 45 degree.
Here is my code which is in Arduino.
const int ledPin = 3; //pin 3 has PWM funtion
const int flexPin = A0; //pin A0 to read analog input
int degree; //save analog value
int sensor;
void setup(){
pinMode(ledPin, OUTPUT); //Set pin 3 as 'output'
Serial.begin(9600); //Begin serial communication
}
void loop(){
sensor = analogRead(flexPin); //Read and save analog value from potentiometer
degree = map(sensor, 460, 850, 45, 90);
Serial.print("analog input: ");
Serial.print(sensor,DEC);
Serial.print(" degrees: ");
Serial.println(degree,DEC);
Serial.print(" ---------------------------------- ");
analogWrite(ledPin, degree); //Send PWM value to led
delay(50); //Small delay
}
but this did not worked, so I tried this one:
const int ledPin = 3; //pin 3 has PWM funtion
const int flexPin = A0; //pin A0 to read analog input
int degree; //save analog value
int sensor;
void setup(){
pinMode(ledPin, OUTPUT); //Set pin 3 as 'output'
Serial.begin(9600); //Begin serial communication
}
void loop(){
sensor = analogRead(flexPin); //Read and save analog value from potentiometer
if(degree<45){
(sensor = 0);
}
degree = map(sensor, 460, 850, 0, 90);
Serial.print("analog input: ");
Serial.print(sensor,DEC);
Serial.print(" degrees: ");
Serial.println(degree,DEC);
Serial.print(" ---------------------------------- ");
analogWrite(ledPin, degree); //Send PWM value to led
delay(50); //Small delay
}
And this did not worked as well. They start lighting up from the 0 degree and gets more as it goes closer to 90 degree. But I want it to be off before 45 degree, start to light up at 45 degree and get more as it gets closer to 90 degree. I will be so thankful if you could help me. I am so exhausted trying and getting to no where.
One problem is that you are setting your sensor to zero when the map function is expecting a value in the range of 460 and 850. It may help to change your default sensor value when below 45 degrees to the lowest value in the expected range (460.)
You could also remove your if condition and shift it later in the program like so:
if (degree < 45) {
digitalWrite(ledPin, LOW);
}
else {
analogWrite(ledPin, degree);
}
It may also be worth noting that the analog read function uses in input between 0 to 255 to determine the duty cycle of the pin. With that said, you could create another variable and use it to map or otherwise change the degree value so it better utilizes this range. i.e:
int freq = map(degree, 0, 90, 0, 255);
I'm trying to display some data to my 16*2 LCD module but there are some random characters being shown. I have some simple code that I used to test my LCD display and it works perfectly. Code:
#include<LiquidCrystal.h>
// initializing pins - RS, E, rest of data pins
LiquidCrystal lcd(1, 2, 4, 5, 6, 7);
void setup() {
lcd.begin(16, 2);
}
void loop() {
lcd.print("Testing"); // thats the top row string
delay(1800);
lcd.setCursor(2, 1); // move to the 2nd row, 1st col
lcd.print("Display this!");
delay(1800);
lcd.clear();
lcd.setCursor(7, 1);
delay(400);
lcd.blink();
lcd.setCursor(6, 1);
delay(400);
lcd.setCursor(5, 1);
delay(400);
lcd.setCursor(4, 1);
delay(400);
lcd.setCursor(3, 1);
delay(400);
lcd.setCursor(2, 1);
delay(400);
lcd.setCursor(1, 1);
delay(400);
lcd.setCursor(0, 1);
lcd.noBlink();
lcd.print("Silly Isn't It?");
lcd.cursor();
delay(1800);
lcd.noCursor();
lcd.clear();
}
However, I have more things on the breadboard now - the LCD, micro SD reader, potentiometer and an LM35 temperature sensor
and this my code:
#include<LiquidCrystal.h>
#include <SD.h>
#include <SPI.h>
////////// LCD
//initializing pins - RS, E, rest of data pins
LiquidCrystal lcd(1, 2, 4, 5, 6, 7);
const int CS_PIN = 10;
const int POW_PIN = 8;
int refreshRate = 2000; // for reading vals
////////// LEDs
int ledPinR = 11;
int ledPinG = 12;
int ledPinY = 13;
////////// LM35
float temp;
int tempPin = A0;
void setup() {
////////// LED
pinMode(ledPinR, OUTPUT);
pinMode(ledPinG, OUTPUT);
pinMode(ledPinY, OUTPUT);
////////// LCD
lcd.begin(16, 2);
lcd.print("please wait..."); //thats the top row string
delay(2000);
lcd.clear();
lcd.blink();
////////// SD
Serial.begin(9600);
Serial.println("\nNow Initializing SD card...");
pinMode(CS_PIN, OUTPUT);
pinMode(POW_PIN, OUTPUT);
digitalWrite(POW_PIN, HIGH);
if(!SD.begin(CS_PIN)){
Serial.println("\nSomething went wrong. Probably card failure, card format, or something else.");
return;
}
Serial.println("\nCard ready!");
File commandFile = SD.open("tempLevels.txt");
if(commandFile){
Serial.println("\nNow Reading Command File...");
while(commandFile.available())
{
refreshRate = commandFile.parseInt();
}
Serial.print("\nTapiwa, the refresh rate is: ");
Serial.print(refreshRate);
Serial.print(" ms");
commandFile.close();
}
else{
Serial.println("Oops! Failing to read command file!");
return;
}
}
void loop() {
////////// LM35
temp = analogRead(tempPin);
float mV = (temp / 1024.0) * 5000;
float tempVal = mV / 10;
Serial.println("\nTemperature is: ");
Serial.println(tempVal);
File dataFile = SD.open("log.csv", FILE_WRITE); // dont know about that .csv format
if(dataFile)
{
dataFile.print("\nTemperature is: ");
dataFile.print(tempVal);
dataFile.println("Deg");
dataFile.close();
Serial.println("\nSaved in DataFile >> Temperature is: ");
Serial.print(tempVal);
}
else
{
Serial.println("DataFile error! Reading not saved");
Serial.println("Could not open log file! Not on SD card!");
}
lcd.print("Temp: ");
lcd.setCursor(2, 1); // 2nd row, 1st col
lcd.print(tempVal);
delay(2000);
lcd.clear();
delay(refreshRate);
}
I'm getting the results in the serial monitor but the LCD displays random characters which resemble encrypted text. Where did I go wrong?
I've looked at at multiple posts on this site and other sites but they are not that useful:
This one made sense but not useful in my case.
This one too!.
And this one
If you take a look at the documentation of Serial, it says:
All Arduino boards have at least one serial port (also known as a UART or USART): Serial. It communicates on digital pins 0 (RX) and 1 (TX) as well as with the computer via USB. Thus, if you use these functions, you cannot also use pins 0 and 1 for digital input or output.
Thus, you should rearrange your scheme so that the LCD doesn't use pin 1.
What a great learning experience my first Arduino project is turning out to be.. I would now like to add a countdown until a sensor reading is taken and displayed, which will repeat infinitely. I've got the sensor and LCD display working fine but my loop is not quite right.. Should I be using a while() of some sort? How do I keep the timer ticking during the big delay between readings?
/*Code for self-watering plant with LCD readout*/
// value for LCD params
char ESC = 0xFE;
// analog input pin that the soil moisture sensor is attached to
const int analogInPin = A1;
// value read from the soil moisture sensor
int sensorValue = 0;
// if the readings from the soil sensor drop below this number, then turn on the pump
int dryValue;
// countdown timer until next soil reading
int timerValue = 9;
void setup() {
pinMode(12, OUTPUT);
// initialize serial communications at 9600 bps:
Serial.begin(9600);
// Set the "dry" value of soil on turning on the device
dryValue = analogRead(analogInPin);
// pause before intialize LCD
delay(2000);
// Initialize LCD module
Serial.write(ESC);
Serial.write(0x41);
Serial.write(ESC);
Serial.write(0x51);
// Set Contrast
Serial.write(ESC);
Serial.write(0x52);
Serial.write(40);
// Set Backlight
Serial.write(ESC);
Serial.write(0x53);
Serial.write(5);
//print the dry value to serial
Serial.print("Dry = " );
Serial.print(dryValue);
Serial.print(" ");
}
void loop(){
watering();
// wait some time (really should be delay(86400000))
delay(10000);
}
void printTimer(){
// Set cursor line 1, column 16
Serial.write(ESC);
Serial.write(0x45);
Serial.write(0x0F);
// print the timer value
Serial.print(timerValue);
timerValue = timerValue - 1;
if(timerValue == 0){
timerValue = 9;
}
}
void printVal(){
// set cursor line 2, column 1
Serial.write(ESC);
Serial.write(0x45);
Serial.write(0x40);
// print the sensor to the serial monitor:
Serial.print("Sensor = " );
Serial.print(sensorValue);
Serial.print(" ");
printTimer();
}
void watering(){
// read the analog in value:
sensorValue = analogRead(analogInPin);
//turn on the water pump for some time if the soil is too dry
if(sensorValue < dryValue){
digitalWrite(12, HIGH);
delay(2000);
digitalWrite(12, LOW);
}
else {
printVal();
}
}
It's actually really simple: Don't delay. Instead, initialize a timer to run a routine whenever it overflows or hits a certain value. Examine the datasheet for the microcontroller used in your Arduino for the specific bits to frob (note that the Arduino libraries use the timer 0 overflow vector for themselves), and the avr-libc documentation for how to denote the ISR(s) for the timer. Your loop() then becomes a big sleep while the timer runs the entire show for you.
I would use a timer library for Arduino like this http://playground.arduino.cc//Code/SimpleTimer
Just download the library, put it in the "libraries" folder in your sketchbook and restart your Arduino IDE to load the new library.
Then your code would look something like this. Basically what it does it updates the screen every loop and then once every 86400000 ms it checks the "watering" function. Just so you know this code would only check the soil once every 24 hours (86400000ms). I think a better solution would be to constantly check the soil and water anytime it is needed. But Im no gardener so maybe there is a reason for just checking once a day.
#include <SimpleTimer.h>
// the timer object
SimpleTimer timer;
void setup() {
Serial.begin(9600);
timer.setInterval(86400000, watering); // how often you would call your watering function is set with the first variable
}
void loop() {
timer.run();
printTimer();
}
void printTimer(){
// Set cursor line 1, column 16
Serial.write(ESC);
Serial.write(0x45);
Serial.write(0x0F);
// print the timer value
Serial.print(timerValue);
timerValue = timerValue - 1;
if(timerValue == 0){
timerValue = 9;
}
}
void printVal(){
// set cursor line 2, column 1
Serial.write(ESC);
Serial.write(0x45);
Serial.write(0x40);
// print the sensor to the serial monitor:
Serial.print("Sensor = " );
Serial.print(sensorValue);
Serial.print(" ");
printTimer();
}
void watering(){
// read the analog in value:
sensorValue = analogRead(analogInPin);
// send it to the display
printVal();
//turn on the water pump for some time if the soil is too dry
if(sensorValue < dryValue){
digitalWrite(12, HIGH);
delay(2000);
digitalWrite(12, LOW);
}
}