GPS venemittaristoa (Versio 1.0 nyt toiminnassa).

terve.

Projektinani ollut vuoden verran GPS:llä toimiva venemittaristo.
Käytössä perus kaksirivinen LCD-näyttö ja Arduino Uno.

Olen "leikkaa + liimaa" menetelmällä saanut jonkinlaista tulosta, mutta vieläkään ei tahdo kunnolla toimia.

Unolle olen syöttämässä:
-NMEA dataa GPS:ltä
-Moottorin kierroslukutietoa (pulssia)

Muuttuvia lukuja on:
-Potkurin nousu (kaksinumeroinen lukuarvo)
-Vaihteiston perävälitys ( lukuarvo kahdella desimaalilla)

GPS:ltä lasketaan näyttöön reaaliaikaista nopeutta
Moottorin kierrosnopeus myös näytöllä
Kierrosluvun, potkurinousun ja vaihteistovälityksen avulla lasketaan teoreettinen nopeus.
Näytölle lasketaan GPS-nopeuden ja teoreettisen nopeuden ero => potkurin luisto %

Näytöstä poiketen ei vedenpainetta enää mitata. => Mutta sen tilalle olisi tarkoitus saada maksimi nopeus pysymään näytössä.

Projekti jäi jäihin keväällä, kun piti mitata moottorista kierroslukutiedon amplitudi... Ei viitsisi polttaa piiriä sen takia.

Lisään jo olevan raakilekoodin naurettavaksenne, kun vanhalta koneelta sen löydän.
Sitten pitäisi taas jatkaa projektia.

se lcd-settinksi valikko- tallennus juttu josta oli puhetta toisessa topikissa, meillä on tulossa/menossa(mikäli projektin rautapuolta ei todeta sudeksi) eräs projekti johon näillä näkymin tulee vastaava asetusten muutos mahdollisuus, voin lainata valikko systeemiä käyttöösi jos/kun projektimme etenee siihen pisteeseen...

Kiitos tarjouksesta.

Tuossa ollut koodi kaverilla katseltavana... Toimii, mutta ei tajua kuin se on tehty.
Pitää hieman opiskella alkeita, jotta tietää edes vähän mitä nuo käskyt tarkoittaa :wink:

Nyt olisi jonkinmoista koodia tarjolla.
GPS toimii ja vuorossa olisi luiston laskeminen.

En saa Arduinoa laskemaan millään oikein?

Nyt koodin tarkistamiseksi olen laittanut nopeuden ja kierrokset kiinteiksi numeroiksi (nopeus & kierros)
Tuo "SLIP" olisi se lopullinen tuotos.
alla olevin arvoin tulokseksi pitäisi tulla 13%

SPEED X RATIO X C
SLIP = 100 X [ 1 - (-------------------) ]
RPM X PITCH

const int nousu = 30;
const int gear = 2;
const int kerroin = 1215.2;
const int nopeus = 60;
const int kierros = 5600;
const int yla = (nopeusgearkerroin); // Luistolaskelman jakoviivan yläpuoli = 145824
const int ala = (kierros*nousu);
const int lasku = (yla/ala);

Lopullinen lasku:

lcd.print(100*(1-lasku));
lcd.print("%");

Nyt se laskee tulokseksi 200%

?? Auttakaahan onnetonta.

itselleni vastaten :wink:

const double yla = (gps.f_speed_knots()gearkerroin); // Luistolaskelman jakoviivan yläpuoli = 145824
const double ala = (kierros*nousu);
const double lasku = (yla/ala);
const double valmis = (1-(yla/ala));

const double näytti olevan ratkaísu ongelmaan.
Nyt laskee laskutkin oikein :wink:

Seuraavaksi pitäisi saada askarreltua valikot?

const double nousu = 23;
const double gear = 2.4;

"nousu & gear" olisi kiva vaihtaa ilman kompuutteria?
Onko ohjeita for dummies, kuinka saad muutamalla napilla vaihdettua noita arvoja?

Eka käyttötesti menossa...

Laskenta ja näyttö toimii odotetulla tavalla :wink:
Ainoastaan kierroslukusignaalin puuttuessa, laitoin sille kiinteän arvon. 6100 RPM
Muuten potkurinousuksi 23" ja vaihteiston välitykseksi 2.4:1, jotka on mökkipikkuveneeni arvot.

Näin ollen ~80km/h autolla ajaessa näyttää aikalailla sitä mitä venekkin menee.
Luistoksikin laskee vielä aivan oikeat arvot :wink:

