Friday, November 14, 2014

2.4" touch TFT LCD shield

   I purchased from ebay  a cheap 2.4" touch TFT LCD shield for Arduino Uno:
   For control the display I try library recomanded by buyer but not work at me. I search on net and I found article named A 2.4″ TFT TOUCHSCREEN SHIELD FOR ARDUINO
   Smoke and Wires change TFT libray from Adafruit for works with this display. The new library is SWTFT. You must have alse Touch Screen library and Adafruit GFX library.
   First, I tryed examples from SWTFT library and I made a movie:
and few pics:
   For understund the example from SWTFT library, I change the sketch and my results are:


   Finally, I try this:

and my sketch is:
// Original code provided by Smoke And Wires
// http://www.smokeandwires.co.nz
// This code has been taken from the Adafruit TFT Library and modified
//  by us for use with our TFT Shields / Modules
// For original code / licensing please refer to
// https://github.com/adafruit/TFTLCD-Library

// adapted sketch by niq_ro from http://arduinotehniq.blogspot.com/
// ver. 1m5 - 13.11.2014, Craiova - Romania

#include <Adafruit_GFX.h>    // Core graphics library
#include "SWTFT.h" // Hardware-specific library

// The control pins for the LCD can be assigned to any digital or
// analog pins...but we'll use the analog pins as this allows us to
// double up the pins with the touch screen (see the TFT paint example).
// #define LCD_CS A3 // Chip Select goes to Analog 3
// #define LCD_CD A2 // Command/Data goes to Analog 2
// #define LCD_WR A1 // LCD Write goes to Analog 1
// #define LCD_RD A0 // LCD Read goes to Analog 0

// #define LCD_RESET A4 // Can alternately just connect to Arduino's reset pin

// When using the BREAKOUT BOARD only, use these 8 data lines to the LCD:
// For the Arduino Uno, Duemilanove, Diecimila, etc.:
//   D0 connects to digital pin 8  (Notice these are
//   D1 connects to digital pin 9   NOT in order!)
//   D2 connects to digital pin 2
//   D3 connects to digital pin 3
//   D4 connects to digital pin 4
//   D5 connects to digital pin 5
//   D6 connects to digital pin 6
//   D7 connects to digital pin 7
// For the Arduino Mega, use digital pins 22 through 29
// (on the 2-row header at the end of the board).


#include <Adafruit_GFX.h>    // Core graphics library
#include <SWTFT.h> // Hardware-specific library
#include <TouchScreen.h>




#define YP A1  // must be an analog pin, use "An" notation!
#define XM A2  // must be an analog pin, use "An" notation!
#define YM 7   // can be a digital pin
#define XP 6   // can be a digital pin

#define TS_MINX 150
#define TS_MINY 120
#define TS_MAXX 920
#define TS_MAXY 940

// For better pressure precision, we need to know the resistance
// between X+ and X- Use any multimeter to read it
// For the one we're using, its 300 ohms across the X plate
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);

// Assign human-readable names to some common 16-bit color values:
#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 ROZ     0xFD20
#define ROZ     0xFBE0
#define GRI     0xBDF7
// http://stackoverflow.com/questions/13720937/c-defined-16bit-high-color
// http://wiibrew.org/wiki/U16_colors

SWTFT tft;

#define BOXSIZE 40
#define PENRADIUS 3
int oldcolor, currentcolor;
int ics; 

void setup(void) {
  Serial.begin(9600);
  Serial.println(F("Paint!"));
  
  tft.reset();
  
  uint16_t identifier = tft.readID();

  Serial.print(F("LCD driver chip: "));
  Serial.println(identifier, HEX);
    

  tft.begin(identifier);

  tft.fillScreen(BLACK);
  tft.fillRect(0, 0, 320, 240, BLACK);
  tft.setRotation(3);
  tft.setCursor(30, 100);
  tft.setTextColor(RED);  tft.setTextSize(3);
  tft.println("LCD driver chip: ");
  tft.setCursor(100, 150);
  tft.setTextColor(BLUE);
  tft.println(identifier, HEX);

delay(2000);
tft.fillRect(0, 0, 320, 240, BLACK);
  
tft.setRotation(0);
  tft.fillRect(0, 0, BOXSIZE, BOXSIZE, RED);
  tft.fillRect(0, BOXSIZE, BOXSIZE, BOXSIZE, YELLOW);
  tft.fillRect(0, BOXSIZE*2, BOXSIZE, BOXSIZE, GREEN);
  tft.fillRect(0, BOXSIZE*3, BOXSIZE, BOXSIZE, CYAN);
  tft.fillRect(0, BOXSIZE*4, BOXSIZE, BOXSIZE, BLUE);
  tft.fillRect(0, BOXSIZE*5, BOXSIZE, BOXSIZE, MAGENTA);
  tft.fillRect(0, BOXSIZE*6, BOXSIZE, BOXSIZE, GRI);
  tft.fillRect(0, BOXSIZE*7, BOXSIZE, BOXSIZE,  ROZ);
//tft.fillRect(BOXSIZE, BOXSIZE, BOXSIZE, BOXSIZE, WHITE);
 
  tft.drawRect(0, 0, BOXSIZE, BOXSIZE, WHITE);
  currentcolor = RED;


 cifre (WHITE);
  pinMode(13, OUTPUT);
}

