Neopixel and TFT?

The first part of this project is solved but the 2nd part, including a color slider is ongoing.
The attachment on this Post has the working 4 Button Sketch, but not the Slider...

Hi all!
I am having a bit of a problem. I am trying to set up a Touch Screen as buttons to operate a 12 LED Neopixel Ring. The problem is twofold, I do not know how to get it to loop a pattern continuously and I do not know how to make it switch to a different pattern while it is running a pattern.

For example, I would like to press button 1 on the screen and begin a pattern and have it run continuously and then while it is running that pattern, I would like to be able to press button 2 and have it run the pattern assigned to that button without having to wait until it stops running the previous pattern.
I would appreciate any help that I can receive on this!
I am using a 5” CTE CLPD Touch Screen and a Stackable GHL TFT Shield

Thanks!

~Dennis

TFTButtonNeo.ino.ino (11.3 KB)

Hi Dennis

The problem is your code is designed to do only one thing at once. For example all those functions with nested for loops and delay() calls. Anything like that will need to be completely re-written. You have a lot of learning and re-coding to do. Start by reading this. Then I would suggest rather than ploughing straight into your current sketch, try some simpler test project until you are sure you understand the new principles you need to follow.

Paul

Thanks for the help PaulRB, it is much appreciated!

I know that I have a lot of learning to do hopefully I am in the right place to get help along the way.:slight_smile:

After reading the info you provided on "SeveralThingsAtTheSameTime" and researching it more, I believe that I understand the basics. However, therein lies the problem, all the examples/tutorials show me how to make buttons connected to pins work in the way desired but have no reference for a touch button or Neopixels. I searched for days in the Arduino forums and Google for an example of a touchscreen buttons controlling Neopixels but did not find anything that combines the two. This is the reason for posting here.

I did notice a sketch made by a “GrumpyMike” that uses state machine for Neopixels but I am having a hard time making it work with URTouch or touchscreen buttons.

I am not asking anyone to write my code but an example using state machine to control Neopixels by touchscreen buttons would greatly help in this situation. If anyone has an example of this please post it here, I am sure it will help more than just me. :wink:

~Dennis

I searched for days in the Arduino forums and Google for an example of a touchscreen buttons controlling Neopixels but did not find anything that combines the two

But you already did that, didn't you? So you know the principles of using touch screens (which is more than I do) and the principles of using neopixels. Now you need to learn the principles of "non-blocking code" and combine all three techniques. Don't expect to find code examples that include all three, you need to take that next step yourself. Don't expect to conquer it in a day. When you get stuck, I can help, as will others, including Grumpy Mike, I'm sure (just don't expect him to be overjoyed).

Yep, I had to but my head started pounding from "Information Overload" :frowning: So I thought that I would check to see if anybody in the forums had something in their cookbooks.

You gotta get a touchscreen, they are pretty cool. But stating that I know the principles of using touchscreens is an overstatement. :o :slight_smile:

HAha, I guess he earned his name...Now you are scaring me!

Either way, I will not let this beat me and I will definitely post the code when I find the solution. :slight_smile:

~Dennis

HAha, I guess he earned his name..

Well given that it is self given I don't know about earning it.

If you have something that uses a push button all the digital read does is to return HIGH or LOW depending on the state of the button. You can think of this as true or false, or a simple binary state. Your touch button does the same thing. You can tell if it is touched on not can't you? So just substitute the touched or not for the digital read that tells you if the button is pressed.

They say, it is a wise man who knows his self. :0 Just kidding, nice to meet you.

I will try to use "myTouch.dataAvailable()" for that and see what happens, thanks for the advice!

~Dennis

DigiDenny:
I will try to use "myTouch.dataAvailable()" for that and see what happens

I don't think that will be a problem. It sounds similar to Serial.available(), which is an example of a non-blocking function. It simply tests if there is some data waiting and returns a value indicating this. If there is no data waiting, it does not wait until some data become available, it immediately returns a value to indicate to your sketch that there is no data and your sketch is free to do something else.

By contrast, myTouch.read() (which I imagine is similar to Serial.read()) is an example of a blocking function. If there is no data waiting, it will simply wait until some data arrives, preventing your sketch from doing anything else in the mean time. But, you may have noticed, your sketch tests myTouch.dataAvailable() each time before it calls myTouch.read(), and so avoids getting blocked.

Is this making sense to you?

PaulRB, it makes perfect sense, the code will not have to wait for an answer using "myTouch.dataAvailable()" . It will either receive True or False and go on its merry way with the rest of the sketch. However, using "myTouch.read();", it will sit there waiting for a response.

However, I decided to use "myTouch.dataAvailable()" because it looked more like a Boolean than the other and would likely give a True or a False as oppsed to "myTouch.read();", which looks like it would give coordinates instead of a Boolean.

In either case I did try both and the "myTouch.dataAvailable()" worked but "myTouch.read();" did not. So, I am a little closer to making it do what I want. Now, I have 4 buttons that turn on or off the same pattern, I just need to figure out how to set up a different pattern for each button, get rid of a bug that makes the NeoPixel flicker, and I am in business!
I had to take a break from it Yesterday, but today I will have a fresh mindset and will be able to go further...I hope :slight_smile:

~Dennis

By contrast, myTouch.read() (which I imagine is similar to Serial.read()) is an example of a blocking function.

Serial.read() isn't blocking, if there is no data to read it returns -1 or the byte 0xff.

Grumpy_Mike:
Serial.read() isn't blocking, if there is no data to read it returns -1 or the byte 0xff.

Oh. Bang goes my analogy.

Actually, because I am using "myTouch.dataAvailable()" I really have one button that runs the patterns. So where ever I press on the screen it runs the patterns. :frowning:

This makes sense because the code is pretty much saying to run a pattern when ever there is touch data instead of where and when there is touch data. I'm learning slowly but surely. :wink:

I think I may need to make a new sketch with one or two buttons in order to get it to do what I need it to.

~Dennis

Well, I wrote a new sketch for just one button and it is working pretty good with the exception of having to press the button twice to get it to change patterns?

I figured that I would just make a Boolean and flip it in the code instead of using "myTouch.dataAvailable()" with Grumpy Mike's code. It got me a heck of a lot closer to my goal.

Here's the sketch:

#include <UTFT.h>
#include <URTouch.h>
#include <Adafruit_NeoPixel.h>

#define PINforControl   22 // pin connected to the small NeoPixels strip
#define NUMPIXELS1      12 // number of LEDs on second strip

Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS1, PINforControl, NEO_GRB + NEO_KHZ800);

