FillRect

Hello,

My rect is now filling from top to bottom.
I want to to fill from bottom to top, how can i do this?

i've got this now:

tft.drawRect(75,150,10,150,ILI9340_WHITE);
tft.fillRect(75,150,10,150,ILI9340_WHITE);

thanks!

Turn your display around or hack the library.

Are you serious?

A 10x150 rectangle is going to take 3ms to fill if you are using SPI interface.
If it is the 16-bit parallel interface, you are going to take less than 1ms.

You must have pretty sharp eyesight if you can spot the fill direction.

Yes, you can get it to fill in a different direction if you really think it important.

Quite honestly a white box will look the same when finished whichever way it was filled.
However, a photo would look different if you draw it upside down.

David.

well, I want to make it a temprature bar so it fills if the temp rises.

If your temperature rises faster than 1ms, I would make a run for it.

If you want to display a filled bar that represents the mercury and a hollow rectangle that represents the empty capillary in the thermometer, that is a different problem.

    tft.drawRect(75, 150,   10, 150, ILI9340_WHITE);    //draw whole thermometer 
    tft.fillRect(76, 300-20, 8,  20, ILI9340_SILVER);   //draw the mercury

Untested. You should sketch out the coordinates of your thermometer. Work out the length. How much is filled. How much is empty.

David.

Try this

#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"

#define TFT_DC 9
#define TFT_CS 10
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);

char TX[20];
int Temperature1;      // Temperature sensor
int lecT1px;              //  Temperature in pixels
int maxpx = 70;        // Temperature-bar height in pixels
int Dx = 20;               // Bar wide in pixels
int maxscale = 100;   // Scale: 0C to 100C (for example)


void setup() {
  tft.begin();  tft.setRotation(3);  
  tft.fillScreen(ILI9341_BLUE);

  tft.setTextColor(ILI9341_YELLOW);
  tft.setTextSize(2);  tft.setCursor(20, 20);  tft.print("Temperature bar");  
}  
  
void loop() {
   Temperature1 = random(maxscale);   sprintf(TX,"T = %03d  C", Temperature1);   
   tft.setTextSize(2);     tft.setTextColor(ILI9341_WHITE, ILI9341_BLUE); tft.setCursor(50, 50);  tft.print(TX);          
     
     lecT1px = Temperature1*maxpx/maxscale;  //temperature to pixels equivalent

   tft.fillRect(95,100,Dx,maxpx-lecT1px,ILI9341_BLACK);          // bar-direction: up to down
   tft.fillRect(95,100+maxpx-lecT1px,Dx,lecT1px,ILI9341_GREEN); // bar-direction: down to up
   tft.drawRect(95-1,100-1,Dx+2,maxpx+2,ILI9341_WHITE);         // external cover bar

   tft.setTextSize(1);  
   sprintf(TX,"%d  C", maxscale);  tft.setTextColor(ILI9341_WHITE);
   tft.setCursor(120, 95);  tft.print(TX);     
   sprintf(TX,"%d  C", 0);  
   tft.setCursor(120, 95+maxpx);  tft.print(TX);        

  delay(150);
}

Changes:

1 Libs and hadware setup: ILI9341 to ILI9340
2 Color definitions: ILI9341_ to ILI9340_

Enjoy it!

THNX guy, but maybe it's easier if I send my code.
I'm reading out a temp sensor from my car, it works only the bar is filling from the top:

#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9340.h"
#include <SD.h>

#if defined(__SAM3X8E__)
    #undef __FlashStringHelper::F(string_literal)
    #define F(string_literal) string_literal
#endif

// These are the pins used for the Mega
// for Due/Uno/Leonardo use the hardware SPI pins (which are different)
#define _sclk 52
#define _miso 50
#define _mosi 51
#define _cs 53
#define _rst 7
#define _dc 6
#define SD_CS 5



Adafruit_ILI9340 tft = Adafruit_ILI9340(_cs, _dc, _rst);

void setup() {
   Serial.begin(9600);
  
  //Init the SD Card
  Serial.print("Initializing SD card...");
  if (!SD.begin(SD_CS)) {
    Serial.println("failed!");
    //return;
  }
  Serial.println("OK!");
  
  //Start the TFT screen and paint it black
  tft.begin();
  tft.setRotation(4);
  tft.fillScreen(ILI9340_BLACK);
  
  //Draw TRD Logo before turing on backlight
 
  bmpDraw("toyota.bmp", 0, 0);
  
  //fade in back lighting
  for(int b=0; b < 230; b++){
    analogWrite(2, b);
    delay(5);
  }
  
  //Sleep a while to display the logo
  delay(2000);
  tft.fillScreen(ILI9340_BLACK);
   
  //Draw static screen elements
  bmpDraw("temp.bmp", 25, 235);
 // bmpDraw("fuel.bmp", 10, 235);
  
   
}
 