#define MINPRESSURE 10
#define MAXPRESSURE 1000

void loop()
{
  digitalWrite(13, HIGH);
  // Recently Point was renamed TSPoint in the TouchScreen library
  // If you are using an older version of the library, use the
  // commented definition instead.
  // Point p = ts.getPoint();
  TSPoint p = ts.getPoint();
  digitalWrite(13, LOW);

  // if sharing pins, you'll need to fix the directions of the touchscreen pins
  //pinMode(XP, OUTPUT);
  pinMode(XM, OUTPUT);
  pinMode(YP, OUTPUT);
  //pinMode(YM, OUTPUT);

  // we have some minimum pressure we consider 'valid'
  // pressure of 0 means no pressing!

  if (p.z > MINPRESSURE && p.z < MAXPRESSURE) {
  /*  
    Serial.print("X = "); Serial.print(p.x);
    Serial.print("\tY = "); Serial.print(p.y);
    Serial.print("\tPressure = "); Serial.println(p.z);
  */      
if (p.y < (TS_MINY-5)) stergere();
    // scale from 0->1023 to tft.width
    p.x = tft.width()-(map(p.x, TS_MINX, TS_MAXX, tft.width(), 0));
    p.y = tft.height()-(map(p.y, TS_MINY, TS_MAXY, tft.height(), 0));
  /*  
    Serial.print("("); Serial.print(p.x);
    Serial.print(", "); Serial.print(p.y);
    Serial.println(")");
  */  
    if (p.x < BOXSIZE) {
       oldcolor = currentcolor;

       if (p.y < BOXSIZE) { 
         currentcolor = RED; 
         tft.drawRect(0, 0, BOXSIZE, BOXSIZE, WHITE); 
//         text (currentcolor);
       } else if (p.y < BOXSIZE*2) {
         currentcolor = YELLOW;
         tft.drawRect(0, BOXSIZE, BOXSIZE, BOXSIZE, WHITE);
//         text (currentcolor);
       } else if (p.y < BOXSIZE*3) {
         currentcolor = GREEN;
         tft.drawRect(0, BOXSIZE*2, BOXSIZE, BOXSIZE, WHITE);
//         text (currentcolor);
       } else if (p.y < BOXSIZE*4) {
         currentcolor = CYAN;
         tft.drawRect(0, BOXSIZE*3, BOXSIZE, BOXSIZE, WHITE);       
//         text (currentcolor);
       } else if (p.y < BOXSIZE*5) {
         currentcolor = BLUE;
         tft.drawRect(0, BOXSIZE*4, BOXSIZE, BOXSIZE, WHITE);        
//         text (currentcolor);
       } else if (p.y < BOXSIZE*6) {
         currentcolor = MAGENTA;
         tft.drawRect(0,BOXSIZE*5, BOXSIZE, BOXSIZE, WHITE);        
//         text (currentcolor);
       } else if (p.y < BOXSIZE*7) {
         currentcolor = GRI;
         tft.drawRect(0,BOXSIZE*6, BOXSIZE, BOXSIZE, WHITE);        
//         text (currentcolor);
       } else if (p.y < BOXSIZE*8) {
         currentcolor = ROZ;
         tft.drawRect(0,BOXSIZE*7, BOXSIZE, BOXSIZE, WHITE);
         stergere();        
       }

text (currentcolor);
//cifre (currentcolor);
       if (oldcolor != currentcolor) {
          if (oldcolor == RED) tft.fillRect(0, 0, BOXSIZE, BOXSIZE, RED);
          if (oldcolor == YELLOW) tft.fillRect(0, BOXSIZE, BOXSIZE, BOXSIZE, YELLOW);
          if (oldcolor == GREEN) tft.fillRect(0, BOXSIZE*2, BOXSIZE, BOXSIZE, GREEN);
          if (oldcolor == CYAN) tft.fillRect(0, BOXSIZE*3, BOXSIZE, BOXSIZE, CYAN);
          if (oldcolor == BLUE) tft.fillRect(0, BOXSIZE*4, BOXSIZE, BOXSIZE, BLUE);
          if (oldcolor == MAGENTA) tft.fillRect(0, BOXSIZE*5, BOXSIZE, BOXSIZE, MAGENTA);
          if (oldcolor == GRI) tft.fillRect(0, BOXSIZE*6, BOXSIZE, BOXSIZE, GRI);
          if (oldcolor == ROZ) tft.fillRect(0, BOXSIZE*7, BOXSIZE, BOXSIZE, ROZ);
     cifre (currentcolor);  
     }
      
    }
   // if (((p.y-PENRADIUS) > BOXSIZE) && ((p.y+PENRADIUS) < tft.height())) {
/*
if (((p.y-PENRADIUS) > 5) && ((p.y+PENRADIUS) < tft.height())) {
   tft.fillCircle(p.x, p.y, PENRADIUS, currentcolor);
    }
*/
if (((p.x-PENRADIUS) > BOXSIZE) && ((p.x+PENRADIUS) < tft.width())) {
   tft.fillCircle(p.x, p.y, PENRADIUS, currentcolor);
    }

  }
}

