TFT Joystick Shield add/subtract number, decimal places

Hello.. I'm making a project in which in need to insert a number mannualy! More specifically, I want to insert the price of a kWh in my TFT.. Joystick UP will add i++, DOWN i--, and LEFT and RIGHT to move between decimal places.. For example, I want to write the number 0,1415... How can I do this, without using a bunch of windows (that's the only way I can think of doing this)..

Many thanks, António

There are a few ways to do this but first we need to know what you have already, both hardware and software.
Obviously you will need an array but depending on the library you are using for your display, will decide what kind of array you should use. Since you will be using a joystick, I would make it so you start with 5 or 6 boxes for your whole numbers and 3 or 4 boxes for your decimal numbers. Moving the joystick left or right will highlight a certain box and moving up/down will change its value 0 - 9.

Assuming you are using a joystick with a button, you can have the button convert the numbers into a single number, when pressed.

That's basically everything you need, the rest depends on your hardware and software.

amlo13:
Hello.. I'm making a project in which in need to insert a number mannualy! More specifically, I want to insert the price of a kWh in my TFT.. Joystick UP will add i++, DOWN i--, and LEFT and RIGHT to move between decimal places.. For example, I want to write the number 0,1415... How can I do this, without using a bunch of windows (that's the only way I can think of doing this)..

Many thanks, António

Left: multiply increment by 10
Right: divide increment by 10
Up: add increment to number
Down: subtract increment from number

Nothing fancy, just arithmetic.

I´m using a TFT from Adafruit: Adafruit 1.8 Color TFT Shield w/microSD and Joystick [v 2] : ID 802 : $34.95 : Adafruit Industries, Unique & fun DIY electronics and kits and an Arduino Mega... I'm working on an Energy project, so I need to see how much is spent according to the consumed power! The problem is, I cannot figure how to change from one box to another, in the same window... That's my biggest question...

amlo13:
I´m using a TFT from Adafruit: Adafruit 1.8 Color TFT Shield w/microSD and Joystick [v 2] : ID 802 : Adafruit Industries, Unique & fun DIY electronics and kits and an Arduino Mega... I'm working on an Energy project, so I need to see how much is spent according to the consumed power! The problem is, I cannot figure how to change from one box to another, in the same window... That's my biggest question...

As long as you don't need a cursor (highlight of the edited area), reply #2 will work. You wouldn't have to "change boxes". The arithmetic alone would be enough.

If you need a cursor, then the cursor logic is:
Left: cursor left
Right: cursor right

Well, leaving the difficult details to you. :slight_smile:

From what I understood from here, and for example, if I want to insert the number 0.1415, I would have to add increment UP for 1415 times, then RIGHT 4 times more... Doesn´t it take to much time to get there?

amlo13:
From what I understood from here, and for example, if I want to insert the number 0.1415, I would have to add increment UP for 1415 times, then RIGHT 4 times more... Doesn´t it take to much time to get there?

No, starting from 0.0000 it would be UP 5 times, LEFT once, UP once, LEFT once, UP 4 times, UP once (starting from the least significant digit).

Oh, I see! And yes, that makes sense, and it's easy to implement.. Now it's time to make something "graphically friendly" in the TFT. Thank you all!!

Yes, like you said, it was not that difficult! Sometimes simplest is the best :slight_smile:

I have another thing that I want to ask you. I have made a delay between each each option chosen, but it seems to me that the code is being repeated too many times. Any hints on how to simplify this part of the code?

void loop() {


  int joy = CheckButton();

  switch (joy)
  {
    
    case Up:
      if (millis() - lastDebounceTime > choiceDelay) {
        number++;
        Serial.println(number,4);
        lastDebounceTime = millis();
      }
      break;

    case Down:
      if (millis() - lastDebounceTime > choiceDelay) {
        number--;
        Serial.println(number,4);
        lastDebounceTime = millis();
      }
      break;

    case Right:
if (millis() - lastDebounceTime > choiceDelay) {
        number=number*10;
        Serial.println(number,4);
        lastDebounceTime = millis();
      }
      break;

    case Left:
if (millis() - lastDebounceTime > choiceDelay) {
        number=number*0.1;
        Serial.println(number,4);
        lastDebounceTime = millis();
      }
      break;


    default:
      ;
  }
}

