I'm writing some code for a homework assignment, and part of the assignment is to have a 16x2 LCD display a clock that shows how long the arduino has been on for. This clock needs to run off a timer interrupt. I have gotten that part working, but the second part of the assignment is to have another interrupt (an external button as the signal) that will reset the clock to all 0's. Currently the ISR doesn't seem to do anything. Any ideas?
#include <LiquidCrystal.h>
#include <TimerOne.h>
int buttonPin = 2;
LiquidCrystal lcd(12, 11, 6, 5, 4, 3);
int secs, tens, minutes, tenminutes, hours, tenhours;
volatile long counter = 0;
void setup() {
Timer1.initialize(100000);
Timer1.attachInterrupt(timerISR);
pinMode(buttonPin, INPUT_PULLUP);
attachInterrupt(0, buttonPressISR, CHANGE);
lcd.begin(16, 2);
lcd.setCursor(0,1);
lcd.print("0");
lcd.setCursor(1,1);
lcd.print("0");
lcd.setCursor(2, 1);
lcd.print(":");
lcd.setCursor(3,1);
lcd.print("0");
lcd.setCursor(4,1);
lcd.print("0");
lcd.setCursor(5, 1);
lcd.print(":");
lcd.setCursor(6,1);
lcd.print("0");
lcd.setCursor(7,1);
lcd.print("0");
}
void loop() {
secs = (counter/10) % 10;
tens = (counter/100) % 6;
minutes = (counter/600) %10;
tenminutes = (counter/6000) %6;
hours = (counter/36000) %10;
tenhours = (counter/360000) %10;
lcd.setCursor(7, 1);
lcd.print(secs);
lcd.setCursor(6,1);
lcd.print(tens);
lcd.setCursor(4, 1);
lcd.print(minutes);
lcd.setCursor(3, 1);
lcd.print(tenminutes);
lcd.setCursor(1, 1);
lcd.print(hours);
lcd.setCursor(0, 1);
lcd.print(tenhours);
}
void buttonPressISR() {
counter = 0;
}
void timerISR() {
counter++;
}
You know there is an Arduino Stack Exchange beta site for Arduino questions?
I can't see any obvious errors in the code. Are you aware that interrupt pin 0 on the code is actually the digital pin 2 on the Arduino?
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'm working on a project for an automatic Malteser (or similar product) dispenser and I got the code to work, but after leaving it it for a bit, the screen played up and it won't work properly. The LED also is always on and it can seem to move on from the Setup
I have tried:
searching the code for faults
checking the wiring
redoing the wiring in case i missed something
Code:
#include <Servo.h>
#include <DS3231.h>
#include <Wire.h>
#include <LiquidCrystal.h>
DS3231 Clock;
bool Century = false;
bool h12;
bool PM;
byte ADay, AHour, AMinute, ASecond, ABits;
bool ADy, A12h, Apm;
int second, minute, hour, date, month, year, temp;
int button = 8;
int maltesersEaten = 0;
int lastEatenSe = 0;
int lastEatenMi = 0;
int lastEatenHo = 0;
int lastEatenDa = 0;
int lastEatenMo = 0;
int lastEatenYe = 0;
bool eat;
int ledPin = 10;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
Servo myServo;
byte degree[8] = {
B00100,
B01010,
B00100,
B00000,
B00000,
B00000,
B00000,
};
void setup() {
**lcd.createChar(0, degree);
lcd.begin(16, 2);
// Print a message to the LCD
lcd.print("INITIALIZING");
// Start the I2C interface
Wire.begin();
// Start the serial interface
Serial.begin(9600);
pinMode(button, INPUT);
myServo.attach(9);**
myServo.write(10);
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, HIGH);
delay(100);
digitalWrite(ledPin, LOW);
delay(1000);
lcd.clear();
}
void getData() {
second = Clock.getSecond();
minute = Clock.getMinute();
hour = Clock.getHour(h12, PM);
date = Clock.getDate();
month = Clock.getMonth(Century), DEC;
year = Clock.getYear();
temp = Clock.getTemperature();
lcd.setCursor(0, 0);
lcd.print(hour);
lcd.print(":");
lcd.print(minute);
lcd.print(":");
lcd.print(second);
lcd.setCursor(0, 1);
lcd.print(date);
lcd.print(",");
lcd.print(month);
lcd.print(",");
lcd.print(year);
lcd.setCursor(9, 0);
lcd.print(temp);
lcd.write(byte(0));
lcd.print("C");
lcd.setCursor(9,1);
lcd.print("ATE:");
lcd.print(maltesersEaten);
}
void mE() {
maltesersEaten = (maltesersEaten + 1);
lastEatenSe = second;
lastEatenMi = minute;
lastEatenHo = hour;
lastEatenDa = date;
lastEatenMo = month;
lastEatenYe = year;
}
void check() {
lcd.clear();
lcd.print("-Last Malteser-");
delay(500);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(hour);
lcd.print(":");
lcd.print(minute);
lcd.print(":");
lcd.print(second);
lcd.setCursor(0, 1);
lcd.print("Eaten: ");
lcd.print(maltesersEaten);
delay(5000);
lcd.clear();
}
void loop() {
if (digitalRead(button) == LOW) {
digitalWrite(ledPin, HIGH);
myServo.write(170);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("---- Have A ----");
lcd.setCursor(0, 1);
lcd.print(" Malteser ");
delay(5000);
myServo.write(10);
lcd.clear();
check();
mE();
digitalWrite(ledPin, LOW);
}
else if (digitalRead(button) == HIGH) {
getData();
}
}
The desired effect would be the screen produces a message, the LED flashes, then it shows the time, date and temperature of the room, as well as how many Maltesers have been eaten. then when the button is pressed, the servo moves, the LED turns on and the LCD changes through a few different screens, then it returns to the time, date, temp, and number of Maltesers eaten. However the actual result is that the LED turns on permanently, the LCD produces two solid blocks and nothing else, and the servo goes limp, when I press the button nothing changes. I think the problem is in the setup if that is of nay help.
In the program you call the function: check(). In there is a five second delay and in the loop there is another 5s delay. Could it be that you always press the button when the delay is on. Then the program would not notice that the button was pressed and continues with the loop again. This would also explain why the led won't turn off because it is turned on again right away.
To test if this is the case just hold the button down for at least 10s and sea if it works.
If this is the case, to fix this problem try working with an interrupt.
See documentation here: https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/
So, i was trying to make the cursor move on an lcd with a joystick but,
I type this:
int iniCursorX=6;
int iniCursorY=2;
#include <LiquidCrystal.h> //lcd
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); //setting up lcd
// Arduino pin numbers
const int SW_pin = 6; // digital pin connected to switch output
const int X_pin = 0; // analog pin connected to X output
int Y_pin = 1; // analog pin connected to Y output
void setup() {
pinMode(SW_pin, INPUT);
digitalWrite(SW_pin, HIGH);
lcd.print("Hello!");
analogWrite(Y_pin, INPUT);
}
void loop() {
lcd.setCursor(iniCursorX,iniCursorY);
lcd.cursor();
delay(200);
lcd.noCursor();
delay(200);
if(Y_pin=0, iniCursorX >= 2) {
int j=iniCursorX;
lcd.setCursor(j-1);
}
}
Then I Get this:
no matching function for call to LiquidCrystal::setCursor(int)
At the bottom of your code you have:
lcd.setCursor(j-1);
but lcd.setCursor takes two arguments.
Change it to something like lcd.setCursor(0, j-1); or anything you need.
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.
I made a simple lcd display example from this guide.
After it worked I'd like to play with it. I wrote a program to count fps of this screen. The big question is how slow is the Arduino.
Program code is here:
// include the library code:
#include <LiquidCrystal.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
int lastMillis = 0;
long fps = 0;
void setup() {
lcd.begin(16, 2);
lcd.print("seconds ");
lcd.setCursor(0, 1);
lcd.print("fps ");
}
void loop() {
if ((millis() - lastMillis) > 1000) {
lcd.setCursor(8, 0);
lcd.print(millis()/1000);
lcd.setCursor(4, 1);
lcd.print(fps);
fps = 0;
lastMillis = millis();
}
fps = fps + 1;
}
And it worked. I was happy to know that Arduino can do more than 300,000 fps on a small 16x2 lcd display.
But after number of seconds goes beyond 32 second (magic number) fps freezes at value 124,185 and never changes after that.
If someone know why is that happen, please explain it. I don't have a clue why fps ( that's set to 0 every second ) could freeze, while seconds are keep changing.
I got a video that shows what happens. Video
Then, as ahaltindis suggested, I changed the code to this:
// include the library code:
#include <LiquidCrystal.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
int lastMillis = 0;
long fps = 0;
void setup() {
lcd.begin(16, 2);
}
void loop() {
if ((millis() - lastMillis) > 1000) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("seconds ");
lcd.setCursor(0, 1);
lcd.print("fps ");
lcd.setCursor(8, 0);
lcd.print(millis()/1000);
lcd.setCursor(4, 1);
lcd.print(fps);
fps = 0;
lastMillis = millis();
}
fps = fps + 1;
}
And it get worse: video
I tried your code with my arduino uno. But I used Serial.print instead of lcd.print. It acted with same way. When sec hits the 32, serial monitor goes crazy.
Then I found that you defined lastMillis as an integer. In arduino(atmega) integer keeps 16bit value and that means it can store values in range of -32,768 to 32,767. When millis function hits 32,767(32sec), arduino sets your lastMillis's value as -32,768.
So your if block returns always true after 32 sec, because difference of millis() and lastMillis will always be greater than 1000. Thats why the only value you see is 1 and that is also why your lcd cannot respond well print requests after 32 sec.
The only change you should do is, change your lastMillis type as a long.
long lastMillis = 0;
Try changing
int lastMillis = 0;
To
unsigned int lastMillis = 0;
Let me know what happens
If you use an unsigned int you will overflow back to one so that your original code will work