void text (int culoare) 
{
tft.setRotation(3);
tft.setCursor(70, 80);
          tft.setTextColor(culoare);  tft.setTextSize(5);
 /*         tft.println("niq_ro");
          tft.setCursor(12, 130); tft.setTextSize(3);
          tft.println("www.tehnic.go.ro");
          tft.setCursor(20, 165); tft.setTextSize(2);
          tft.println("nicuflorica.blogspot.ro");
*/
          tft.setCursor(5, 220); tft.setTextSize(2);
          tft.println("arduinotehniq.blogspot.com");
tft.setRotation(0);
}

void cifre (int culoare)
{
// number for "buttons"
 tft.setRotation(3);
 tft.setTextColor(culoare);
 tft.setTextSize(3);
 tft.drawLine(0, 0, 40, 40, culoare);
 tft.drawLine(0, 40, 40, 0, culoare);
// tft.setCursor(15, 10);
// tft.println("1");
 tft.setCursor(55, 10);
 tft.println("1");
 tft.setCursor(95, 10);
 tft.println("2");
 tft.setCursor(135, 10);
 tft.println("3");
 tft.setCursor(175, 10);
 tft.println("4");
 tft.setCursor(215, 10);
 tft.println("5");
 tft.setCursor(255, 10);
 tft.println("6");
 tft.setCursor(295, 10);
 tft.println("7");
  
 tft.setRotation(0);
}

void stergere ()
{
      Serial.println("erase");
      // press the bottom of the screen to erase 
 //     tft.fillRect(0, BOXSIZE, tft.width(), tft.height()-BOXSIZE, BLACK);
   tft.fillRect(0, 0, 240, 320, BLACK);
   tft.setRotation(0);
  tft.fillRect(0, 0, BOXSIZE, BOXSIZE, RED);
  tft.fillRect(0, BOXSIZE, BOXSIZE, BOXSIZE, YELLOW);
  tft.fillRect(0, BOXSIZE*2, BOXSIZE, BOXSIZE, GREEN);
  tft.fillRect(0, BOXSIZE*3, BOXSIZE, BOXSIZE, CYAN);
  tft.fillRect(0, BOXSIZE*4, BOXSIZE, BOXSIZE, BLUE);
  tft.fillRect(0, BOXSIZE*5, BOXSIZE, BOXSIZE, MAGENTA);
  tft.fillRect(0, BOXSIZE*6, BOXSIZE, BOXSIZE, GRI);
  tft.fillRect(0, BOXSIZE*7, BOXSIZE, BOXSIZE,  ROZ);
//tft.fillRect(BOXSIZE, BOXSIZE, BOXSIZE, BOXSIZE, WHITE);
 
  tft.drawRect(0, 0, BOXSIZE, BOXSIZE, WHITE);
  currentcolor = RED;
     cifre (WHITE);  
    }
   

Saturday, October 18, 2014

Old GPS receiver and Arduino = speedometer

   I made a speedometer with GPS coordinates and clock using: an old GPS receiver, Arduino board, alphanumeric LCD with 20 columns and 4 rows.
   To find offered datas from GPS receiver, I followed the information provided in article tronixstuffial – Arduino and EM406A GPS:
   After I study article named NMEA data and I selectet usefull datas for speed:
   I use TinyGPS++ library made by Mikal Hart and I extract speed:
TinyGPSCustom zdop(gps, "GPVTG", 7); // $GPVTG sentence, 7th element 
   I designed this schematic for tests:

   I write more sketches but last is 1.6.5 version:
// source: http://arduiniana.org/libraries/tinygpsplus/
// for see your position: http://www.gps-coordinates.net/
// for new article made by niq_ro: http://nicuflorica.blogspot.com/
// & http://arduiniq.blogspot.com/
#include <TinyGPS++.h>
#include <SoftwareSerial.h>

/*
   This sample code demonstrates the normal use of a TinyGPS++ (TinyGPSPlus) object.
   It requires the use of SoftwareSerial, and assumes that you have a
   4800-baud serial GPS device hooked up on pins 4(rx) and 3(tx).
*/
static const int RXPin = 4, TXPin = 3;
static const uint32_t GPSBaud = 4800;

// The TinyGPS++ object
TinyGPSPlus gps;

// The serial connection to the GPS device
SoftwareSerial ss(RXPin, TXPin);

#include <LiquidCrystal.h>
// folosesc libraria pentru afisaje LCD simple
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
// indic modul de legare, vezi mai jos:
/*                                    -------------------
                                      |  LCD  | Arduino |
                                      -------------------
 LCD RS pin to digital pin 7          |  RS   |   D7    |
 LCD Enable pin to digital pin 6      |  E    |   D8    |
 LCD D4 pin to digital pin 5          |  D4   |   D9    |
 LCD D5 pin to digital pin 4          |  D5   |   D10   |
 LCD D6 pin to digital pin 3          |  D6   |   D11   |
 LCD D7 pin to digital pin 2          |  D7   |   D12   |
 LCD R/W pin to ground                |  R/W  |   GND   |
                                      -------------------
niq_ro adapted this sketch for see data on 2004 LCD
*/

/* A set of custom made large numbers for a 16x2 LCD using the 
 LiquidCrystal library. Works with displays compatible with the 
 Hitachi HD44780 driver. Made by Michael Pilcher, 2/9/2010
*/ 

int x = 0;
// the 8 arrays that form each segment of the custom numbers
byte LT[8] = 
{
  B00111,
  B01111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111
};
byte UB[8] =
{
  B11111,
  B11111,
  B11111,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000
};
byte RT[8] =
{
  B11100,
  B11110,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111
};
byte LL[8] =
{
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B01111,
  B00111
};
byte LB[8] =
{
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B11111,
  B11111,
  B11111
};
byte LR[8] =
{
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11110,
  B11100
};
byte UMB[8] =
{
  B11111,
  B11111,
  B11111,
  B00000,
  B00000,
  B00000,
  B11111,
  B11111
};
byte LMB[8] =
{
  B11111,
  B00000,
  B00000,
  B00000,
  B00000,
  B11111,
  B11111,
  B11111
};


// for speed in knots (noduri) 
//TinyGPSCustom sdop(gps, "GPVTG", 5); // $GPVTG sentence, 5th element
// for speed in kilometers per hour
TinyGPSCustom zdop(gps, "GPVTG", 7); // $GPVTG sentence, 7th element 

void setup()
{
  Serial.begin(115200);
  ss.begin(GPSBaud);

  Serial.println(F("FullExample.ino"));
  Serial.println(F("An extensive example of many interesting TinyGPS++ features"));
  Serial.print(F("Testing TinyGPS++ library v. ")); Serial.println(TinyGPSPlus::libraryVersion());
  Serial.println(F("by Mikal Hart"));
  Serial.println();
  Serial.println(F("Sats HDOP Latitude   Longitude   Fix  Date       Time     Date Alt    Course Speed Card  Distance Course Card  Chars Sentences Checksum"));
  Serial.println(F("          (deg)      (deg)       Age                      Age  (m)    --- from GPS ----  ---- to London  ----  RX    RX        Fail"));
  Serial.println(F("---------------------------------------------------------------------------------------------------------------------------------------"));


lcd.begin(20, 4); // set up the LCD's number of columns and rows: 

// assignes each segment a write number
  lcd.createChar(8,LT);
  lcd.createChar(1,UB);
  lcd.createChar(2,RT);
  lcd.createChar(3,LL);
  lcd.createChar(4,LB);
  lcd.createChar(5,LR);
  lcd.createChar(6,UMB);
  lcd.createChar(7,LMB);

 lcd.clear(); // clear the screen
 lcd.setCursor(1, 0); // put cursor at colon x and row y
 lcd.print("GPS data - 7.2014"); // print a text
 lcd.setCursor(0, 1); // put cursor at colon x and row y
 lcd.print("ver 1.6.5 by niq_ro"); // print a text
 lcd.setCursor(1, 2); // put cursor at colon x and row y
 lcd.print("Craiova - Romania"); // print a text
 lcd.setCursor(0, 3); // put cursor at colon x and row y
 lcd.print("(TinyGPS++ library)"); // print a text
 
 delay (2000);
 lcd.clear(); // clear the screen
 
/* 
// testare la inceput mod afisare viteza
lcd.setCursor(2,0);
 lcd.print("niq_ro testeaza");
 lcd.setCursor(1,1);
 lcd.print("afisarea vitezei:"); 
for (int q=0; q<120; q=q++)
 {
 vitezamare(q); 
 lcd.setCursor(12,3); 
 lcd.print("km/h");
 delay(200);
 lcd.setCursor(0,2);
 lcd.print("           ");
 lcd.setCursor(0,3);
 lcd.print("           ");
}
*/
 lcd.clear(); // clear the screen
 delay(500);
}