slipgauge.jpg

En ole LCD-näytöillä vielä pelannut, mutta näyttäisi että tuon kitin napin painallus luetaan analogisesti ja mapataan esimerkkikoodin mukaan seuraavasti.
int adc_key_val[5] ={30, 150, 360, 535, 760 };
Eli:
<29: oikea
30-149: ylös
150-359: alas
360-534: vasen
535-759: valinta

=760: ei painettu
http://www.dfrobot.com/image/data/DFR0009/LCD4Bit_mod.zip

Tuon linkin takaa löytyy ihan hyvännäköinen koodinpätkä, mikä ei jää turhia blokkaamaan luupin sisälle. Turhat delayt luupin sisällä aiheuttavat sen, että näyttö ei vastaisi painalluksiin luotettavasti.

Tuo msgs[5][15] merkkijonotaulu on tässä turha. Sen sijaan pitäisi vain ohjata muuttujan key arvo vaikuttamaan siihen mitä näytöllä näytetään. Tai tarkemmin, jos key on jotain muuta kuin -1, niin päivitetään joku muuttuja kyseiseen arvoon. Sitten vaikka joku switch-case, tai if-else hässäkkä ajamaan tuon muuttujan perusteella se oikea funktio tai lcd.print tms. Minä rakentaisin ohjelman niin, että jokaista näytettävää moodia varten olisi oma funktionsa, mutta se vähän riippuu miten tätä piti ohjata. Käyttöliittymän voisi suunnitella vaikka tilakaaviona ja kirjoittaa sitten auki koodiksi.

Tai sitten jos on tosiaan vain kaksi moodia, niin siihen riittää tilamuuttuja, jolla on arvot 0 ja 1. Napin painallus vaihtaa tilan nollasta ykkökseksi ja päin vastoin. Kannattaa säilyttää koodista tuo key != oldkey ja key>=0 kohta, koska muuten se vetäisi villissä luupissa tilasta toiseen.

Minä en tunne tuota LCD:tä, mutta hyvä että jotenkin saat luettua arvot.

Menuvalinnoissa nappien pitäisi toimia johdonmukaisesti vasen-oikea, ylös-alas, valinta tyyliin, mutta se riippuu siitä että saa jotenkin noin pienen näytön alueella ilmaistua tilan.

Ehkä kuitenkin jotenkin niin, että select nappi vaihtaisi aina tilaa info-näytön ja muokkaus-näytön välillä. Jos info-näytössä, niin näytetään ne asiat mitä haluatkin näyttää, ja muokkaus-näytössä voit vasen-oikea napeilla vaihtaa potkurin nousu-, ja vaihteiston välitys -alitilaa. Ylös-alas lisäisi tai vähentäisi sitä arvoa mikä näkyy näytössä. Kun tässä tilassa painaa select-nappia, niin arvot sijoitetaan muuttujiin, tai voihan ne sijoittaa jo suoraan napin painalluksesta.

Joka tapauksessa select-nappi palauttaisi tilaan info-näyttöön muutosten jälkeen. Tarvitaan muuttuja ainakin sille, onko muokkausnäyttö päällä vai ei. Jos muokkausnäyttö on päällä, toinen muuttuja kertoo kumpaan muuttujaan ylös-alas painallukset vaikuttavat. Melko yksinkertainen tilakone siitä muodostuisi.

Maksiminopeus on vain muuttuja, jonka arvo näytetään info-tilassa. Nopeuden varmasti jo mittaat. Kunhan vain tila riittää näytöllä.
if (nopeus > maxnopeus) maxnopeus = nopeus;
Tarvinnee jonkin tavan resetoida maxnopeus takaisin nollaksi. Ellei tässä riitä Arduinon oma reset-nappi, ja sitten setup- tai alustusfunktioon maxnopeuden nollaus. Reset-nappi tosin tarkoittaa myös sitä, että muut muistiasetukset alustettaisiin myös.

Nappien sijaintia minä vaan ajattelin, kun kirjoitin ylös-alas. Kyllä kai ne jotenkin neliön sisälle on aseteltu näytön alle.

http://playground.arduino.cc/Main/InterfacingWithHardware#tui
Täältä löytyy muutama kirjasto, joilla voi rakentaa menujakin 16x2 tms näytöille, mutta saattaa olla hieman overkill tähän tarkoitukseen. Esimerkiksi se viimeinen LCD Menu, tai jokin sitä ylempänä, mistä vaan löytyy parhaat esimerkit - en ehtinyt tarkistaa.