I want to try to write lastDebounceTime = millis();  and  if (millis() - lastDebounceTime > choiceDelay) just once instead of in every case statements.

Mmmm... at first glance your approach seems not too bad. I would not worry too much about restructuring it just to do that, at this point.

But I would rename lastDebounceTime to something else, as it really has nothing to do with bounce. It's more of an autorepeat delay, as far as I can see.

Yes you're right! This if from the Debounce Delay code, I forgot to change it :slight_smile: Thanks a lot! I made this question because I'm working on my thesis, and I'm realizing that the code is getting too big! I'm from Physics Engineering, and so not an Arduino Expert! Probably, after I finish the code, I have to ask someone to see if the code can be simplified!

Thanks a lot again, for the help! :slight_smile:

You need not just one number, but two of them. One number is for the "step size" (in your case, this will be 0.0001, 0.001, 0.01, 0.1, or 1), and the other is for the "number being built" (this could be anything from 0.0000 to 9.9999).

Left and right change the step size (but do not affect the number being built).

Up and down change the number being built (but do not affect the step size).

I strongly suggest using a long to store the number. This can only store whole numbers, but it can handle 9 (sometimes 10) digits. Thus, the "step size" will be 1, 10, 100, 1000, or 10000; and the "number being built" will be in the range 0 to 99999. Once you have the number you want, just divide by 10000.0 (you will need the decimal point) to get a float for display or further calculations.