void loop()
{
  // partea de ecran LCD 20x4
  afisareecran();


  // scot viteza 
 int viteza = atoi (zdop.value());
 //int viteza = 123;
 //int viteza = 456;
 //int viteza = 789;
 //int viteza = 92;
 //int viteza = 6;
 //int viteza = 0;
 vitezamare(viteza); 
 lcd.setCursor(12,3); 
 lcd.print("km/h");
  
  
  
  static const double LONDON_LAT = 51.508131, LONDON_LON = -0.128002;

  printInt(gps.satellites.value(), gps.satellites.isValid(), 5);
  printInt(gps.hdop.value(), gps.hdop.isValid(), 5);
  printFloat(gps.location.lat(), gps.location.isValid(), 11, 6);
  printFloat(gps.location.lng(), gps.location.isValid(), 12, 6);
  printInt(gps.location.age(), gps.location.isValid(), 5);
  printDateTime(gps.date, gps.time);
  printFloat(gps.altitude.meters(), gps.altitude.isValid(), 7, 2);
  printFloat(gps.course.deg(), gps.course.isValid(), 7, 2);
  printFloat(gps.speed.kmph(), gps.speed.isValid(), 6, 2);
  printStr(gps.course.isValid() ? TinyGPSPlus::cardinal(gps.course.value()) : "*** ", 6);

  unsigned long distanceKmToLondon =
    (unsigned long)TinyGPSPlus::distanceBetween(
      gps.location.lat(),
      gps.location.lng(),
      LONDON_LAT, 
      LONDON_LON) / 1000;
  printInt(distanceKmToLondon, gps.location.isValid(), 9);

  double courseToLondon =
    TinyGPSPlus::courseTo(
      gps.location.lat(),
      gps.location.lng(),
      LONDON_LAT, 
      LONDON_LON);

  printFloat(courseToLondon, gps.location.isValid(), 7, 2);

  const char *cardinalToLondon = TinyGPSPlus::cardinal(courseToLondon);

  printStr(gps.location.isValid() ? cardinalToLondon : "*** ", 6);

  printInt(gps.charsProcessed(), true, 6);
  printInt(gps.sentencesWithFix(), true, 10);
  printInt(gps.failedChecksum(), true, 9);

  // speed in km/h
  Serial.print(" ");
  Serial.print(zdop.value());
  int vitesa1 = atoi (zdop.value());
  Serial.print("/");
  Serial.print(vitesa1);
  Serial.println();
  
  smartDelay(1000);

  if (millis() > 5000 && gps.charsProcessed() < 10)
    Serial.println(F("No GPS data received: check wiring"));
}

// This custom version of delay() ensures that the gps object
// is being "fed".
static void smartDelay(unsigned long ms)
{
  unsigned long start = millis();
  do 
  {
    while (ss.available())
      gps.encode(ss.read());
  } while (millis() - start < ms);
}

static void printFloat(float val, bool valid, int len, int prec)
{
  if (!valid)
  {
    while (len-- > 1)
      Serial.print('*');
    Serial.print(' ');
  }
  else
  {
    Serial.print(val, prec);
    int vi = abs((int)val);
    int flen = prec + (val < 0.0 ? 2 : 1); // . and -
    flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
    for (int i=flen; i<len; ++i)
      Serial.print(' ');
  }
  smartDelay(0);
}

static void printInt(unsigned long val, bool valid, int len)
{
  char sz[32] = "*****************";
  if (valid)
    sprintf(sz, "%ld", val);
  sz[len] = 0;
  for (int i=strlen(sz); i<len; ++i)
    sz[i] = ' ';
  if (len > 0) 
    sz[len-1] = ' ';
  Serial.print(sz);
  smartDelay(0);
}

