Okay I know the code is a hot mess but I am very new to this... I have an Arduino Mega with a 2.4 tft lcd (no touch) connected with four push buttons and an lcd strip. When you press button one screen shows number 1 led lights change color same with 2,3,4.. Trouble is I need to press the buttons several times before it kicks in, think I maybe need delay or something somewhere. Also the lcd screen blinks the words. Thinking maybe everytime it loops? Maybe a delay or something will help that I have tried but it only made the blink slower. Serial stuff is in there because I am going to pair it to another mega but waiting on parts to come in. Code is below and sorry its a mess any help would be great!
#include <EasyTransfer.h>
#include <mega_24_shield.h>
#include <uno_24_shield.h>
#include <EasyTransfer.h> //https://github.com/madsci1016/Arduino-EasyTransfer#include "OneButton.h"
#include <Wire.h> // Include Wire library (required for I2C devices)
#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;
uint16_t version = MCUFRIEND_KBV_H_;
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
#define GRAY 0x8410
#define LOOP_STATE_STOPPED 0
#define LOOP_STATE_STARTED 1
int bt_state = 3;
int BT_connected = 0;
#include <SoftwareSerial.h>
#include "OneButton.h"
SoftwareSerial HC12(50, 51);
// Setup a new OneButton on pin A1.
OneButton button1(22, true);
// Setup a new OneButton on pin A2.
OneButton button2(23, true);
// Setup a new OneButton on pin A1.
OneButton button3(24, true);
// Setup a new OneButton on pin A2.
OneButton button4(25, true);
#include <FastLED.h>
#define LED_PIN 27
#define NUM_LEDS 30
CRGB leds[NUM_LEDS];
int state = 0;
int period = 500; // 500 ms
unsigned long time_now = 0, time_now_2 = 0;
struct SEND_DATA_STRUCTURE
{
// state of 4 buttons
int btn1_state;
int btn2_state;
int btn3_state;
int btn4_state;
};
int btn_state = 0;
SEND_DATA_STRUCTURE data;
EasyTransfer ETout;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
if (!Serial) delay(5000); //allow some time for Leonardo
uint16_t ID = tft.readID(); //
tft.print(F("Diagnose whether this controller is supported"));
tft.begin(ID);
ETout.begin(details(data), &Serial);
//tft.fillScreen(BLACK);
// link the button 1 functions.
button1.attachClick(click1);
// link the button 2 functions.
button2.attachClick(click2);
//link the button 3 functions.
button3.attachClick(click3);
// link the button 4 functions.
button4.attachClick(click4);
FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
HC12.begin(9600);
ETout.begin(details(data), &HC12);
}
void loop() {
// put your main code here, to run repeatedly:
static uint8_t aspect = 0;
const char *colorname[] = { "BLUE", "GREEN", "RED", "GRAY" };
uint16_t colormask[] = { BLUE, GREEN, RED, GRAY };
uint16_t ID = tft.readID(); //
tft.setRotation(1);
int width = tft.width();
int height = tft.height();
tft.fillScreen(colormask[aspect]);
// tft.fillScreen(BLACK);
tft.setTextSize(5);
tft.setTextColor(RED);
tft.setCursor(0, 20);
button1.tick();
button2.tick();
button3.tick();
button4.tick();
//ETout.sendData();
HC12.write(btn_state);
if (btn_state == 1)
{
for (int i = 0; i <= 19; i++) {
leds[i] = CRGB ( 0, 255, 0);
FastLED.show();
//delay(100);
}
tft.println("number 1");
Serial.print ("number 1");
if (btn_state ==1)
delay(1);
}
if (btn_state == 2)
{
for (int i = 0; i <= 19; i++) {
leds[i] = CRGB ( 255, 0, 0);
FastLED.show();
//delay(100);
}
tft.print("number2");
}
if (btn_state == 3)
{
if (millis() >= time_now + period) {
time_now += period;
state = !state;
}
if (state)
{
for (int i = 0; i <= 19; i++) {
leds[i] = CRGB ( 255, 140, 0);
FastLED.show();
//delay(100);
}
}
else
{
for (int i = 0; i <= 19; i++) {
leds[i] = CRGB ( 0, 0, 0);
FastLED.show();
//delay(100);
}
}
tft.print("number 3");
}
if (btn_state == 4)
{
if (millis() >= time_now_2 + period) {
time_now_2 += period;
state = !state;
}
if (state)
{
for (int i = 0; i <= 19; i++) {
leds[i] = CRGB ( 255, 100, 0);
FastLED.show();
//delay(100);
}
}
else
{
for (int i = 0; i <= 19; i++) {
leds[i] = CRGB ( 0, 0, 0);
FastLED.show();
//delay(1000);
}
}
tft.print("number4");
}
}
Generally that will make things worse. Any delay means you can’t poll your buttons so it will only detect a button push at the right time. Stick a serial print in to tell you what the millis is so you can se how slow your loop is. Fast is good for buttons otherwise you need interrupts and that is rarely the answer.
You have lots of delays and commented out delays.
No just print millis to the serial monitor once per loop. You will see how fast each loop is. I.è the time between one millis and the next. You want to make your loop fast. Get rid of delays. Think about state machines, debouncing and non blocking timing
Those figures look extremely slow! If that is in your loop(), then 500 ms between each - a whole half second - is ridiculously slow and there is an obvious problem with the code.
Unless it actually takes half a second to print six characters of course.
Ahh as I said I am a newbie here and I know there is problems with the code, any suggestions on fixing the problems with the buttons/lcd? I would image the slow loops would resolve with that as well.. Thank you!
Look up millis, blink without delay, state machines. The idea here is to learn how to code your project. There is a section where you can pay others to do it if you don’t wish to learn.
It is normally best to break your project down into individual chunks and work on getting each one functioning. You save each chunk in an appropriately named sketch and then start combining them at the end. Eg LCD screen, buttons, lcd and buttons! Thy way you can isolate errors and wind back to functioning code. It also makes it easier to encapsulate your code.
Thank you for the great advice, I will look that stuff up now.. No, I do wish to learn and I have learned alot over the last few weeks but now that I sort of have it working I was just looking for advice on while it works sometimes.. I will check out your tips, thank you!
Okay just looking for direction here, I have worked on this and fixed the problem with the buttons and lcd by calling a new function but by doing so I only get the led lights to blink once, so I tried to add something to loop like if serial = this then the led but kept getting errors. Is there a way in the new function to keep blinking until a new button is pushed?
void longPressStart1() {
Serial.println("Button 1 longPress start");
tft.fillScreen(BLACK);
tft.setTextColor(RED, GREY);
tft.setTextSize(5);
tft.setCursor(50, 120);
tft.print("Button 1 longpress");
fill_solid (leds, NUM_LEDS, CRGB(255,0,0));
FastLED.show();
delay(500);
// Now turn the LED off, then pause
fill_solid (leds, NUM_LEDS, CRGB (0,0,0));
FastLED.show();
delay(500);
Note that I have only made it down to button1 so far, everything runs and works but the led only blinks once.. Any advice would be great! Thank you!
#include <Adafruit_GFX.h> // Core graphics library
#include <MCUFRIEND_kbv.h> // Hardware-specific library
MCUFRIEND_kbv tft;
#include "OneButton.h"
#include <FreeDefaultFonts.h>
#include <FastLED.h>
#define NUM_LEDS 30
#define DATA_PIN 27
CRGB leds[NUM_LEDS];
int LedStat;
//Display colors
#define BLACK 0x0000
#define RED 0xF800
#define GREEN 0x07E0
#define WHITE 0xFFFF
#define GREY 0x8410
//Setting button pins
OneButton button1(22, true);
OneButton button2(23, true);
OneButton button3(24, true);
OneButton button4(25, true);
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
{
//Display settings
uint16_t ID = tft.readID();
if (ID == 0xD3D3) ID = 0x9481; //force ID if write-only display
tft.begin(ID);
tft.setRotation(1);
tft.setTextSize(5);
tft.print("Starting");
//Led setup
FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS); // GRB ordering is assumed
}
//Button linking to function
Serial.println("Starting...");
button1.attachLongPressStart(longPressStart1);
button2.attachLongPressStart(longPressStart2);
button3.attachLongPressStart(longPressStart3);
button4.attachLongPressStart(longPressStart4);
}
void loop() {
// put your main code here, to run repeatedly:
//Button Ticks looking for press
button1.tick();
button2.tick();
button3.tick();
button4.tick();
Serial.print('Starting');
}
// This function will be called once, when the button1 is pressed for a long time.
void longPressStart1() {
Serial.println("Button 1 longPress start"); //Printing to LCD
tft.fillScreen(BLACK);
tft.setTextColor(RED, GREY);
tft.setTextSize(5);
tft.setCursor(50, 120);
tft.print("Button 1 longpress");
fill_solid (leds, NUM_LEDS, CRGB(255,0,0)); //Blinking LED
FastLED.show();
delay(500);
// Now turn the LED off, then pause
fill_solid (leds, NUM_LEDS, CRGB (0,0,0));
FastLED.show();
delay(500);
}
// This function will be called once, when the button2 is pressed for a long time.
void longPressStart2() {
Serial.println("Button 2 longPress start");
}
// This function will be called once, when the button3 is pressed for a long time.
void longPressStart3() {
Serial.println("Button 3 longPress start");
}
// This function will be called once, when the button4 is pressed for a long time.
void longPressStart4() {
Serial.println("Button 4 longPress start");
}
See reply #9. You have no state machine, you have no use of millis(), you have used delay() for timing instead. Thus you can not blink or implement any LED sequence that runs concurrently with the rest of the program logic.
That is your real problem, not that the function only blinks once. If you make it blink continuously without fundamentally changing your program structure to the mentioned approach, it will blink but it will freeze all other program activity.