Jotain tähän suuntaan sitten. Käänsin, mutta en ole ajanut kertaakaan läpi, kun ei ole mitään millä testata. Jos sinulla onkin digitaaliset napit, niin pitäisi korvata analogRead useammalla digitalRead-kutsulla ja toimia sen mukaan mikä nappi oli pohjassa. Funktiota get_key ei silloin välttämättä tarvita ainakaan tuossa muodossa. Tämäkin koodi lukee napin tilan kahteen kertaan ja ilmeisesti tarkoitus on välttää reagoimasta kohinaan tms (debounce).

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

const int NUM_KEYS = 5;
int adc_key_val[NUM_KEYS] ={30, 150, 360, 535, 760 };
int adc_key_in;
int key=-1;
int oldKey=-1;

enum tila_t { INFO, NOUSU, GEAR } tila;

const double MIN_NOUSU = 10;
const double MAX_NOUSU = 32;
const double MIN_GEAR = 1.32;
const double MAX_GEAR = 2.60;
double nousu;
double gear;
double maxnopeus;

void setup()
{ 
  pinMode(13, OUTPUT);

  lcd.begin(16,2);
  lcd.print("Initializing...");

  nousu = 17.00;
  gear = 2.60;
  maxnopeus = 0.00;
  tila = INFO;
}

void loop() 
{
  adc_key_in = analogRead(0);    // read the value from the sensor  
  digitalWrite(13, HIGH);  
  
  key = get_key(adc_key_in);
  if (key != oldKey)
  {
    delay(50);                        // wait for debounce time
    adc_key_in = analogRead(0);            // read the value from the sensor  
    key = get_key(adc_key_in); 
    if (key != oldKey)
    {
      oldKey = key;
      if (key >= 0)
        paivitaTila(key);
    }
  }
  
  switch(tila)
  {
    case INFO:
      menuInfo();
      break;
    case NOUSU:
      menuNousu();
      break;
    case GEAR:
      menuGear();
      break;
  }
  
  digitalWrite(13, LOW);
}

// näytä infotila
// lue nopeus, jos nopeus suurempi kuin max, päivitä.
// lue kierrosluku, laske, päivitä näyttö uusilla arvoilla.
void menuInfo()
{
  lcd.print("info");
}

// näytä potkurin asetustila
// lue nousu
void menuNousu()
{
  lcd.print("nousu");
}

// näytä vaihteiston asetustila
// lue gear
void menuGear()
{
  lcd.print("gear");
}

//tilakone
// muokkaa muuttujien arvoja
void paivitaTila(int input)
{
  switch(input)
  {
    case 0: // oikea
    case 3: // vasen
      if (tila == NOUSU)
        tila = GEAR;
      else if (tila == GEAR)
        tila = NOUSU;      
      break;
    case 1: // ylos
      if (tila == NOUSU && nousu < MAX_NOUSU)
        nousu++;
      else if (tila == GEAR && gear < MAX_GEAR)
        gear += 0.01;
      break;
    case 2: // alas
      if (tila == NOUSU && nousu > MIN_NOUSU)
        nousu--;
      else if (tila == GEAR && gear > MAX_GEAR)
        gear -= 0.01;
      break;
    case 4: // select
      if (tila == INFO)
        tila = NOUSU;      
      else
        tila = INFO;
      break;
  }
}

// Convert ADC value to key number
int get_key(unsigned int input)
{
  int k;
    
  for (k = 0; k < NUM_KEYS; k++)
  {
    if (input < adc_key_val[k])
      return k;
  }
    
  if (k >= NUM_KEYS)
    k = -1;     // No valid key pressed
    
  return k;
}

Kiitos koodista. Ei se tähän toiminut, mutta kaveri vähän auttoi.

Nyt on Mittari valmis (tähän hätään).

Menuvalikolla saa tallennettua tiedot EEPROM:lle.
Nyt vaan veneenrakennukseen ja odottamaan testiajoja :wink:

Nyt avattu oma sivukin mittaria varten :wink:

http://vauhtiveneily.fi/vauhtiveneilyelektroniikkaa/

No hyvä että nyt toimii. Minäkin hommasin LCD:n, eikä sekään sitten edes toiminut.. pitää viritellä paremmalla kärsivällisyydellä joskus myöhemmin.