static void printDateTime(TinyGPSDate &d, TinyGPSTime &t)
{
  if (!d.isValid())
  {
    Serial.print(F("********** "));
  }
  else
  {

    char sz[32];
   sprintf(sz, "%02d/%02d/%02d ", d.month(), d.day(), d.year());
//    sprintf(sz, "%02d/%02d/%02d ", gps.date.month(), gps.date.day(), gps.date.year());
    Serial.print(sz);
  }
  
  if (!t.isValid())
  {
    Serial.print(F("******** "));
  }
  else
  {
    char sz[32];
    sprintf(sz, "%02d:%02d:%02d ", t.hour(), t.minute(), t.second());
//  sprintf(sz, "%02d:%02d:%02d ", gps.time.hour(), gps.time.minute(), gps.time.second());
    Serial.print(sz);

  }

  printInt(d.age(), d.isValid(), 5);
  smartDelay(0);
}

static void printStr(const char *str, int len)
{
  int slen = strlen(str);
  for (int i=0; i<len; ++i)
    Serial.print(i<slen ? str[i] : ' ');
  smartDelay(0);
}

static void afisareecran()
{
// lcd.clear(); // clear the screen

// partea de ora
// ora de vara a Romaniei - 
// trebuie sa pun un comutator pentru selectie de iarna si de vara
 int ora = 3 + gps.time.hour();
 if (ora ==24) ora=0;
 if (ora ==25) ora=1;
 if (ora ==26) ora=2;
 lcd.setCursor(12,2); // put cursor at colon 2 and row 2
 if (ora<10) lcd.print(" "); 
 lcd.print(ora); 
 lcd.print(":");
 if (gps.time.minute()<10) lcd.print("0"); 
 lcd.print(gps.time.minute()); 
 lcd.print(":");
 if (gps.time.second()<10) lcd.print("0"); 
 lcd.print(gps.time.second()); 


// parte de coordonate GPS
 lcd.setCursor(0,0); // put cursor at colon 0 and row 0 = left/up
 lcd.print("LAT:");
 lcd.print(gps.location.lat(),6);
 lcd.write(0b11011111);
 lcd.setCursor(0,1); // put cursor at colon 0 and row 1 
 lcd.print("LON:");
 lcd.print(gps.location.lng(),6);
 lcd.write(0b11011111);

// numar sateliti receptionati
 lcd.setCursor(16,0); // put cursor at colon 15 and row 2
 lcd.print(gps.satellites.value());
// if (gps.satellites.value() == 1) lcd.print(" satelit ");
// else
 lcd.print("sat");

// viteza
/*
lcd.setCursor(10,3); // put cursor at colon x and row y
double viteza = gps.speed.kmph(); 
// tests
// double viteza = 0.;
// double viteza = 5;
// double viteza = 14;
// double viteza = 104;
 if (viteza>100.0) lcd.print(viteza);
 else
 if (viteza>10.0) {lcd.print(" "); lcd.print(viteza);}
 else 
 if (viteza<10.0) {lcd.print("  "); lcd.print(viteza);}
// lcd.print(viteza);
// lcd.print(gps.speed.kmph());
 lcd.print("km/h");
*/

/*
// altitudine
  lcd.setCursor(16,0); // put cursor at colon 16 and row 0
  lcd.print("ALT:");
  int cota = gps.altitude.meters();
  lcd.setCursor(15,1); // put cursor at colon 15 and row 1
// cota=5;
//cota=15;
//cota=497;
//cota=2056;
 if (cota>1000) lcd.print(cota);
 else
 if (cota>100) {lcd.print(" "); lcd.print(cota);}
 else
 if (cota>10) {lcd.print("  "); lcd.print(cota);}
 if (cota<10) {lcd.print("   "); lcd.print(cota);}
 lcd.print("m");
*/

/* 
// viteza extrasa custom
 lcd.setCursor(0,3); // put cursor at colon x and row y
 lcd.print("viteza: ");
 int viteza = atoi (zdop.value());
// lcd.print(zdop.value());
 if (viteza>100.0) lcd.print(viteza);
 else
 if (viteza>10.0) {lcd.print(" "); lcd.print(viteza);}
 else 
 if (viteza<10.0) {lcd.print("  "); lcd.print(viteza);}
 lcd.print("km/h");
*/ 
 }  



 
void custom0O()  // uses segments to build the number 0
{ 
  lcd.setCursor(x, 2); 
  lcd.write(8);  
  lcd.write(1); 
  lcd.write(2);
  lcd.setCursor(x, 3); 
  lcd.write(3);  
  lcd.write(4);  
  lcd.write(5);
}