// the loop routine runs over and over again forever:
void loop(){
int sensorValue = analogRead(A0);
  // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
  float voltage = sensorValue * (5.0 / 1023.0);
  // print out the value you read:
  Serial.println(voltage);
  
  int sensorValue2 = analogRead(A1);
  // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
  float fuel = sensorValue2 * (5.0 / 1023.0);
  // print out the value you read:
  Serial.println(fuel);
  
  tft.fillScreen(ILI9340_BLACK);
   
  tft.drawRect(75,150,10,150,ILI9340_WHITE);  // Draw Temp Rect
  if(voltage > 4.93 && voltage <=4.97) {tft.fillRect(75,150,10,0,ILI9340_WHITE);}
  if(voltage > 4.86 && voltage <=4.93){ tft.fillRect(75,150,10,18.75,ILI9340_WHITE);}
  if(voltage > 4.72 && voltage <=4.86) {tft.fillRect(75,150,10,37.5,ILI9340_WHITE);}
  if(voltage > 4.47 && voltage <=4.72){ tft.fillRect(75,150,10,56.25,ILI9340_WHITE);}
  if(voltage > 4.04 && voltage <=4.47) {tft.fillRect(75,150,10,75,ILI9340_WHITE);}
  if(voltage > 3.40 && voltage <=4.04){ tft.fillRect(75,150,10,93.75,ILI9340_WHITE);}
  if(voltage > 3.22 && voltage <=3.40) {tft.fillRect(75,150,10,112.5,ILI9340_RED);}
  if(voltage > 2.57 && voltage <=3.22){ tft.fillRect(75,150,10,131.25,ILI9340_RED);}
  if(voltage > 0 && voltage <=2.57){ tft.fillRect(75,150,10,150,ILI9340_RED);}

  tft.drawRect(165,150,10,150,ILI9340_WHITE);  // Draw Fuel Rect
  if(fuel > 4.93 && fuel <=4.97) {tft.fillRect(165,150,10,0,ILI9340_WHITE);}
  if(fuel > 4.86 && fuel <=4.93){ tft.fillRect(165,150,10,18.75,ILI9340_WHITE);}
  if(fuel > 4.72 && fuel <=4.86) {tft.fillRect(165,150,10,37.5,ILI9340_WHITE);}
  if(fuel > 4.47 && fuel <=4.72){ tft.fillRect(165,150,10,56.25,ILI9340_WHITE);}
  if(fuel > 4.04 && fuel <=4.47) {tft.fillRect(165,150,10,75,ILI9340_WHITE);}
  if(fuel > 3.40 && fuel <=4.04){ tft.fillRect(165,150,10,93.75,ILI9340_WHITE);}
  if(fuel > 3.22 && fuel <=3.40) {tft.fillRect(165,150,10,112.5,ILI9340_RED);}
  if(fuel > 2.57 && fuel <=3.22){ tft.fillRect(165,150,10,131.25,ILI9340_RED);}
  if(fuel > 0 && fuel <=2.57){ tft.fillRect(165,150,10,150,ILI9340_RED);}

  delay(5000);   
  }

Wouldn't you jut "unfill" the bar rather than filling it? You have to re-draw it all anyway.

johanb7:
I want to to fill from bottom to top, how can i do this?

Rectangles are drawn relative to the top left corner.

The x coord increases from left to right and the y coord from top to bottom. See here.

So to take one example line from your code you need to change it to:

  if(voltage > 4.47 && voltage <=4.72){ tft.fillRect(75,150 + (150 - 56) ,10, 56 ,ILI9340_WHITE);}

Note the extra (150 - 56) where 56 is the height of the filled rectangle. You can use the same approach for all other lines.

Note that the width and height values for the rectangles are integers so there is no need to use floating point values.

If you did not clear the screen each time then you would not have to draw it all again, instead you could only draw the bits that change, however the code is then a bit more complex.

You may like to look at the map() function as that could be used to eliminate the "if" statements by translating the raw integer analog sensor value to filled rectangle height.

do this

tft.fillScreen(ILI9340_BLACK);
tft.drawRect(75,150,10,150,ILI9340_WHITE);  // Draw Temp Rect
tft.drawRect(165,150,10,150,ILI9340_WHITE);  // Draw Fuel Rect

