• The end goal is to have a GPS that is also connected to other inputs - such as Wind direction, Wind speed, heeling, etc. Of course: there is plenty of electronics to buy (and rely on), but it is a fun and entertaining training project to get all these things working together.

    Basis for the basic GPS code (module) is the extended code as posted with title GPS Module, Extensions for handling other sentences, and u-blox NEO-6M GPS receiver on http://forum.espruino.com/conversations/­255757/. Get the GPS code from there.

    The gpsHandlerObject is picking up and transforming the gps receiver sentences and sending it to the navi object which displays the information on the LCD display (code below).

    In this stage, the whole Hardware and Software system works as GPS / satellite driven clock... with time zone adjustment ;). Provisions for handling changes due to jitters and displaying of other essential data are in infancy to absence.

    The satelliteClock.mp4 clip - link below the code - shows a send-to-board / restart phase.

    // ===== LCD (ILI9341) common setup;
    B2.set();
    SPI1.setup({sck:B3, miso:B4, mosi:B5, baud: 1000000});
    var lcd = require("ILI9341");
    
    // ----- navi to display (changed) data on (ILI9341 controlled) LDC as 'sent' by GPS
    
    var navi = 
    { lcd: null
    , gpsHandler: null
    , data:
      { timAdj: -7
      , timc: ""
      }
    , timc: function(v,p) {
        var v0 = this.data.timc; this.data.timc = v;
        var j = 0, i = 5; while (i > 0) { i--;
          if (v.charAt(i) == v0.charAt(i)) { j = i + 1; i = -1; }
        }
        v0 = v.split("");
        if (j < 2) { j = 0;
          i = parseInt(v[0],10) * 10 + parseInt(v[1],10) + this.data.timAdj;
            i = (i < 0) ? i + 24 : (i > 24) ? i - 24 : i;
            v0[1] = i % 10; v0[0] = (i - v0[1]) / 10;
        }
        j = (j >= 4 ) ? j + 2 : (j >= 2) ? j + 1 : j;
        v0.splice(4,0,":"); v0.splice(2,0,":"); 
    //    console.log(".......".substr(0,j) + v0.join("").substr(j));
        var s = this.fonts[2], x = 240 - 8 * s * 0.8, y = 5;
        this.setClr(0); this.lcd.fillRect((i=x+j*s*0.8),y,i+(8-j­)*s*0.8,y+s*1.45);
        while (j < 8) { this.drawString(2,1,v0[j],x + j * s * 0.8,y); j++; }
      }
    , initDsp: function() {
        this.lcd.clear();
      }
    , clrs:
        [ [ 0.0, 0.0, 0.0] // 0 = black
        , [ 1.0, 1.0, 1.0] // 1 = white
        , [ 0.8, 1.0, 0.8] // 2 = ...
        ]
    , cid: -1
    , setClr: function(cid) { 
        if ((cid >= 0) && (this.cid != cid)) { this.cid = cid;
           var rgb = this.clrs[cid]; lcd.setColor(rgb[0], rgb[1], rgb[2]);
      } }
    , fonts:
        [ 12 // 0 = 'small'
        , 20 // 1 = 'medium' 
        , 32 // 2 = 'large'
      ]
    , fid: -1
    , setFont: function(fid) {
        if ((fid >= 0) && (this.fid != fid)) { this.fid = fid;
          lcd.setFontVector(this.fonts[fid]);
      } }
    , drawString: function(f,c,s,x,y) {
        this.setFont(f); this.setClr(c); this.lcd.drawString(s,x,y);
      }
    , init: function(lcd,gpsHandler) {
        this.lcd = lcd;
        this.gpsHandler = gpsHandler;
        gpsHandler.navi = this;
        this.initDsp();
        
      }
    };
    
    // ===== GPS common setup
    Serial4.setup(9600,{tx:C10,rx:C11});
    // var gps = require("GPS"); // uncomment when using GPS code as module
    
    // ----- gpsHandler(Object) calls navi to display (changed) data on ILI9341 controlled LCD
    
    var gpsHandler = { 
      // GGA (default): tag, time, lat[deg], lon[deg], fix, satellites, altitude[m]
      // GSA:
      // GSV (multiples):
      // GLL
      // RMC // NMEA's pvs - position, velocity, and speed (plus other things: true angle, date and time, mag var)
      includesDefaultLineHandler: false,
      enabled: false,
      enable: function(ena) {
        if (ena) { 
          if (!this.enabled) { this.data.reset(); this.enabled = true; } 
        } else {
          this.disable();
        }
      },
      disable: function() { this.enabled = false; },
      lineHandler: function(line, handler) {
        if (handler.enabled) { try {
          var tag = line.substr(3,3);
          if/*sel*/ (tag=="GGA") {
    //        console.log(line);
            handler.handleGGA(line,handler.data.hand­leChange,handler);
    //        console.log(line);
          } else if (tag=="RMC") {
            handler.handleRMC(line,handler.data.hand­leChange,handler);
    //      } else {
    //        gpsHandlerFunction({"raw":line});
          }
        } catch (x) { if (console && console.log) { console.log(x); } } }
      },
      handleGGA: function(line,callback,handler) {
        var d = line.split(",");
         callback({ tag:"GGA",
    //      fix : parseInt(d[6],10),
          sata : parseInt(d[7],10),
          alta : parseFloat(d[9])
        },handler);
      },
      handleRMC: function(line,callback,handler) {
        var d = line.split(",");
        callback({ tag:"RMC",
          timc: d[1].substr(0,6),
          latc: (parseInt(d[3].substr(0,2),10) + parseFloat(d[3].substr(2))/60) * (d[4]=="S"?-1:1),
          lonc: (parseInt(d[5].substr(0,3),10) + parseFloat(d[5].substr(3))/60) * (d[4]=="W"?-1:1),
          velc: parseFloat(d[7]),
    //      angl: d[8],
          datc: d[9]
        },handler);
      },
      navi: null,
      data: {
        handleChange: function(d,handler) {
    //      console.log(d);
          for (var p in d) handler.data.changed[p](d[p],p,handler);­ 
        },
        reset: function() {
          this.latc = -999.9;
          this.lonc = -999.9;
          this.velc = -999.9;
          this.alta = -999.9;
          this.sata = 0;
          this.datc = "";
          this.timc = "";
        },
        tag:  "-",
        latc: -999.9,
        lonc: -999.9,
        velc: -999.9,
        alta: -999.9,
        sata: 0,
        datc: "",
        timc: "",
        latcd: 0.0,
        loncd: 0.0,
        velcd: 0.0,
        altad: 0.0,
        satad: 0.0,
        latct: 0.0,
        lonct: 0.0,
        velct: 0.0,
        altat: 0.5,
        satat: 0.1,
        
        changed: {
          adj: -7, // -7 = UTC-PSD, -8 = PST-UTC
          tag:  function(v,p,h) { h.data[p] = v; },
          latc: function(v,p,h) { 
            var v0 = h.data[p]; 
            var d = v0 - v;
            
            h.data[p] = v; 
          },
          lonc: function(v,p,h) { 
            var v0 = h.data[p]; 
            var d = v0 - v;
            
            h.data[p] = v; 
          },
          velc: function(v,p,h) {
            var v0 = h.data[p];
            var d = v0 - v;
            
            h.data[p] = v; 
          },
          alta: function(v,p,h) { 
            var v0 = h.data[p];
            
            h.data[p] = v;
          },
          sata: function(v,p,h) { 
            var v0 = h.data[p]; 
            
            h.data[p] = v; 
          },
          datc: function(v,p,h) { 
            var v0 = h.data[p]; 
            h.data[p] = v; 
          },
          timc: function(v,p,h) { 
            h.data[p] = v;
            h.navi[p](v,p);
          },
        }
      }
    };
    
    
    // function naviInit() {
      lcd = lcd.connect(SPI1, B6, B8, B7, function(){
        setTimeout(function(){
          gps.connect(Serial4, gpsHandler);
          navi.init(lcd,gpsHandler);
          gpsHandler.enable(true);
        },100);
      });
    // }
    

    The satelliteClock.mp4 clip (link below) shows a send-to-board / restart phase. Notice the nice skipping of displaying some time, and also that only the part of the string that changes is redrawn. Uncommenting line 28 will show the not redrawn part as dots followed by the part to redraw on the LCD in the console pane (see below). Most of the code of .timc() method is dedicated to that part and is combined with the time zone adjustment for display. In other words, internally, UTC is used, and converted only to local time for display.

    >echo(0);
    =undefined
    12:50:59
    ....1:00
    .......3
    .......4
    .......5
    .......6
    .......7
    .......8
    .......9
    ......10
    .......1
    >gpsHandler.disable()
    =undefined
    >gpsHandler.enable(true)
    =undefined
    ......48
    .......9
    ......50
    .......1
    .......2
    .......3
    .......4
    .......5
    .......6
    .......7
    .......8
    .......9
    ....2:00
    =undefined
    >gpsHandler.enable(true)
    =undefined
    ......49
    ......50
    .......1
    .......2
    .......3
    .......4
    .......5
    .......6
    .......7
    .......8
    .......9
    ....3:00
    .......1
    .......2
    

    The difference detection algorithm has though still a flaw! What is the flaw? When will it show? And how could it be fixed with practically the same code lines?


    2 Attachments

About

Avatar for allObjects @allObjects started