void custom1()
{
  lcd.setCursor(x,2);
  lcd.write(1);
  lcd.write(2);
  lcd.setCursor(x,3);
  lcd.write(4);
  lcd.write(255);
  lcd.write(4);
}

void custom2()
{
  lcd.setCursor(x,2);
  lcd.write(6);
  lcd.write(6);
  lcd.write(2);
  lcd.setCursor(x, 3);
  lcd.write(3);
  lcd.write(7);
  lcd.write(7);
}

void custom3()
{
  lcd.setCursor(x,2);
  lcd.write(6);
  lcd.write(6);
  lcd.write(2);
  lcd.setCursor(x, 3);
  lcd.write(7);
  lcd.write(7);
  lcd.write(5); 
}

void custom4()
{
  lcd.setCursor(x,2);
  lcd.write(3);
  lcd.write(4);
  lcd.write(2);
  lcd.setCursor(x+2, 3);
  lcd.write(255);
}

void custom5()
{
  lcd.setCursor(x,2);
  lcd.write(255);
  lcd.write(6);
  lcd.write(6);
  lcd.setCursor(x, 3);
  lcd.write(7);
  lcd.write(7);
  lcd.write(5);
}

void custom6()
{
  lcd.setCursor(x,2);
  lcd.write(8);
  lcd.write(6);
  lcd.write(6);
  lcd.setCursor(x, 3);
  lcd.write(3);
  lcd.write(7);
  lcd.write(5);
}

void custom7()
{
  lcd.setCursor(x,2);
  lcd.write(1);
  lcd.write(1);
  lcd.write(2);
  lcd.setCursor(x+1, 3);
  lcd.write(8);
}

void custom8()
{
  lcd.setCursor(x,2);
  lcd.write(8);
  lcd.write(6);
  lcd.write(2);
  lcd.setCursor(x, 3);
  lcd.write(3);
  lcd.write(7);
  lcd.write(5);
}

void custom9()
{
  lcd.setCursor(x,2);
  lcd.write(8);
  lcd.write(6);
  lcd.write(2);
  lcd.setCursor(x, 3);
  lcd.write(7);
  lcd.write(7);
  lcd.write(5);
}

// subrutina de afisare a numerelor
void afisarenumar(int numar)
{
  switch (numar)
  {
    case 0:
    custom0O();
    break;

    case 1:
    custom1();
    break;

    case 2:
    custom2();
    break;

    case 3:
    custom3();
    break;

    case 4:
    custom4();
    break;

    case 5:
    custom5();
    break;

    case 6:
    custom6();
    break;

    case 7:
    custom7();
    break;

    case 8:
    custom8();
    break;

    case 9:
    custom9();
    break;
  }
}

void vitezamare(int viteza)
{
  // sterg zona de afisare a vitezei
 lcd.setCursor(0,2);
 lcd.print("           ");
 lcd.setCursor(0,3);
 lcd.print("           ");
   
if (viteza>=100)
{
  x = 0;
  afisarenumar(int(viteza/100));
  viteza=viteza % 100;

  x = x + 4;
  afisarenumar(viteza/10);
  
  x = x + 4;
  afisarenumar(viteza % 10);
}
else
if (viteza>=10)
{
 lcd.setCursor(0,2);
 lcd.print("   ");
 lcd.setCursor(0,3);
 lcd.print("   ");
  
  x = 4;
  afisarenumar(viteza/10);
  
  x = x + 4;
  afisarenumar(viteza % 10);
}
else 
if (viteza<10)
{
 lcd.setCursor(0,2);
 lcd.print("       ");
 lcd.setCursor(0,3);
 lcd.print("       ");
  x = 8;
  afisarenumar(viteza);
}
}
   I made few pics with speedometer in moving car:
Also, I made few movies:

   Bibliography:


BMP180 sensor and Arduino

   BMP180 sensor can give us information about pressure an temperature.
   This sensor is delivered on small module with 4 pins: Vin (+3.3V), GND, SDA and SCL.
   For testing, schematic is very simple:
   For control BMP180 sensor I use Adafruit-BMP085-Library, them test the example sketch.
   For a stand alone weather station with information about temperature and presure, I put a alphanumeric LCD display with 16 colons and 2 rows (1602):
and test montage is:
   I use this sketch:
// adapted sketch by niq_ro from http://nicuflorica.blogspot.ro/ & http://arduinotehniq.blogspot.com/
// https://github.com/adafruit/Adafruit-BMP085-Library
#include <Wire.h>
#include <Adafruit_BMP085.h>