only once in setup() and remove it from loop(). There is no need to clear the whole screen and draw the white rectangles every 5 seconds. You only need to refresh the bars inside those rectangles.
So within the white rectangle/border there are basically 2 bars. One is black (which is the background) and second is either white or red depending on the value. If the value increases draw the white/red filled rectangle, if the value decreases draw the black/background filled rectangle.

I love you Marek!

I would always draw both filled rectangles. Your suggestion is so much better.

David.

The ultimate approach is to remember the last value and only draw the difference rectangle (foreground or background etc) between the new and old values depending on whether the new value is bigger or smaller.

This is the approach I use on animated graphics displays and makes the display very responsive. Video is an UNO driving a 2.2" TFT via SPI.

1 Draw first rectangle up to down: 100% to data%
2 Draw second rectangle down to up: 0 to data%

Video: fill rect

@rowboteer It's works like a charm , Thanks !
@MarekB if i remove it from the loop, the bar wont go down anymore only up because its not refreshing.

OK, great. The trick is to realise the y coordinate increases going from top to bottom so the top side of the rectangle has the lowest y coordinate value. This inversion of the y axis is a peculiarity of display coordinate systems.

Good luck with your project.

P.S. I note words like "Toyota" and "Fuel level" in your code that provide hints to your project objective.... be aware that interfacing with fuel level sensors in cars is potentially hazardous and the supply voltage spikes you typically get on the 12V power (really short 100V+ spikes are not unusual when starting the car!) can destroy boards like Arduinos. If you are installing your project (as hinted) in a car I suggest using a fused USB 5V feed from an accessory (cigarette lighter) socket as good quality USB adapters contain spike suppression. If you add long leads from the analogue ports to sensors in a car they will pick up spikes by magnetic induction/electric coupling and may blow the Arduinos input port buffer, so add RC filters to those inputs. Using twisted pair wires and/or shielded cables to sensors will help with noise and spike pickup.

johanb7:
@rowboteer It's works like a charm , Thanks !
@MarekB if i remove it from the loop, the bar wont go down anymore only up because its not refreshing.

Yes, because you need to do this as well:
So within the white rectangle/border there are basically 2 bars. One is black (which is the background) and second is either white or red depending on the value. If the value increases draw the white/red filled rectangle, if the value decreases draw the black/background filled rectangle.

Otherwise it won't work. You are only drawing the white/red filled rectangle at the moment. You need to remember the last voltage/fuel level value that you drew in the last loop and compare it to the current value. If you current value is higher than the last value then draw the white/red fillled rect, if it's lower then draw the black filled rect. On the video from TFTLCDCyg your white/red rect is his green one and your black rect is his red rect. You always draw that filled rect which has increased in height.

Sorry my stupidity I'm new to Arduino I would like this bar to stay horizontal How to do this Can someone help me

TFTLCDCyg:
Try this

#include "SPI.h"

#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"

#define TFT_DC 9
#define TFT_CS 10
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);

char TX[20];
int Temperature1;      // Temperature sensor
int lecT1px;              //  Temperature in pixels
int maxpx = 70;        // Temperature-bar height in pixels
int Dx = 20;              // Bar wide in pixels
int maxscale = 100;  // Scale: 0C to 100C (for example)

void setup() {
  tft.begin();  tft.setRotation(3); 
  tft.fillScreen(ILI9341_BLUE);

tft.setTextColor(ILI9341_YELLOW);
  tft.setTextSize(2);  tft.setCursor(20, 20);  tft.print("Temperature bar"); 

 
void loop() {
  Temperature1 = random(maxscale);  sprintf(TX,"T = %03d  C", Temperature1); 
  tft.setTextSize(2);    tft.setTextColor(ILI9341_WHITE, ILI9341_BLUE); tft.setCursor(50, 50);  tft.print(TX);         
   
    lecT1px = Temperature1*maxpx/maxscale;  //temperature to pixels equivalent

tft.fillRect(95,100,Dx,maxpx-lecT1px,ILI9341_BLACK);          // bar-direction: up to down
  tft.fillRect(95,100+maxpx-lecT1px,Dx,lecT1px,ILI9341_GREEN); // bar-direction: down to up
  tft.drawRect(95-1,100-1,Dx+2,maxpx+2,ILI9341_WHITE);        // external cover bar

tft.setTextSize(1); 
  sprintf(TX,"%d  C", maxscale);  tft.setTextColor(ILI9341_WHITE);
  tft.setCursor(120, 95);  tft.print(TX);   
  sprintf(TX,"%d  C", 0); 
  tft.setCursor(120, 95+maxpx);  tft.print(TX);

delay(150);
}




Changes:

1 Libs and hadware setup: ILI9341 to ILI9340
2 Color definitions: ILI9341_ to ILI9340_

Enjoy it!