I have taken an intro-level electronics class in college, so I think it's fair to say that I am still new to all of this.
For my project, I want my receipt printer to react to a button press. When the button is pressed and released, I want it to spit out a portion of a text. When it's pressed again, I want it to spit out the portion after. and onward until it loops back to the beginning.
I was able to get the printer to react to the button, but what happens is that it will continuously print out that specific section of the text until I press the button. Then it does the same for the next case. What I want to happen is that it prints out the text once and waits until I press again to move on.
I think I understand what's wrong with my code, but I am unsure of how to fix it: the code is constantly referring to its corresponding case and is looping that case until it can move on to the next. I tried to put the printer to sleep at the end of each case, but that didn't work.
I did try looking for the solution online, but I couldn't figure it out. Maybe it's because I don't have the vocabulary to search up my issue yet or maybe there wasn't an answer.
#include "Adafruit_Thermal.h"
#include "SoftwareSerial.h"
#define TX_PIN 6 // Arduino transmit YELLOW WIRE labeled RX on printer
#define RX_PIN 5 // Arduino receive GREEN WIRE labeled TX on printer
SoftwareSerial mySerial(RX_PIN, TX_PIN); // Declare SoftwareSerial obj
Adafruit_Thermal printer(&mySerial, 4); // Pass addr to printer constructor
const int buttonPin = 3;
int state = 0; //integer to hold current state
int old = 0; //integer to hold last state
int buttonPoll = 0; //integer to hold button state
int buttonState = 0; // variable for reading the pushbutton status
void setup() {
pinMode(buttonPin, INPUT); // initialize the pushbutton pin as an input:
mySerial.begin(19200); // Initialize SoftwareSerial
printer.begin(); // Init printer (same regardless of serial type)
}
void loop() {
buttonState = digitalRead(buttonPin);
printer.justify('R');
if (buttonState == HIGH) {
delay(50);
buttonState = digitalRead(buttonPin);
if (buttonState == LOW) {
state = old + 1;
}
}
else {
delay(100);
}
switch (state) {
case 1:
printer.println(F("case 1"));
printer.feed(2);
// printer.sleep(); // Tell printer to sleep
// delay(3000L); // Sleep for 3 seconds
printer.setDefault(); // Restore printer to defaults
old = state;
break;
case 2:
printer.println(F("case 2"));
printer.feed(2);
// printer.sleep(); // Tell printer to sleep
// delay(3000L); // Sleep for 3 seconds
printer.setDefault(); // Restore printer to defaults
old = state;
break;
case 3:
printer.println(F("case 3"));
printer.feed(2);
// printer.sleep(); // Tell printer to sleep
// delay(3000L); // Sleep for 3 seconds
printer.setDefault(); // Restore printer to defaults
old = state;
break;
delay(700);
}
}
Thanks in advance for the help! It is much appreciated!
What it's doing now is spitting out all three cases right when I upload the code onto the Arduino. It's not listening to the button anymore.
I also added a default at the bottom but I don't think it's doing anything.
#include "Adafruit_Thermal.h"
#include "SoftwareSerial.h"
#define TX_PIN 6 // Arduino transmit YELLOW WIRE labeled RX on printer
#define RX_PIN 5 // Arduino receive GREEN WIRE labeled TX on printer
SoftwareSerial mySerial(RX_PIN, TX_PIN); // Declare SoftwareSerial obj
Adafruit_Thermal printer(&mySerial, 4); // Pass addr to printer constructor
const int buttonPin = 3;
int state = 0; //integer to hold current state
int old = 0; //integer to hold last state
int buttonPoll = 0; //integer to hold button state
int buttonState = 0; // variable for reading the pushbutton status
unsigned char printed; // did we print this case yet
void setup() {
pinMode(buttonPin, INPUT); // initialize the pushbutton pin as an input:
mySerial.begin(19200); // Initialize SoftwareSerial
printer.begin(); // Init printer (same regardless of serial type)
}
void loop() {
buttonState = digitalRead(buttonPin);
if (buttonState == HIGH) {
delay(50);
buttonState = digitalRead(buttonPin);
} if (buttonState == LOW);
{
state = old + 1;
printed = false;
}
switch (state) {
case 1:
{ if (printed == false) {
printer.println(F("case 1"));
old = state;
printed = true;
break;
}
}
case 2:
{ if (printed == false) {
printer.println(F("case 2"));
old = state;
printed = true;
break;
}
}
case 3:
{ if (printed == false) {
printer.println(F("case 3"));
old = state;
printed = true;
break;
}
}
default:
printed == false;
delay(700);
}
}
.
.
I should note that I'm partially basing my code on this.
From LearnElectronics on Youtube:
#define button 3 //Push button on D3
#define redLED 5 //red LED on D5
#define greenLED 6 //green LED on D6
#define yellowLED 7 //yellow LED on D7
int state = 0;
//integer to hold current state
int old = 0;
//integer to hold last state
int buttonPoll = 0;
//integer to hold button state
void setup() {
pinMode(button, INPUT_PULLUP);
//button as input
pinMode(redLED, OUTPUT);
//LEDs as output
pinMode(greenLED, OUTPUT);
pinMode(yellowLED, OUTPUT);
digitalWrite(redLED, LOW);
//set initial state as off
digitalWrite(greenLED, LOW);
//set initial state as off
digitalWrite(yellowLED, LOW);
//set initial state as off
}
void loop() {
buttonPoll = digitalRead(button);
if (buttonPoll == 1) {
delay(50);
buttonPoll = digitalRead(button);
if (buttonPoll == 0) {
state = old + 1;
}
}
else {
delay(100);
}
switch (state) {
case 1:
digitalWrite(redLED, HIGH);
digitalWrite(greenLED, LOW);
digitalWrite(yellowLED, LOW);
old = state;
break;
case 2:
digitalWrite(redLED, LOW);
digitalWrite(greenLED, HIGH);
digitalWrite(yellowLED, LOW);
old = state;
break;
case 3:
digitalWrite(redLED, LOW);
digitalWrite(greenLED, LOW);
digitalWrite(yellowLED, HIGH);
old = state;
break;
default:
digitalWrite(redLED, LOW);
digitalWrite(greenLED, LOW);
digitalWrite(yellowLED, HIGH);
old = 0;
break;
}
}
I would suggest you initialise printed to true in setup().
I think your intention at the start of loop() is to detect when your pushbutton is released. I would add a new global variable at the top of your sketch:
int prevButtonState = 0;
In your loop(), I would suggest something like:
buttonState = digitalRead(buttonPin);
if (buttonState != prevButtonState) {
// button has been pressed or released
if (buttonState == LOW) {
// move to the next state
state++;
printed = false;
}
}
// remember the button state for the next time
prevButtonState = buttonState;
Your switch statement then becomes something like:
switch (state) {
case 1:
if (printed == false) {
printer.println(F("case 1"));
printed = true;
}
break;
case 2:
if (printed == false) {
printer.println(F("case 2"));
printed = true;
}
break;
case 3:
if (printed == false) {
printer.println(F("case 3"));
printed = true;
}
break;
default:
// reset back to state 0
state = 0;
printed = true;
It's untested as i'm on a tablet at the moment, butI hope that helps/works.
EDIT: I couldn't see how you've wired up your button. I assume you've wired it between pin 3 and 0v. If you have, then you might want to change your pinMode in setup() to:
pinMode(buttonPin, INPUT_PULLUP);
That should activate the internal pullup resistor on that pin. The pin will read high when not pressed.
Agree. Missing I think is any of the delay() seen in @mantismei's code which had the roll of debouncing the switch.
The simplest debouncing just ignores the switch after detecting a state change, so the switch reacts instant but not again until the debounce interval is passed:
const unsigned char buttonPin = 7;
void setup() {
Serial.begin(115200);
Serial.println("Hello\n");
pinMode(buttonPin, INPUT_PULLUP);
}
# define DEBOUNCE 50 // milliseconds to ignore switch
unsigned char buttonState, prevButtonState;
unsigned long lastButtonTime;
unsigned char state;
unsigned char printed;
void loop() {
unsigned long now = millis();
if (now - lastButtonTime > DEBOUNCE) { // switch still hot from last time? ignore it.
buttonState = digitalRead(buttonPin);
if (buttonState != prevButtonState) {
// button has been pressed or released
if (buttonState == LOW) {
// move to the next state
state++;
if (state == 4) state = 0; // reset
printed = false;
}
// remember the button state and time
prevButtonState = buttonState;
lastButtonTime = now;
}
}
if (!printed) {
Serial.println(state);
printed = true;
}
}
Of course I did:
The OP may want to do the cases just once, or only print something once and still do the case over and over as the loop(), well, loops. It is not clear which is the problem.
I was able to get it to work with @markd833 's edits
As for the delay I had included, for some reason, I thought it would act as a good stabilizer. It was really something that I had when it would print non-stop to make it more manageable. So apologies for that! The code works without the debouncing edits for my project, but it is much appreciated, @alto777
These two days have been my first on the Arduino forum and it's really nice knowing there is a community of people that dedicate their time to helping folks like me