• My project consists of espruino, environment sensors and 4 blue 7 segment displays

    Datasheet(specifically decimals): https://github.com/sparkfun/Serial7Segme­ntDisplay/wiki/Special-Commands#decimal

    What I would like to accomplish is send data, for an example send the room temp, i.e. 76.7F to the 7-segment display. Depending on where the decimal place is, turn on that decimal which I dont think is that hard to do. What I am struggling with is calculating the bytes to send in order to turn on the specific decimal.

    To better understand this i will use the github totorial for my example. For example, To turn on the colon, apostrophe, and far-right decimal point we need to set bits 4, 5, and 3, respectively. Our data byte will therefore be: 0b00111000 (ie. hex 0x38, or decimal 56).

    From experience, I know the 0b signifies the data following is in binary format and 00111000 equals 56. Where did the 56 come from? There's a handy chart explaining the bit layout, however I still don't understand.

  • 56 is the decimal representation of 0b00111000. As binary is base 2, bit 5 is 32, bit 4 is 16, bit 3 is 8 32+16+8=56.

    You can use both binary and hexadecimal notation (0b.... and 0x... ) in Espruino, as well as decimal. Usually we use whatever format makes the most sense - for example, here, the decimal value is not particularly meaningful - 56? why 56? - but if you look at the binary or hexadecimal form, you can see that it's a byte with bits 3, 4 and 5 as ones.

  • Thank you for explaining. I think I understand now :) . Each bit represents the decimals, colon and apostrophe. So, I should send 0b10000000 to only turn on the decimal furthest to the left.

    Update
    I meant to write 0b00000001

  • The code below may give you what you are looking for. @DrAzzy explained you the decimal and apostrophe workings (but I'm not sure of your conclusion: To set the decimal point of the first/most left digit, I'd send 0b00000001).

    Display pH 0...14.4 (theoretically up to 99.4) in 2 digits:

    // assuming ph value = [0..14.4...], ser = serial
    // displays as 0.0..9.9,10..14 PH
    // - var ds = digits, ps = punctuations
    // - set ds and ps for (>=9.95) ? 10..14 : (>=0.995) ? 1.0..9.9 : 0.0..0.9
    //   no dec pt: 0bxx000000 = 0b01000000 = "@"
    //   dec pt 1st digit: 0bxx000001 = 0b01000001 = "A"
    var dspPH = function(ph,ser) {
        var cs, ps;
        if (ph >= 9.95) {
          ds = ("" + Math.round(ph)).substr(0,2);
          ps = "@";
        } else if (ph >= 0.95) {
          ds = ("" + Math.round(ph * 10)).substr(0,2);
          ps = "A"; 
        } else {
          ds = ("0" + Math.round(ph * 100)).substr(0,2);
          ps = "A"; 
        }
        ser.write("v" + ds + "PHw" + ps);
    };
    

    Display temperature 0...999.4### in 3 digits:

    // assuming t (temp) value = [0..999.4###], ser = serial
    // displays as 0.00..9.99,10.0..99.9,100..999 F
    // - var ds = digits, ps = punctuations
    // - set ds and ps for t (>=99.95) ? 100..999 : (>=9.95) ? 10.0..99.9 : (>=0.995) ? 1.00..9.99 : 00.0..00.9 
    //   no dec pt, degree (apos): 0bxx100000 = 0b01100000 = 96 = "`"
    //   dec pt 1st digit, degree (apos): 0bxx100001 = 0b01100001 = 97 = "a"
    //   dec pt 2nd digit, degree (apos): 0bxx100010 = 0b01100010 = 98 = 'b'
    var dspT = function(t,ser) {
        var cs, ps;
        if (t >= 99.95) {
          ds = ("" + Math.round(t)).substr(0,3);
          ps = "`";
        } else if (t >= 9.995) {
          ds = ("" + Math.round(t * 10)).substr(0,3);
          ps = 'b'; 
        } else if (t >= 0.995) {
          ds = ("" + Math.round(t * 100)).substr(0,3);
          ps = "a"; 
        } else if (t >= 0.095) {
          ds = ("0" + Math.round(t * 100)).substr(0,3);
          ps = "a"; 
        } else {
          ds = ("00" + Math.round(t * 1000)).substr(0,3);
          ps = "a"; 
        }
        ser.write("v" + ds + "Fw" + ps);
    };
    

    Since I do not have the display at hand, I can only test so far as creating the sting to send to it and look at it. In the attachment you find a .html file hat you can download anywhere on your hard drive, open with your browser, and enter value and see the string sent to the display. The .html includes the display pH and display temperature function and a interactive test bed around them (in another post I may add an emulation for the display.

    For the calculation of the display value I tried to follow what I remembered from my stoichiometry / chemistry classes, where the teacher yelled at us to not consider the error calculation on reading scales, etc... and applied I reversely. You are the scientific judge to that... ;-)

    For setting the decimal point - and for temperature the apostrophe for degree - I set the 6th (counting from 0) bit always to 1, which brings the character to send into the nicely printable range of either '@ABCD' and '`abcd', respectively.

    If you want to set 'crazy' characters, you have to make a mapping from a character not used otherwise to a binary value. You achieve this by setting up a lookup string for getting an index, and with the index you go and get the binary value. It looks something like that:

    var lookupString = "()[]#";
    var map =
    [ 0b00110101
    , 0b01001101
    , 0b00101101
    , 0b00100001
    , 0b01111111
    };
    
    var lookup = function(c) {
      var idx = lookupString.indexOf(c);
      return map[idx];
    }
    

    The following code will return turn all segments of the first digit on:

    serialX.write("v" + lookup("#");
    

    You would use the lookup() function to create the string before sending it. Since the module can display all digits and the letters F, P, and H (and more), only for crazy patterns a lookup/mapping is required.


    2 Attachments

  • @DrAzzy @allObjects thank you for the explanations

    Sorry, I'm a bit dyslexic at times :) I meant to write 0b00000001

  • Everything seems to be functioning quite nicely :-) Now all I need to do is make an object of the functionality and placements of the decimal points. I'll post back in a few days with the code. @allObjects I will for sure read over your post from earlier.

  • Code that I threw together to get decimal places to work. It looks a bit rough, but it seems to work.

    function s7s (sensor, theAddress) {
      this.displayFor = sensor;
      this.address = theAddress;
      this.displayTable = {
        "Clear" : 0x76,
        "dp"    : {
          "cmd" : 0x77,
          "location"   : [
              0b00000001, //Digit 0
              0b00000010, //Digit 1
              0b00000100, //Digit 2
              0b00001000  //Digit 3
          ]
        }
      };
    }
    
    setInterval(function (e) {
      ph.getSensorResult(function(value) {
        var toChar = "";
        var a = phDisplay.address;
        var clr = phDisplay.displayTable.Clear; //Display clear command
        var dpc = phDisplay.displayTable.dp.cmd; //Decimal point command
        var dplo = phDisplay.displayTable.dp.location; //Decimal point location map
    
        var i;
    
        I2C1.writeTo(a, clr); //Clear display
    
        if(value[0] === 1) {
          for(i=0; i<value.length; i++) {
            if (value[i] !== 1 && value[i] !== 0) {
              var c = String.fromCharCode(value[i]);
    
              if (c != '.') {
                toChar += c;
              }
              if (c == '.') {
                var n = i - 2;
    
                I2C1.writeTo(a, dpc);
                I2C1.writeTo(a, dplo[n]);
              }
              if (i == (value.length - 2)) {
                console.log(toChar);
                I2C1.writeTo(a, toChar);
                toChar="";
              }
            }
          }
        }
      });
    }, 2000);
    
  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Sparkfun 7 segment display: turning decimals on and off

Posted by Avatar for d0773d @d0773d

Actions