As a programmer (because that's what you are now, at least for this project), you will have to be aware of things that can go wrong, such as:

What happens if the "step size" is already at the right-hand digit, and I push the joystick to the right?
What if it's at the left-hand digit, and I push the joystick to the left?
What happens if I try to push the "number being built" below zero?
What if I try to push it above "all nines"?
In these cases, saying to the user, "Don't do this!" isn't good enough. You will have to write your program to "defend" against this kind of "misbehavior" by the user.

I don't know what kind of display you are using, but perhaps you could put a sort of "cursor" below the number by using a ^ character. Here is an example of what the display would look like during the process of inputting a number (in this case, 0.0012):

0.0000
     ^

 *up*
     
0.0001
     ^

 *up*
     
0.0002
     ^
     
 *left*
     
0.0002
    ^
    
 *up*
    
0.0012
    ^

This makes things a tiny bit more complicated, but certainly not impossible.

That's what I suggested, only I said to put each number in its own box instead of putting a cursor under the number. If you use individual boxes then you can highlight that number by changing its color, instead of moving another character on the screen.

Adding more characters on screen means you need to move it then hide the old character by saving its past values and making the old character's color match the background color. It's a lot more work, uses more memory and takes more time.

HazardsMind:
That's what I suggested, only I said to put each number in its own box instead of putting a cursor under the number.

The OP has not told us what kind of display he is using. What you suggested may be impractical or even impossible. But also, my suggestion might be impossible: if the display has only one line, then there is no second line to hold the cursor.

@amlo13: What kind of display are you using?

If you use individual boxes then you can highlight that number by changing its color, instead of moving another character on the screen.

In order to do that, you must be able to change the color of the number. What if the display is monochrome? Or the user is colorblind?

Adding more characters on screen means you need to move it then hide the old character by saving its past values and making the old character's color match the background color. It's a lot more work, uses more memory and takes more time.

It's a lot less work than isolating a single digit from a multi-digit number (very tricky for beginners) and displaying it, and only it, in a different color than the rest of the digits.
You can move the relevant character thus:

                         //  digits:  0.0000
if     (step==10000L) Serial.println("^     ");
else if (step==1000L) Serial.println("  ^   ");
else if  (step==100L) Serial.println("   ^  ");
else if   (step==10L) Serial.println("    ^ ");
else if    (step==1L) Serial.println("     ^");
else                  Serial.println("HELP!!");

except, instead of Serial.println() you would use the display you want it to appear on.

It's a lot less work than isolating a single digit from a multi-digit number (very tricky for beginners) and displaying it, and only it, in a different color than the rest of the digits.

Which is why I also suggested to use an array.

long value[5] = {0};
float finalVal;

/*
  move cursor to select value
*/

finalVal = (value[0]*10000) + (value[1] * 1000) + (value[2] * 100) + (value[3] * 10) + value[4]; //condense to function
finalVal *= 0.0001;

//print(finalVal);

http://cpp.sh/5ybl

odometer:
What happens if the "step size" is already at the right-hand digit, and I push the joystick to the right?
What if it's at the left-hand digit, and I push the joystick to the left?
What happens if I try to push the "number being built" below zero?
What if I try to push it above "all nines"?
In these cases, saying to the user, "Don't do this!" isn't good enough. You will have to write your program to "defend" against this kind of "misbehavior" by the user.

@Hazards Mind: My first idea was to do something like you're saying here in your last post! But how is it possible to know in which on of the numbers of the array we are? How to store each one of these values using just the R,L, Up, Down Rules?

@odometer...
How can I implement those restrictions, particulary, push right when we're in the last digit? And the reverse situation, in the left side? My first idea was to do something like you are saying, but I faced that problem, and I don't know how to make the code "know" when we're in the first/last digit, and apply a different rule for Right and Left!

Btw, I'm using a 1.8" TFT Shield from Adafruit, Adafruit 1.8 Color TFT Shield w/microSD and Joystick [v 2] : ID 802 : Adafruit Industries, Unique & fun DIY electronics and kits!! Thanks again for you time!!

How can I make something like, Press Left --> forward one place in the array; Right ---> back one place in the array.. Is it possible? And then make a restriction like if value[5] and Press Right ---> value [0] ?

What does the joystick return when you press left or right? Does it work like buttons or an actual joystick with a range of 0 - 1023? Just asking because I have seen both types.

I'm going to assume it returns (0 - 1023), so you will need something like this.

This shows how to move through the indexes in the array. You can do the same thing to change the values too.

#define numOfElement 5 // x.xxxx

void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:
  static int 
    lastVal = 0, //prevents holding 
    index = 0; // starts at index 0 in the array

  int joyX = analogRead( /*pin*/ ); // i'm not familiar with that model so I don't know if there is already a function for getting the joystick values 

  if (joyX != lastVal) // if not being held
  {
    if ( joyX == 0 ) // all the way to the left
    {
      index--;
      if ((index - 1) <= 0) // make sure it goes not go past the first index
        index = 0;
    }
    else if ( joyX == 1023 ) // all the way to the rightt
    {
      index++;
      if (index >= (numOfElement - 1)) // make sure it does not go past the last index
        index = (numOfElement - 1);
    }
    lastVal = joyX; // update lastVal
  }

  // change values here  

}

You can also get rid of these and just use the constrain() function too. index = constrain(index, 0, 5);

if ((index - 1) <= 0) // make sure it goes not go past the first index
index = 0;

Or if you want you can make the indexes rollover so if you go past 0, it will go straight to 5 and vice versa.

It works between a range 0-1023!

int CheckButton()
{
  int joystickState = analogRead(3);

  if (joystickState < 50) return Left;
  if (joystickState < 150) return Down;
  if (joystickState < 250) return Press;
  if (joystickState < 500) return Right;
  if (joystickState < 650) return Up;
  return Neutral;

How don't understand by your code when we're in the end/begining. Why did you write something like:

joyX == 0 --> all the way to the left? If I continue to push Left, the analog read will become equal to zero?