UTFT myGLCD(CPLD, 27, 26, 25, 28);  // CTE DUE
URTouch myTouch(6, 5, 32, 3, 2); //byte tclk, byte tcs, byte din, byte dout, byte irq CTE DUE

extern uint8_t Blooper[];
extern uint8_t BigFont[];

int x, y;

int yR = 148;
int yG = 148;
int yB = 148;

unsigned long patternInterval = 30 ; // time between steps in the pattern
unsigned long lastUpdate = 0 ; // for millis() when last update occoured
unsigned long intervals [] = { 0, 20, 20, 50, 100 } ; // speed for each pattern
const byte button = 11; // pin to connect button switch to between pin and ground

boolean touched = false;

void setup() {

  strip.begin();
  wipe(); // wipes the LED buffers

  myGLCD.InitLCD();                   //Initialize Screen
  myGLCD.clrScr();                    //Clear Screen

  myGLCD.setColor(VGA_BLACK);         // Set font color here
  myGLCD.setBackColor(VGA_LIME);      // Set font backcolor here

  myTouch.InitTouch();
  myTouch.setPrecision(PREC_MEDIUM);

  ButtonDraw();
  
}

void loop() {
  buttonOne();

  static int pattern = 0, lastReading;
  int reading = touched;
  if(lastReading == true && reading == false){
    pattern++ ; // change pattern number
    if(pattern > 4) pattern = 0; // wrap round if too big
    patternInterval = intervals[pattern]; // set speed for this pattern
    wipe(); // clear out the buffer 
    delay(50); // debounce delay
  }
  lastReading = reading; // save for next time

if(millis() - lastUpdate > patternInterval) updatePattern(pattern);
}

/////////////////////////////////////////////////////////////////////////////////////////////////////
void  updatePattern(int pat){ // call the pattern currently being created
  switch(pat) {
    case 0:
         wipe(); // clear out the buffer 
         break; 
    case 1: 
        colorWipe(strip.Color(0, 0, 255)); // BLUE
        break;
    case 2:
        colorWipe(strip.Color(0, 255, 0)); // GREEN
        break;
    case 3:
        colorWipe(strip.Color(255, 0, 0)); // RED
        break;        
    case 4:
         rainbow(); 
         break; 
         
  }  
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
void ButtonDraw() {

  myGLCD.setFont(Blooper);
  myGLCD.setBackColor(VGA_BLACK);     // Set back color of Font
  myGLCD.setColor(VGA_WHITE);         // Set Color of Font
  
  myGLCD.setFont(BigFont);                // Set Font
  
  myGLCD.drawRect(350, 190, 450, 290);    // RAINBOW LED EFFECT
  myGLCD.print("LED P1", 353, 233);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
void buttonOne() {

  if (myTouch.dataAvailable()) {
    myTouch.read();
    x = myTouch.getX();
    y = myTouch.getY();
    
//       (x1,  y1,  x2,  y2)
//       (350, 190, 450, 290)
      if ((y >= 190) && (y <= 290)) // Upper row
      {
        if ((x >= 350) && (x <= 450)) // top left LED P1
        {
          touched = !touched;
          TouchIt(350, 190, 450, 290);
        }
      }
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
void TouchIt(int x1, int y1, int x2, int y2)
{
  myGLCD.setColor(VGA_RED);
  myGLCD.drawRoundRect (x1, y1, x2, y2);
  while (myTouch.dataAvailable())
  myTouch.read();
  myGLCD.setColor(VGA_WHITE);
  myGLCD.drawRoundRect (x1, y1, x2, y2);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
void rainbow() { // modified from Adafruit example to make it a state machine
  static uint16_t j=0;
    for(int i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel((i+j) & 255));
    }
    strip.show();
     j++;
  if(j >= 256) j=0;
  lastUpdate = millis(); // time for next change to the display
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
void rainbowCycle() { // modified from Adafruit example to make it a state machine
  static uint16_t j=0;
    for(int i=0; i< strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    }
    strip.show();
  j++;
  if(j >= 256*5) j=0;
  lastUpdate = millis(); // time for next change to the display
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
void theaterChaseRainbow() { // modified from Adafruit example to make it a state machine
  static int j=0, q = 0;
  static boolean on = true;
  // for (int j=0; j < 256; j++) {     // cycle all 256 colors in the wheel
  //  for (int q=0; q < 3; q++) {
     if(on){
            for (int i=0; i < strip.numPixels(); i=i+3) {
                strip.setPixelColor(i+q, Wheel( (i+j) % 255));    //turn every third pixel on
             }
     }
      else {
           for (int i=0; i < strip.numPixels(); i=i+3) {
               strip.setPixelColor(i+q, 0);        //turn every third pixel off
                 }
      }
     on = !on; // toggel pixelse on or off for next time
      strip.show(); // display
      q++; // update the q variable
      if(q >=3 ){ // if it overflows reset it and update the J variable
        q=0;
        j++;
        if(j >= 256) j = 0;
      }
  lastUpdate = millis(); // time for next change to the display    
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
void colorWipe(uint32_t c) { // modified from Adafruit example to make it a state machine
  static int i =0;
    strip.setPixelColor(i, c);
    strip.show();
  i++;
  if(i >= strip.numPixels()){
    i = 0;
    wipe(); // blank out strip
  }
  lastUpdate = millis(); // time for next change to the display
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
void wipe(){ // clear all LEDs
     for(int i=0;i<strip.numPixels();i++){
       strip.setPixelColor(i, strip.Color(0,0,0)); 
       }
       strip.show();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}
///////////////////////////////////////////////////////////////////////////////////////////////////

I am not sure why its making me press the button twice...any Ideas?

~Dennis

I'm guessing it's because of this

touched = !touched;

and this

 int reading = touched;
  if(lastReading == true && reading == false){

So each time the screen is touched, the boolean "touched" toggles between true and false. But action is only taken when it changes from true to false. No action when it changes from false to true.

Tip for you: if you click Tools->Auto Format in the IDE, it will sort out all your incorrect indentation, making your code easier to follow.

been toying around with it since my last post and found out the problem, it was

void TouchIt(int x1, int y1, int x2, int y2)
{
  myGLCD.setColor(VGA_RED);
  myGLCD.drawRoundRect (x1, y1, x2, y2);
  while (myTouch.dataAvailable())
    myTouch.read();
  myGLCD.setColor(VGA_WHITE);
  myGLCD.drawRoundRect (x1, y1, x2, y2);
  touched = !touched;
}

It has a while in it that I think was fouling up

touched = !touched;

It now works beautifully...on one button.
That is the example works exactly as Grumpy Mike's Sketch for a physical button, using touch button instead. Although, I learned a lot I still have the original problem of needing to use 4 buttons for 4 different patterns. Any Ideas?

You addressed the problems I pointed or in my first reply with apparent ease. I suspect you will have it will working as you want in another day!

I still have the original problem of needing to use 4 buttons for 4 different patterns.

So with one button the code increments a variable each time it is pressed and that variable controls the light pattern. So if you have four buttons just make each of the detected push ( or touch ) set that variable to a fixed value.

Grumpy_Mike:
So with one button the code increments a variable each time it is pressed and that variable controls the light pattern. So if you have four buttons just make each of the detected push ( or touch ) set that variable to a fixed value.

I'm lost!

I just replaced your digitalRead(button); with a Boolean "touched" and flipped it inside of the touch button code in order to replicate the high/low of a button press.

Here is the sketch:

#include <UTFT.h>
#include <URTouch.h>
#include <Adafruit_NeoPixel.h>

#define PINforControl   22 // pin connected to the small NeoPixels strip
#define NUMPIXELS1      12 // number of LEDs on second strip

Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS1, PINforControl, NEO_GRB + NEO_KHZ800);

UTFT myGLCD(CPLD, 27, 26, 25, 28);  // CTE DUE
URTouch myTouch(6, 5, 32, 3, 2); //byte tclk, byte tcs, byte din, byte dout, byte irq CTE DUE

extern uint8_t Blooper[];
extern uint8_t BigFont[];

int x, y;



unsigned long patternInterval = 30 ; // time between steps in the pattern
unsigned long lastUpdate = 0 ; // for millis() when last update occoured
unsigned long intervals [] = { 0, 20, 20, 50, 100 } ; // speed for each pattern
const byte button = 11; // pin to connect button switch to between pin and ground

boolean touched = false;

void setup() {

  strip.begin();
  wipe(); // wipes the LED buffers

  myGLCD.InitLCD();                   //Initialize Screen
  myGLCD.clrScr();                    //Clear Screen

  myGLCD.setColor(VGA_BLACK);         // Set font color here
  myGLCD.setBackColor(VGA_LIME);      // Set font backcolor here

  myTouch.InitTouch();
  myTouch.setPrecision(PREC_MEDIUM);

  ButtonDraw();

}

void loop() {
  buttonPone();
  buttonPtwo();

  static int pattern = 0, lastReading;
  int reading = touched;
  if (lastReading == true && reading == false) {
    pattern++ ; // change pattern number
    if (pattern > 4) pattern = 0; // wrap round if too big
    patternInterval = intervals[pattern]; // set speed for this pattern
    wipe(); // clear out the buffer
    delay(125);
  }
  lastReading = reading; // save for next time

  if (millis() - lastUpdate > patternInterval) updatePattern(pattern);
}

/////////////////////////////////////////////////////////////////////////////////////////////////////
void  updatePattern(int pat) { // call the pattern currently being created
  switch (pat) {
    case 0:
      wipe(); // clear out the buffer
      break;
    case 1:
      colorWipe(strip.Color(0, 0, 255)); // BLUE
      break;
    case 2:
      colorWipe(strip.Color(0, 255, 0)); // GREEN
      break;
    case 3:
      colorWipe(strip.Color(255, 0, 0)); // RED
      break;
    case 4:
      rainbow();
      break;

  }
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
void ButtonDraw() {

  myGLCD.setFont(Blooper);
  myGLCD.setBackColor(VGA_BLACK);     // Set back color of Font
  myGLCD.setColor(VGA_WHITE);         // Set Color of Font

  myGLCD.setFont(BigFont);                // Set Font

  myGLCD.drawRect(250, 190, 350, 290);    // Button P1
  myGLCD.print("LED P1", 253, 233);

  myGLCD.drawRect(450, 190, 550, 290);    // Button P2
  myGLCD.print("LED P2", 453, 233);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
void buttonPone() {

  if (myTouch.dataAvailable()) {
    myTouch.read();
    x = myTouch.getX();
    y = myTouch.getY();

    //       (x1,  y1,  x2,  y2)
    //       (250, 190, 350, 290)
    if ((y >= 190) && (y <= 290)) // Upper row
    {
      if ((x >= 250) && (x <= 350)) // top left LED P1
      {
        touched = !touched;
      }
    }
  }
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
void buttonPtwo() {

  if (myTouch.dataAvailable()) {
    myTouch.read();
    x = myTouch.getX();
    y = myTouch.getY();

    //       (x1,  y1,  x2,  y2)
    //       (450, 190, 550, 290)
    if ((y >= 190) && (y <= 290)) // Upper row
    {
      if ((x >= 450) && (x <= 550)) // top left LED P1
      {
        touched = !touched;

        //TouchIt(350, 190, 450, 290);
      }
    }
  }
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
void TouchIt(int x1, int y1, int x2, int y2)
{
  myGLCD.setColor(VGA_RED);
  myGLCD.drawRoundRect (x1, y1, x2, y2);
  while (myTouch.dataAvailable())
    myTouch.read();
  myGLCD.setColor(VGA_WHITE);
  myGLCD.drawRoundRect (x1, y1, x2, y2);
  touched = !touched;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
void rainbow() { // modified from Adafruit example to make it a state machine
  static uint16_t j = 0;
  for (int i = 0; i < strip.numPixels(); i++) {
    strip.setPixelColor(i, Wheel((i + j) & 255));
  }
  strip.show();
  j++;
  if (j >= 256) j = 0;
  lastUpdate = millis(); // time for next change to the display
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
void rainbowCycle() { // modified from Adafruit example to make it a state machine
  static uint16_t j = 0;
  for (int i = 0; i < strip.numPixels(); i++) {
    strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
  }
  strip.show();
  j++;
  if (j >= 256 * 5) j = 0;
  lastUpdate = millis(); // time for next change to the display
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
void theaterChaseRainbow() { // modified from Adafruit example to make it a state machine
  static int j = 0, q = 0;
  static boolean on = true;
  // for (int j=0; j < 256; j++) {     // cycle all 256 colors in the wheel
  //  for (int q=0; q < 3; q++) {
  if (on) {
    for (int i = 0; i < strip.numPixels(); i = i + 3) {
      strip.setPixelColor(i + q, Wheel( (i + j) % 255)); //turn every third pixel on
    }
  }
  else {
    for (int i = 0; i < strip.numPixels(); i = i + 3) {
      strip.setPixelColor(i + q, 0);      //turn every third pixel off
    }
  }
  on = !on; // toggel pixelse on or off for next time
  strip.show(); // display
  q++; // update the q variable
  if (q >= 3 ) { // if it overflows reset it and update the J variable
    q = 0;
    j++;
    if (j >= 256) j = 0;
  }
  lastUpdate = millis(); // time for next change to the display
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
void colorWipe(uint32_t c) { // modified from Adafruit example to make it a state machine
  static int i = 0;
  strip.setPixelColor(i, c);
  strip.show();
  i++;
  if (i >= strip.numPixels()) {
    i = 0;
    wipe(); // blank out strip
  }
  lastUpdate = millis(); // time for next change to the display
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
void wipe() { // clear all LEDs
  for (int i = 0; i < strip.numPixels(); i++) {
    strip.setPixelColor(i, strip.Color(0, 0, 0));
  }
  strip.show();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if (WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if (WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}
///////////////////////////////////////////////////////////////////////////////////////////////////

I am not sure how to do what you suggest with a Boolean?

~Dennis

This bit of code

int reading = touched;
  if (lastReading == true && reading == false) {
    pattern++ ; // change pattern number
    if (pattern > 4) pattern = 0; // wrap round if too big

Increments the variable called pattern and restricts it to five values zero to four.

To do what you want, you need to check each of your sensors in turn, and if sensor one is being touched make the variable "pattern" equal to zero.
If sensor two is being touched make the variable call "pattern" equal one. And so on for your four buttons.

Grumpy_Mike:
This bit of code

int reading = touched;

if (lastReading == true && reading == false) {
    pattern++ ; // change pattern number
    if (pattern > 4) pattern = 0; // wrap round if too big



Increments the variable called pattern and restricts it to five values zero to four.

To do what you want, you need to check each of your sensors in turn, and if sensor one is being touched make the variable "pattern" equal to zero.
If sensor two is being touched make the variable call "pattern" equal one. And so on for your four buttons.

I see, but I would like each button to act as an on/off switch for its own pattern.

When button one is pressed once, it turns on pattern1 and when it is pressed again it turns it off. When button two is pressed once, it turns on pattern2 and when it is pressed again it turns it off. etc...

and when it is running a pattern, pressing another button would stop that pattern and make it run the pattern assigned to that button.

Trying to keep the state machine working for all buttons and using a different pattern for each button has me perplexed! :frowning:

~Dennis