Basically with two of the pushbuttons it's supposed to add 1 to my can or bottle value and display it on the LCD. If I press the third button, I want it to print out what I have written in the code.
One issue I have is that I have to hold down the button for a while before it's registered. I know it's because it's in the beginning of the loop but not sure how to have it constantly checking this.
The second problem is that my printer is not printing when I press the third button. Originally I had "if (val3 == LOW)" instead of my "do...while" command. Not sure why it's not getting the command to print. I've checked my wiring numerous times to try and see if there's something wrong there but it should all be working in that aspect.
#include <LiquidCrystal.h>
#include <SoftwareSerial.h>
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
SoftwareSerial Thermal(2, 3);
int heatTime = 150;
int heatInterval = 255;
char printDensity = 15;
char printBreakTime = 15;
int ButtonPin1 = 4;
int ButtonPin2 = 5;
int ButtonPin3 = 6;
int Can = 0;
int Bottle = 0;
int val1 = 0;
int val2 = 0;
int val3 = 0;
void setup()
{
Serial.begin(57600);
Thermal.begin(19200);
initPrinter();
lcd.begin(16,2);
lcd.clear();
pinMode(ButtonPin1, INPUT);
pinMode(ButtonPin2, INPUT);
pinMode(ButtonPin3, INPUT);
}
void initPrinter()
{
Thermal.write(27);
Thermal.write(55);
Thermal.write(7);
Thermal.write(heatTime);
Thermal.write(heatInterval);
Thermal.write(18);
Thermal.write(35);
int printSetting = (printDensity<<4) | printBreakTime;
Thermal.write(printSetting);
Serial.println();
Serial.println("Print ready");
}
void loop()
{
val1 = digitalRead(ButtonPin1);
val2 = digitalRead(ButtonPin2);
val3 = digitalRead(ButtonPin3);
if (val1 == LOW)
{
Can += 1;
delay(200);
}
if (val2 == LOW)
{
Bottle += 1;
delay(200);
}
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Current Cans:");
lcd.print(Can);
delay(3000);
lcd.clear();
lcd.home();
lcd.print("Current Bottles:");
lcd.setCursor(0,1);
lcd.print(Bottle);
delay(3000);
}
do
{
Thermal.println("Thank you for recycling!");
Thermal.write(10);
Thermal.println("Voucher is good for one two-way trip");
Thermal.write(10);
Thermal.println("on any TriMet public system");
Thermal.write(10);
Thermal.print("Number of cans:");
Thermal.println(Can);
Thermal.write(10);
Thermal.print("Number of bottles:");
Thermal.println(Bottle);
Thermal.write(10);
Thermal.write(10);
Thermal.write(10);
} while (val3 == LOW);
}
Any help would be greatly appreciated. Thank you.
moderator update: added code tags ==> #button above the smileys
One issue I have is that I have to hold down the button for a while before it's registered. I know it's because it's in the beginning of the loop but not sure how to have it constantly checking this.
The buttons are being checked each time through the loop() function but that is not happening as fast as it could because of your use of the delay() function in your program. Until the delay() is over the program stops and can do nothing else.
There is an example in the IDE called BlinkWithoutDelay that shows how to use the millis() function for timing. Basically you note the start time of an action and check each time through loop() whether the required period has elapsed. If so, act on it, if not do something else like reading inputs and acting on them.
This is the section of code causing most of your problem in responding to button presses although you have other unnecessary delays elsewhere too. Why do you need the delays in this section anyway and why is it enclosed in braces ?
Why the delays after updating the bottle and can counts ?
Why do you need the delays in this section anyway and why is it enclosed in braces ?
Why the delays after updating the bottle and can counts ?
So the delays are just simply to let the LCD screen show that reading (Like "Current cans: 10") for a little while instead of instantly switching to the next screen. As far as why it's in braces, I thought it needed to be. I'm very new to programming and that's one of the things I struggle with the most in this coding is trying to figure out when braces are needed or not.
Do you want to increment or decrement the counter when the switch IS pressed? Or when it BECOMES pressed?
I'm wanting it to change when it IS pressed so I will check out that state change code and give that a shot.
To anyone else, I still need help with the printer aspect of it. I'm gonna mess with my circuitry again today and see check if it's something wrong there because it seems like it should be working code-wise? (Please correct me if I'm wrong)
So, if you press and hold the switch, you want the count to increment over and over? That's what reading IS pressed will do. Determining when the switch BECOMES pressed (is now; was not last time) means that you increment once, regardless of how long you hold the switch down.
Any clue if that'll help my printing issue at all?
Not a bit.
do
{
Thermal.println("Thank you for recycling!");
Thermal.write(10);
Thermal.println("Voucher is good for one two-way trip");
Thermal.write(10);
Thermal.println("on any TriMet public system");
Thermal.write(10);
Thermal.print("Number of cans:");
Thermal.println(Can);
Thermal.write(10);
Thermal.print("Number of bottles:");
Thermal.println(Bottle);
Thermal.write(10);
Thermal.write(10);
Thermal.write(10);
} while (val3 == LOW);
First, I suggest that you get rid of the do/while statement. It is almost always misused, as it appears to be here. The action happens at least once, regardless of the termination condition. That is almost always not what you want to do.
The termination condition is not affected by anything that happens in the do/while loop, so, once the loop starts, it will never terminate.
First, I suggest that you get rid of the do/while statement. It is almost always misused, as it appears to be here.
Yeah originally I had it as:
if (val3 == LOW)
{
Thermal.println("Thank you for recycling!");
Thermal.write(10);
Thermal.println("Voucher is good for one two-way trip");
Thermal.write(10);
Thermal.println("on any TriMet public system");
Thermal.write(10);
Thermal.print("Number of cans:");
Thermal.println(Can);
Thermal.write(10);
Thermal.print("Number of bottles:");
Thermal.println(Bottle);
Thermal.write(10);
Thermal.write(10);
Thermal.write(10);
}
This wasn't working for me so I gave the do...while a shot to see if it would help things any. I'm gonna be changing the button to the state change code instead of how I have it set up now because I only want it to print once per button press. The problem is getting it to print period though... I have an example code that I copied pretty much verbatim. I only changed what I wanted it to say and added a button so one of those two things must be what's causing my problem.
Does the printer work if you run the sample program from the page you linked to ?
Yes I've gotten the printer to run just fine using the example program. I changed the words a bit from the original but it still printed just fine using the following code.
/*
Example 38.1 - Sparkfun Thermal Printer Test (COM-10438)
http://tronixstuff.com/tutorials > chapter 38
Based on code by Nathan Seidle of Spark Fun Electronics 2011
*/
#include <SoftwareSerial.h>
SoftwareSerial Thermal(2, 3);
int heatTime = 150;
int heatInterval = 255;
char printDensity = 15;
char printBreakTime = 15;
void setup()
{
Serial.begin(57600); // for debug info to serial monitor
Thermal.begin(19200); // to write to our new printer
initPrinter();
}
void initPrinter()
{
//Modify the print speed and heat
Thermal.write(27);
Thermal.write(55);
Thermal.write(7); //Default 64 dots = 8*('7'+1)
Thermal.write(heatTime); //Default 80 or 800us
Thermal.write(heatInterval); //Default 2 or 20us
//Modify the print density and timeout
Thermal.write(18);
Thermal.write(35);
int printSetting = (printDensity<<4) | printBreakTime;
Thermal.write(printSetting); //Combination of printDensity and printBreakTime
Serial.println();
Serial.println("Printer ready");
}
void loop()
{
Thermal.println(" Thank you ");
Thermal.write(10); //Sends the LF to the printer, advances the paper
Thermal.println(" Good For One ");
Thermal.println(" Two-Way Trip");
Thermal.write(10);
Thermal.write(10);
do { } while (1>0);
}
Well, I guess I'll have to retract that last reply. I just tried to upload simply that last program again to see if it would print it out and alas there was nothing printed. So I've done something wrong. I had it working before but at least I have a little bit of direction now.
I have the RX plugged into Pin 2 Tx into PIN 3 and the other to ground which is really the only wiring (besides the external power supply coming from my 9v AC adapter) so not sure what's not working here. I'll keep looking to see if I can find out what the problem is...
Alright well this is a bit frustrating but I got it going. Either the printer is labeled wrong or the example I was using gave me wrong info bc I had the TX and RX backwards. I switched them and the code is doing as I want.... Mostly..... The buttons are still quite slow to respond. I tried using the example of the blink without delay and here's what I have, didn't seem to make much difference.
#include <LiquidCrystal.h>
#include <SoftwareSerial.h>
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
SoftwareSerial Thermal(2, 3);
//Constats
const int heatTime = 150;
const int heatInterval = 255;
const char printDensity = 15;
const char printBreakTime = 15;
const int ButtonPin1 = 4;
const int ButtonPin2 = 5;
const int ButtonPin3 = 6;
// Variables
int Can = 0;
int Bottle = 0;
int ButtonState1 = 0; //Can Button
int ButtonState2 = 0; //Bottle Button
int ButtonState3 = 0; //Printer Button
int LastButtonState1 = 0;
int LastButtonState2 = 0;
int LastButtonState3 = 0;
long previousMillis = 0;
long interval = 2000; //interval at which to check buttons
void setup()
{
Serial.begin(57600);
Thermal.begin(19200);
initPrinter();
lcd.begin(16,2);
lcd.clear();
pinMode(ButtonPin1, INPUT);
pinMode(ButtonPin2, INPUT);
pinMode(ButtonPin3, INPUT);
}
void initPrinter()
{
Thermal.write(27);
Thermal.write(55);
Thermal.write(7);
Thermal.write(heatTime);
Thermal.write(heatInterval);
Thermal.write(18);
Thermal.write(35);
int printSetting = (printDensity<<4) | printBreakTime;
Thermal.write(printSetting);
Serial.println();
Serial.println("Print ready");
}
void loop()
{
ButtonState1 = digitalRead(ButtonPin1);
ButtonState2 = digitalRead(ButtonPin2);
ButtonState3 = digitalRead(ButtonPin3);
if (ButtonState1 != LastButtonState1 ){
if (ButtonState1 == HIGH){
Can += 1;
}}
LastButtonState1 = ButtonState1;
if (ButtonState2 != LastButtonState2 ){
if (ButtonState2 == HIGH){
Bottle += 1;
}}
LastButtonState2 = ButtonState2;
if (ButtonState3 != LastButtonState3){
if (ButtonState3 == HIGH)
{
Thermal.println("Thank you for recycling!");
Thermal.write(10);
Thermal.println("Voucher is good for one two-way trip");
Thermal.write(10);
Thermal.println("on any TriMet public system");
Thermal.write(10);
Thermal.print("Number of cans:");
Thermal.println(Can);
Thermal.write(10);
Thermal.print("Number of bottles:");
Thermal.println(Bottle);
Thermal.write(10);
Thermal.write(10);
Thermal.write(10);
}
LastButtonState3 == ButtonState3;
}
unsigned long currentMillis = millis();
if (currentMillis - previousMillis > interval) {
previousMillis = currentMillis;
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Current Cans:");
lcd.print(Can);
delay(2000);
lcd.clear();
lcd.home();
lcd.print("Current Bottles:");
lcd.setCursor(0,1);
lcd.print(Bottle);
delay(2000);
}}
What are those delays still doing in there ?
Another thing. All of your timing variables need to be unsigned longs to ensure that the elapsed time calculations continue to work.
one leg goes into the breadboard's power, which is connected to the 5v on the arduino. The other leg goes into row 1 of the breadboard. Row 1 also has a 10k resistor going to ground and a pin going to the arduino's 4 pin (just one for example, the others are all similar).
What are those delays still doing in there ?
I tried taking the delays out completely and the LCD would just sit there showing "Current Bottles: 0" It wouldn't rotate between that one and "Current cans:"
Rewire your switches. Get rid of the external resistor. One leg to ground. One leg to the pin you want to read. Turn on the internal pullup resistor. LOW is pressed. HIGH is not pressed.
Get rid of the delays.
Fix this crap:
}}
ONE } per line. NOTHING else on the same line. Use Tools + Auto Format.
Post your code again, with a description of what happens when you press one switch (and rell us which one that was).
So the LCD screen constantly shows ""Current Bottles: " When I press the button (Button2) for the bottles it went to 3, pressed again, went to 6, pressed again went 7,8,9 and then 16.
Button1 which is for the cans, there's no telling what it's doing because the display won't show anything but the bottle count.
Button3 for printing will not make the printer run.
#include <LiquidCrystal.h>
#include <SoftwareSerial.h>
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
SoftwareSerial Thermal(2, 3);
//Constats
const int heatTime = 150;
const int heatInterval = 255;
const char printDensity = 15;
const char printBreakTime = 15;
char barCode[]={
'9','2','3','0','5','6','4','8','9','8','4','4'};
int zero=0;
const int ButtonPin1 = 4;
const int ButtonPin2 = 5;
const int ButtonPin3 = 6;
// Variables
int Can = 0;
int Bottle = 0;
int ButtonState1 = 0; //Can Button
int ButtonState2 = 0; //Bottle Button
int ButtonState3 = 0; //Printer Button
int LastButtonState1 = 0;
int LastButtonState2 = 0;
int LastButtonState3 = 0;
long previousMillis = 0;
long interval = 2000; //interval at which to check buttons
void setup()
{
Serial.begin(57600);
Thermal.begin(19200);
initPrinter();
lcd.begin(16,2);
lcd.clear();
pinMode(ButtonPin1, INPUT_PULLUP);
pinMode(ButtonPin2, INPUT_PULLUP);
pinMode(ButtonPin3, INPUT_PULLUP);
}
void initPrinter()
{
Thermal.write(27);
Thermal.write(55);
Thermal.write(7);
Thermal.write(heatTime);
Thermal.write(heatInterval);
Thermal.write(18);
Thermal.write(35);
int printSetting = (printDensity<<4) | printBreakTime;
Thermal.write(printSetting);
Serial.println();
Serial.println("Print ready");
}
void printBarcode(char zz[])
{
Thermal.write(29); //GS
Thermal.write(107); //k
Thermal.write(zero); //m = 0
for (int z=0; z<12; z++)
{
Thermal.write(zz[z]);
}
Thermal.write(zero); // bar code terminator
delay(3000); // necessary delay
Thermal.write(10);
Thermal.write(10);
Thermal.write(10);
}
void loop()
{
ButtonState1 = digitalRead(ButtonPin1);
ButtonState2 = digitalRead(ButtonPin2);
ButtonState3 = digitalRead(ButtonPin3);
if (ButtonState1 != LastButtonState1 ){
if (ButtonState1 == LOW){
Can += 1;
}
}
LastButtonState1 = ButtonState1;
if (ButtonState2 != LastButtonState2 ){
if (ButtonState2 == LOW){
Bottle += 1;
}
}
LastButtonState2 = ButtonState2;
if (ButtonState3 != LastButtonState3){
if (ButtonState3 == LOW)
{
Thermal.println("Thank you for recycling!");
Thermal.write(10);
Thermal.println("Voucher is good for one two-way trip");
Thermal.write(10);
Thermal.println("on any TriMet public system");
Thermal.write(10);
Thermal.print("Number of cans:");
Thermal.println(Can);
Thermal.write(10);
Thermal.print("Number of bottles:");
Thermal.println(Bottle);
Thermal.write(10);
Thermal.write(10);
Thermal.write(10);
printBarcode(barCode);
}
LastButtonState3 == ButtonState3;
}
unsigned long currentMillis = millis();
if (currentMillis - previousMillis > interval) {
previousMillis = currentMillis;
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Current Cans:");
lcd.print(Can);
lcd.clear();
lcd.home();
lcd.print("Current Bottles:");
lcd.setCursor(0,1);
lcd.print(Bottle);
}
}
int ButtonState1 = 0; //Can Button
int ButtonState2 = 0; //Bottle Button
int ButtonState3 = 0; //Printer Button
I have to wonder why the names don't match the comments.
LastButtonState3 == ButtonState3;
Really? What if they are equal?
You have too much going on in this code. Put the printer in a drawer, with the LCD, until you accurately read the switch states. Show a schematic of the wiring.