/*************************************************** 
  This is an example for the BMP085 Barometric Pressure & Temp Sensor
  Designed specifically to work with the Adafruit BMP085 Breakout 
  ----> https://www.adafruit.com/products/391
  These displays use I2C to communicate, 2 pins are required to  
  interface
  Adafruit invests time and resources providing this open source code, 
  please support Adafruit and open-source hardware by purchasing 
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.  
  BSD license, all text above must be included in any redistribution
 ****************************************************/

// Connect VCC of the BMP085 sensor to 3.3V (NOT 5.0V!)
// Connect GND to Ground
// Connect SCL to i2c clock - on '168/'328 Arduino Uno/Duemilanove/etc thats Analog 5
// Connect SDA to i2c data - on '168/'328 Arduino Uno/Duemilanove/etc thats Analog 4
// EOC is not used, it signifies an end of conversion
// XCLR is a reset pin, also not used here

// include the library code:
#include <LiquidCrystal.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

/*                                    -------------------
                                      |  LCD  | Arduino |
                                      -------------------
 LCD RS pin to digital pin 7          |  RS   |   D7    |
 LCD Enable pin to digital pin 6      |  E    |   D6    |
 LCD D4 pin to digital pin 5          |  D4   |   D6    |
 LCD D5 pin to digital pin 4          |  D5   |   D4    |
 LCD D6 pin to digital pin 3          |  D6   |   D3    |
 LCD D7 pin to digital pin 2          |  D7   |   D2    |
 LCD R/W pin to ground                |  R/W  |   GND   |
                                      -------------------
*/



Adafruit_BMP085 bmp;
  
void setup() {
  lcd.begin(16, 2);
  // Print a logo message to the LCD.
  lcd.print("www.tehnic.go.ro");  
  lcd.setCursor(0, 1);
  lcd.print("creat de niq_ro");
  delay (2500);
  lcd.clear();

  // Print another message to the LCD.
  lcd.setCursor(2, 0);
  lcd.print("termometru -");  
  lcd.setCursor(0, 1);
  lcd.print("barometru ver1.0");
  delay (2500);
  lcd.clear();

  Serial.begin(9600);
  if (!bmp.begin()) {
 Serial.println("nu exita senzor compatibil BMP085 sau BMP180");
 while (1) {}
  }
}
  
void loop() {
    Serial.print("Temperatura = ");
    Serial.print(bmp.readTemperature());
    Serial.println(" *C");
    
    Serial.print("Presiune = ");
    Serial.print(bmp.readPressure());
    Serial.print(" Pa / ");
    
 //   Serial.print("Presiune = ");
    float presiune1 = bmp.readPressure()/101.325;
    presiune1 = presiune1 * 0.760;
    Serial.print(presiune1);
    Serial.println(" mmHg");
    
    
    // Calculate altitude assuming 'standard' barometric
    // pressure of 1013.25 millibar = 101325 Pascal
    Serial.print("Altitudine = ");
    Serial.print(bmp.readAltitude());
    Serial.println(" m");

    Serial.print("Presiune la nivelul marii (calculata) = ");
    Serial.print(bmp.readSealevelPressure());
    Serial.print(" Pa / ");
    
    // http://en.wikipedia.org/wiki/Atmospheric_pressure#Mean_sea_level_pressure
  //  Serial.print("Presiure la nivelul marii (calculata) = ");
    float presiune = bmp.readSealevelPressure()/101.325;
    presiune = presiune * 0.760;
    Serial.print(presiune);
    Serial.println(" mmHg");
    

  // you can get a more precise measurement of altitude
  // if you know the current sea level pressure which will
  // vary with weather and such. If it is 1015 millibars
  // that is equal to 101500 Pascals.
    Serial.print("Altitudine reala = ");
    Serial.print(bmp.readAltitude(101500));
    Serial.println(" m");
    
    Serial.println();
    
    
   lcd.setCursor(1, 0);
   lcd.print("temp.=  ");
    if ( bmp.readTemperature() < 10)
   {
     lcd.print(" "); 
     lcd.print(bmp.readTemperature());
   }
   else
   {
   lcd.print(bmp.readTemperature(),1);
   }
   lcd.write(0b11011111);
   lcd.print("C   ");
   
   lcd.setCursor(1, 1);
   lcd.print("pres.= p");
   lcd.print(presiune,0);
   lcd.print("mmHg  ");
    
   delay(2500);
}
24.11.2014
   In last weak-end, I received 3 pics from Dave (http://g4rvh.wordpress.com/) with a shield for Arduino Uno, made after my schematic:
   He made with board with CNC Cutter:
   I change the sketch for present the temperature in Fahrenheit, not in Celsius degree, using information from article http://www.mathsisfun.com/temperature-conversion.html: